use std::sync::LazyLock;
use gsym::convert::{ConversionOptions, ConversionReport, ElfConverter, ElfInputs};
use object::Object;
static CURRENT_IMAGE: LazyLock<Vec<u8>> =
LazyLock::new(|| std::fs::read(std::env::current_exe().unwrap()).unwrap());
pub(crate) fn current_image() -> &'static [u8] {
&CURRENT_IMAGE
}
pub(crate) fn convert(inputs: ElfInputs<'_>) -> gsym::Result<ConversionReport> {
ElfConverter::new(ConversionOptions::default()).convert(inputs)
}
pub(crate) fn find_function<'report>(
report: &'report ConversionReport,
name: &[u8],
) -> Option<&'report gsym::Function> {
report
.builder
.functions()
.iter()
.find(|function| function.name == name)
}
pub(crate) fn retarget_machine(bytes: &mut [u8]) {
const X86_64: u16 = 62;
const AARCH64: u16 = 183;
assert_eq!(&bytes[..4], b"\x7fELF");
let little_endian = bytes[5] == 1;
let current = if little_endian {
u16::from_le_bytes(bytes[18..20].try_into().unwrap())
} else {
u16::from_be_bytes(bytes[18..20].try_into().unwrap())
};
let target = if current == AARCH64 { X86_64 } else { AARCH64 };
let machine = if little_endian {
target.to_le_bytes()
} else {
target.to_be_bytes()
};
bytes[18..20].copy_from_slice(&machine);
}
pub(crate) fn corrupt_build_id(bytes: &mut [u8]) {
let build_id = object::File::parse(&*bytes)
.unwrap()
.build_id()
.unwrap()
.expect("test binaries are linked with a build ID")
.to_vec();
assert!(!build_id.is_empty());
let position = bytes
.windows(build_id.len())
.position(|window| window == build_id)
.unwrap();
bytes[position] ^= 0x80;
}