Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linking of ARM ELF fails in presence of .ARM.exidx section #19

Closed
calebh opened this issue Mar 1, 2024 · 2 comments
Closed

Linking of ARM ELF fails in presence of .ARM.exidx section #19

calebh opened this issue Mar 1, 2024 · 2 comments
Assignees

Comments

@calebh
Copy link
Contributor

calebh commented Mar 1, 2024

I have an ELF file for one of the upcoming AMP Hackathon problems that I am attempting to patch. The ELF file in question is ARM, and it contains a section .ARM.exidx, which from my understanding is related to stack unwinding. Attempting either an InsertFunctionPatch or a InsertInstructionPatch results in failure due to some sort of relative addressing related to this section.

Here is the stacktrace and error message that I obtained:

ERROR    | 2024-03-01 14:52:42,847 | patcherex2.components.compilers.compiler | ld.lld-15: error: /tmp/tmpnykktgjr/obj.o:(.ARM.exidx+0x0): relocation R_ARM_PREL31 out of range: 1610719160 is not in [-1073741824, 1073741823]
>>> referenced by code.c

Traceback (most recent call last):
  File "/home/caleb/Documents/vibesproject/cozy/test_programs/GridIDPS/build/micropatch.py", line 40, in <module>
    apply_badpatch()
  File "/home/caleb/Documents/vibesproject/cozy/test_programs/GridIDPS/build/micropatch.py", line 37, in apply_badpatch
    proj.apply_patches()
  File "/home/caleb/Documents/vibesproject/VIBES-internal/experiments/cozy/venv/lib/python3.11/site-packages/patcherex2/patcherex.py", line 57, in apply_patches
    patch.apply(self)
  File "/home/caleb/Documents/vibesproject/VIBES-internal/experiments/cozy/venv/lib/python3.11/site-packages/patcherex2/patches/function_patches.py", line 134, in apply
    p.compiler.compile(
  File "/home/caleb/Documents/vibesproject/VIBES-internal/experiments/cozy/venv/lib/python3.11/site-packages/patcherex2/components/compilers/clang_arm.py", line 37, in compile
    compiled = super().compile(
               ^^^^^^^^^^^^^^^^
  File "/home/caleb/Documents/vibesproject/VIBES-internal/experiments/cozy/venv/lib/python3.11/site-packages/patcherex2/components/compilers/compiler.py", line 83, in compile
    raise e
  File "/home/caleb/Documents/vibesproject/VIBES-internal/experiments/cozy/venv/lib/python3.11/site-packages/patcherex2/components/compilers/compiler.py", line 80, in compile
    subprocess.run(args, check=True, capture_output=True)
  File "/usr/lib/python3.11/subprocess.py", line 571, in run
    raise CalledProcessError(retcode, process.args,
subprocess.CalledProcessError: Command '['ld.lld-15', '-relocatable', '/tmp/tmpnykktgjr/obj.o', '-T', '/tmp/tmpnykktgjr/linker.ld', '-o', '/tmp/tmpnykktgjr/obj_linked.o']' returned non-zero exit status 1.

Here is my Python script:

import patcherex2

proj = patcherex2.Patcherex("amp_challenge_arm.ino_unstripped.elf")

# Make sure InsertFunctionPatch is working
# Applying the InsertFunctionPatch fails even if we comment out the body of flushSerial()
flushSerial_code = '''
void flushSerial() {
    while(usb_serial_available() > 0) {
        char t = usb_serial_getchar();
    }
}
'''
flushSerial_patch = patcherex2.InsertFunctionPatch("flushSerial", flushSerial_code)
proj.patches.append(flushSerial_patch)

# Make sure InsertInstructionPatch is working
instructionPatch_code = '''
nop
nop
'''
loop_addr = proj.binary_analyzer.get_function('loop')['addr']
instruction_patch = patcherex2.InsertInstructionPatch(loop_addr, instructionPatch_code)
proj.patches.append(instruction_patch)

proj.apply_patches()
proj.binfmt_tool.save_binary("amp_challenge_arm.ino_unstripped-draper-badpatch.elf")

Some information I have found on this exidx section:

The linker script that patcherex2 generates does not seem to have anything about the exidx. Unfortunately I am not well versed enough in the ELF format or linker scripts to make a determination on how to fix this issue.

I have attached the ELF file and the Python script to this issue.
arm_exidx_bug.zip

@DennyDai
Copy link
Collaborator

DennyDai commented Mar 3, 2024

@calebh Thank you for reporting it!

The short answer is I'm still currently working on this and will ideally get it done by Hackathon.
You can use ↓ for now (anywhere before apply_patches()) to manually mark certain unused functions as free space. Patcherex will then utilize this space to insert additional code, overwriting the original content.

proj.allocation_manager.add_free_space(addr, size, "RX")

We have received similar feedback through AMP Slack. In both instances, the root cause is Patcherex's attempt to allocate memory blocks at a distance from the patch site that exceeds the range a branch instruction can cover.

While implementing a solution for long-jump capabilities is on our agenda, a more pressing issue stems from how the ELF file is used for the board. Assuming the board in question is Teensy 4.1 (please correct me if I'm wrong), the process begins with converting the ELF file to Intel Hex format using objcopy. This is followed by loading it onto the board via Teensy's proprietary loader. This conversion process removes all segment/section information from the ELF file, and the behavior of the loader remains unclear. Consequently, this makes it challenging for Patcherex to identify appropriate memory addresses for injecting additional code based solely on the ELF or Hex file.

To mitigate this issue, I am developing a component that will extract relevant information from the linker script included in the Teensy toolchain. This enhancement will enable Patcherex to better comprehend the structure of the Teensy 4.1 ELF format. Following this, I plan to investigate the behavior of the firmware loader. In combination with the linker script extractor, this will enable Patcherex to accurately locate and allocate the correct positions for additional code.

@DennyDai DennyDai self-assigned this Mar 3, 2024
@DennyDai
Copy link
Collaborator

DennyDai commented Apr 6, 2024

#25

@DennyDai DennyDai closed this as completed Apr 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants