Skip to content

Commit 345e788

Browse files
author
Seva Alekseyev
committed
Fix for 1516: no sibbos on ELF/PPC
1 parent a80df14 commit 345e788

File tree

4 files changed

+68
-18
lines changed

4 files changed

+68
-18
lines changed

dwex/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from .treedlg import TreeDlg
2020

2121
# Sync with version in setup.py
22-
version = (4, 54)
22+
version = (4, 55)
2323
the_app = None
2424

2525
# TODO:

dwex/formats.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ class FormatError(Exception):
1313
def __init__(self, s):
1414
Exception.__init__(self, s)
1515

16+
def decorate_di(di, f, a, sa):
17+
di._format = f
18+
di._arch_code = a
19+
di._start_address = sa
20+
di._frames = None
21+
di._use_siblings = not(f in (0, 4) and a in ("EM_PPC", 'EM_PPC64'))
22+
1623
def read_pe(filename):
1724
from filebytes.pe import PE, IMAGE_FILE_MACHINE, BinaryError
1825
import struct, zlib
@@ -76,9 +83,7 @@ def read_section(name, is_compressed, section, virtual_size, raw_size):
7683
gnu_debugaltlink_sec = data.get('.gnu_debugaltlink'),
7784
debug_types_sec = data.get('.debug_types')
7885
)
79-
di._format = 2
80-
di._arch_code = machine
81-
di._start_address = pefile.imageNtHeaders.header.OptionalHeader.ImageBase
86+
decorate_di(di, 2, machine, pefile.imageNtHeaders.header.OptionalHeader.ImageBase)
8287
di._frames = None
8388
return di
8489
except BinaryError as err:
@@ -328,14 +333,11 @@ def string_at(off):
328333
gnu_debugaltlink_sec = data.get('__gnu_debugaltlink'),
329334
debug_types_sec = data.get('__debug_types'),
330335
)
336+
text_cmd = next((cmd for cmd in macho.loadCommands if cmd.header.cmd in (LC.SEGMENT, LC.SEGMENT_64) and cmd.name == "__TEXT"), False)
337+
decorate_di(di, 1, macho_arch_code(macho), text_cmd.header.vmaddr if text_cmd else 0)
331338
di._unwind_sec = sections.get('__unwind_info') # VERY unlikely to be None
332-
di._format = 1 # Will be adjusted later if Mach-O within A within fat Mach-O
333-
di._arch_code = macho_arch_code(macho)
334339
di._slice_code = slice_code
335340
di._uuid = uuid
336-
text_cmd = next((cmd for cmd in macho.loadCommands if cmd.header.cmd in (LC.SEGMENT, LC.SEGMENT_64) and cmd.name == "__TEXT"), False)
337-
di._start_address = text_cmd.header.vmaddr if text_cmd else 0
338-
di._frames = None
339341
di._has_exec = False
340342
return di
341343

@@ -495,10 +497,7 @@ def read_wasm(file):
495497
gnu_debugaltlink_sec = None,
496498
debug_types_sec = data.get('.debug_types')
497499
)
498-
di._format = 3
499-
di._arch_code = None #N/A
500-
di._start_address = 0
501-
di._frames = None
500+
decorate_di(di, 3, None, 0)
502501
return di
503502

504503
# Filename is only needed for supplemental DWARF resolution
@@ -519,10 +518,7 @@ def read_elf(file, filename):
519518
di = parse_dwarf1(elffile)
520519

521520
if di:
522-
di._format = 0
523-
di._start_address = start_address
524-
di._arch_code = elffile.header.e_machine
525-
di._frames = None
521+
decorate_di(di, 0, elffile.header.e_machine, start_address)
526522
return di
527523

528524
###########################################################################

dwex/patch.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,60 @@ def _init_dispatch_table(structs):
127127
return dt
128128
elftools.dwarf.dwarf_expr._init_dispatch_table = _init_dispatch_table
129129

130+
# Fix for 1516: ignore DW_AT_sibling for child enumeration on ELF/PPC
131+
def iter_DIE_children(self, die):
132+
""" Given a DIE, yields either its children, without null DIE list
133+
terminator, or nothing, if that DIE has no children.
134+
135+
The null DIE terminator is saved in that DIE when iteration ended.
136+
"""
137+
if not die.has_children:
138+
return
139+
140+
# `cur_offset` tracks the stream offset of the next DIE to yield
141+
# as we iterate over our children,
142+
cur_offset = die.offset + die.size
143+
144+
while True:
145+
child = self._get_cached_DIE(cur_offset)
146+
147+
child.set_parent(die)
148+
149+
if child.is_null():
150+
die._terminator = child
151+
return
152+
153+
yield child
154+
155+
if not child.has_children:
156+
cur_offset += child.size
157+
elif "DW_AT_sibling" in child.attributes and self.dwarfinfo._use_siblings:
158+
sibling = child.attributes["DW_AT_sibling"]
159+
if sibling.form in ('DW_FORM_ref1', 'DW_FORM_ref2',
160+
'DW_FORM_ref4', 'DW_FORM_ref8',
161+
'DW_FORM_ref', 'DW_FORM_ref_udata'):
162+
cur_offset = sibling.value + self.cu_offset
163+
elif sibling.form == 'DW_FORM_ref_addr':
164+
cur_offset = sibling.value
165+
else:
166+
raise NotImplementedError('sibling in form %s' % sibling.form)
167+
else:
168+
# If no DW_AT_sibling attribute is provided by the producer
169+
# then the whole child subtree must be parsed to find its next
170+
# sibling. There is one zero byte representing null DIE
171+
# terminating children list. It is used to locate child subtree
172+
# bounds.
173+
174+
# If children are not parsed yet, this instruction will manage
175+
# to recursive call of this function which will result in
176+
# setting of `_terminator` attribute of the `child`.
177+
if child._terminator is None:
178+
for _ in self.iter_DIE_children(child):
179+
pass
180+
181+
cur_offset = child._terminator.offset + child._terminator.size
182+
elftools.dwarf.compileunit.CompileUnit.iter_DIE_children = iter_DIE_children
183+
130184
# Short out import directory parsing for now
131185
filebytes.pe.PE._parseDataDirectory = lambda self,a,b,c: None
132186

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def run(self):
123123

124124
setup(
125125
name='dwex',
126-
version='4.54', # Sync with version in __main__
126+
version='4.55', # Sync with version in __main__
127127
packages=['dwex'],
128128
url="https://github.com/sevaa/dwex/",
129129
entry_points={"gui_scripts": ["dwex = dwex.__main__:main"]},

0 commit comments

Comments
 (0)