Dmitriy Nikiforov via llvm-dev
2017-Mar-15 19:21 UTC
[llvm-dev] Missing coverage instrumentation with trace-pc-guard option
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>