From 7150ffc5e6861cd892342629de6f9bc8ecf21879 Mon Sep 17 00:00:00 2001 From: Evan Richter Date: Wed, 16 Feb 2022 14:34:56 -0600 Subject: [PATCH] [libafl_qemu] EasyElf::resolve_symbol return GuestAddr (#540) Also enforce Linux support at the crate level instead of item by item --- libafl_qemu/build.rs | 405 +------------------------------------ libafl_qemu/build_linux.rs | 399 ++++++++++++++++++++++++++++++++++++ libafl_qemu/src/elf.rs | 8 +- libafl_qemu/src/lib.rs | 22 +- 4 files changed, 415 insertions(+), 419 deletions(-) create mode 100644 libafl_qemu/build_linux.rs diff --git a/libafl_qemu/build.rs b/libafl_qemu/build.rs index 98da94e10a..9badc1d340 100644 --- a/libafl_qemu/build.rs +++ b/libafl_qemu/build.rs @@ -1,404 +1,13 @@ -use std::{env, fs, path::Path, process::Command}; -use which::which; +mod host_specific { + #[cfg(target_os = "linux")] + include!("build_linux.rs"); -const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge"; -const QEMU_DIRNAME: &str = "qemu-libafl-bridge"; -const QEMU_REVISION: &str = "152fdbe024493f31e60060714caee3b90fdf3d9e"; - -fn build_dep_check(tools: &[&str]) { - for tool in tools { - which(tool).unwrap_or_else(|_| panic!("Build tool {} not found", tool)); + #[cfg(not(target_os = "linux"))] + pub fn build() { + println!("cargo:warning=libafl_qemu only builds on Linux hosts"); } } -#[macro_export] -macro_rules! assert_unique_feature { - () => {}; - ($first:tt $(,$rest:tt)*) => { - $( - #[cfg(not(feature = "clippy"))] // ignore multiple definition for clippy - #[cfg(all(feature = $first, feature = $rest))] - compile_error!(concat!("features \"", $first, "\" and \"", $rest, "\" cannot be used together")); - )* - assert_unique_feature!($($rest),*); - } -} - -#[allow(clippy::too_many_lines)] fn main() { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-changed=src/asan-giovese.c"); - println!("cargo:rerun-if-changed=src/asan-giovese.h"); - println!("cargo:rerun-if-env-changed=CROSS_CC"); - - let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); - if target_os != "linux" { - return; - } - - // Make sure we have at most one architecutre feature set - // Else, we default to `x86_64` - having a default makes CI easier :) - assert_unique_feature!("arm", "aarch64", "i386", "i86_64"); - - let cpu_target = if cfg!(feature = "x86_64") { - "x86_64".to_string() - } else if cfg!(feature = "arm") { - "arm".to_string() - } else if cfg!(feature = "aarch64") { - "aarch64".to_string() - } else if cfg!(feature = "i386") { - "i386".to_string() - } else { - env::var("CPU_TARGET").unwrap_or_else(|_| { - println!( - "cargo:warning=No architecture feature enabled or CPU_TARGET env specified for libafl_qemu, supported: arm, aarch64, i386, x86_64 - defaulting to x86_64" - ); - "x86_64".to_string() - }) - }; - - let jobs = env::var("NUM_JOBS"); - - let cross_cc = env::var("CROSS_CC").unwrap_or_else(|_| { - println!("cargo:warning=CROSS_CC is not set, default to cc (things can go wrong if the selected cpu target ({}) is not the host arch ({}))", cpu_target, env::consts::ARCH); - "cc".to_owned() - }); - - println!("cargo:rustc-cfg=cpu_target=\"{}\"", cpu_target); - - if std::env::var("DOCS_RS").is_ok() { - return; // only build when we're not generating docs - } - - let out_dir = env::var_os("OUT_DIR").unwrap(); - let out_dir = out_dir.to_string_lossy().to_string(); - let out_dir_path = Path::new(&out_dir); - let mut target_dir = out_dir_path.to_path_buf(); - target_dir.pop(); - target_dir.pop(); - target_dir.pop(); - let qasan_dir = Path::new("libqasan"); - let qasan_dir = fs::canonicalize(&qasan_dir).unwrap(); - let src_dir = Path::new("src"); - - println!("cargo:rerun-if-changed=libqasan"); - - build_dep_check(&["git", "make"]); - - let qemu_rev = out_dir_path.join("QEMU_REVISION"); - let qemu_path = out_dir_path.join(QEMU_DIRNAME); - - if qemu_rev.exists() - && fs::read_to_string(&qemu_rev).expect("Failed to read QEMU_REVISION") != QEMU_REVISION - { - drop(fs::remove_dir_all(&qemu_path)); - } - - if !qemu_path.is_dir() { - println!( - "cargo:warning=Qemu not found, cloning with git ({})...", - QEMU_REVISION - ); - fs::create_dir_all(&qemu_path).unwrap(); - Command::new("git") - .current_dir(&qemu_path) - .arg("init") - .status() - .unwrap(); - Command::new("git") - .current_dir(&qemu_path) - .arg("remote") - .arg("add") - .arg("origin") - .arg(QEMU_URL) - .status() - .unwrap(); - Command::new("git") - .current_dir(&qemu_path) - .arg("fetch") - .arg("--depth") - .arg("1") - .arg("origin") - .arg(QEMU_REVISION) - .status() - .unwrap(); - Command::new("git") - .current_dir(&qemu_path) - .arg("checkout") - .arg("FETCH_HEAD") - .status() - .unwrap(); - /*Command::new("git") - .current_dir(&out_dir_path) - .arg("clone") - .arg(QEMU_URL) - .status() - .unwrap(); - Command::new("git") - .current_dir(&qemu_path) - .arg("checkout") - .arg(QEMU_REVISION) - .status() - .unwrap();*/ - fs::write(&qemu_rev, QEMU_REVISION).unwrap(); - } - - let build_dir = qemu_path.join("build"); - let output_lib = build_dir.join(&format!("libqemu-{}.so", cpu_target)); - if !output_lib.is_file() { - drop( - Command::new("make") - .current_dir(&qemu_path) - .arg("distclean") - .status(), - ); - Command::new("./configure") - .current_dir(&qemu_path) - //.arg("--as-static-lib") - .arg("--as-shared-lib") - .arg(&format!("--target-list={}-linux-user", cpu_target)) - .args(&[ - "--audio-drv-list=", - "--disable-blobs", - "--disable-bochs", - "--disable-brlapi", - "--disable-bsd-user", - "--disable-bzip2", - "--disable-cap-ng", - "--disable-cloop", - "--disable-curl", - "--disable-curses", - "--disable-dmg", - "--disable-fdt", - "--disable-gcrypt", - "--disable-glusterfs", - "--disable-gnutls", - "--disable-gtk", - "--disable-guest-agent", - "--disable-iconv", - "--disable-libiscsi", - "--disable-libnfs", - "--disable-libssh", - "--disable-libusb", - "--disable-linux-aio", - "--disable-live-block-migration", - "--disable-lzo", - "--disable-nettle", - "--disable-numa", - "--disable-opengl", - "--disable-parallels", - "--disable-plugins", - "--disable-qcow1", - "--disable-qed", - "--disable-rbd", - "--disable-rdma", - "--disable-replication", - "--disable-sdl", - "--disable-seccomp", - "--disable-smartcard", - "--disable-snappy", - "--disable-spice", - "--disable-system", - "--disable-tools", - "--disable-tpm", - "--disable-usb-redir", - "--disable-vde", - "--disable-vdi", - "--disable-vhost-crypto", - "--disable-vhost-kernel", - "--disable-vhost-net", - "--disable-vhost-scsi", - "--disable-vhost-user", - "--disable-vhost-vdpa", - "--disable-vhost-vsock", - "--disable-virglrenderer", - "--disable-virtfs", - "--disable-vnc", - "--disable-vnc-jpeg", - "--disable-vnc-png", - "--disable-vnc-sasl", - "--disable-vte", - "--disable-vvfat", - "--disable-xen", - "--disable-xen-pci-passthrough", - ]) - .status() - .expect("Configure failed"); - if let Ok(j) = jobs { - Command::new("make") - .current_dir(&qemu_path) - .arg("-j") - .arg(&j) - .status() - .expect("Make failed"); - } else { - Command::new("make") - .current_dir(&qemu_path) - .arg("-j") - .status() - .expect("Make failed"); - } - //let _ = remove_file(build_dir.join(&format!("libqemu-{}.so", cpu_target))); - } - - #[cfg(feature = "python")] - { - let mut objects = vec![]; - for dir in &[ - build_dir.join("libcommon.fa.p"), - build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)), - //build_dir.join("libcommon-user.fa.p"), - //build_dir.join("libqemuutil.a.p"), - //build_dir.join("libqom.fa.p"), - //build_dir.join("libhwcore.fa.p"), - //build_dir.join("libcapstone.a.p"), - ] { - for path in fs::read_dir(dir).unwrap() { - let path = path.unwrap().path(); - if path.is_file() { - if let Some(name) = path.file_name() { - if name.to_string_lossy().starts_with("stubs") { - continue; - } else if let Some(ext) = path.extension() { - if ext == "o" { - objects.push(path); - } - } - } - } - } - } - - for obj in &objects { - println!("cargo:rustc-cdylib-link-arg={}", obj.display()); - } - - println!("cargo:rustc-cdylib-link-arg=-Wl,--start-group"); - - println!("cargo:rustc-cdylib-link-arg=-Wl,--whole-archive"); - println!( - "cargo:rustc-cdylib-link-arg={}/libhwcore.fa", - build_dir.display() - ); - println!( - "cargo:rustc-cdylib-link-arg={}/libqom.fa", - build_dir.display() - ); - println!("cargo:rustc-cdylib-link-arg=-Wl,--no-whole-archive"); - println!( - "cargo:rustc-cdylib-link-arg={}/libcapstone.a", - build_dir.display() - ); - println!( - "cargo:rustc-cdylib-link-arg={}/libqemuutil.a", - build_dir.display() - ); - println!( - "cargo:rustc-cdylib-link-arg={}/libhwcore.fa", - build_dir.display() - ); - println!( - "cargo:rustc-cdylib-link-arg={}/libqom.fa", - build_dir.display() - ); - - println!("cargo:rustc-cdylib-link-arg=-lrt"); - println!("cargo:rustc-cdylib-link-arg=-lutil"); - println!("cargo:rustc-cdylib-link-arg=-lgthread-2.0"); - println!("cargo:rustc-cdylib-link-arg=-lglib-2.0"); - println!("cargo:rustc-cdylib-link-arg=-lstdc++"); - - println!("cargo:rustc-cdylib-link-arg=-Wl,--end-group"); - } - - #[cfg(not(feature = "python"))] - { - fs::copy( - build_dir.join(&format!("libqemu-{}.so", cpu_target)), - target_dir.join(&format!("libqemu-{}.so", cpu_target)), - ) - .expect("Failed to copy the QEMU shared object"); - - println!( - "cargo:rustc-link-search=native={}", - &target_dir.to_string_lossy().to_string() - ); - println!("cargo:rustc-link-lib=qemu-{}", cpu_target); - - println!("cargo:rustc-env=LD_LIBRARY_PATH={}", target_dir.display()); - } - - drop( - Command::new("make") - .current_dir(&out_dir_path) - .env("CC", &cross_cc) - .env("OUT_DIR", &target_dir) - .arg("-C") - .arg(&qasan_dir) - .arg("clean") - .status(), - ); - drop( - Command::new("make") - .current_dir(&out_dir_path) - .env("CC", &cross_cc) - .env("OUT_DIR", &target_dir) - .arg("-C") - .arg(&qasan_dir) - .status(), - ); - - cc::Build::new() - .warnings(false) - .file(src_dir.join("asan-giovese.c")) - .compile("asan_giovese"); + host_specific::build(); } - -/* - // Build a static library - let mut objects = vec![]; - for dir in &[ - build_dir.join("libcommon.fa.p"), - build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)), - build_dir.join("libqemuutil.a.p"), - build_dir.join("libqom.fa.p"), - build_dir.join("libhwcore.fa.p"), - build_dir.join("libcapstone.a.p"), - ] { - for path in read_dir(dir).unwrap() { - let path = path.unwrap().path(); - if path.is_file() { - if let Some(name) = path.file_name() { - if name.to_string_lossy().starts_with("stubs") { - continue; - } - else if let Some(ext) = path.extension() { - if ext == "o" { - objects.push(path); - } - } - } - } - } - } - - - Command::new("ar") - .current_dir(&out_dir_path) - .arg("crus") - .arg("libqemu-bridge.a") - .args(&objects) - .status() - .expect("Ar failed"); - - println!("cargo:rustc-link-search=native={}", &out_dir); - println!("cargo:rustc-link-lib=static=qemu-bridge"); - - println!("cargo:rustc-link-lib=rt"); - println!("cargo:rustc-link-lib=util"); - println!("cargo:rustc-link-lib=gthread-2.0"); - println!("cargo:rustc-link-lib=glib-2.0"); - println!("cargo:rustc-link-lib=stdc++"); - -} -*/ diff --git a/libafl_qemu/build_linux.rs b/libafl_qemu/build_linux.rs new file mode 100644 index 0000000000..a91ad84cce --- /dev/null +++ b/libafl_qemu/build_linux.rs @@ -0,0 +1,399 @@ +use std::{env, fs, path::Path, process::Command}; +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 = "152fdbe024493f31e60060714caee3b90fdf3d9e"; + +fn build_dep_check(tools: &[&str]) { + for tool in tools { + which(tool).unwrap_or_else(|_| panic!("Build tool {} not found", tool)); + } +} + +#[macro_export] +macro_rules! assert_unique_feature { + () => {}; + ($first:tt $(,$rest:tt)*) => { + $( + #[cfg(not(feature = "clippy"))] // ignore multiple definition for clippy + #[cfg(all(feature = $first, feature = $rest))] + compile_error!(concat!("features \"", $first, "\" and \"", $rest, "\" cannot be used together")); + )* + assert_unique_feature!($($rest),*); + } +} + +#[allow(clippy::too_many_lines)] +pub fn build() { + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=src/asan-giovese.c"); + println!("cargo:rerun-if-changed=src/asan-giovese.h"); + println!("cargo:rerun-if-env-changed=CROSS_CC"); + + // Make sure we have at most one architecutre feature set + // Else, we default to `x86_64` - having a default makes CI easier :) + assert_unique_feature!("arm", "aarch64", "i386", "i86_64"); + + let cpu_target = if cfg!(feature = "x86_64") { + "x86_64".to_string() + } else if cfg!(feature = "arm") { + "arm".to_string() + } else if cfg!(feature = "aarch64") { + "aarch64".to_string() + } else if cfg!(feature = "i386") { + "i386".to_string() + } else { + env::var("CPU_TARGET").unwrap_or_else(|_| { + println!( + "cargo:warning=No architecture feature enabled or CPU_TARGET env specified for libafl_qemu, supported: arm, aarch64, i386, x86_64 - defaulting to x86_64" + ); + "x86_64".to_string() + }) + }; + + let jobs = env::var("NUM_JOBS"); + + let cross_cc = env::var("CROSS_CC").unwrap_or_else(|_| { + println!("cargo:warning=CROSS_CC is not set, default to cc (things can go wrong if the selected cpu target ({}) is not the host arch ({}))", cpu_target, env::consts::ARCH); + "cc".to_owned() + }); + + println!("cargo:rustc-cfg=cpu_target=\"{}\"", cpu_target); + + if std::env::var("DOCS_RS").is_ok() { + return; // only build when we're not generating docs + } + + let out_dir = env::var_os("OUT_DIR").unwrap(); + let out_dir = out_dir.to_string_lossy().to_string(); + let out_dir_path = Path::new(&out_dir); + let mut target_dir = out_dir_path.to_path_buf(); + target_dir.pop(); + target_dir.pop(); + target_dir.pop(); + let qasan_dir = Path::new("libqasan"); + let qasan_dir = fs::canonicalize(&qasan_dir).unwrap(); + let src_dir = Path::new("src"); + + println!("cargo:rerun-if-changed=libqasan"); + + build_dep_check(&["git", "make"]); + + let qemu_rev = out_dir_path.join("QEMU_REVISION"); + let qemu_path = out_dir_path.join(QEMU_DIRNAME); + + if qemu_rev.exists() + && fs::read_to_string(&qemu_rev).expect("Failed to read QEMU_REVISION") != QEMU_REVISION + { + drop(fs::remove_dir_all(&qemu_path)); + } + + if !qemu_path.is_dir() { + println!( + "cargo:warning=Qemu not found, cloning with git ({})...", + QEMU_REVISION + ); + fs::create_dir_all(&qemu_path).unwrap(); + Command::new("git") + .current_dir(&qemu_path) + .arg("init") + .status() + .unwrap(); + Command::new("git") + .current_dir(&qemu_path) + .arg("remote") + .arg("add") + .arg("origin") + .arg(QEMU_URL) + .status() + .unwrap(); + Command::new("git") + .current_dir(&qemu_path) + .arg("fetch") + .arg("--depth") + .arg("1") + .arg("origin") + .arg(QEMU_REVISION) + .status() + .unwrap(); + Command::new("git") + .current_dir(&qemu_path) + .arg("checkout") + .arg("FETCH_HEAD") + .status() + .unwrap(); + /*Command::new("git") + .current_dir(&out_dir_path) + .arg("clone") + .arg(QEMU_URL) + .status() + .unwrap(); + Command::new("git") + .current_dir(&qemu_path) + .arg("checkout") + .arg(QEMU_REVISION) + .status() + .unwrap();*/ + fs::write(&qemu_rev, QEMU_REVISION).unwrap(); + } + + let build_dir = qemu_path.join("build"); + let output_lib = build_dir.join(&format!("libqemu-{}.so", cpu_target)); + if !output_lib.is_file() { + drop( + Command::new("make") + .current_dir(&qemu_path) + .arg("distclean") + .status(), + ); + Command::new("./configure") + .current_dir(&qemu_path) + //.arg("--as-static-lib") + .arg("--as-shared-lib") + .arg(&format!("--target-list={}-linux-user", cpu_target)) + .args(&[ + "--audio-drv-list=", + "--disable-blobs", + "--disable-bochs", + "--disable-brlapi", + "--disable-bsd-user", + "--disable-bzip2", + "--disable-cap-ng", + "--disable-cloop", + "--disable-curl", + "--disable-curses", + "--disable-dmg", + "--disable-fdt", + "--disable-gcrypt", + "--disable-glusterfs", + "--disable-gnutls", + "--disable-gtk", + "--disable-guest-agent", + "--disable-iconv", + "--disable-libiscsi", + "--disable-libnfs", + "--disable-libssh", + "--disable-libusb", + "--disable-linux-aio", + "--disable-live-block-migration", + "--disable-lzo", + "--disable-nettle", + "--disable-numa", + "--disable-opengl", + "--disable-parallels", + "--disable-plugins", + "--disable-qcow1", + "--disable-qed", + "--disable-rbd", + "--disable-rdma", + "--disable-replication", + "--disable-sdl", + "--disable-seccomp", + "--disable-smartcard", + "--disable-snappy", + "--disable-spice", + "--disable-system", + "--disable-tools", + "--disable-tpm", + "--disable-usb-redir", + "--disable-vde", + "--disable-vdi", + "--disable-vhost-crypto", + "--disable-vhost-kernel", + "--disable-vhost-net", + "--disable-vhost-scsi", + "--disable-vhost-user", + "--disable-vhost-vdpa", + "--disable-vhost-vsock", + "--disable-virglrenderer", + "--disable-virtfs", + "--disable-vnc", + "--disable-vnc-jpeg", + "--disable-vnc-png", + "--disable-vnc-sasl", + "--disable-vte", + "--disable-vvfat", + "--disable-xen", + "--disable-xen-pci-passthrough", + ]) + .status() + .expect("Configure failed"); + if let Ok(j) = jobs { + Command::new("make") + .current_dir(&qemu_path) + .arg("-j") + .arg(&j) + .status() + .expect("Make failed"); + } else { + Command::new("make") + .current_dir(&qemu_path) + .arg("-j") + .status() + .expect("Make failed"); + } + //let _ = remove_file(build_dir.join(&format!("libqemu-{}.so", cpu_target))); + } + + #[cfg(feature = "python")] + { + let mut objects = vec![]; + for dir in &[ + build_dir.join("libcommon.fa.p"), + build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)), + //build_dir.join("libcommon-user.fa.p"), + //build_dir.join("libqemuutil.a.p"), + //build_dir.join("libqom.fa.p"), + //build_dir.join("libhwcore.fa.p"), + //build_dir.join("libcapstone.a.p"), + ] { + for path in fs::read_dir(dir).unwrap() { + let path = path.unwrap().path(); + if path.is_file() { + if let Some(name) = path.file_name() { + if name.to_string_lossy().starts_with("stubs") { + continue; + } else if let Some(ext) = path.extension() { + if ext == "o" { + objects.push(path); + } + } + } + } + } + } + + for obj in &objects { + println!("cargo:rustc-cdylib-link-arg={}", obj.display()); + } + + println!("cargo:rustc-cdylib-link-arg=-Wl,--start-group"); + + println!("cargo:rustc-cdylib-link-arg=-Wl,--whole-archive"); + println!( + "cargo:rustc-cdylib-link-arg={}/libhwcore.fa", + build_dir.display() + ); + println!( + "cargo:rustc-cdylib-link-arg={}/libqom.fa", + build_dir.display() + ); + println!("cargo:rustc-cdylib-link-arg=-Wl,--no-whole-archive"); + println!( + "cargo:rustc-cdylib-link-arg={}/libcapstone.a", + build_dir.display() + ); + println!( + "cargo:rustc-cdylib-link-arg={}/libqemuutil.a", + build_dir.display() + ); + println!( + "cargo:rustc-cdylib-link-arg={}/libhwcore.fa", + build_dir.display() + ); + println!( + "cargo:rustc-cdylib-link-arg={}/libqom.fa", + build_dir.display() + ); + + println!("cargo:rustc-cdylib-link-arg=-lrt"); + println!("cargo:rustc-cdylib-link-arg=-lutil"); + println!("cargo:rustc-cdylib-link-arg=-lgthread-2.0"); + println!("cargo:rustc-cdylib-link-arg=-lglib-2.0"); + println!("cargo:rustc-cdylib-link-arg=-lstdc++"); + + println!("cargo:rustc-cdylib-link-arg=-Wl,--end-group"); + } + + #[cfg(not(feature = "python"))] + { + fs::copy( + build_dir.join(&format!("libqemu-{}.so", cpu_target)), + target_dir.join(&format!("libqemu-{}.so", cpu_target)), + ) + .expect("Failed to copy the QEMU shared object"); + + println!( + "cargo:rustc-link-search=native={}", + &target_dir.to_string_lossy().to_string() + ); + println!("cargo:rustc-link-lib=qemu-{}", cpu_target); + + println!("cargo:rustc-env=LD_LIBRARY_PATH={}", target_dir.display()); + } + + drop( + Command::new("make") + .current_dir(&out_dir_path) + .env("CC", &cross_cc) + .env("OUT_DIR", &target_dir) + .arg("-C") + .arg(&qasan_dir) + .arg("clean") + .status(), + ); + drop( + Command::new("make") + .current_dir(&out_dir_path) + .env("CC", &cross_cc) + .env("OUT_DIR", &target_dir) + .arg("-C") + .arg(&qasan_dir) + .status(), + ); + + cc::Build::new() + .warnings(false) + .file(src_dir.join("asan-giovese.c")) + .compile("asan_giovese"); +} + +/* + // Build a static library + let mut objects = vec![]; + for dir in &[ + build_dir.join("libcommon.fa.p"), + build_dir.join(&format!("libqemu-{}-linux-user.fa.p", cpu_target)), + build_dir.join("libqemuutil.a.p"), + build_dir.join("libqom.fa.p"), + build_dir.join("libhwcore.fa.p"), + build_dir.join("libcapstone.a.p"), + ] { + for path in read_dir(dir).unwrap() { + let path = path.unwrap().path(); + if path.is_file() { + if let Some(name) = path.file_name() { + if name.to_string_lossy().starts_with("stubs") { + continue; + } + else if let Some(ext) = path.extension() { + if ext == "o" { + objects.push(path); + } + } + } + } + } + } + + + Command::new("ar") + .current_dir(&out_dir_path) + .arg("crus") + .arg("libqemu-bridge.a") + .args(&objects) + .status() + .expect("Ar failed"); + + println!("cargo:rustc-link-search=native={}", &out_dir); + println!("cargo:rustc-link-lib=static=qemu-bridge"); + + println!("cargo:rustc-link-lib=rt"); + println!("cargo:rustc-link-lib=util"); + println!("cargo:rustc-link-lib=gthread-2.0"); + println!("cargo:rustc-link-lib=glib-2.0"); + println!("cargo:rustc-link-lib=stdc++"); + +} +*/ diff --git a/libafl_qemu/src/elf.rs b/libafl_qemu/src/elf.rs index 5ee8fbb36c..84270fbd79 100644 --- a/libafl_qemu/src/elf.rs +++ b/libafl_qemu/src/elf.rs @@ -5,6 +5,8 @@ use std::{convert::AsRef, fs::File, io::Read, path::Path, str}; use libafl::Error; +use crate::GuestAddr; + pub struct EasyElf<'a> { elf: Elf<'a>, } @@ -38,16 +40,16 @@ impl<'a> EasyElf<'a> { } #[must_use] - pub fn resolve_symbol(&self, name: &str, load_addr: u64) -> Option { + pub fn resolve_symbol(&self, name: &str, load_addr: GuestAddr) -> Option { for sym in self.elf.syms.iter() { if let Some(sym_name) = self.elf.strtab.get_at(sym.st_name) { if sym_name == name { return if sym.st_value == 0 { None } else if self.is_pic() { - Some(sym.st_value + load_addr) + Some(sym.st_value as GuestAddr + load_addr) } else { - Some(sym.st_value) + Some(sym.st_value as GuestAddr) }; } } diff --git a/libafl_qemu/src/lib.rs b/libafl_qemu/src/lib.rs index 541f98d0b5..b74ea0520d 100644 --- a/libafl_qemu/src/lib.rs +++ b/libafl_qemu/src/lib.rs @@ -1,3 +1,5 @@ +// libafl_qemu only supports Linux currently +#![cfg(target_os = "linux")] // This lint triggers too often on the current GuestAddr type when emulating 64-bit targets because // u64::from(GuestAddr) is a no-op, but the .into() call is needed when GuestAddr is u32. #![cfg_attr( @@ -30,40 +32,24 @@ pub use x86_64::*; pub mod elf; -#[cfg(target_os = "linux")] pub mod helper; -#[cfg(target_os = "linux")] pub use helper::*; -#[cfg(target_os = "linux")] pub mod hooks; -#[cfg(target_os = "linux")] pub use hooks::*; -#[cfg(target_os = "linux")] pub mod edges; -#[cfg(target_os = "linux")] pub use edges::QemuEdgeCoverageHelper; -#[cfg(target_os = "linux")] pub mod cmplog; -#[cfg(target_os = "linux")] pub use cmplog::QemuCmpLogHelper; -#[cfg(target_os = "linux")] pub mod snapshot; -#[cfg(target_os = "linux")] pub use snapshot::QemuSnapshotHelper; -#[cfg(target_os = "linux")] pub mod asan; -#[cfg(target_os = "linux")] pub use asan::{init_with_asan, QemuAsanHelper}; -#[cfg(target_os = "linux")] pub mod executor; -#[cfg(target_os = "linux")] pub use executor::{QemuExecutor, QemuForkExecutor}; -#[cfg(target_os = "linux")] pub mod emu; -#[cfg(target_os = "linux")] pub use emu::*; #[must_use] @@ -83,10 +69,10 @@ pub fn filter_qemu_args() -> Vec { args } -#[cfg(all(target_os = "linux", feature = "python"))] +#[cfg(feature = "python")] use pyo3::prelude::*; -#[cfg(all(target_os = "linux", feature = "python"))] +#[cfg(feature = "python")] #[pymodule] #[pyo3(name = "libafl_qemu")] #[allow(clippy::items_after_statements, clippy::too_many_lines)]