diff --git a/pyproject.toml b/pyproject.toml index fc4520e..d3839e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pelfy" -version = "1.0.7" +version = "1.0.8" authors = [ { name="Nicolas Kruse", email="nicolas.kruse@nonan.net" }, ] diff --git a/src/pelfy/_fields_data.py b/src/pelfy/_fields_data.py index f489095..ce9cb1b 100644 --- a/src/pelfy/_fields_data.py +++ b/src/pelfy/_fields_data.py @@ -390,38 +390,48 @@ relocation_table_types = { }, "EM_ARM": { 0: ("R_ARM_NONE", 0, ""), + 1: ("R_ARM_PC24", 24, "S - P + A"), 2: ("R_ARM_ABS32", 32, "S + A"), 3: ("R_ARM_REL32", 32, "S - P + A"), - 4: ("R_ARM_PC13", 13, "S - P + A"), + 4: ("R_ARM_LDR_PC_G0", 12, "S - P + A"), + 5: ("R_ARM_ABS16", 16, "S + A"), 6: ("R_ARM_ABS12", 12, "S + A"), 7: ("R_ARM_THM_ABS5", 5, "S + A"), 8: ("R_ARM_ABS8", 8, "S + A"), 9: ("R_ARM_SBREL32", 32, "S - B + A"), - 10: ("R_ARM_THM_PC22", 22, "S - P + A"), + + 10: ("R_ARM_THM_CALL", 22, "S - P + A"), 11: ("R_ARM_THM_PC8", 8, "S - P + A"), - 12: ("Reserved", 0, ""), - 13: ("R_ARM_SWI24", 24, "S + A"), + 12: ("R_ARM_BREL_ADJ", 0, ""), + 13: ("R_ARM_TLS_DESC", 0, ""), 14: ("R_ARM_THM_SWI8", 8, "S + A"), + 15: ("R_ARM_XPC25", 25, ""), 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, ""), - 32: ("R_ARM_ALU_PCREL_7_0", 7, "(S - P + A) & 0x000000FF"), - 33: ("R_ARM_ALU_PCREL_15_8", 15, "(S - P + A) & 0x0000FF00"), - 34: ("R_ARM_ALU_PCREL_23_15", 23, "(S - P + A) & 0x00FF0000"), - 35: ("R_ARM_LDR_SBREL_11_0", 11, "(S - B + A) & 0x00000FFF"), - 36: ("R_ARM_ALU_SBREL_19_12", 19, "(S - B + A) & 0x000FF000"), - 37: ("R_ARM_ALU_SBREL_27_20", 27, "(S - B + A) & 0x0FF00000"), - 38: ("R_ARM_RELABS32", 32, "S + A or S - P + A"), - 39: ("R_ARM_ROSEGREL32", 32, "S - E + A"), + 30: ("R_ARM_THM_JUMP24", 24, "((S + A) - P) >> 1"), + + 32: ("R_ARM_ALU_PCREL_7_0", 8, "(S - P + A) & 0x000000FF"), + 33: ("R_ARM_ALU_PCREL_15_8", 8, "(S - P + A) & 0x0000FF00"), + 34: ("R_ARM_ALU_PCREL_23_15", 9, "(S - P + A) & 0x00FF8000"), + + 35: ("R_ARM_LDR_SBREL_11_0", 12, "(S - B + A) & 0x00000FFF"), + 36: ("R_ARM_ALU_SBREL_19_12", 8, "(S - B + A) & 0x000FF000"), + 37: ("R_ARM_ALU_SBREL_27_20", 8, "(S - B + A) & 0x0FF00000"), + + 38: ("R_ARM_TARGET1", 32, "implementation defined"), + 39: ("R_ARM_SBREL31", 31, "S - B + A"), + 40: ("R_ARM_V4BX", 0, ""), - 41: ("R_ARM_STKCHK", 0, ""), - 42: ("R_ARM_THM_STKCHK", 0, ""), + 41: ("R_ARM_TARGET2", 32, "implementation defined"), + 42: ("R_ARM_PREL31", 31, "S - P + A"), + 43: ("R_ARM_MOVW_ABS_NC", 16, "S + A"), - 44: ("R_ARM_MOVT_ABS", 16, "S + A") + 44: ("R_ARM_MOVT_ABS", 16, "S + A"), }, "EM_AARCH64": { 0: ("R_AARCH64_NONE", 0, ""), diff --git a/src/pelfy/_main.py b/src/pelfy/_main.py index 206a2aa..bea2f66 100644 --- a/src/pelfy/_main.py +++ b/src/pelfy/_main.py @@ -26,6 +26,53 @@ def open_elf_file(file_path: str) -> 'elf_file': return elf_file(f.read()) +def _decode_thumb_branch_imm(field: int, bits: int) -> int: + """ + Decode Thumb-2 wide branch immediate. + bits: 22 (R_ARM_THM_PC22) or 24 (R_ARM_THM_JUMP24) + """ + + h1 = (field >> 16) & 0xFFFF + h2 = field & 0xFFFF + + S = (h1 >> 10) & 1 + imm10 = h1 & 0x03FF + J1 = (h2 >> 13) & 1 + J2 = (h2 >> 11) & 1 + imm11 = h2 & 0x07FF + + # Decode J1/J2 → I1/I2 + I1 = (~(J1 ^ S)) & 1 + I2 = (~(J2 ^ S)) & 1 + + if bits == 24: + imm = ( + (S << 23) | + (I1 << 22) | + (I2 << 21) | + (imm10 << 11) | + (imm11 << 0) + ) + sign_bit = 23 + else: + assert bits == 22 + imm = ( + (S << 21) | + (I1 << 20) | + (I2 << 19) | + (imm10 << 9) | + (imm11 << 0) + ) + sign_bit = 21 + + # Sign extend + if imm & (1 << sign_bit): + imm |= ~((1 << (sign_bit + 1)) - 1) + + # Thumb branch offsets are halfword aligned + return imm << 1 + + class elf_symbol(): """A class for representing data of an ELF symbol @@ -42,6 +89,7 @@ class elf_symbol(): offset_in_section: Position of first symbol byte relative to section start offset_in_file: Position of first symbol byte in object file + size: size of symbol in bytes fields: All symbol header fields as dict """ @@ -71,19 +119,17 @@ class elf_symbol(): self.thumb_mode = bool((file.architecture == 'EM_ARM') & fields['st_value'] & 1) self.offset_in_section = fields['st_value'] & ~int(self.thumb_mode) self.offset_in_file = self.section['sh_offset'] + self.offset_in_section if self.section else 0 + self.size = self.fields['st_size'] @property def data(self) -> bytes: """Returns the binary data the symbol is pointing to. - The offset in the ELF file is calculated by: - sections[symbol.st_shndx].sh_offset + symbol.st_value """ assert self.section, 'This symbol is not associated to a data section' if self.section.type == 'SHT_NOBITS': return b'\x00' * self['st_size'] else: - offset = self.section['sh_offset'] + self['st_value'] - return self.file.read_bytes(offset, self['st_size']) + return self.file.read_bytes(self.offset_in_file, self['st_size']) @property def data_hex(self) -> str: @@ -102,7 +148,7 @@ class elf_symbol(): assert self.section and self.section.type == 'SHT_PROGBITS' for reloc in self.file.get_relocations(): if reloc.target_section == self.section: - offset = reloc['r_offset'] - self['st_value'] + offset = reloc['r_offset'] - self.offset_in_section if 0 <= offset < self['st_size']: ret.append(reloc) return relocation_list(ret) @@ -544,8 +590,12 @@ class elf_file: if imm24 & 0x800000: imm24 |= ~0xFFFFFF return imm24 << 2 + if name == 'R_ARM_THM_PC22': + return _decode_thumb_branch_imm(field, 22) + if name in ('R_ARM_THM_JUMP24', 'R_ARM_THM_CALL'): + return _decode_thumb_branch_imm(field, 24) if '_THM_' in name: - print('Warning: Thumb relocation addend extraction is not implemented') + print(f'Warning: Thumb relocation addend extraction is for {name} not implemented') return 0 if '_MIPS_' in name: print('Warning: MIPS relocations addend extraction is not implemented')