From 82ed46aca18275970b1b8a4eaf6fc1298e988ee3 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Jun 2022 15:31:02 +0800 Subject: [PATCH 1/3] reloc: add PC-relative relocation support --- src/libdyld/src/reloc.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/libdyld/src/reloc.rs b/src/libdyld/src/reloc.rs index dc5655f..ad6780e 100644 --- a/src/libdyld/src/reloc.rs +++ b/src/libdyld/src/reloc.rs @@ -59,7 +59,8 @@ impl Relocatable for Elf32_Rela { enum RelType { None, Relative, - Lookup, + LookupAbs, + LookupRel, } impl RelType { @@ -76,9 +77,11 @@ impl RelType { Some(RelType::Relative), R_OR1K_32 | R_OR1K_GLOB_DAT | R_OR1K_JMP_SLOT - if arch == Arch::OpenRisc => Some(RelType::Lookup), + if arch == Arch::OpenRisc => Some(RelType::LookupAbs), R_ARM_GLOB_DAT | R_ARM_JUMP_SLOT | R_ARM_ABS32 - if arch == Arch::Arm => Some(RelType::Lookup), + if arch == Arch::Arm => Some(RelType::LookupAbs), + + R_ARM_PREL31 if arch == Arch::Arm => Some(RelType::LookupRel), _ => None @@ -106,31 +109,38 @@ pub fn relocate( let rel_type = RelType::new(arch, rel.type_info()) .ok_or("unsupported relocation type")?; - let value; - match rel_type { + let value = match rel_type { RelType::None => return Ok(()), RelType::Relative => { let addend = rel.addend(&lib.image); - value = lib.image.ptr().wrapping_offset(addend as isize) as Elf32_Word; + lib.image.ptr().wrapping_offset(addend as isize) as Elf32_Word } - RelType::Lookup => { + RelType::LookupAbs | RelType::LookupRel => { let sym = sym.ok_or("relocation requires an associated symbol")?; let sym_name = lib.name_starting_at(sym.st_name as usize)?; - if let Some(addr) = lib.lookup(sym_name) { + let sym_addr = if let Some(addr) = lib.lookup(sym_name) { // First, try to resolve against itself. trace!("looked up symbol {} in image", format_sym_name(sym_name)); - value = addr; + addr } else if let Some(addr) = resolve(sym_name) { // Second, call the user-provided function. trace!("resolved symbol {:?}", format_sym_name(sym_name)); - value = addr; + addr } else { // We couldn't find it anywhere. return Err(Error::Lookup(format_sym_name(sym_name))) + }; + + match rel_type { + RelType::LookupAbs => sym_addr, + RelType::LookupRel => + sym_addr.wrapping_sub( + lib.image.ptr().wrapping_offset(rel.offset() as isize) as Elf32_Addr), + _ => unreachable!() } } } @@ -145,7 +155,7 @@ pub fn rebind( let rel_type = RelType::new(arch, rela.type_info()) .ok_or("unsupported relocation type")?; match rel_type { - RelType::Lookup => { + RelType::LookupAbs => { 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)?; -- 2.42.0 From 690c6374ee1d624de956d76968119e02925a5f72 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Jun 2022 15:34:12 +0800 Subject: [PATCH 2/3] reloc: impl ARM_PREL31 handling --- src/libdyld/src/reloc.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libdyld/src/reloc.rs b/src/libdyld/src/reloc.rs index ad6780e..1bbacea 100644 --- a/src/libdyld/src/reloc.rs +++ b/src/libdyld/src/reloc.rs @@ -143,9 +143,17 @@ pub fn relocate( _ => unreachable!() } } - } + }; - lib.image.write(rel.offset(), value) + match rel.type_info() { + R_ARM_PREL31 => { + let reloc_word = lib.image.get_ref::(rel.offset()) + .ok_or("relocation offset cannot be read")?; + lib.image.write(rel.offset(), (reloc_word & 0x80000000) | (value & 0x7FFFFFFF)) + }, + + _ => lib.image.write(rel.offset(), value), + } } pub fn rebind( -- 2.42.0 From 5fba1c8bf46013f16df7d4d1ec664f3229971273 Mon Sep 17 00:00:00 2001 From: occheung Date: Wed, 1 Jun 2022 17:44:17 +0800 Subject: [PATCH 3/3] dyld/rebind: support rela generation with nac3ld --- src/libdyld/src/reloc.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/libdyld/src/reloc.rs b/src/libdyld/src/reloc.rs index 1bbacea..93f4bbc 100644 --- a/src/libdyld/src/reloc.rs +++ b/src/libdyld/src/reloc.rs @@ -159,23 +159,36 @@ pub fn relocate( 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::LookupAbs => { - 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)?; + fn rebind_symbol_to_value( + arch: Arch, lib: &Library,name: &[u8], value: Elf32_Word, relocs: &[R] + ) -> Result<(), Error> { + for reloc in relocs { + let rel_type = RelType::new(arch, reloc.type_info()) + .ok_or("unsupported relocation type")?; + match rel_type { + RelType::LookupAbs => { + let sym = lib.symtab().get(reloc.sym_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)? + if sym_name == name { + lib.image.write(reloc.offset(), value)? + } } + // No associated symbols for other relocation types. + _ => {} } - // No associated symbols for other relocation types. - _ => {} } + + Ok(()) } + + if lib.pltrel().is_empty() { + rebind_symbol_to_value(arch, lib, name, value, lib.rela())?; + } else { + rebind_symbol_to_value(arch, lib, name, value, lib.pltrel())?; + } + // FIXME: the cache maintainance operations may be more than enough, // may cause performance degradation. dcci_slice(lib.image.data); -- 2.42.0