This directory contains a LibFuzzer-based fuzzer for the libloong LoongArch emulator.
The fuzzer tests the instruction set by:
- Taking random input data from LibFuzzer
- Rounding it to 4-byte alignment (LoongArch instructions are 4 bytes)
- Using
init_execute_area()to create a fast-path execute segment - Executing the instructions with a limited instruction count (5,000 instructions max)
This approach is inspired by the libriscv fuzzer and helps discover bugs in instruction decoding and execution.
The fuzzer requires Clang (for LibFuzzer support) and should be built separately from the main project:
cd fuzz
mkdir -p build && cd build
cmake -DCMAKE_CXX_COMPILER=clang++-18 -DCMAKE_C_COMPILER=clang-18 ..
makeNote: LibFuzzer is only available with Clang. GCC is not supported.
Basic fuzzing (runs indefinitely):
./vmfuzzerLimited runs:
./vmfuzzer -runs=10000With custom max length:
./vmfuzzer -runs=10000 -max_len=256With a corpus directory:
mkdir corpus
./vmfuzzer corpus/ -runs=10000The fuzzer is built with AddressSanitizer and UndefinedBehaviorSanitizer by default. You can change this in CMakeLists.txt by modifying the FUZZER_MODE variable:
# Current: address,undefined
# Alternative: memory,undefined (MemorySanitizer)
set(FUZZER_MODE "address,undefined")The fuzzer generates coverage information. To view coverage reports, use:
# After running the fuzzer
llvm-cov show vmfuzzer -instr-profile=default.profrawThe fuzzer specifically tests:
- Instruction decoding (all instruction formats)
- Bytecode translation and optimization
- Instruction execution handlers
- Edge cases in instruction operands
- Memory protection and bounds checking
- Syscall handling (basic exit syscall)
You'll see output like:
#100 NEW cov: 1271 ft: 1492 corp: 10/37b lim: 4 exec/s: 0 rss: 38Mb
Where:
cov: Code coverage (edges covered)ft: Features (unique execution paths)corp: Corpus size (number of interesting inputs / total bytes)lim: Current input length limitexec/s: Executions per secondrss: Memory usage
UNIMPLEMENTED: Indicates the fuzzer found an unimplemented instruction. This is expected and not a bug.
Protection fault: Indicates an instruction tried to access invalid memory. This is caught and handled.
Machine exception: Indicates an instruction triggered an exception. This is expected during fuzzing.
- Start with small runs (100-1000) to verify everything works
- Use a corpus directory to preserve interesting inputs
- For long fuzzing sessions, use
-max_total_time=3600(1 hour) - Monitor memory usage with the
rssfield - Save crashes with
-artifact_prefix=crashes/
Find crashes and save them:
mkdir crashes
./vmfuzzer -artifact_prefix=crashes/ -runs=100000Resume from a corpus:
./vmfuzzer corpus/ -runs=100000Minimize a crashing input:
./vmfuzzer -minimize_crash=1 crash-file