1
+ #! /bin/bash
2
+ set -e
3
+ set -x
4
+
5
+ # Define the fuzz directory relative to the project root
6
+ FUZZ_DIR=" fuzz"
7
+
8
+ TOOLCHAIN=" nightly"
9
+ FEATURES=" libfuzzer_fuzz"
10
+
11
+ # --- Dependencies ---
12
+ echo " Checking/installing dependencies..."
13
+ # cargo-llvm-cov implicitly uses/installs necessary LLVM tools
14
+ rustup +${TOOLCHAIN} component add llvm-tools-preview
15
+ # Check if cargo-llvm-cov is installed, install if not
16
+ if ! cargo +${TOOLCHAIN} --list | grep -q " llvm-cov" ; then
17
+ echo " Installing cargo-llvm-cov..."
18
+ cargo +${TOOLCHAIN} install cargo-llvm-cov
19
+ fi
20
+
21
+ # Clean previous builds and coverage artifacts relative to project root
22
+ echo " Cleaning previous build and coverage artifacts..."
23
+ cargo +${TOOLCHAIN} clean
24
+ rm -rf target/llvm-cov-target
25
+ rm -rf target/coverage
26
+
27
+ echo " Running fuzz targets with cargo-llvm-cov to collect coverage..."
28
+ export RUSTFLAGS=" --cfg=fuzzing --cfg=secp256k1_fuzz --cfg=hashes_fuzz"
29
+
30
+ # Determine host triple dynamically for the --target flag
31
+ HOST_TRIPLE=$( rustc +${TOOLCHAIN} --version --verbose | grep host | cut -d' ' -f2)
32
+ if [ -z " $HOST_TRIPLE " ]; then
33
+ echo " Error: Could not determine host triple."
34
+ exit 1
35
+ fi
36
+ echo " Detected host triple: $HOST_TRIPLE "
37
+
38
+ COMBINED_FEATURES=" $FEATURES ,lightning/_test_utils,lightning/std,lightning-invoice/std"
39
+
40
+ # Iterate over target binaries located within the FUZZ_DIR
41
+ for TARGET_PATH in " $FUZZ_DIR " /src/bin/* _target.rs; do
42
+ FILENAME=$( basename " $TARGET_PATH " )
43
+ TARGET_NAME=" ${FILENAME% .* } " # Remove .rs extension
44
+ TARGET_CORPUS_DIR=" $FUZZ_DIR /corpus/$TARGET_NAME "
45
+
46
+ if [ -d " $TARGET_CORPUS_DIR " ]; then
47
+ echo " Running cargo llvm-cov for target: $TARGET_NAME with corpus $TARGET_CORPUS_DIR "
48
+ if ! CARGO_TARGET_DIR=./target cargo +${TOOLCHAIN} llvm-cov run --no-report --manifest-path " $FUZZ_DIR /Cargo.toml" --target " $HOST_TRIPLE " --features " $COMBINED_FEATURES " --bin " $TARGET_NAME " -- " $TARGET_CORPUS_DIR " -runs=1; then
49
+ echo " Warning: Execution of $TARGET_NAME with cargo-llvm-cov finished with non-zero status."
50
+ fi
51
+ else
52
+ echo " Warning: Corpus directory ($TARGET_CORPUS_DIR ) not found for target $TARGET_NAME . Skipping."
53
+ fi
54
+ done
55
+
56
+ unset RUSTFLAGS
57
+
58
+ # Define paths relative to project root
59
+ MERGED_PROFDATA_PATH=" target/llvm-cov-target/fuzz.profdata"
60
+ HTML_REPORT_DIR=" target/coverage/html"
61
+ mkdir -p " $HTML_REPORT_DIR "
62
+
63
+ # Find all .profraw files generated by the runs in target/ relative to root
64
+ PROFRAW_FILES=$( find target/llvm-cov-target -name " *.profraw" )
65
+
66
+ if [ -z " $PROFRAW_FILES " ]; then
67
+ echo " Error: No .profraw files found in target/llvm-cov-target. Cannot generate coverage report."
68
+ exit 1
69
+ fi
70
+
71
+ # Merge .profraw files into a single .profdata file
72
+ echo " Merging profraw files..."
73
+ if ! llvm-profdata merge $PROFRAW_FILES -o " $MERGED_PROFDATA_PATH " ; then
74
+ echo " Error: llvm-profdata merge failed."
75
+ exit 1
76
+ fi
77
+ echo " Merged profile data created at $MERGED_PROFDATA_PATH "
78
+
79
+ # Identify the instrumented binary files
80
+ echo " Identifying instrumented binaries..."
81
+ declare -a OBJECT_FLAGS
82
+ BINARY_DIR=" target/llvm-cov-target/$HOST_TRIPLE /debug"
83
+
84
+ # Re-iterate over target sources to get names
85
+ for TARGET_PATH in " $FUZZ_DIR " /src/bin/* _target.rs; do
86
+ FILENAME=$( basename " $TARGET_PATH " )
87
+ TARGET_NAME=" ${FILENAME% .* } "
88
+ TARGET_CORPUS_DIR=" $FUZZ_DIR /corpus/$TARGET_NAME "
89
+ BINARY_PATH=" $BINARY_DIR /$TARGET_NAME "
90
+
91
+ # Check if the corresponding corpus dir existed (meaning the target was likely run)
92
+ # and if the binary file actually exists
93
+ if [ -d " $TARGET_CORPUS_DIR " ] && [ -f " $BINARY_PATH " ]; then
94
+ echo " Found binary for target $TARGET_NAME at $BINARY_PATH "
95
+ OBJECT_FLAGS+=(" -object" " $BINARY_PATH " )
96
+ else
97
+ echo " Warning: Skipping binary for $TARGET_NAME (corpus dir existed: $( [ -d " $TARGET_CORPUS_DIR " ] && echo true || echo false) , binary exists: $( [ -f " $BINARY_PATH " ] && echo true || echo false) )"
98
+ fi
99
+ done
100
+
101
+ if [ ${# OBJECT_FLAGS[@]} -eq 0 ]; then
102
+ echo " Error: No instrumented binaries found in $BINARY_DIR . Cannot generate report."
103
+ exit 1
104
+ fi
105
+
106
+ # Generate the HTML report using llvm-cov show
107
+ echo " Generating HTML report using llvm-cov show..."
108
+ IGNORE_REGEX=" (/.cargo/|/${FUZZ_DIR} /|/target/|/contrib/|/tests/|/benches/|lightning-invoice/src/convert\.rs|lightning-block-sync/src/lib\.rs|lightning-net-tokio/src/lib\.rs|lightning-persister/src/lib\.rs|lightning-rapid-gossip-sync/src/lib\.rs|lightning-transaction-sync/src/lib\.rs|lightning/src/util/ser\.rs)"
109
+
110
+ # generate html report
111
+ if ! llvm-cov show \
112
+ " ${OBJECT_FLAGS[@]} " \
113
+ -instr-profile=" $MERGED_PROFDATA_PATH " \
114
+ -format=html \
115
+ -output-dir=" $HTML_REPORT_DIR " \
116
+ -ignore-filename-regex=" $IGNORE_REGEX " \
117
+ -show-line-counts-or-regions \
118
+ -show-instantiations=false; then
119
+ echo " Error: llvm-cov show command failed."
120
+ exit 1
121
+ fi
122
+
123
+ # --- Done ---
124
+ echo " --------------------------------------------------"
125
+ echo " Combined coverage report generation finished."
126
+ echo " Report available at: $HTML_REPORT_DIR /index.html"
127
+ echo " --------------------------------------------------"
0 commit comments