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