Skip to content

Commit

Permalink
Fix libafl_unicorn CI (#2991)
Browse files Browse the repository at this point in the history
* fix: clippy

* fix: allow specifying thumb mode or not

* fix: timeout for testcase
  • Loading branch information
henri2h authored Feb 17, 2025
1 parent 53004f9 commit 9a2a42c
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 54 deletions.
2 changes: 1 addition & 1 deletion fuzzers/full_system/unicorn/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test_single arch="arm":
#!/bin/bash
echo "Testing {{arch}}"

RUST_LOG="debug" timeout 10s {{FUZZER}} {{arch}} 2>&1 | tee fuzz_stdout.log || true
RUST_LOG="debug" timeout 30s {{FUZZER}} {{arch}} 2>&1 | tee fuzz_stdout.log || true
if grep -qa "objectives: 1" fuzz_stdout.log; then
echo "Fuzzer is working"
else
Expand Down
14 changes: 10 additions & 4 deletions fuzzers/full_system/unicorn/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@ use libafl_bolts::{
};
use libafl_targets::EDGES_MAP_DEFAULT_SIZE;
pub use libafl_targets::EDGES_MAP_PTR;
#[cfg(feature = "code_hook")]
use libafl_unicorn::helper::get_stack_pointer;
use libafl_unicorn::{
emu::{debug_print, memory_dump},
helper::get_stack_pointer,
hooks::set_coverage_hook,
};
#[cfg(feature = "mem_hook")]
use unicorn_engine::{unicorn_const::MemType, HookType};
use unicorn_engine::{
unicorn_const::{Arch, MemType, SECOND_SCALE},
HookType, Mode, Permission, RegisterARM, RegisterARM64, RegisterX86, Unicorn,
unicorn_const::{Arch, SECOND_SCALE},
Mode, Permission, RegisterARM, RegisterARM64, RegisterX86, Unicorn,
};

pub const CODE_ADDRESS: u64 = 0x9000;
Expand Down Expand Up @@ -223,7 +226,7 @@ fn fuzzer(should_emulate: bool, arch: Arch) {
log::error!("Error: {:?}", err);

memory_dump(&emu, 2);
debug_print(&emu);
debug_print(&emu, true);
}
}

Expand Down Expand Up @@ -323,13 +326,16 @@ fn unicorn_map_and_load_code(emu: &mut Unicorn<()>, address: u64, size: usize, p
buffer.len() as u64
}

#[cfg(feature = "code_hook")]
fn add_code_hook(emu: &mut Unicorn<()>) {
emu.add_code_hook(0x0, !0x0_u64, |emu, pc, _| {
let sp = get_stack_pointer(emu);
log::debug!("[PC: 0x{pc:x}] Hook: SP 0x:{sp:x}");
})
.unwrap();
}

#[cfg(feature = "mem_hook")]
fn mem_callback(
emu: &mut unicorn_engine::Unicorn<()>,
mem: MemType,
Expand Down
2 changes: 1 addition & 1 deletion libafl/src/events/launcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ where
if self.stdout_file.is_some() || self.stderr_file.is_some() {
stdout = Stdio::inherit();
stderr = Stdio::inherit();
};
}
}

std::thread::sleep(Duration::from_millis(
Expand Down
93 changes: 48 additions & 45 deletions libafl_unicorn/src/emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ pub fn memory_dump(emu: &Unicorn<()>, len: u64) {
}
}

pub fn debug_print(emu: &Unicorn<()>) {
// Display some register values and disassemble the instructions around the program counter
// address. The thumb_mode parameter is only taken into account when the architecture used is ARM.
pub fn debug_print(emu: &Unicorn<()>, thumb_mode: bool) {
log::debug!("Status when crash happened:");

let pc = emu.pc_read().unwrap();
Expand Down Expand Up @@ -68,54 +70,55 @@ pub fn debug_print(emu: &Unicorn<()>) {

// Provide disassembly at instant of crash
let regions = emu.mem_regions().expect("Could not get memory regions");
for i in 0..regions.len() {
if regions[i].perms.contains(Permission::EXEC) {
if pc >= regions[i].begin && pc <= regions[i].end {
let mut begin = pc - 32;
let mut end = pc + 32;
if begin < regions[i].begin {
begin = regions[i].begin;
}
if end > regions[i].end {
end = regions[i].end;
}
for region in regions {
if region.perms.contains(Permission::EXEC) && pc >= region.begin && pc <= region.end {
let mut begin = pc - 32;
let mut end = pc + 32;
if begin < region.begin {
begin = region.begin;
}
if end > region.end {
end = region.end;
}

let bytes = emu
.mem_read_as_vec(begin, (end - begin) as usize)
.expect("Could not get program code");
let cs = match emu.get_arch() {
Arch::ARM => Capstone::new()
.arm()
.mode(arch::arm::ArchMode::Thumb)
.detail(true)
.build()
.expect("Failed to create Capstone object"),
Arch::ARM64 => Capstone::new()
.arm64()
.mode(arch::arm64::ArchMode::Arm)
.detail(true)
.build()
.expect("Failed to create Capstone object"),
let bytes = emu
.mem_read_as_vec(begin, (end - begin) as usize)
.expect("Could not get program code");
let cs = match emu.get_arch() {
Arch::ARM => Capstone::new()
.arm()
.mode(match thumb_mode {
true => arch::arm::ArchMode::Thumb,
false => arch::arm::ArchMode::Arm,
})
.detail(true)
.build()
.expect("Failed to create Capstone object"),
Arch::ARM64 => Capstone::new()
.arm64()
.mode(arch::arm64::ArchMode::Arm)
.detail(true)
.build()
.expect("Failed to create Capstone object"),

_ => Capstone::new()
.x86()
.mode(arch::x86::ArchMode::Mode64)
.syntax(arch::x86::ArchSyntax::Intel)
.detail(true)
.build()
.expect("Failed to create Capstone object"),
};
let insns = cs.disasm_all(&bytes, begin).expect("Failed to disassemble");
_ => Capstone::new()
.x86()
.mode(arch::x86::ArchMode::Mode64)
.syntax(arch::x86::ArchSyntax::Intel)
.detail(true)
.build()
.expect("Failed to create Capstone object"),
};
let insns = cs.disasm_all(&bytes, begin).expect("Failed to disassemble");

if !insns.is_empty() {
log::debug!("Code dump: [0x{begin:x} -> 0x{end:x}]");
} else {
log::debug!("No disassembly available at PC: 0x{pc:x}");
}
if !insns.is_empty() {
log::debug!("Code dump: [0x{begin:x} -> 0x{end:x}]");
} else {
log::debug!("No disassembly available at PC: 0x{pc:x}");
}

for i in insns.as_ref() {
log::debug!("{}", i);
}
for i in insns.as_ref() {
log::debug!("{}", i);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions libafl_unicorn/src/helper.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use unicorn_engine::{unicorn_const::Arch, RegisterARM, RegisterARM64, RegisterX86};

pub fn get_stack_pointer(emu: &unicorn_engine::Unicorn<()>) -> u64 {
let sp = match emu.get_arch() {
match emu.get_arch() {
Arch::ARM => emu.reg_read(RegisterARM::SP).unwrap(),
Arch::ARM64 => emu.reg_read(RegisterARM64::SP).unwrap(),
Arch::X86 => emu.reg_read(RegisterX86::ESP).unwrap(),
_ => 0,
};
sp
}
}

0 comments on commit 9a2a42c

Please sign in to comment.