Qemu arm launcher (#708)

* Adding qemu_arm_launcher crate

* Trying to fix qemu arm usermode

* Cargo fmt

* Adding CROSS_CC env

* Remove hardcoded arm-linux-gnueabi-gcc and replace by CROSS_CC

* Adding arm-linux-gnueabi-gcc to github workflows for ubuntu

* Fixing typo in apt install package

* Resetting LR after each fuzzing emulation

* Cargo fmt after merge conflict

* Using GuestAddr

* Compiling, running and running with artificial crash detection

* Adding dependencies for github workflow to cross compile for arm

* Fixing github workflow for ubuntu fuzzer

* arm-linux-binutils for mac in github workflows

* Qemu does not work for mac, no need to compile qemu_arm_launcher harness for it
This commit is contained in:
Patrick Gersch 2022-08-02 11:46:24 +02:00 committed by GitHub
parent 376e3adfcd
commit b2a1e03703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 657 additions and 18 deletions

View File

@ -52,7 +52,7 @@ jobs:
- name: set mold linker as default linker
uses: rui314/setup-mold@v1
- name: Install deps
run: sudo apt-get install -y llvm llvm-dev clang ninja-build clang-format-13 shellcheck
run: sudo apt-get install -y llvm llvm-dev clang ninja-build clang-format-13 shellcheck gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
- name: get clang version
run: command -v llvm-config && clang -v
- name: Install cargo-hack
@ -149,7 +149,7 @@ jobs:
run: rustup toolchain install nightly --component rustfmt --component clippy --allow-downgrade
- uses: lyricwulf/abc@v1
with:
linux: llvm llvm-dev clang nasm ninja-build
linux: llvm llvm-dev clang nasm ninja-build gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
# update bash for macos to support `declare -A` command`
macos: llvm libpng nasm coreutils z3 bash
- name: install cargo-make

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ vendor
.env
*.tmp
*.swp
*.o
*.a
*.so

6
fuzzers/qemu_arm_launcher/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
libpng-*
libpng_harness
libpng_harness_crashing
zlib-*
crashes
target

View File

@ -0,0 +1,19 @@
[package]
name = "qemu_arm_launcher"
version = "0.8.0"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2018"
[features]
default = ["std"]
std = []
[profile.release]
#lto = true
#codegen-units = 1
#opt-level = 3
debug = true
[dependencies]
libafl = { path = "../../libafl/" }
libafl_qemu = { path = "../../libafl_qemu/", features = ["usermode", "arm"] }

View File

@ -0,0 +1,170 @@
# Variables
[env]
FUZZER_NAME='libpng_harness'
FUZZER_NAME_CRASHING='libpng_harness_crashing'
PROJECT_DIR = { script = ["pwd"] }
CROSS_CC = "arm-linux-gnueabi-gcc"
[tasks.unsupported]
script_runner="@shell"
script='''
echo "Qemu fuzzer not supported on windows/mac"
'''
#zlib
[tasks.zlib]
linux_alias = "zlib_unix"
mac_alias = "unsupported"
windows_alias = "unsupported"
[tasks.zlib_unix_wget]
condition = { files_not_exist = [ "./zlib-1.2.12" ] }
script_runner="@shell"
script='''
wget http://www.zlib.net/zlib-1.2.12.tar.gz
tar -xvf zlib-1.2.12.tar.gz
'''
[tasks.zlib_unix]
condition = { files_not_exist = [ "./zlib-1.2.12/zlib/lib/libz.a" ] }
script_runner="@shell"
script='''
cd zlib-1.2.12 && CC=$CROSS_CC ./configure --prefix=./zlib
make install
'''
dependencies = [ "zlib_unix_wget" ]
# libpng
[tasks.libpng]
linux_alias = "libpng_unix"
mac_alias = "unsupported"
windows_alias = "unsupported"
[tasks.libpng_unix_wget]
condition = { files_not_exist = [ "./libpng-1.6.37" ] }
script_runner="@shell"
script='''
wget https://deac-fra.dl.sourceforge.net/project/libpng/libpng16/1.6.37/libpng-1.6.37.tar.xz
tar -xvf libpng-1.6.37.tar.xz
'''
[tasks.libpng_unix]
condition = { files_not_exist = [ "./libpng-1.6.37/.libs/libpng16.a" ] }
script_runner="@shell"
script='''
cd libpng-1.6.37 && CC=$CROSS_CC CFLAGS=-I../zlib-1.2.12/zlib/lib LDFLAGS=-L../zlib-1.2.12/zlib/lib ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=yes --host=arm
make
'''
dependencies = [ "zlib", "libpng_unix_wget" ]
# fuzzer
[tasks.fuzzer]
linux_alias = "fuzzer_unix"
mac_alias = "fuzzer_unix"
windows_alias = "unsupported"
[tasks.fuzzer_unix]
command = "cargo"
args = ["build", "--release"]
# Harness
[tasks.harness]
linux_alias = "harness_unix"
mac_alias = "unsupported"
windows_alias = "unsupported"
[tasks.harness_unix]
script_runner="@shell"
script='''
# Build the libpng harness
arm-linux-gnueabi-g++ \
./harness.cc \
./libpng-1.6.37/.libs/libpng16.a \
./zlib-1.2.12/zlib/lib/libz.a \
-I./libpng-1.6.37/ \
-I../zlib-1.2.12/zlib/lib \
-L../zlib-1.2.12/zlib/lib \
-o ${FUZZER_NAME} \
-lm \
-static
'''
dependencies = [ "libpng" ]
# Run the fuzzer
[tasks.run]
linux_alias = "run_unix"
mac_alias = "run_unix"
windows_alias = "unsupported"
[tasks.run_unix]
command = "cargo"
args = ["run", "--release", "./${FUZZER_NAME}"]
dependencies = [ "harness", "fuzzer" ]
# Harness with an artifical crash
[tasks.harness_crashing]
linux_alias = "harness_unix_crashing"
mac_alias = "unsupported"
windows_alias = "unsupported"
[tasks.harness_unix_crashing]
script_runner="@shell"
script='''
# Build the libpng harness
arm-linux-gnueabi-g++ \
./harness.cc \
./libpng-1.6.37/.libs/libpng16.a \
./zlib-1.2.12/zlib/lib/libz.a \
-I./libpng-1.6.37/ \
-I../zlib-1.2.12/zlib/lib \
-L../zlib-1.2.12/zlib/lib \
-o ${FUZZER_NAME_CRASHING} \
-lm \
-DHAS_DUMMY_CRASH \
-static
'''
dependencies = [ "libpng" ]
# Run the fuzzer with an artificial crash
[tasks.run_crashing]
linux_alias = "run_unix_crashing"
mac_alias = "unsupported"
windows_alias = "unsupported"
[tasks.run_unix_crashing]
command = "cargo"
args = ["run", "--release", "./${FUZZER_NAME_CRASHING}"]
dependencies = [ "harness_crashing", "fuzzer" ]
# Run the fuzzer
[tasks.test]
linux_alias = "test_unix"
mac_alias = "test_unix"
windows_alias = "unsupported"
# Short test
[tasks.test_unix]
script_runner = "@shell"
script='''
rm -rf libafl_unix_shmem_server || true
timeout 11s cargo run --release ./${FUZZER_NAME} 2>/dev/null &
'''
dependencies = [ "harness", "fuzzer" ]
# Clean up
[tasks.clean]
linux_alias = "clean_unix"
mac_alias = "clean_unix"
windows_alias = "unsupported"
[tasks.clean_unix]
# Disable default `clean` definition
clear = true
script_runner="@shell"
script='''
rm -f ./${FUZZER_NAME}
rm -f ./${FUZZER_NAME_CRASHING}
rm -rf zlib-*
rm -rf libpng-*
cargo clean
'''

View File

@ -0,0 +1,24 @@
# LibAFL with launcher for libpng with qemu arm32 in usermode
This folder contains an example fuzzer for libpng using the qemu emulator in arm32 usermode.
To show off crash detection, we added an optional undefined instruction to the harness.
Everything has been tested on Linux.
In contrast to the normal libfuzzer libpng example, this uses the `launcher` feature, that automatically spawns `n` child processes, and binds them to a free core.
## Prerequisites
```bash
sudo apt install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
```
## Run
```bash
cargo make run
```
## Run with artifical crash
```bash
cargo make run_crashing
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

View File

@ -0,0 +1,193 @@
// libpng_read_fuzzer.cc
// Copyright 2017-2018 Glenn Randers-Pehrson
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that may
// be found in the LICENSE file https://cs.chromium.org/chromium/src/LICENSE
// Last changed in libpng 1.6.35 [July 15, 2018]
// The modifications in 2017 by Glenn Randers-Pehrson include
// 1. addition of a PNG_CLEANUP macro,
// 2. setting the option to ignore ADLER32 checksums,
// 3. adding "#include <string.h>" which is needed on some platforms
// to provide memcpy().
// 4. adding read_end_info() and creating an end_info structure.
// 5. adding calls to png_set_*() transforms commonly used by browsers.
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <vector>
#define PNG_INTERNAL
#include "png.h"
#define PNG_CLEANUP \
if (png_handler.png_ptr) { \
if (png_handler.row_ptr) \
png_free(png_handler.png_ptr, png_handler.row_ptr); \
if (png_handler.end_info_ptr) \
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
&png_handler.end_info_ptr); \
else if (png_handler.info_ptr) \
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
nullptr); \
else \
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
png_handler.png_ptr = nullptr; \
png_handler.row_ptr = nullptr; \
png_handler.info_ptr = nullptr; \
png_handler.end_info_ptr = nullptr; \
}
struct BufState {
const uint8_t *data;
size_t bytes_left;
};
struct PngObjectHandler {
png_infop info_ptr = nullptr;
png_structp png_ptr = nullptr;
png_infop end_info_ptr = nullptr;
png_voidp row_ptr = nullptr;
BufState *buf_state = nullptr;
~PngObjectHandler() {
if (row_ptr) { png_free(png_ptr, row_ptr); }
if (end_info_ptr)
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
else if (info_ptr)
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
else
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
delete buf_state;
}
};
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
memcpy(data, buf_state->data, length);
buf_state->bytes_left -= length;
buf_state->data += length;
}
static const int kPngHeaderSize = 8;
// Entry point for LibFuzzer.
// Roughly follows the libpng book example:
// http://www.libpng.org/pub/png/book/chapter13.html
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < kPngHeaderSize) { return 0; }
std::vector<unsigned char> v(data, data + size);
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
// not a PNG.
return 0;
}
PngObjectHandler png_handler;
png_handler.png_ptr = nullptr;
png_handler.row_ptr = nullptr;
png_handler.info_ptr = nullptr;
png_handler.end_info_ptr = nullptr;
png_handler.png_ptr =
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (!png_handler.png_ptr) { return 0; }
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
if (!png_handler.info_ptr) {
PNG_CLEANUP
return 0;
}
png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr);
if (!png_handler.end_info_ptr) {
PNG_CLEANUP
return 0;
}
png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
#ifdef PNG_IGNORE_ADLER32
png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);
#endif
// Setting up reading from buffer.
png_handler.buf_state = new BufState();
png_handler.buf_state->data = data + kPngHeaderSize;
png_handler.buf_state->bytes_left = size - kPngHeaderSize;
png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data);
png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize);
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
PNG_CLEANUP
return 0;
}
// Reading.
png_read_info(png_handler.png_ptr, png_handler.info_ptr);
// reset error handler to put png_deleter into scope.
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
PNG_CLEANUP
return 0;
}
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, compression_type;
int filter_type;
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
&bit_depth, &color_type, &interlace_type, &compression_type,
&filter_type)) {
PNG_CLEANUP
return 0;
}
// This is going to be too slow.
if (width && height > 100000000 / width) {
PNG_CLEANUP
#ifdef HAS_DUMMY_CRASH
#if defined(__aarch64__) || defined(__arm__)
asm volatile(".word 0xf7f0a000\n");
#else
asm("ud2");
#endif
#endif
return 0;
}
// Set several transforms that browsers typically use:
png_set_gray_to_rgb(png_handler.png_ptr);
png_set_expand(png_handler.png_ptr);
png_set_packing(png_handler.png_ptr);
png_set_scale_16(png_handler.png_ptr);
png_set_tRNS_to_alpha(png_handler.png_ptr);
int passes = png_set_interlace_handling(png_handler.png_ptr);
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
png_handler.row_ptr =
png_malloc(png_handler.png_ptr,
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
for (int pass = 0; pass < passes; ++pass) {
for (png_uint_32 y = 0; y < height; ++y) {
png_read_row(png_handler.png_ptr,
static_cast<png_bytep>(png_handler.row_ptr), nullptr);
}
}
png_read_end(png_handler.png_ptr, png_handler.end_info_ptr);
PNG_CLEANUP
return 0;
}
int main() {
uint8_t buf[10] = {0};
LLVMFuzzerTestOneInput(buf, 10);
}

View File

@ -0,0 +1,210 @@
//! A libfuzzer-like fuzzer using qemu for binary-only coverage
//!
use core::time::Duration;
use std::{env, path::PathBuf, process};
use libafl::{
bolts::{
core_affinity::Cores,
current_nanos,
launcher::Launcher,
rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider},
tuples::tuple_list,
AsSlice,
},
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::EventConfig,
executors::{ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
observers::{HitcountsMapObserver, TimeObserver, VariableMapObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::StdMutationalStage,
state::{HasCorpus, StdState},
Error,
};
use libafl_qemu::{
//asan::QemuAsanHelper,
edges,
edges::QemuEdgeCoverageHelper,
elf::EasyElf,
emu::Emulator,
MmapPerms,
QemuExecutor,
QemuHooks,
Regs,
};
pub fn fuzz() {
// Hardcoded parameters
let timeout = Duration::from_secs(1);
let broker_port = 1337;
let cores = Cores::from_cmdline("0-11").unwrap();
let corpus_dirs = [PathBuf::from("./corpus")];
let objective_dir = PathBuf::from("./crashes");
// Initialize QEMU
env::remove_var("LD_LIBRARY_PATH");
let args: Vec<String> = env::args().collect();
let env: Vec<(String, String)> = env::vars().collect();
let emu = Emulator::new(&args, &env);
let mut elf_buffer = Vec::new();
let elf = EasyElf::from_file(emu.binary_path(), &mut elf_buffer).unwrap();
let test_one_input_ptr = elf
.resolve_symbol("LLVMFuzzerTestOneInput", emu.load_addr())
.expect("Symbol LLVMFuzzerTestOneInput not found");
println!("LLVMFuzzerTestOneInput @ {:#x}", test_one_input_ptr);
emu.set_breakpoint(test_one_input_ptr); // LLVMFuzzerTestOneInput
unsafe { emu.run() };
println!("Break at {:#x}", emu.read_reg::<_, u64>(Regs::Pc).unwrap());
// Get the return address
let stack_ptr: u64 = emu.read_reg(Regs::Sp).unwrap();
let ret_addr: u32 = emu.read_reg(Regs::Lr).unwrap();
println!("Stack pointer = {:#x}", stack_ptr);
println!("Return address = {:#x}", ret_addr);
emu.remove_breakpoint(test_one_input_ptr); // LLVMFuzzerTestOneInput
emu.set_breakpoint(ret_addr); // LLVMFuzzerTestOneInput ret addr
let input_addr = emu.map_private(0, 4096, MmapPerms::ReadWrite).unwrap();
println!("Placing input at {:#x}", input_addr);
// The wrapped harness function, calling out to the LLVM-style harness
let mut harness = |input: &BytesInput| {
let target = input.target_bytes();
let mut buf = target.as_slice();
let mut len = buf.len();
if len > 4096 {
buf = &buf[0..4096];
len = 4096;
}
unsafe {
emu.write_mem(input_addr, buf);
emu.write_reg(Regs::R0, input_addr).unwrap();
emu.write_reg(Regs::R1, len).unwrap();
emu.write_reg(Regs::Pc, test_one_input_ptr).unwrap();
emu.write_reg(Regs::Lr, ret_addr).unwrap();
emu.run();
}
ExitKind::Ok
};
let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// Create an observation channel using the coverage map
let edges = unsafe { &mut edges::EDGES_MAP };
let edges_counter = unsafe { &mut edges::MAX_EDGES_NUM };
let edges_observer =
HitcountsMapObserver::new(VariableMapObserver::new("edges", edges, edges_counter));
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
StdState::new(
// RNG
StdRand::with_seed(current_nanos()),
// Corpus that will be evolved, we keep it in memory for performance
InMemoryCorpus::new(),
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir.clone()).unwrap(),
// States of the feedbacks.
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
// A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new(QueueScheduler::new());
// A fuzzer with feedbacks and a corpus scheduler
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
let mut hooks = QemuHooks::new(&emu, tuple_list!(QemuEdgeCoverageHelper::default()));
// Create a QEMU in-process executor
let executor = QemuExecutor::new(
&mut hooks,
&mut harness,
tuple_list!(edges_observer, time_observer),
&mut fuzzer,
&mut state,
&mut mgr,
)
.expect("Failed to create QemuExecutor");
// Wrap the executor to keep track of the timeout
let mut executor = TimeoutExecutor::new(executor, timeout);
if state.corpus().count() < 1 {
state
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &corpus_dirs)
.unwrap_or_else(|_| {
println!("Failed to load initial corpus at {:?}", &corpus_dirs);
process::exit(0);
});
println!("We imported {} inputs from disk.", state.corpus().count());
}
// Setup an havoc mutator with a mutational stage
let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?;
Ok(())
};
// The shared memory allocator
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
// The stats reporter for the broker
let monitor = MultiMonitor::new(|s| println!("{}", s));
// Build and run a Launcher
match Launcher::builder()
.shmem_provider(shmem_provider)
.broker_port(broker_port)
.configuration(EventConfig::from_build_id())
.monitor(monitor)
.run_client(&mut run_client)
.cores(&cores)
.stdout_file(Some("/dev/null"))
.build()
.launch()
{
Ok(()) => (),
Err(Error::ShuttingDown) => println!("Fuzzing stopped by user. Good bye."),
Err(err) => panic!("Failed to run launcher: {:?}", err),
}
}

View File

@ -0,0 +1,13 @@
//! A libfuzzer-like fuzzer using qemu for binary-only coverage
#[cfg(target_os = "linux")]
mod fuzzer;
#[cfg(target_os = "linux")]
pub fn main() {
fuzzer::fuzz();
}
#[cfg(not(target_os = "linux"))]
pub fn main() {
panic!("qemu-user and libafl_qemu is only supported on linux!");
}

View File

@ -3,7 +3,7 @@ use which::which;
const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
const QEMU_REVISION: &str = "8d8fc6b1bd69684a5ea57e2354153708cc2b3eed";
const QEMU_REVISION: &str = "ebda58f3e94a82f769890814339295b467f16680";
fn build_dep_check(tools: &[&str]) {
for tool in tools {
@ -332,6 +332,8 @@ pub fn build() {
println!("cargo:rustc-link-lib=glib-2.0");
println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=z");
/* #[cfg(not(feature = "python"))]
{
fs::copy(

View File

@ -446,7 +446,7 @@ where
pub fn gen_readwrite_asan<I, QT, S>(
hooks: &mut QemuHooks<'_, I, QT, S>,
_state: Option<&mut S>,
pc: u64,
pc: GuestAddr,
_size: usize,
) -> Option<u64>
where
@ -454,13 +454,12 @@ where
QT: QemuHelperTuple<I, S>,
{
let h = hooks.match_helper_mut::<QemuAsanHelper>().unwrap();
if h.must_instrument(pc) {
Some(pc)
if h.must_instrument(pc.into()) {
Some(pc.into())
} else {
None
}
}
pub fn trace_read1_asan<I, QT, S>(
hooks: &mut QemuHooks<'_, I, QT, S>,
_state: Option<&mut S>,

View File

@ -124,7 +124,7 @@ where
{
let emu = hooks.emulator();
if let Some(h) = hooks.helpers().match_first_type::<QemuCallTracerHelper>() {
if !h.must_instrument(pc) {
if !h.must_instrument(pc.into()) {
return None;
}
@ -144,7 +144,7 @@ where
let mut iaddr = pc;
'disasm: while let Ok(insns) = h.cs.disasm_count(code, iaddr, 1) {
'disasm: while let Ok(insns) = h.cs.disasm_count(code, iaddr.into(), 1) {
if insns.is_empty() {
break;
}
@ -186,7 +186,8 @@ where
}
}
iaddr += insn.bytes().len() as u64;
iaddr += insn.bytes().len() as GuestAddr;
#[cfg(feature = "usermode")]
unsafe {
code = std::slice::from_raw_parts(emu.g2h(iaddr), 512);

View File

@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{
helper::{hash_me, QemuHelper, QemuHelperTuple, QemuInstrumentationFilter},
hooks::QemuHooks,
GuestAddr,
};
#[derive(Debug, Default, Serialize, Deserialize)]
@ -118,7 +119,7 @@ where
pub fn gen_unique_cmp_ids<I, QT, S>(
hooks: &mut QemuHooks<'_, I, QT, S>,
state: Option<&mut S>,
pc: u64,
pc: GuestAddr,
_size: usize,
) -> Option<u64>
where
@ -127,7 +128,7 @@ where
QT: QemuHelperTuple<I, S>,
{
if let Some(h) = hooks.match_helper_mut::<QemuCmpLogHelper>() {
if !h.must_instrument(pc) {
if !h.must_instrument(pc.into()) {
return None;
}
}
@ -141,7 +142,7 @@ where
.unwrap();
let id = meta.current_id as usize;
Some(*meta.map.entry(pc).or_insert_with(|| {
Some(*meta.map.entry(pc.into()).or_insert_with(|| {
meta.current_id = ((id + 1) & (CMPLOG_MAP_W - 1)) as u64;
id as u64
}))
@ -150,7 +151,7 @@ where
pub fn gen_hashed_cmp_ids<I, QT, S>(
hooks: &mut QemuHooks<'_, I, QT, S>,
_state: Option<&mut S>,
pc: u64,
pc: GuestAddr,
_size: usize,
) -> Option<u64>
where
@ -159,11 +160,11 @@ where
QT: QemuHelperTuple<I, S>,
{
if let Some(h) = hooks.match_helper_mut::<QemuCmpLogChildHelper>() {
if !h.must_instrument(pc) {
if !h.must_instrument(pc.into()) {
return None;
}
}
Some(hash_me(pc) & (CMPLOG_MAP_W as u64 - 1))
Some(hash_me(pc.into()) & (CMPLOG_MAP_W as u64 - 1))
}
pub extern "C" fn trace_cmp1_cmplog(id: u64, v0: u8, v1: u8, _data: u64) {

View File

@ -164,7 +164,7 @@ where
QT: QemuHelperTuple<I, S>,
{
if let Some(h) = hooks.helpers().match_first_type::<QemuEdgeCoverageHelper>() {
if !h.must_instrument(src) && !h.must_instrument(dest) {
if !h.must_instrument(src.into()) && !h.must_instrument(dest.into()) {
return None;
}
}
@ -224,7 +224,7 @@ where
.helpers()
.match_first_type::<QemuEdgeCoverageChildHelper>()
{
if !h.must_instrument(src) && !h.must_instrument(dest) {
if !h.must_instrument(src.into()) && !h.must_instrument(dest.into()) {
return None;
}
}