symtool_backend/
object.rs1use crate::error::{Error, TransformError, TransformResult};
4use crate::patch::Patch;
5use goblin::elf::Elf;
6use goblin::mach::MachO;
7use std::convert::TryInto;
8
9pub enum Object<'a> {
11 Elf(Box<Elf<'a>>),
12 MachO(Box<MachO<'a>>),
13}
14
15pub type ObjectTransform<Error> =
20 dyn for<'a> Fn(&'a [u8], Object) -> std::result::Result<Vec<Patch>, Error>;
21
22pub fn transform_object<E>(
27 object: &mut [u8],
28 transformation: &ObjectTransform<E>,
29) -> TransformResult<(), E>
30where
31 E: std::error::Error,
32{
33 let mut objects = Vec::new();
35 if let Ok(archive) = goblin::archive::Archive::parse(object) {
36 for i in 0..archive.len() {
37 let member = archive.get_at(i).unwrap();
38 objects.push((
39 member.offset.try_into().expect("object too large to parse"),
40 member.header.size,
41 ));
42 }
43 } else {
44 objects.push((0, object.len()));
45 }
46
47 for (offset, size) in objects {
49 let buf = &mut object[offset..offset + size];
50 let object = match goblin::Object::parse(&buf)? {
51 goblin::Object::Elf(elf) => Ok(Object::Elf(Box::new(elf))),
52 goblin::Object::Mach(goblin::mach::Mach::Binary(macho)) => {
53 Ok(Object::MachO(Box::new(macho)))
54 }
55 _ => Err(Error::UnknownObject),
56 }?;
57 let patches = transformation(&buf, object).map_err(TransformError::Transform)?;
58 for patch in patches {
59 patch.apply(buf);
60 }
61 }
62 Ok(())
63}