use super::{closest_arm, run};
use crate::cli::Command;
use crate::image::{Image, Segment};
use crate::tables::Table;
#[test]
fn the_closest_arm_across_tables_wins() {
let far = Table { dispatch: 0x10, base: 0x900, arms: vec![0x100, 0x200] };
let near = Table { dispatch: 0x20, base: 0xa00, arms: vec![0x2f0, 0x300] };
let tables = [far, near];
assert_eq!(closest_arm(&tables, 0x2f8).map(|(d, t, i, a)| (d, t.base, i, a)), Some((8, 0xa00, vec![0], 0x2f0)));
let mut data = vec![0u8; 0x200];
let code: &[u8] = &[
0x48, 0x8d, 0x0d, 0xf9, 0x00, 0x00, 0x00, 0x48, 0x63, 0x04, 0x89, 0xff, 0xe0, 0x48, 0x8d, 0x05, 0x1c, 0x00, 0x00, 0x00, 0xc3, ];
data[..code.len()].copy_from_slice(code);
data[0x20..0x28].copy_from_slice(&[0x48, 0x8d, 0x15, 0x19, 0x00, 0x00, 0x00, 0xc3]);
data[0x30..0x35].copy_from_slice(b"hello");
data[0x35..0x3b].copy_from_slice(b"lib.rs");
data[0x48..0x50].copy_from_slice(&6u64.to_le_bytes());
data[0x50..0x54].copy_from_slice(&1u32.to_le_bytes());
data[0x54..0x58].copy_from_slice(&1u32.to_le_bytes());
data[0x100..0x104].copy_from_slice(&(-0xf3i32).to_le_bytes());
let image = Image {
data,
segments: vec![Segment { va: 0x1000, offset: 0, size: 0x200 }],
functions: vec![0x1000..0x1015, 0x1020..0x1028],
pointers: vec![(0x1040, 0x1035), (0x1060, 0x1030)],
imports: Vec::new(),
symbols: vec![(0x1000, "main_fn".to_owned())],
metadata: crate::image_format::Metadata::default(),
};
let empty = Image {
data: Vec::new(),
segments: Vec::new(),
functions: Vec::new(),
pointers: Vec::new(),
imports: Vec::new(),
symbols: Vec::new(),
metadata: crate::image_format::Metadata::default(),
};
let mut out = Vec::new();
assert!(run(&empty, Command::Stats, &mut out).is_ok());
for cmd in [
Command::Stats,
Command::Sym { pattern: "main".to_owned() },
Command::Func { addrs: vec![0x1000, 0x9999] },
Command::Refs {
targets: vec!["0x1030".to_owned(), "hello".to_owned(), "missing".to_owned()],
back: 1,
inline: false,
},
Command::Refs { targets: vec!["missing".to_owned()], back: 1, inline: true },
Command::Istr { targets: vec!["missing".to_owned()] },
Command::Imm { value: 0, store: false, cmp: false, within: Some(0x1000) },
Command::Imm { value: 0, store: false, cmp: false, within: None },
Command::Disp {
values: vec![0],
write: false,
lea: false,
all: false,
stride: None,
stack: false,
within: Some(0x1000),
},
Command::Disp {
values: vec![0],
write: false,
lea: false,
all: true,
stride: None,
stack: false,
within: None,
},
Command::Layout { addr: "0x1000".to_owned(), reg: "rdi".to_owned(), callees: false },
Command::Callers { addr: 0x1030 },
Command::Calls { addr: 0x1000 },
Command::Path { from: "0x1000".to_owned(), to: "0x1020".to_owned(), depth: 2 },
Command::Tree { addr: "0x1000".to_owned(), callers: false, callees: true, depth: 1 },
Command::Asm { addr: 0x1000, from: Some(0x1000), to: Some(0x1007) },
Command::C { addrs: vec![0x1000], from: None, to: None, out: None, fields: true, keep_gotos: false },
Command::Slice { addr: "0x1000".to_owned(), to: "hello".to_owned(), fields: false, keep_gotos: false },
Command::Error { text: "hello".to_owned(), back: 1 },
Command::Error { text: "lib.rs".to_owned(), back: 1 },
Command::Variant { addr: 0x1000, indices: vec![0, 9] },
Command::Arm { addrs: vec![0x100d, 0x1020] },
Command::Src { addr: 0x1020 },
Command::Where { pattern: "lib.rs".to_owned(), line: Some(1) },
Command::Files { pattern: Some("lib.rs".to_owned()) },
] {
assert!(run(&image, cmd, &mut out).is_ok());
}
assert!(
crate::scan::search_in(&image, std::slice::from_ref(&(0x9000..0x9004)), &crate::scan::Query::Branch(0))
.is_empty()
);
assert!(run(&image, Command::Error { text: "missing".to_owned(), back: 1 }, &mut out).is_err());
assert!(run(&image, Command::Variant { addr: 0x1020, indices: vec![0] }, &mut out).is_err());
}