mirror of https://github.com/Nonannet/pelfy.git
addend calculation for R_ARM_THM_PC22, R_ARM_THM_JUMP24 and R_ARM_THM_CALL fixed
This commit is contained in:
parent
5a77c72064
commit
a8139e3739
|
|
@ -27,51 +27,12 @@ def open_elf_file(file_path: str) -> 'elf_file':
|
||||||
return elf_file(f.read())
|
return elf_file(f.read())
|
||||||
|
|
||||||
|
|
||||||
def _decode_thumb_branch_imm(field: int, bits: int) -> int:
|
def _sign_extend(value: int, bits: int) -> int:
|
||||||
"""
|
"""Sign-extend a value with given bit width to 32 bits."""
|
||||||
Decode Thumb-2 wide branch immediate.
|
sign_bit = 1 << (bits - 1)
|
||||||
bits: 22 (R_ARM_THM_PC22) or 24 (R_ARM_THM_JUMP24)
|
if value & sign_bit:
|
||||||
"""
|
return value - (1 << bits)
|
||||||
|
return value
|
||||||
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():
|
class elf_symbol():
|
||||||
|
|
@ -592,9 +553,33 @@ class elf_file:
|
||||||
imm24 |= ~0xFFFFFF
|
imm24 |= ~0xFFFFFF
|
||||||
return imm24 << 2
|
return imm24 << 2
|
||||||
if name == 'R_ARM_THM_PC22':
|
if name == 'R_ARM_THM_PC22':
|
||||||
return _decode_thumb_branch_imm(field, 22)
|
# BL Encoding T2
|
||||||
|
h1 = field & 0xFFFF
|
||||||
|
h2 = (field >> 16) & 0xFFFF
|
||||||
|
s = (h1 >> 10) & 0x1 # Bit 10 of h1
|
||||||
|
imm10H = h1 & 0x3FF # Bits 9..0 of h1
|
||||||
|
j1 = (h2 >> 13) & 0x1 # Bit 13 of h2
|
||||||
|
j2 = (h2 >> 11) & 0x1 # Bit 11 of h2
|
||||||
|
imm10L = (h2 >> 1) & 0x3FF # Bits 10..1 of h2
|
||||||
|
i1 = ~(j1 ^ s) & 0x1
|
||||||
|
i2 = ~(j2 ^ s) & 0x1
|
||||||
|
imm22 = (s << 21) | (i1 << 20) | (i2 << 19) | (imm10H << 9) | imm10L
|
||||||
|
imm32 = _sign_extend(imm22 << 1, 23) # Shift left by 1, then sign-extend 23 bits
|
||||||
|
return imm32
|
||||||
if name in ('R_ARM_THM_JUMP24', 'R_ARM_THM_CALL'):
|
if name in ('R_ARM_THM_JUMP24', 'R_ARM_THM_CALL'):
|
||||||
return _decode_thumb_branch_imm(field, 24)
|
# B.W Encoding T4
|
||||||
|
h1 = field & 0xFFFF
|
||||||
|
h2 = (field >> 16) & 0xFFFF
|
||||||
|
s = (h1 >> 10) & 0x1 # Bit 10 of h1
|
||||||
|
imm10 = h1 & 0x3FF # Bits 9..0 of h1
|
||||||
|
j1 = (h2 >> 13) & 0x1 # Bit 13 of h2
|
||||||
|
j2 = (h2 >> 11) & 0x1 # Bit 11 of h2
|
||||||
|
imm11 = h2 & 0x7FF # Bits 10..0 of h2
|
||||||
|
i1 = ~(j1 ^ s) & 0x1
|
||||||
|
i2 = ~(j2 ^ s) & 0x1
|
||||||
|
imm24 = (s << 23) | (i1 << 22) | (i2 << 21) | (imm10 << 11) | imm11
|
||||||
|
imm32 = _sign_extend(imm24 << 1, 25) # Shift left by 1, then sign-extend 25 bits
|
||||||
|
return imm32
|
||||||
if name == 'R_ARM_THM_MOVW_ABS_NC' or name == 'R_ARM_THM_MOVT_ABS':
|
if name == 'R_ARM_THM_MOVW_ABS_NC' or name == 'R_ARM_THM_MOVT_ABS':
|
||||||
i = (field >> 10) & 1
|
i = (field >> 10) & 1
|
||||||
imm4 = field & 0xF
|
imm4 = field & 0xF
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import pelfy._main as _main
|
import pelfy._main as _main
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def test_arm_addend_extraction():
|
|
||||||
|
def test_arm_addend_extraction() -> None:
|
||||||
# Path to the test object file
|
# Path to the test object file
|
||||||
obj_path = os.path.join('tests', 'obj', 'stencils_armv7_O3.o')
|
obj_path = os.path.join('tests', 'obj', 'stencils_armv7_O3.o')
|
||||||
elf = _main.open_elf_file(obj_path)
|
elf = _main.open_elf_file(obj_path)
|
||||||
|
|
@ -59,7 +60,3 @@ def test_arm_addend_extraction():
|
||||||
found = True
|
found = True
|
||||||
break
|
break
|
||||||
assert found, f"Missing or incorrect addend for {ref_type} offset=0x{ref_offset:X} symbol={ref_symbol} (value={addend}, expected {ref_addend})"
|
assert found, f"Missing or incorrect addend for {ref_type} offset=0x{ref_offset:X} symbol={ref_symbol} (value={addend}, expected {ref_addend})"
|
||||||
|
|
||||||
print(found, f"Missing or incorrect addend for {ref_type} offset=0x{ref_offset:X} symbol={ref_symbol} (value={addend}, expected {ref_addend})")
|
|
||||||
|
|
||||||
assert False
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import pelfy._main as _main
|
import pelfy._main as _main
|
||||||
import os
|
import os
|
||||||
|
|
||||||
def test_thumb_addend_extraction():
|
|
||||||
|
def test_thumb_addend_extraction() -> None:
|
||||||
# Path to the test object file
|
# Path to the test object file
|
||||||
obj_path = os.path.join('tests', 'obj', 'stencils_armv7thumb_O3_THM_MOVW.o')
|
obj_path = os.path.join('tests', 'obj', 'stencils_armv7thumb_O3_THM_MOVW.o')
|
||||||
elf = _main.open_elf_file(obj_path)
|
elf = _main.open_elf_file(obj_path)
|
||||||
|
|
@ -13,46 +14,46 @@ def test_thumb_addend_extraction():
|
||||||
reloc_addends.append((reloc.type, reloc['r_offset'], reloc['r_addend'], reloc.symbol.name))
|
reloc_addends.append((reloc.type, reloc['r_offset'], reloc['r_addend'], reloc.symbol.name))
|
||||||
|
|
||||||
# Reference values from the .asm file (addend = 0 for all Thumb relocations)
|
# Reference values from the .asm file (addend = 0 for all Thumb relocations)
|
||||||
reference = [
|
reference: list[tuple[str, int | None, int, str]] = [
|
||||||
('R_ARM_THM_MOVW_ABS_NC', None, 0, 'dummy_int'),
|
('R_ARM_THM_MOVW_ABS_NC', None, 0, 'dummy_int'),
|
||||||
('R_ARM_THM_MOVT_ABS', None, 0, 'dummy_int'),
|
('R_ARM_THM_MOVT_ABS', None, 0, 'dummy_int'),
|
||||||
('R_ARM_THM_MOVW_ABS_NC', None, 0, 'dummy_float'),
|
('R_ARM_THM_MOVW_ABS_NC', None, 0, 'dummy_float'),
|
||||||
('R_ARM_THM_MOVT_ABS', None, 0, 'dummy_float'),
|
('R_ARM_THM_MOVT_ABS', None, 0, 'dummy_float'),
|
||||||
('R_ARM_THM_JUMP24', 0x14, 0, 'auxsub_get_42'),
|
('R_ARM_THM_JUMP24', 0x14, -4, 'auxsub_get_42'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'result_int'),
|
('R_ARM_THM_CALL', 0xA, -4, 'result_int'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float_int'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float_int'),
|
||||||
('R_ARM_THM_JUMP24', 0xC, 0, 'result_float_float'),
|
('R_ARM_THM_JUMP24', 0xC, -4, 'result_float_float'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_int_int'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_int_int'),
|
||||||
('R_ARM_THM_JUMP24', 0xC, 0, 'result_int_float'),
|
('R_ARM_THM_JUMP24', 0xC, -4, 'result_int_float'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'aux_get_42'),
|
('R_ARM_THM_CALL', 0xA, -4, 'aux_get_42'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'aux_get_42'),
|
('R_ARM_THM_CALL', 0x2, -4, 'aux_get_42'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float'),
|
||||||
('R_ARM_THM_JUMP24', 0x2, 0, 'result_int'),
|
('R_ARM_THM_JUMP24', 0x2, -4, 'result_int'),
|
||||||
('R_ARM_THM_JUMP24', 0x4, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x4, -4, 'result_float'),
|
||||||
('R_ARM_THM_JUMP24', 0x28, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x28, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2C, 0, 'sqrtf'),
|
('R_ARM_THM_CALL', 0x2C, -4, 'sqrtf'),
|
||||||
('R_ARM_THM_JUMP24', 0x20, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x20, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x24, 0, 'sqrtf'),
|
('R_ARM_THM_CALL', 0x24, -4, 'sqrtf'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'expf'),
|
('R_ARM_THM_CALL', 0xA, -4, 'expf'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'expf'),
|
('R_ARM_THM_CALL', 0x2, -4, 'expf'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'logf'),
|
('R_ARM_THM_CALL', 0xA, -4, 'logf'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'logf'),
|
('R_ARM_THM_CALL', 0x2, -4, 'logf'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'sinf'),
|
('R_ARM_THM_CALL', 0xA, -4, 'sinf'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'sinf'),
|
('R_ARM_THM_CALL', 0x2, -4, 'sinf'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'cosf'),
|
('R_ARM_THM_CALL', 0xA, -4, 'cosf'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'cosf'),
|
('R_ARM_THM_CALL', 0x2, -4, 'cosf'),
|
||||||
('R_ARM_THM_JUMP24', 0xA, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0xA, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0xA, 0, 'tanf'),
|
('R_ARM_THM_CALL', 0xA, -4, 'tanf'),
|
||||||
('R_ARM_THM_JUMP24', 0x12, 0, 'result_float'),
|
('R_ARM_THM_JUMP24', 0x12, -4, 'result_float'),
|
||||||
('R_ARM_THM_CALL', 0x2, 0, 'tanf'),
|
('R_ARM_THM_CALL', 0x2, -4, 'tanf'),
|
||||||
]
|
]
|
||||||
# For each reference, check that at least one matching relocation has the expected addend
|
# For each reference, check that at least one matching relocation has the expected addend
|
||||||
for ref_type, _, ref_addend, ref_symbol in reference:
|
for ref_type, _, ref_addend, ref_symbol in reference:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue