Skip to content

Commit

Permalink
GUI fixed, long description for pypi
Browse files Browse the repository at this point in the history
  • Loading branch information
Seva Alekseyev committed Feb 7, 2020
1 parent 9a00e42 commit fac0a2e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 24 deletions.
23 changes: 8 additions & 15 deletions dwex/__main__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import sys, os, io, platform
from PyQt5.QtCore import Qt, QAbstractItemModel, QAbstractTableModel, QModelIndex, QSettings, QUrl
from PyQt5.QtCore import Qt, QModelIndex, QSettings, QUrl
from PyQt5.QtGui import QFontMetrics, QKeySequence, QDesktopServices
from PyQt5.QtWidgets import *
from .die import DIETableModel
from .formats import read_dwarf
from .tree import DWARFTreeModel, has_code_location
from .scriptdlg import ScriptDlg

version=(0,53)
version=(0,54)

# TODO:
# Low level raw bytes for expressions in location lists
# Autotest on corpus
# What else is section_offset?
# const_value as FORM_block1: an array of 4 bytes, found in iOS/4.69.8/ARMv7/DecompItem.mm
# Test back-forward mouse buttons
# On MacOS, start without a main window, instead show the Open dialog
# What's the deal with DW_AT_entry_pc? Find, check with readelf - found in \\mac\seva\quincy\3.42\Jishop.app.dSYM:ARMv6 under YarxiCE.cpp under inlined_subroutine at '0xed9'
# Reproduce the data4 in const_value (not a location), make a unit test

#-----------------------------------------------------------------
Expand All @@ -27,7 +25,6 @@
class TheWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.wait_level = 0
self.in_tree_nav = False
self.font_metrics = QFontMetrics(QApplication.font())

Expand Down Expand Up @@ -483,12 +480,13 @@ def on_view_prefix(self, checked):
self.refresh_details()

# Checkmark toggling is handled by the framework
def on_view_lowlevel(self, checked):
def on_view_lowlevel(self, checked):
self.lowlevel = checked
self.sett.setValue('General/LowLevel', self.lowlevel)
if self.die_model:
self.die_model.set_lowlevel(checked)
self.refresh_details()
new_sel = self.die_model.set_lowlevel(checked, self.die_table.currentIndex())
if new_sel:
self.die_table.setCurrentIndex(new_sel)

def on_view_hex(self, checked):
self.hex = checked
Expand Down Expand Up @@ -554,15 +552,10 @@ def on_homepage(self):

# Doesn't quite work for the delay on tree expansion :(
def start_wait(self):
if self.wait_level == 0:
self.setCursor(Qt.WaitCursor)
self.wait_level += 1
QApplication.setOverrideCursor(Qt.WaitCursor)

def end_wait(self):
if self.wait_level > 0:
self.wait_level -= 1
if self.wait_level == 0:
self.setCursor(Qt.ArrowCursor)
QApplication.restoreOverrideCursor()

def main():
if sys.settrace is None: # Lame way to detect a debugger
Expand Down
32 changes: 26 additions & 6 deletions dwex/die.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ def format_value(self, attr):
if isinstance(val, bytes):
if form == 'DW_FORM_strp':
return val.decode('utf-8', errors='ignore')
elif val == b'':
elif val == b'': # What's a good value for a blank blob?
return '[]'
else:
return val.hex()
return ' '.join("%02x" % b for b in val) # Something like "01 ff 33 55"
elif form == 'DW_FORM_addr' and isinstance(val, int):
return hex(val)
elif form == 'DW_FORM_flag_present':
Expand All @@ -173,7 +173,7 @@ def format_value(self, attr):
elif key == 'DW_AT_stmt_list':
return 'LNP at 0x%x' % val
else:
return hex(val) if isinstance(val, int) and self.hex else str(attr.raw_value)
return hex(val) if self.hex and isinstance(val, int) else str(val)

