Skip to content

Commit

Permalink
Aranges jump to CU
Browse files Browse the repository at this point in the history
  • Loading branch information
sevaa committed Aug 30, 2024
1 parent 47eb4b7 commit e1da8d2
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 42 deletions.
10 changes: 8 additions & 2 deletions dwex/__main__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from bisect import bisect_left
import sys, os
from PyQt6.QtCore import Qt, QModelIndex, QSettings, QUrl, QEvent
from PyQt6.QtGui import QFontMetrics, QDesktopServices, QWindow
Expand Down Expand Up @@ -742,8 +743,13 @@ def on_localsat(self):
def on_aranges(self):
ara = self.dwarfinfo.get_aranges()
if ara:
ArangesDlg(self, ara, self.dwarfinfo).exec()
# TODO: navigate to CU
dlg = ArangesDlg(self, ara, self.dwarfinfo)
if dlg.exec() == QDialog.DialogCode.Accepted and dlg.selected_cu_offset is not None:
di = self.dwarfinfo
i = bisect_left(di._CU_offsets, dlg.selected_cu_offset)
if i < len(di._CU_offsets) and di._CU_offsets[i] == dlg.selected_cu_offset:
die = di._unsorted_CUs[i].get_top_DIE()
self.the_tree.setCurrentIndex(self.tree_model.index_for_die(die))
else:
QMessageBox(QMessageBox.Icon.Warning, "DWARF Explorer", "This binary does not have an aranges section.",
QMessageBox.StandardButton.Ok, self).show()
Expand Down
34 changes: 25 additions & 9 deletions dwex/aranges.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from PyQt6.QtCore import Qt, QAbstractTableModel
from PyQt6.QtWidgets import *

from .dwarfutil import safe_DIE_name
from .dwarfutil import top_die_file_name

headers = ["Start address", "Length", 'CU offset', 'Source name']

Expand Down Expand Up @@ -35,28 +35,44 @@ def data(self, index, role):
return hex(entry.info_offset)
elif col == 3:
cu = self.dwarfinfo.get_CU_at(entry.info_offset)
return safe_DIE_name(cu.get_top_DIE(), '?')
return top_die_file_name(cu.get_top_DIE())

######################################################################################

# TODO: sort by header click

class ArangesDlg(QDialog):
def __init__(self, win, ara, di):
QDialog.__init__(self, win, Qt.WindowType.Dialog)
self.resize(500, 400)
self.selected_cu_offset = False
self.resize(500, 500)
ly = QVBoxLayout()

self.the_table = QTableView()
self.the_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.the_table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.the_table.setModel(AraModel(ara, di))
# self.the_table.doubleClicked.connect(self.on_dclick)
self.the_table.selectionModel().currentChanged.connect(self.on_sel)
self.the_table.doubleClicked.connect(self.navigate_to_index)
self.the_table.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeMode.ResizeToContents)
ly.addWidget(self.the_table)

buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close, Qt.Orientation.Horizontal, self)
#self.nav_bu = QPushButton("Navigate", self)
#self.nav_bu.clicked.connect(self.on_navigate)
#self.nav_bu.setEnabled(False)
#buttons.addButton(self.nav_bu, QDialogButtonBox.ButtonRole.ApplyRole)
self.nav_bu = QPushButton("Navigate", self)
self.nav_bu.clicked.connect(lambda: self.navigate_to_index(self.the_table.currentIndex()))
self.nav_bu.setEnabled(False)
buttons.addButton(self.nav_bu, QDialogButtonBox.ButtonRole.ApplyRole)
buttons.accepted.connect(self.reject)
buttons.rejected.connect(self.reject)
ly.addWidget(buttons)

self.setWindowTitle('Aranges')
self.setLayout(ly)
self.setLayout(ly)

def on_sel(self, index, prev = None):
self.nav_bu.setEnabled(index.isValid())

def navigate_to_index(self, index):
row = index.row()
self.selected_cu_offset = self.the_table.model().entries[row].info_offset
self.done(QDialog.DialogCode.Accepted)
22 changes: 22 additions & 0 deletions dwex/dwarfutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,28 @@ def is_block(form):
def DIE_name(die):
return die.attributes['DW_AT_name'].value.decode('utf-8', errors='ignore')

# Supports both / and \ - current system separator might not match the system the file came from
# so os.path.basename won't do
def strip_path(filename):
p = filename.rfind("/")
pbsl = filename.rfind("\\")
if pbsl >= 0 and (p < 0 or pbsl > p):
p = pbsl
return filename[p+1:] if p >= 0 else filename

def top_die_file_name(die, Default = 'N/A'):
if 'DW_AT_name' in die.attributes:
source_name = die.attributes['DW_AT_name'].value.decode('utf-8', errors='ignore')
return strip_path(source_name)
elif 'DW_AT_decl_file' in die.attributes:
val = die.attributes['DW_AT_decl_file'].value
if val > 0:
if die.cu._lineprogram is None:
die.cu._lineprogram = die.dwarfinfo.line_program_for_CU(die.cu)
delta = 1 if die.cu.version < 5 else 0
return strip_path(die.cu._lineprogram.header.file_entry[val-delta].name.decode('utf-8', errors='ignore'))
return Default

