Skip to content

Commit

Permalink
Chasing loclist error
Browse files Browse the repository at this point in the history
  • Loading branch information
sevaa committed Nov 14, 2023
1 parent e976f7b commit 6aefa83
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 36 deletions.
2 changes: 1 addition & 1 deletion dwex/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .locals import LocalsDlg

# Sync with version in setup.py
version = (3, 21)
version = (3, 22)

# TODO:
# On MacOS, start without a main window, instead show the Open dialog
Expand Down
4 changes: 3 additions & 1 deletion dwex/die.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ def format_value(self, attr):
return str(bool(val))
elif LocationParser.attribute_has_location(attr, self.die.cu['version']):
ll = self.parse_location(attr)
if isinstance(ll, LocationExpr):
if ll is None:
return "(parse error - please report at github.com/sevaa/dwex)"
elif isinstance(ll, LocationExpr):
return '; '.join(self.dump_expr(ll.loc_expr))
else:
return "Loc list: 0x%x" % attr.value
Expand Down
2 changes: 1 addition & 1 deletion dwex/formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,6 @@ def get_debug_sections(di):
section_names['gnu_debugaltlink'] = 'gnu_debugaltlink'

# Display name to section object
return {display_name: di.__dict__[field_name]
return {display_name: getattr(di, field_name)
for (display_name, field_name) in section_names.items()
if getattr(di, field_name, False)}
44 changes: 42 additions & 2 deletions dwex/locs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from elftools.dwarf.locationlists import LocationParser, LocationExpr, BaseAddressEntry
from elftools.common.exceptions import ELFParseError
from .details import GenericTableModel
from .dwarfutil import *
from .ranges import lowlevel_v5_tooltips, one_of
Expand All @@ -7,14 +8,53 @@ def parse_location(self, attr):
di = self.die.dwarfinfo
if di._locparser is None:
di._locparser = LocationParser(di.location_lists())
return di._locparser.parse_from_attribute(attr, self.die.cu['version'], die = self.die)
try:
return di._locparser.parse_from_attribute(attr, self.die.cu['version'], die = self.die)
except ELFParseError as exc:
from .__main__ import version
from .crash import report_crash
from inspect import currentframe

die = self.die
header = die.cu.header
dwarf_version = die.cu.header.version
di = die.cu.dwarfinfo
ctxt = {'attr': attr,
'die': die,
'cu_header': header,
'LE': di.config.little_endian,
'dwarf_version': dwarf_version}
try:
if LocationParser._attribute_has_loc_list(attr, self.die.cu['version']):
tb = exc.__traceback__
tracebacks = []
while tb.tb_next:
tracebacks.insert(0, tb) # Innermost in the beginning of the list
tb = tb.tb_next
loc_section = di.debug_loclists_sec if dwarf_version >= 5 else di.debug_loc_sec
if loc_section:
buf = loc_section.stream.getbuffer()
ctxt['loc_section_len'] = len(buf)
if len(tracebacks) > 1 and 'entry_offset' in tracebacks[1].tb_frame.f_locals:
fail_entry_offset = tracebacks[1].tb_frame.f_locals['entry_offset']
ctxt['fail_entry_offset'] = fail_entry_offset
llend = fail_entry_offset + 8*2+2 if fail_entry_offset - attr.value <= 1024 else attr.value + 1024
llbytes = buf[attr.value:llend]
ctxt['llbytes'] = ' '.join("%02x" % b for b in llbytes)
except:
pass

report_crash(exc, tb, version, currentframe(), ctxt)
return None

def show_location(self, attr):
# Expression is a list of ints
# TODO: clickable expression maybe?
# TODO: truncate long expressions?
ll = self.parse_location(attr)
if isinstance(ll, LocationExpr):
if ll is None:
return None
elif isinstance(ll, LocationExpr):
# TODO: low level maybe
# Spell out args?
# Opcode tooltips?
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def run(self):

setup(
name='dwex',
version='3.21', # Sync with version in __main__
version='3.22', # Sync with version in __main__
packages=['dwex'],
url="https://github.com/sevaa/dwex/",
entry_points={"gui_scripts": ["dwex = dwex.__main__:main"]},
Expand Down
48 changes: 18 additions & 30 deletions test/intest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,21 @@
sys.path.insert(1, os.getcwd()) # To make sure dwex resolves to local path
import dwex.__main__

# Hook exceptions all the same
#dwex.__main__.on_exception.prev_exchook = sys.excepthook
#sys.excepthook = dwex.__main__.on_exception

# TODO: stable test file
if len(sys.argv) == 1:
sys.argv = ['dwex', 'samples\\An-2.60.3-j-ARMv7-libyarxi.so']

# Monkeypatch to mess with file contents
old_open_file = dwex.__main__.TheWindow.open_file
def open_file(self, filename, arch = None):
r = old_open_file(self, filename, arch)
buf = self.dwarfinfo.debug_info_sec.stream.getbuffer()
#buf[0x9e900] = 0xff # Bogus abbrev code
#9e81e - subprogram die
#buf[0x9e8ed+3] = 0xff # Bogus offset in AT_type, so that it leads nowhere

# Frame_base, bogus opcode in attr block
#buf[0x9e8f9] = 0x7f
#return r

# Artificial repro for #1572
# DIE on 4790, loclist attr at 479a (data4), originally at 0
buf = self.dwarfinfo.debug_info_sec.stream.getbuffer()
buf[0x479d] = 0xff


dwex.__main__.TheWindow.open_file = open_file

dwex.__main__.main()
def main(debug_crash_reporting, filename, hook_file):
# Do we need to hook exceptions all the same
if debug_crash_reporting:
dwex.__main__.on_exception.prev_exchook = sys.excepthook
sys.excepthook = dwex.__main__.on_exception

if len(sys.argv) == 1:
sys.argv = ['dwex', filename]

# Monkeypatch to mess with file contents
old_open_file = dwex.__main__.TheWindow.open_file
def open_file(self, filename, arch = None):
r = old_open_file(self, filename, arch)
hook_file(self.dwarfinfo)
return r

dwex.__main__.TheWindow.open_file = open_file
dwex.__main__.main()

0 comments on commit 6aefa83

Please sign in to comment.