def format_form(self, form):
return form if self.prefix or not str(form).startswith('DW_FORM_') else form[8:]
Expand All @@ -200,20 +200,31 @@ def set_prefix(self, prefix):
if self._exprdumper:
self._exprdumper.set_prefix(prefix)

def set_lowlevel(self, lowlevel):
# Index is the current selected index
# Returns the new selected index, if there was one
def set_lowlevel(self, lowlevel, index):
if lowlevel != self.lowlevel:
self.lowlevel = lowlevel
self.headers = _ll_headers if self.lowlevel else _noll_headers
new_index = None
if lowlevel:
self.beginInsertColumns(QModelIndex(), 2, 3)
self.endInsertColumns()
self.meta_count = 2
self.rowsInserted.emit(QModelIndex(), 0, self.meta_count - 1)
if index.isValid(): # Shift the selection two down
new_index = self.createIndex(index.row() + 2, 0)
else:
self.beginRemoveColumns(QModelIndex(), 2, 3)
self.endRemoveColumns()
self.rowsRemoved.emit(QModelIndex(), 0, self.meta_count - 1)
self.meta_count = 0
if index.isValid() and index.row() >= 2: # Shift the selection two down
new_index = self.createIndex(index.row() - 2, 0)
else:
new_index = QModelIndex() # Select none
return new_index


def set_hex(self, hex):
if hex != self.hex:
Expand Down Expand Up @@ -244,13 +255,22 @@ def get_attribute_details(self, index):
return GenericTableModel(("Start offset", "End offset"),
((hex(cu_base + r.begin_offset), hex(cu_base + r.end_offset)) for r in ranges))
elif LocationParser.attribute_has_location(attr, self.die.cu['version']):
# Expression is a list of ints
ll = self.parse_location(attr)
if isinstance(ll, LocationExpr):
return GenericTableModel(("Command",), ((cmd,) for cmd in self._exprdumper.dump(ll.loc_expr)))
else:
cu_base = get_cu_base(self.die)
return GenericTableModel(("Start offset", "End offset", "Expression"),
((hex(cu_base + l.begin_offset), hex(cu_base + l.end_offset), '; '.join(self._exprdumper.dump(l.loc_expr))) for l in ll))
if self.lowlevel:
headers = ("Start offset", "End offset", "Expr bytes", "Expression")
values = ((hex(cu_base + l.begin_offset),
hex(cu_base + l.end_offset),
' '.join("%02x" % b for b in l.loc_expr),
'; '.join(self._exprdumper.dump(l.loc_expr))) for l in ll)
else:
headers = ("Start offset", "End offset", "Expression")
values = ((hex(cu_base + l.begin_offset), hex(cu_base + l.end_offset), '; '.join(self._exprdumper.dump(l.loc_expr))) for l in ll)
return GenericTableModel(headers, values)
elif key == 'DW_AT_stmt_list':
if self.die.cu._lineprogram is None:
self.die.cu._lineprogram = self.die.dwarfinfo.line_program_for_CU(self.die.cu)
Expand Down
13 changes: 10 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,16 @@ def run(self):
if platform.system() == 'Windows':
create_shortcut()

# Pull the long desc from the readme
try:
with open(path.join(path.abspath(path.dirname(__file__)), 'README.md')) as f:
long_desc = f.read()
except:
long_desc = "GUI viewer for DWARF debug information"

setup(
name='dwex',
version='0.53',
version='0.54',
packages=['dwex',
'dwex.dwex_elftools',
'dwex.dwex_elftools.elf',
Expand All @@ -51,8 +58,8 @@ def run(self):
author="Seva Alekseyev",
author_email="sevaa@sprynet.com",
description="GUI viewer for DWARF debug information",
long_description="GUI viewer for DWARF debug information",
long_description_content_type="text/plain",
long_description=long_desc,
long_description_content_type="text/markdown",
python_requires=">=3.5",
setup_requires=[],
install_requires=['PyQt5'],
Expand Down

0 comments on commit fac0a2e

Please sign in to comment.