[llvm-dev] Missing coverage instrumentation with trace-pc-guard option

Dmitriy Nikiforov via llvm-dev llvm-dev at lists.llvm.org
Wed Mar 15 12:21:33 PDT 2017


Hi,

I was trying to get a coverage for sanitizers for my library and then I have encountered a problem that some calls to __sanitizer_coverage_trace_pc_guards are missing in several basic blocks. I made a
reduced reprocase for this (reduced.c in attachments) and built it with '-gline-tables-only -O0 -fsanitize=address -fsanitize-coverage=trace-pc-guard' flags:

clang -gline-tables-only -O0 -fsanitize=address -fsanitize-coverage=trace-pc-guard -S reduced.c

extern void clobber1(int *state_ptr);
extern void clobber2(int *state_ptr);
extern void clobber3(int *state_ptr);

int foo(char c, int state, int threshold) {
   while (state < threshold) {
     switch (state) {
     case 1:
       clobber1(&state);
       if (c == '*') {
         state++;
       } else if (c == '/') {
         state--;                            <============== missing __sanitizer_cov_trace_pc_guard call
       } else {
         clobber1(&state);
         goto out;
       }
       clobber2(&state);
       break;
     case 2:
       clobber3(&state);
       break;
     }
   }
out:
   return state;
}

int main(int argc, char **argv) {
   return foo(argv[1][2], argc + 4, 255) > 100;
}

After examination of dumped LLVM IR (-print-after-all) I have found that there are no calls of __sanitizer_coverage_trace_pc_guard in 'if.then6' basic block that corresponds to "else if (c == '/')"
fall through case:

sw.bb:                                            ; preds = %while.body
   call void @clobber1(i32* %state.addr), !dbg !15
   %3 = load i8, i8* %c.addr, align 1, !dbg !16
   %conv = sext i8 %3 to i32, !dbg !16
   %cmp1 = icmp eq i32 %conv, 42, !dbg !17
   br i1 %cmp1, label %if.then, label %if.else, !dbg !16

if.then:                                          ; preds = %sw.bb
   call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 8) to i32*)), !dbg !18
   call void asm sideeffect "", ""(), !dbg !18
   %4 = load i32, i32* %state.addr, align 4, !dbg !18
   %inc = add nsw i32 %4, 1, !dbg !18
   store i32 %inc, i32* %state.addr, align 4, !dbg !18
   br label %if.end8, !dbg !19

if.else:                                          ; preds = %sw.bb
   %5 = load i8, i8* %c.addr, align 1, !dbg !20
   %conv3 = sext i8 %5 to i32, !dbg !20
   %cmp4 = icmp eq i32 %conv3, 47, !dbg !21
   br i1 %cmp4, label %if.then6, label %if.else7, !dbg !20

if.then6:                                         ; preds = %if.else       <======= no __sanitizer_cov_trace_pc_guard
   %6 = load i32, i32* %state.addr, align 4, !dbg !22
   %dec = add nsw i32 %6, -1, !dbg !22
   store i32 %dec, i32* %state.addr, align 4, !dbg !22
   br label %if.end, !dbg !23

if.else7:                                         ; preds = %if.else
   call void @__sanitizer_cov_trace_pc_guard(i32* inttoptr (i64 add (i64 ptrtoint ([6 x i32]* @__sancov_gen_ to i64), i64 12) to i32*)), !dbg !24
   call void asm sideeffect "", ""(), !dbg !24
   call void @clobber1(i32* %state.addr), !dbg !24
   br label %out, !dbg !25

if.end:                                           ; preds = %if.then6
   br label %if.end8

if.end8:                                          ; preds = %if.end, %if.then
   call void @clobber2(i32* %state.addr), !dbg !26
   br label %sw.epilog, !dbg !27


But, if I remove the 'goto out' instruction, then '__sanitizer_cov_trace_pc_guard' call appears in all if clauses as expected.

Is this an intended behavior or some kind of a bug? And if it's intended, how can I deduce a real coverage from these instrumented points?

Thanks,
Dmitriy
-------------- next part --------------
A non-text attachment was scrubbed...
Name: reduced.c
Type: text/x-csrc
Size: 623 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170315/65f7417d/attachment.c>


More information about the llvm-dev mailing list