def safe_DIE_name(die, default = ''):
return die.attributes['DW_AT_name'].value.decode('utf-8', errors='ignore') if 'DW_AT_name' in die.attributes else default

Expand Down
2 changes: 2 additions & 0 deletions dwex/frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,14 @@ def __init__(self, win, cfi, di, regnames):
top_pane.addWidget(w)

entries.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
entries.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
top_pane.addWidget(entries)
w = QWidget()
w.setLayout(top_pane)
spl.addWidget(w)

details.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
details.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
#details.doubleClicked.connect(win.on_attribute_dclick)
bottom_pane = QVBoxLayout()
bottom_pane.setContentsMargins(0, 0, 0, 0)
Expand Down
16 changes: 7 additions & 9 deletions dwex/locals.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ def __init__(self, win):
def reset(cl, di):
cl._last_start_address = di._start_address

#############################################################################

class LocalsDlg(LoadedModuleDlgBase):
_last_address = '' # Stored as string to allow for blank

Expand Down Expand Up @@ -126,12 +128,13 @@ def __init__(self, win, di, prefix, regnames, hexadecimal):

self.locals = QTableView()
self.locals.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.locals.doubleClicked.connect(self.on_dclick)
self.locals.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.locals.doubleClicked.connect(self.navigate_to_index)
ly.addWidget(self.locals)

buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Close, Qt.Orientation.Horizontal, self)
self.nav_bu = QPushButton("Navigate", self)
self.nav_bu.clicked.connect(self.on_navigate)
self.nav_bu.clicked.connect(lambda: self.navigate_to_index(self.locals.currentIndex()))
self.nav_bu.setEnabled(False)
buttons.addButton(self.nav_bu, QDialogButtonBox.ButtonRole.ApplyRole)
buttons.accepted.connect(self.reject)
Expand Down Expand Up @@ -224,16 +227,11 @@ def on_check(self): #TODO: relocate absolute addresses in expressions
except Exception as exc:
QMessageBox(QMessageBox.Icon.Critical, "DWARF Explorer",
"Unexpected error while analysing the debug information.", QMessageBox.StandardButton.Ok, self).show()

def on_navigate(self):
row = self.locals.currentIndex().row()
self.selected_die = self.locals.model().data[row][3]
self.done(QDialog.DialogCode.Accepted)

def on_dclick(self, index):
def navigate_to_index(self, index):
row = index.row()
self.selected_die = self.locals.model().data[row][3]
self.done(QDialog.DialogCode.Accepted)
self.done(QDialog.DialogCode.Accepted)

def on_sel(self, index, prev = None):
self.nav_bu.setEnabled(index.isValid())
Expand Down
23 changes: 1 addition & 22 deletions dwex/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,7 @@
from PyQt6.QtCore import Qt, QAbstractItemModel, QModelIndex
from PyQt6.QtGui import QFont, QFontInfo, QBrush
from PyQt6.QtWidgets import QApplication, QMessageBox
from .dwarfutil import has_code_location, safe_DIE_name

# Supports both / and \ - current system separator might not match the system the file came from
# so os.path.basename won't do
def strip_path(filename):
p = filename.rfind("/")
pbsl = filename.rfind("\\")
if pbsl >= 0 and (p < 0 or pbsl > p):
p = pbsl
return filename[p+1:] if p >= 0 else filename

def top_die_file_name(die):
if 'DW_AT_name' in die.attributes:
source_name = die.attributes['DW_AT_name'].value.decode('utf-8', errors='ignore')
return strip_path(source_name)
elif 'DW_AT_decl_file' in die.attributes:
val = die.attributes['DW_AT_decl_file'].value
if val > 0:
if die.cu._lineprogram is None:
die.cu._lineprogram = die.dwarfinfo.line_program_for_CU(die.cu)
return strip_path(die.cu._lineprogram.header.file_entry[val-1].name.decode('utf-8', errors='ignore'))
return "(no name)"
from .dwarfutil import has_code_location, safe_DIE_name, top_die_file_name

def cu_sort_key(cu):
return top_die_file_name(cu.get_top_DIE()).lower()
Expand Down
3 changes: 3 additions & 0 deletions dwex/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ def setup_menu(win):
win.localsat_menuitem = ana_menu.addAction("Locals at address...")
win.localsat_menuitem.setEnabled(False)
win.localsat_menuitem.triggered.connect(win.on_localsat)
ana_menu.addSeparator()
win.aranges_menuitem = ana_menu.addAction("Aranges...")
win.aranges_menuitem.setEnabled(False)
win.aranges_menuitem.triggered.connect(win.on_aranges)
Expand Down Expand Up @@ -236,6 +237,7 @@ def setup_ui(win):
rpane = QSplitter(Qt.Orientation.Vertical)
die_table = win.die_table = QTableView()
die_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
die_table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
die_table.doubleClicked.connect(win.on_attribute_dclick)
rpane.addWidget(die_table)

Expand All @@ -246,6 +248,7 @@ def setup_ui(win):
rbpane.addWidget(details_warning)
details_table = win.details_table = QTableView()
details_table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
details_table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
rbpane.addWidget(details_table)
rbp = QWidget()
rbp.setLayout(rbpane)
Expand Down

0 comments on commit e1da8d2

Please sign in to comment.