Skip to content

Commit 9462610

Browse files
committed
Using sancov with no-prune instead of bb for better coverage precision
1 parent e2129b6 commit 9462610

File tree

4 files changed

+16
-12
lines changed

4 files changed

+16
-12
lines changed

fuzzers/forkserver_libafl_cc/src/bin/libafl_cc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn main() {
2424
.parse_args(&args)
2525
.expect("Failed to parse the command line")
2626
// Enable libafl's coverage instrumentation
27-
.add_arg("-fsanitize-coverage=pc-table,bb,trace-pc-guard")
27+
.add_arg("-fsanitize-coverage=pc-table,no-prune,trace-pc-guard")
2828
// Imitate afl-cc's compile definitions
2929
.add_arg("-D__AFL_FUZZ_INIT()=int __afl_sharedmem_fuzzing = 1;extern unsigned int *__afl_fuzz_len;extern unsigned char *__afl_fuzz_ptr;unsigned char __afl_fuzz_alt[1048576];unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;void libafl_start_forkserver(void)")
3030
.add_arg("-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : __afl_fuzz_alt_ptr)")

fuzzers/libfuzzer_libpng/src/bin/libafl_cc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn main() {
2525
.parse_args(&args)
2626
.expect("Failed to parse the command line")
2727
.link_staticlib(&dir, "libfuzzer_libpng")
28-
.add_arg("-fsanitize-coverage=pc-table,bb,trace-pc-guard")
28+
.add_arg("-fsanitize-coverage=pc-table,no-prune,trace-pc-guard")
2929
.run()
3030
.expect("Failed to run the wrapped compiler")
3131
{

utils/drcov/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Original DrCov files have a rigid format that does not include the counters, thu
1313
DynamoRio collects DrCov using its runtime instrumentation. In LibAFL, we support collecting it using both compile-time and runtime instrumentation. This allows for a unified backend processing and analytics.
1414

1515
## Static instrumentation
16-
LibAFL uses llvm coverage instrumentation when compiling form sources. This is done by using a compiler wrapper libafl_cc that adds the needed options to the clang's command line. While regular LibAFL coverage adds just `-fsanitize-coverage=trace-pc-guard`, for DrCov coverage the libafl_cc should add `-fsanitize-coverage=pc-table,bb,trace-pc-guard`.
16+
LibAFL uses llvm coverage instrumentation when compiling form sources. This is done by using a compiler wrapper libafl_cc that adds the needed options to the clang's command line. While regular LibAFL coverage adds just `-fsanitize-coverage=trace-pc-guard`, for DrCov coverage the libafl_cc should add `-fsanitize-coverage=pc-table,no-prune,trace-pc-guard`.
1717
The meaning of the additions is:
18-
- `bb` causes the compiler to instrument each basic block (the default is 'edge' which introduces artificial BBs to track the edges that are known statically).
18+
- `no-prune` causes the compiler to instrument each basic block including those that it would optimize-out otherwise.
1919
- `pc-table` adds to the result ELF file a section that holds offsets of each BB. Without it, trace-pc-guard instrumentation does not provide any address information, just inserts callbacks to thecoverage instrumentation.
2020

2121
It is also important to compile the source with the debug information (`-g`) to be able to map the addresses to the source code lines.
@@ -102,9 +102,9 @@ The simplest way to merge the files:
102102
**Notes:**
103103
1. Merging will produce a `merged.drcov`, that can be processed by DrCov utilities. The produced files are in the old, version 2 format, thus some utilitites can warn about it.
104104
1. In order to maintain the counters data and to be able to process it and to display it in HTML, one needs to specify `-c`. This will produce a `merged.drcov.json` file that contains the counters for each executed basic block.
105-
1. When using static instrumentation, the sizes of the basic blocks are unknown. This will result in wrong line coverage displayed in HTML, as only the first file of each block will have the correct counter.The `-f` option fixes the problem by extracting the BB infromation from the binary. Thus it is recommened to use `-f` option when working with static instrumentation.
105+
1. When using static instrumentation, the sizes of the basic blocks are unknown. This will result in wrong line coverage displayed in HTML, as only the first file of each block will have the correct counter.The `-f` option fixes the problem by extracting the BB information from the binary. Thus it is recommened to use `-f` option when working with static instrumentation.
106106
1. By default, the original .drcov and .drcov.cnt files are deleted. `-k` will keep them after the merge.
107-
1. It is possible to create `merged.drcov` and `drcov.cnt` based on the `drcov.cnt` files only providing a single `.drcov` file (for the modules infromation missing from the .cnt files). This allows for more efficient distributed flow, so that you can send less files. Use `-co` for this mode, just make sure that at least one correct `.drcov` is present.
107+
1. It is possible to create `merged.drcov` and `drcov.cnt` based on the `drcov.cnt` files only providing a single `.drcov` file (for the modules information missing from the .cnt files). This allows for more efficient distributed flow, so that you can send less files. Use `-co` for this mode, just make sure that at least one correct `.drcov` is present.
108108
1. Convert Drcov to lcov. Use DynamoRio utility for that.
109109
**Notes:**:
110110
1. make sure to use the 64 bit utility for 64 bit targets. Example: `~/DynamoRIO-Linux-10.0.19798/tools/bin64/drcov2lcov -input ./coverage/merged.drcov -output ./coverage.info -src_filter libpng-1.6.37`

utils/drcov/merge_drcov.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ def symbolize(args):
670670
output = p.read()
671671
p.close()
672672
if args.verbose:
673-
print(f" {addresses_str} (size{v1[0]}): {v1[1]} times")
673+
print(f" {addresses_str} (size {v1[0]}): {v1[1]} times")
674674
print(output)
675675
if coverage_info is not None:
676676
# The llvm-symbolizer output is in the following format (for each address):
@@ -694,13 +694,17 @@ def symbolize(args):
694694
print(f" Line {line} not found in coverage info file, adding it")
695695
coverage_info[file][line] = v1[1]
696696
if args.verbose:
697-
print(f" Line {line}: {coverage_info[file][line]} times")
697+
print(f"{addr} Line {line}: {coverage_info[file][line]} times")
698698
else:
699699
if file != "??":
700-
if args.verbose:
701-
print(f" File {file} not found in coverage info file, adding it")
702-
coverage_info[file] = defaultdict(int)
703-
coverage_info[file][line] = v1[1]
700+
if args.coverage_info is None:
701+
if args.verbose:
702+
print(f" File {file} not found in coverage info file, adding it")
703+
coverage_info[file] = defaultdict(int)
704+
coverage_info[file][line] = v1[1]
705+
else:
706+
if args.verbose:
707+
print(f" File {file} not found in coverage info file, skipping")
704708

705709
# # Symbolize using pyelftools
706710
# pfile, pline = py_symbolizers[mod_path].get_file_line(int(k1, 16))

0 commit comments

Comments
 (0)