Multiple issues in firmware symbolizer tool

Summary

firmware_symbolizer.py that comes with the Playdate SDK ($PLAYDATE_SDK_PATH/bin/firmware_symbolizer.py) has two issues that are nice to be addressed:

Issue 1

The command that this script calls doesn't wrap the arguments to be passed to arm-none-eabi-addr2line, causing a file not found error when trying to decode the crash log.

Issue 2

On Windows, this script crashes because The system cannot find the path specified.
This is because the path to the tool is hardcoded.

Repro steps

  1. Make Playdate (PD) crash (preferably with e0) one way or another.
  2. Put PD into data disk mode.
  3. Extract crashlog.txt.
  4. Set up firmware_symbolizer.py.
    $ pip3 install click
    
  5. Place your ELF symbol file to a path that contains a whitespace (0x20).
  6. Try to decode the crash log.
    $ python3 firmware_symbolizer.py /path/to/crashlog.txt "/path/to/elf/containing space/game.elf"
    

Expected behaviour

The script correctly associates the address with the symbol, if possible.

Actual behaviour

If the toolchain exists at the hardcoded path

The script crashes at this line - firmware_symbolizer.py:L34-35:

cmd = f"/usr/local/playdate/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-addr2line -f -i -p -e {elf} 0x{pc} 0x{lr}"
stack = subprocess.check_output(cmd, shell=True).decode('ASCII')

...saying that arm-none-eabi-addr2line not being able to find /path/to/elf/containing, instead of the full path to the ELF file.

If the toolchain doesn't exist in an expected path

The script crashes at subprocess.check_output because the command cannot be found.

Suggested fix

- cmd = f"/usr/local/playdate/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-addr2line -f -i -p -e {elf} 0x{pc} 0x{lr}"
+ cmd = f"arm-none-eabi-addr2line -f -i -p -e \"{elf}\" 0x{pc} 0x{lr}"
  stack = subprocess.check_output(cmd, shell=True).decode('ASCII')
  1. Quote the ELF path.
  2. Directly call arm-none-eabi-addr2line.
    Since ARM GCC toolchain should already be in the computer's PATH as long as we follow the instruction, we could just call it directly and the script should become OS-agnostic since subprocess.check_output inherits the environment variables present in the terminal session.

Thanks for the feedback. I'll add this to our issue list.

1 Like