Compare commits

...

8 Commits
v1.0.4 ... main

Author SHA1 Message Date
Nicolas Kruse 4330c4015a
Merge pull request #2 from Nonannet/dev
Dev
2025-11-23 17:14:35 +01:00
Nicolas e5be50ba2e version bump to 1.0.7 2025-11-23 17:13:02 +01:00
Nicolas 16a9450100 addend extraction for ARM relocations added 2025-11-23 17:08:33 +01:00
Nicolas 36b0d1db5c version bumped to 1.0.6 2025-11-17 09:06:09 +01:00
Nicolas 05f78ed09e R_ARM_MOVW_ABS_NC and R_ARM_MOVT_ABS relocation added 2025-11-17 09:05:01 +01:00
Nicolas 5886cf40f4 Fix in addend for SHT_REL and version bump to 1.0.5 2025-11-14 08:41:45 +01:00
Nicolas 854a70cc95 added support for addend for SHT_REL relocations (used for 32 bit x86) 2025-11-13 20:24:11 +01:00
Nicolas 2e865b0785 __contains__ for lists added with test 2025-11-13 20:23:16 +01:00
4 changed files with 69 additions and 11 deletions

View File

@ -1,6 +1,6 @@
[project] [project]
name = "pelfy" name = "pelfy"
version = "1.0.4" version = "1.0.7"
authors = [ authors = [
{ name="Nicolas Kruse", email="nicolas.kruse@nonan.net" }, { name="Nicolas Kruse", email="nicolas.kruse@nonan.net" },
] ]

View File

@ -406,6 +406,8 @@ relocation_table_types = {
14: ("R_ARM_THM_SWI8", 8, "S + A"), 14: ("R_ARM_THM_SWI8", 8, "S + A"),
15: ("R_ARM_XPC25", 25, ""), 15: ("R_ARM_XPC25", 25, ""),
16: ("R_ARM_THM_XPC22", 22, ""), 16: ("R_ARM_THM_XPC22", 22, ""),
28: ("R_ARM_CALL", 24, "((S + A) - P) >> 2"),
29: ("R_ARM_JUMP24", 24, "((S + A) - P) >> 2"),
30: ("R_ARM_TLS_DESC", 0, ""), 30: ("R_ARM_TLS_DESC", 0, ""),
32: ("R_ARM_ALU_PCREL_7_0", 7, "(S - P + A) & 0x000000FF"), 32: ("R_ARM_ALU_PCREL_7_0", 7, "(S - P + A) & 0x000000FF"),
33: ("R_ARM_ALU_PCREL_15_8", 15, "(S - P + A) & 0x0000FF00"), 33: ("R_ARM_ALU_PCREL_15_8", 15, "(S - P + A) & 0x0000FF00"),
@ -418,6 +420,8 @@ relocation_table_types = {
40: ("R_ARM_V4BX", 0, ""), 40: ("R_ARM_V4BX", 0, ""),
41: ("R_ARM_STKCHK", 0, ""), 41: ("R_ARM_STKCHK", 0, ""),
42: ("R_ARM_THM_STKCHK", 0, ""), 42: ("R_ARM_THM_STKCHK", 0, ""),
43: ("R_ARM_MOVW_ABS_NC", 16, "S + A"),
44: ("R_ARM_MOVT_ABS", 16, "S + A")
}, },
"EM_AARCH64": { "EM_AARCH64": {
0: ("R_AARCH64_NONE", 0, ""), 0: ("R_AARCH64_NONE", 0, ""),

View File

@ -265,6 +265,14 @@ class elf_list(Generic[_T]):
def __iter__(self) -> Iterator[_T]: def __iter__(self) -> Iterator[_T]:
return iter(self._data) return iter(self._data)
def __contains__(self, item: Union[str, int, _T]) -> bool:
if isinstance(item, str):
return any(getattr(el, 'name', '') == item for el in self._data)
elif isinstance(item, int):
return 0 <= item < len(self._data)
else:
return item in self._data
def _compact_table(self) -> tuple[list[str], list[list[Union[str, int]]], list[str]]: def _compact_table(self) -> tuple[list[str], list[list[Union[str, int]]], list[str]]:
return [], [[]], [] return [], [[]], []
@ -483,22 +491,61 @@ class elf_file:
Returns: Returns:
Relocations from specified elf_section Relocations from specified elf_section
""" """
offs = sh['sh_offset'] sh_offset = sh['sh_offset']
for i, el_off in enumerate(range(offs, sh['sh_size'] + offs, sh['sh_entsize'])): for i, el_off in enumerate(range(sh_offset, sh['sh_size'] + sh_offset, sh['sh_entsize'])):
ret: dict[str, int] = dict() ret: dict[str, int] = dict()
if self.bit_width == 32: if self.bit_width == 32:
ret['r_offset'] = self.read_int(el_off, 4) r_offset = self.read_int(el_off, 4)
r_info = self.read_int(el_off + 4, 4) r_info = self.read_int(el_off + 4, 4)
ret['r_info'] = r_info symbol_index = r_info >> 8
ret['r_addend'] = self.read_int(el_off + 8, 4, True) if sh.type == 'SHT_RELA' else 0 relocation_type = r_info & 0xFF
yield elf_relocation(self, ret, r_info >> 8, r_info & 0xFF, sh['sh_info'], i) ret['r_addend'] = self.read_int(el_off + 8, 4, True) \
if sh.type == 'SHT_RELA' else self._get_rel_addend(relocation_type, r_offset, sh)
elif self.bit_width == 64: elif self.bit_width == 64:
ret['r_offset'] = self.read_int(el_off, 8) r_offset = self.read_int(el_off, 8)
r_info = self.read_int(el_off + 8, 8) r_info = self.read_int(el_off + 8, 8)
ret['r_info'] = r_info symbol_index = r_info >> 32
ret['r_addend'] = self.read_int(el_off + 16, 8, True) if sh.type == 'SHT_RELA' else 0 relocation_type = r_info & 0xFFFFFFFF
yield elf_relocation(self, ret, r_info >> 32, r_info & 0xFFFFFFFF, sh['sh_info'], i) ret['r_addend'] = self.read_int(el_off + 16, 8, True) \
if sh.type == 'SHT_RELA' else self._get_rel_addend(relocation_type, r_offset, sh)
else:
raise NotImplementedError(f"{self.bit_width} bit is not supported")
ret['r_offset'] = r_offset
ret['r_info'] = r_info
yield elf_relocation(self, ret, symbol_index, relocation_type, sh['sh_info'], i)
def _get_rel_addend(self, relocation_type: int, r_offset: int, reloc_section: elf_section) -> int:
reloc_types = fdat.relocation_table_types.get(self.architecture)
if reloc_types and 'A' in reloc_types[relocation_type][2]:
name = reloc_types[relocation_type][0]
sh = self.sections[reloc_section['sh_info']]
field = self.read_int(r_offset + sh['sh_offset'], 4, True)
if name in ('R_386_PC32', 'R_386_32', 'R_X86_64_PC32', 'R_X86_64_PLT32', 'R_ARM_REL32', 'R_ARM_ABS32'):
return field
if name == 'R_ARM_MOVW_ABS_NC':
imm4 = (field >> 16) & 0xF
imm12 = field & 0xFFF
return imm12 | (imm4 << 12)
if name == 'R_ARM_MOVT_ABS':
imm4 = (field >> 16) & 0xF
imm12 = field & 0xFFF
return (imm12 << 16) | (imm4 << 28) # Upper 16 bit
if name in ('R_ARM_JUMP24', 'R_ARM_CALL'):
imm24 = field & 0xFFFFFF
if imm24 & 0x800000:
imm24 |= ~0xFFFFFF
return imm24 << 2
if '_THM_' in name:
print('Warning: Thumb relocation addend extraction is not implemented')
return 0
if '_MIPS_' in name:
print('Warning: MIPS relocations addend extraction is not implemented')
return 0
raise NotImplementedError(f"Relocation addend extraction for {name} is not implemented")
return 0
def read_bytes(self, offset: int, num_bytes: int) -> bytes: def read_bytes(self, offset: int, num_bytes: int) -> bytes:
"""Read bytes from ELF file. """Read bytes from ELF file.

View File

@ -38,6 +38,13 @@ def test_simple_c() -> None:
for reloc in elf.get_relocations(): for reloc in elf.get_relocations():
assert known_name(reloc.type), f"Relocation type {reloc.type} for {elf.architecture} in {path} is unknown." assert known_name(reloc.type), f"Relocation type {reloc.type} for {elf.architecture} in {path} is unknown."
assert 'imageWidth' in elf.objects or 'read_float_ret' in elf.objects, path
assert 'leet456456456n4ghn4hf56n4f' not in elf.objects
assert 0 in elf.objects
assert 1000 not in elf.objects
assert elf.objects[0] in elf.symbols
assert elf.objects[0] not in elf.functions
if __name__ == '__main__': if __name__ == '__main__':
test_simple_c() test_simple_c()