|
1 |
| -use std::{path::PathBuf, process::Command}; |
2 |
| - |
| 1 | +use std::{ |
| 2 | + fs::File, |
| 3 | + io::{BufRead, BufReader, BufWriter, Write}, |
| 4 | + path::PathBuf, |
| 5 | + process::{Command, Stdio}, |
| 6 | +}; |
| 7 | + |
| 8 | +#[cfg(feature = "rabbit")] |
| 9 | +const NAMESPACE: &str = "🐇"; |
| 10 | +#[cfg(not(feature = "rabbit"))] |
| 11 | +const NAMESPACE: &str = "__libafl"; |
| 12 | +const NAMESPACE_LEN: usize = NAMESPACE.as_bytes().len(); |
| 13 | + |
| 14 | +#[allow(clippy::too_many_lines)] |
3 | 15 | fn main() {
|
4 | 16 | if cfg!(any(feature = "cargo-clippy", docsrs)) {
|
5 | 17 | return; // skip when clippy or docs is running
|
@@ -69,20 +81,143 @@ fn main() {
|
69 | 81 | let mut lib_path = custom_lib_dir.join(std::env::var_os("TARGET").unwrap());
|
70 | 82 | lib_path.push("release");
|
71 | 83 |
|
72 |
| - #[cfg(all(feature = "embed-runtime", target_family = "unix"))] |
73 |
| - { |
74 |
| - // NOTE: lib, .a are added always on unix-like systems as described in: |
75 |
| - // https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b |
| 84 | + if cfg!(target_family = "unix") { |
| 85 | + use std::path::Path; |
| 86 | + |
| 87 | + lib_path.push("libafl_libfuzzer_runtime.a"); |
| 88 | + let target_libdir = Command::new("rustc") |
| 89 | + .args(["--print", "target-libdir"]) |
| 90 | + .output() |
| 91 | + .expect("Couldn't find rustc's target-libdir"); |
| 92 | + let target_libdir = String::from_utf8(target_libdir.stdout).unwrap(); |
| 93 | + let target_libdir = Path::new(target_libdir.trim()); |
| 94 | + |
| 95 | + let rust_lld = target_libdir.join("../bin/rust-lld"); |
| 96 | + let rust_ar = target_libdir.join("../bin/llvm-ar"); // NOTE: depends on llvm-tools |
| 97 | + let rust_objcopy = target_libdir.join("../bin/llvm-objcopy"); // NOTE: depends on llvm-tools |
| 98 | + let nm = "nm"; // NOTE: we use system nm here because llvm-nm doesn't respect the encoding? |
| 99 | + |
| 100 | + let redefined_symbols = custom_lib_dir.join("redefs.txt"); |
| 101 | + |
| 102 | + let objfile_orig = custom_lib_dir.join("libFuzzer.o"); |
| 103 | + let objfile_dest = custom_lib_dir.join("libFuzzer-mimalloc.o"); |
| 104 | + |
| 105 | + let mut command = Command::new(rust_lld); |
| 106 | + command |
| 107 | + .args(["-flavor", "gnu"]) |
| 108 | + .arg("-r") |
| 109 | + .arg("--whole-archive") |
| 110 | + .arg(lib_path) |
| 111 | + .args(["-o", objfile_orig.to_str().expect("Invalid path characters present in your current directory prevent us from linking to the runtime")]); |
| 112 | + |
| 113 | + assert!( |
| 114 | + !command.status().map(|s| !s.success()).unwrap_or(true), |
| 115 | + "Couldn't link runtime crate! Do you have the llvm-tools component installed?" |
| 116 | + ); |
| 117 | + |
| 118 | + let mut child = Command::new(nm) |
| 119 | + .arg(&objfile_orig) |
| 120 | + .stdout(Stdio::piped()) |
| 121 | + .spawn() |
| 122 | + .unwrap(); |
| 123 | + |
| 124 | + let mut redefinitions_file = BufWriter::new(File::create(&redefined_symbols).unwrap()); |
| 125 | + |
| 126 | + let replacement = format!("_ZN{NAMESPACE_LEN}{NAMESPACE}"); |
| 127 | + |
| 128 | + // redefine all the rust-mangled symbols we can |
| 129 | + // TODO this will break when v0 mangling is stabilised |
| 130 | + for line in BufReader::new(child.stdout.take().unwrap()).lines() { |
| 131 | + let line = line.unwrap(); |
| 132 | + let (_, symbol) = line.rsplit_once(' ').unwrap(); |
| 133 | + if symbol.starts_with("_ZN") { |
| 134 | + writeln!( |
| 135 | + redefinitions_file, |
| 136 | + "{} {}", |
| 137 | + symbol, |
| 138 | + symbol.replacen("_ZN", &replacement, 1) |
| 139 | + ) |
| 140 | + .unwrap(); |
| 141 | + } |
| 142 | + } |
| 143 | + redefinitions_file.flush().unwrap(); |
| 144 | + drop(redefinitions_file); |
| 145 | + |
| 146 | + assert!( |
| 147 | + !child.wait().map(|s| !s.success()).unwrap_or(true), |
| 148 | + "Couldn't link runtime crate! Do you have the llvm-tools component installed?" |
| 149 | + ); |
| 150 | + |
| 151 | + let mut command = Command::new(rust_objcopy); |
| 152 | + |
| 153 | + for symbol in [ |
| 154 | + "__rust_drop_panic", |
| 155 | + "__rust_foreign_exception", |
| 156 | + "rust_begin_unwind", |
| 157 | + "rust_panic", |
| 158 | + "rust_eh_personality", |
| 159 | + "__rg_oom", |
| 160 | + "__rdl_oom", |
| 161 | + "__rdl_alloc", |
| 162 | + "__rust_alloc", |
| 163 | + "__rdl_dealloc", |
| 164 | + "__rust_dealloc", |
| 165 | + "__rdl_realloc", |
| 166 | + "__rust_realloc", |
| 167 | + "__rdl_alloc_zeroed", |
| 168 | + "__rust_alloc_zeroed", |
| 169 | + "__rust_alloc_error_handler", |
| 170 | + "__rust_no_alloc_shim_is_unstable", |
| 171 | + "__rust_alloc_error_handler_should_panic", |
| 172 | + ] { |
| 173 | + command |
| 174 | + .arg("--redefine-sym") |
| 175 | + .arg(format!("{symbol}={symbol}_libafl_libfuzzer_runtime")); |
| 176 | + } |
| 177 | + |
| 178 | + command |
| 179 | + .arg("--redefine-syms") |
| 180 | + .arg(redefined_symbols) |
| 181 | + .args([&objfile_orig, &objfile_dest]); |
| 182 | + |
| 183 | + assert!( |
| 184 | + !command.status().map(|s| !s.success()).unwrap_or(true), |
| 185 | + "Couldn't rename allocators in the runtime crate! Do you have the llvm-tools component installed?" |
| 186 | + ); |
| 187 | + |
| 188 | + let mut command = Command::new(rust_ar); |
| 189 | + command |
| 190 | + .arg("cr") |
| 191 | + .arg(custom_lib_dir.join("libFuzzer.a")) |
| 192 | + .arg(objfile_dest); |
| 193 | + |
| 194 | + assert!( |
| 195 | + !command.status().map(|s| !s.success()).unwrap_or(true), |
| 196 | + "Couldn't create runtime archive!" |
| 197 | + ); |
| 198 | + |
| 199 | + #[cfg(feature = "embed-runtime")] |
| 200 | + { |
| 201 | + // NOTE: lib, .a are added always on unix-like systems as described in: |
| 202 | + // https://gist.github.com/novafacing/1389cbb2f0a362d7eb103e67b4468e2b |
| 203 | + println!( |
| 204 | + "cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}", |
| 205 | + custom_lib_dir.join("libFuzzer.a").display() |
| 206 | + ); |
| 207 | + } |
| 208 | + |
76 | 209 | println!(
|
77 |
| - "cargo:rustc-env=LIBAFL_LIBFUZZER_RUNTIME_PATH={}", |
78 |
| - lib_path.join("libafl_libfuzzer_runtime.a").display() |
| 210 | + "cargo:rustc-link-search=native={}", |
| 211 | + custom_lib_dir.to_str().unwrap() |
79 | 212 | );
|
| 213 | + println!("cargo:rustc-link-lib=static=Fuzzer"); |
| 214 | + } else { |
| 215 | + println!( |
| 216 | + "cargo:rustc-link-search=native={}", |
| 217 | + lib_path.to_str().unwrap() |
| 218 | + ); |
| 219 | + println!("cargo:rustc-link-lib=static=afl_fuzzer_runtime"); |
80 | 220 | }
|
81 | 221 |
|
82 |
| - println!( |
83 |
| - "cargo:rustc-link-search=native={}", |
84 |
| - lib_path.to_str().unwrap() |
85 |
| - ); |
86 |
| - println!("cargo:rustc-link-lib=static=afl_libfuzzer_runtime"); |
87 | 222 | println!("cargo:rustc-link-lib=stdc++");
|
88 | 223 | }
|
0 commit comments