Skip to content

Commit

Permalink
Support for XC16/PIC phantom bytes (#522)
Browse files Browse the repository at this point in the history
* Support for XC16/PIC phantom bytes

* Typo
  • Loading branch information
sevaa authored Dec 8, 2023
1 parent 596b065 commit 47eea55
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
25 changes: 21 additions & 4 deletions elftools/elf/elffile.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,22 +784,28 @@ def _read_dwarf_section(self, section, relocate_dwarf_sections):
""" Read the contents of a DWARF section from the stream and return a
DebugSectionDescriptor. Apply relocations if asked to.
"""
phantom_bytes = self.has_phantom_bytes()
# The section data is read into a new stream, for processing
section_stream = BytesIO()
section_stream.write(section.data())
section_data = section.data()
section_stream.write(section_data[::2] if phantom_bytes else section_data)

if relocate_dwarf_sections:
reloc_handler = RelocationHandler(self)
reloc_section = reloc_handler.find_relocations_for_section(section)
if reloc_section is not None:
reloc_handler.apply_section_relocations(
section_stream, reloc_section)
if phantom_bytes:
# No guidance how should the relocation work - before or after the odd byte skip
raise ELFParseError("This binary has relocations in the DWARF sections, currently not supported.")
else:
reloc_handler.apply_section_relocations(
section_stream, reloc_section)

return DebugSectionDescriptor(
stream=section_stream,
name=section.name,
global_offset=section['sh_offset'],
size=section.data_size,
size=section.data_size//2 if phantom_bytes else section.data_size,
address=section['sh_addr'])

@staticmethod
Expand Down Expand Up @@ -845,3 +851,14 @@ def __enter__(self):

def __exit__(self, type, value, traceback):
self.close()

def has_phantom_bytes(self):
"""The XC16 compiler for the PIC microcontrollers emits DWARF where all odd bytes in all DWARF sections
are to be discarded ("phantom").
We don't know where does the phantom byte discarding fit into the usual chain of section content transforms.
There are no XC16/PIC binaries in the corpus with relocations against DWARF, and the DWARF section compression
seems to be unsupported by XC16.
"""
# Vendor flag EF_PIC30_NO_PHANTOM_BYTE=0x80000000: clear means phantom bytes are present
return self['e_machine'] == 'EM_DSPIC30F' and (self['e_flags'] & 0x80000000) == 0
26 changes: 26 additions & 0 deletions test/test_dwarf_phantombytes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#------------------------------------------------------------------------------
# elftools tests
#
# Seva Alekseyev ([email protected])
# This code is in the public domain
#------------------------------------------------------------------------------

import unittest
import os, sys, io

from elftools.elf.elffile import ELFFile

class TestPhantomBytes(unittest.TestCase):
# Prior to 11/17/2023, trying to get DWARF from binaries built by
# the XC16 compiler for PIC microcontrollers would crash
def _test_file(self, filename):
filepath = os.path.join('test', 'testfiles_for_unittests', filename)
with open(filepath, 'rb') as f:
elffile = ELFFile(f)
self.assertTrue(elffile.has_phantom_bytes())
dwarfinfo = elffile.get_dwarf_info()
for CU in dwarfinfo.iter_CUs():
self.assertEqual(CU.get_top_DIE().tag, 'DW_TAG_compile_unit')

def test_main(self):
self._test_file('dwarf_phantombytes.elf')
Binary file not shown.

0 comments on commit 47eea55

Please sign in to comment.