diff --git a/src/libdyld/src/lib.rs b/src/libdyld/src/lib.rs index 1396947..54a07dd 100644 --- a/src/libdyld/src/lib.rs +++ b/src/libdyld/src/lib.rs @@ -93,6 +93,7 @@ extern fn dl_unwind_find_exidx(pc: u32, len_ptr: *mut u32) -> u32 { pub struct Library { pub image: Image, + pub arch: Arch, dyn_section: DynamicSection, } @@ -163,6 +164,11 @@ impl Library { Ok(self.strtab().get(offset..offset + size) .ok_or("cannot read symbol name")?) } + + /// Rebind Rela by `name` to a new `addr` + pub fn rebind(&self, name: &[u8], addr: *const ()) -> Result<(), Error> { + reloc::rebind(self.arch, self, name, addr as Elf32_Word) + } } pub fn load( @@ -235,6 +241,7 @@ pub fn load( debug!("Relocating {} rela, {} rel, {} pltrel", dyn_section.rela.len(), dyn_section.rel.len(), dyn_section.pltrel.len()); let lib = Library { + arch, image, dyn_section }; diff --git a/src/libdyld/src/reloc.rs b/src/libdyld/src/reloc.rs index 0c0cb7a..9200703 100644 --- a/src/libdyld/src/reloc.rs +++ b/src/libdyld/src/reloc.rs @@ -133,3 +133,27 @@ pub fn relocate( lib.image.write(rel.offset(), value) } + +pub fn rebind( + arch: Arch, lib: &Library, name: &[u8], value: Elf32_Word +) -> Result<(), Error> { + for rela in lib.pltrel() { + let rel_type = RelType::new(arch, rela.type_info()) + .ok_or("unsupported relocation type")?; + match rel_type { + RelType::Lookup => { + let sym = lib.symtab().get(ELF32_R_SYM(rela.r_info) as usize) + .ok_or("symbol out of bounds of symbol table")?; + let sym_name = lib.name_starting_at(sym.st_name as usize)?; + + if sym_name == name { + lib.image.write(rela.offset(), value)? + } + } + // No associated symbols for other relocation types. + _ => {} + } + } + + Ok(()) +}