mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-04-17 13:51:21 +00:00

*** to conform to clang-format’s LLVM style. This kind of mass change has *** two obvious implications: Firstly, merging this particular commit into a downstream fork may be a huge effort. Alternatively, it may be worth merging all changes up to this commit, performing the same reformatting operation locally, and then discarding the merge for this particular commit. The commands used to accomplish this reformatting were as follows (with current working directory as the root of the repository): find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} + find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ; The version of clang-format used was 3.9.0, and autopep8 was 1.2.4. Secondly, “blame” style tools will generally point to this commit instead of a meaningful prior commit. There are alternatives available that will attempt to look through this change and find the appropriate prior commit. YMMV. llvm-svn: 280751
614 lines
20 KiB
Python
614 lines
20 KiB
Python
#!/usr/bin/python
|
|
|
|
import lldb
|
|
import shlex
|
|
import sys
|
|
from Tkinter import *
|
|
import ttk
|
|
|
|
|
|
class ValueTreeItemDelegate(object):
|
|
|
|
def __init__(self, value):
|
|
self.value = value
|
|
|
|
def get_item_dictionary(self):
|
|
name = self.value.name
|
|
if name is None:
|
|
name = ''
|
|
typename = self.value.type
|
|
if typename is None:
|
|
typename = ''
|
|
value = self.value.value
|
|
if value is None:
|
|
value = ''
|
|
summary = self.value.summary
|
|
if summary is None:
|
|
summary = ''
|
|
has_children = self.value.MightHaveChildren()
|
|
return {'#0': name,
|
|
'typename': typename,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': has_children,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
for i in range(self.value.num_children):
|
|
item_delegate = ValueTreeItemDelegate(
|
|
self.value.GetChildAtIndex(i))
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class FrameTreeItemDelegate(object):
|
|
|
|
def __init__(self, frame):
|
|
self.frame = frame
|
|
|
|
def get_item_dictionary(self):
|
|
id = self.frame.GetFrameID()
|
|
name = 'frame #%u' % (id)
|
|
value = '0x%16.16x' % (self.frame.GetPC())
|
|
stream = lldb.SBStream()
|
|
self.frame.GetDescription(stream)
|
|
summary = stream.GetData().split("`")[1]
|
|
return {
|
|
'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': self.frame.GetVariables(
|
|
True,
|
|
True,
|
|
True,
|
|
True).GetSize() > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
variables = self.frame.GetVariables(True, True, True, True)
|
|
n = variables.GetSize()
|
|
for i in range(n):
|
|
item_delegate = ValueTreeItemDelegate(variables[i])
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class ThreadTreeItemDelegate(object):
|
|
|
|
def __init__(self, thread):
|
|
self.thread = thread
|
|
|
|
def get_item_dictionary(self):
|
|
num_frames = self.thread.GetNumFrames()
|
|
name = 'thread #%u' % (self.thread.GetIndexID())
|
|
value = '0x%x' % (self.thread.GetThreadID())
|
|
summary = '%u frames' % (num_frames)
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': num_frames > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
for frame in self.thread:
|
|
item_delegate = FrameTreeItemDelegate(frame)
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class ProcessTreeItemDelegate(object):
|
|
|
|
def __init__(self, process):
|
|
self.process = process
|
|
|
|
def get_item_dictionary(self):
|
|
id = self.process.GetProcessID()
|
|
num_threads = self.process.GetNumThreads()
|
|
value = str(self.process.GetProcessID())
|
|
summary = self.process.target.executable.fullpath
|
|
return {'#0': 'process',
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': num_threads > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
for thread in self.process:
|
|
item_delegate = ThreadTreeItemDelegate(thread)
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class TargetTreeItemDelegate(object):
|
|
|
|
def __init__(self, target):
|
|
self.target = target
|
|
|
|
def get_item_dictionary(self):
|
|
value = str(self.target.triple)
|
|
summary = self.target.executable.fullpath
|
|
return {'#0': 'target',
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': True,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
image_item_delegate = TargetImagesTreeItemDelegate(self.target)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class TargetImagesTreeItemDelegate(object):
|
|
|
|
def __init__(self, target):
|
|
self.target = target
|
|
|
|
def get_item_dictionary(self):
|
|
value = str(self.target.triple)
|
|
summary = self.target.executable.fullpath
|
|
num_modules = self.target.GetNumModules()
|
|
return {'#0': 'images',
|
|
'value': '',
|
|
'summary': '%u images' % num_modules,
|
|
'children': num_modules > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
for i in range(self.target.GetNumModules()):
|
|
module = self.target.GetModuleAtIndex(i)
|
|
image_item_delegate = ModuleTreeItemDelegate(
|
|
self.target, module, i)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class ModuleTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, module, index):
|
|
self.target = target
|
|
self.module = module
|
|
self.index = index
|
|
|
|
def get_item_dictionary(self):
|
|
name = 'module %u' % (self.index)
|
|
value = self.module.file.basename
|
|
summary = self.module.file.dirname
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': True,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
sections_item_delegate = ModuleSectionsTreeItemDelegate(
|
|
self.target, self.module)
|
|
item_dicts.append(sections_item_delegate.get_item_dictionary())
|
|
|
|
symbols_item_delegate = ModuleSymbolsTreeItemDelegate(
|
|
self.target, self.module)
|
|
item_dicts.append(symbols_item_delegate.get_item_dictionary())
|
|
|
|
comp_units_item_delegate = ModuleCompileUnitsTreeItemDelegate(
|
|
self.target, self.module)
|
|
item_dicts.append(comp_units_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class ModuleSectionsTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, module):
|
|
self.target = target
|
|
self.module = module
|
|
|
|
def get_item_dictionary(self):
|
|
name = 'sections'
|
|
value = ''
|
|
summary = '%u sections' % (self.module.GetNumSections())
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': True,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
num_sections = self.module.GetNumSections()
|
|
for i in range(num_sections):
|
|
section = self.module.GetSectionAtIndex(i)
|
|
image_item_delegate = SectionTreeItemDelegate(self.target, section)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class SectionTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, section):
|
|
self.target = target
|
|
self.section = section
|
|
|
|
def get_item_dictionary(self):
|
|
name = self.section.name
|
|
section_load_addr = self.section.GetLoadAddress(self.target)
|
|
if section_load_addr != lldb.LLDB_INVALID_ADDRESS:
|
|
value = '0x%16.16x' % (section_load_addr)
|
|
else:
|
|
value = '0x%16.16x *' % (self.section.file_addr)
|
|
summary = ''
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': self.section.GetNumSubSections() > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
num_sections = self.section.GetNumSubSections()
|
|
for i in range(num_sections):
|
|
section = self.section.GetSubSectionAtIndex(i)
|
|
image_item_delegate = SectionTreeItemDelegate(self.target, section)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class ModuleCompileUnitsTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, module):
|
|
self.target = target
|
|
self.module = module
|
|
|
|
def get_item_dictionary(self):
|
|
name = 'compile units'
|
|
value = ''
|
|
summary = '%u compile units' % (self.module.GetNumSections())
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': self.module.GetNumCompileUnits() > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
num_cus = self.module.GetNumCompileUnits()
|
|
for i in range(num_cus):
|
|
cu = self.module.GetCompileUnitAtIndex(i)
|
|
image_item_delegate = CompileUnitTreeItemDelegate(self.target, cu)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class CompileUnitTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, cu):
|
|
self.target = target
|
|
self.cu = cu
|
|
|
|
def get_item_dictionary(self):
|
|
name = self.cu.GetFileSpec().basename
|
|
value = ''
|
|
num_lines = self.cu.GetNumLineEntries()
|
|
summary = ''
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': num_lines > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
item_delegate = LineTableTreeItemDelegate(self.target, self.cu)
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class LineTableTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, cu):
|
|
self.target = target
|
|
self.cu = cu
|
|
|
|
def get_item_dictionary(self):
|
|
name = 'line table'
|
|
value = ''
|
|
num_lines = self.cu.GetNumLineEntries()
|
|
summary = '%u line entries' % (num_lines)
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': num_lines > 0,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
num_lines = self.cu.GetNumLineEntries()
|
|
for i in range(num_lines):
|
|
line_entry = self.cu.GetLineEntryAtIndex(i)
|
|
item_delegate = LineEntryTreeItemDelegate(
|
|
self.target, line_entry, i)
|
|
item_dicts.append(item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class LineEntryTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, line_entry, index):
|
|
self.target = target
|
|
self.line_entry = line_entry
|
|
self.index = index
|
|
|
|
def get_item_dictionary(self):
|
|
name = str(self.index)
|
|
address = self.line_entry.GetStartAddress()
|
|
load_addr = address.GetLoadAddress(self.target)
|
|
if load_addr != lldb.LLDB_INVALID_ADDRESS:
|
|
value = '0x%16.16x' % (load_addr)
|
|
else:
|
|
value = '0x%16.16x *' % (address.file_addr)
|
|
summary = self.line_entry.GetFileSpec().fullpath + ':' + \
|
|
str(self.line_entry.line)
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': False,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
return item_dicts
|
|
|
|
|
|
class InstructionTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, instr):
|
|
self.target = target
|
|
self.instr = instr
|
|
|
|
def get_item_dictionary(self):
|
|
address = self.instr.GetAddress()
|
|
load_addr = address.GetLoadAddress(self.target)
|
|
if load_addr != lldb.LLDB_INVALID_ADDRESS:
|
|
name = '0x%16.16x' % (load_addr)
|
|
else:
|
|
name = '0x%16.16x *' % (address.file_addr)
|
|
value = self.instr.GetMnemonic(
|
|
self.target) + ' ' + self.instr.GetOperands(self.target)
|
|
summary = self.instr.GetComment(self.target)
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': False,
|
|
'tree-item-delegate': self}
|
|
|
|
|
|
class ModuleSymbolsTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, module):
|
|
self.target = target
|
|
self.module = module
|
|
|
|
def get_item_dictionary(self):
|
|
name = 'symbols'
|
|
value = ''
|
|
summary = '%u symbols' % (self.module.GetNumSymbols())
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': True,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
num_symbols = self.module.GetNumSymbols()
|
|
for i in range(num_symbols):
|
|
symbol = self.module.GetSymbolAtIndex(i)
|
|
image_item_delegate = SymbolTreeItemDelegate(
|
|
self.target, symbol, i)
|
|
item_dicts.append(image_item_delegate.get_item_dictionary())
|
|
return item_dicts
|
|
|
|
|
|
class SymbolTreeItemDelegate(object):
|
|
|
|
def __init__(self, target, symbol, index):
|
|
self.target = target
|
|
self.symbol = symbol
|
|
self.index = index
|
|
|
|
def get_item_dictionary(self):
|
|
address = self.symbol.GetStartAddress()
|
|
name = '[%u]' % self.index
|
|
symbol_load_addr = address.GetLoadAddress(self.target)
|
|
if symbol_load_addr != lldb.LLDB_INVALID_ADDRESS:
|
|
value = '0x%16.16x' % (symbol_load_addr)
|
|
else:
|
|
value = '0x%16.16x *' % (address.file_addr)
|
|
summary = self.symbol.name
|
|
return {'#0': name,
|
|
'value': value,
|
|
'summary': summary,
|
|
'children': False,
|
|
'tree-item-delegate': self}
|
|
|
|
def get_child_item_dictionaries(self):
|
|
item_dicts = list()
|
|
return item_dicts
|
|
|
|
|
|
class DelegateTree(ttk.Frame):
|
|
|
|
def __init__(self, column_dicts, delegate, title, name):
|
|
ttk.Frame.__init__(self, name=name)
|
|
self.pack(expand=Y, fill=BOTH)
|
|
self.master.title(title)
|
|
self.delegate = delegate
|
|
self.columns_dicts = column_dicts
|
|
self.item_id_to_item_dict = dict()
|
|
frame = Frame(self)
|
|
frame.pack(side=TOP, fill=BOTH, expand=Y)
|
|
self._create_treeview(frame)
|
|
self._populate_root()
|
|
|
|
def _create_treeview(self, parent):
|
|
frame = ttk.Frame(parent)
|
|
frame.pack(side=TOP, fill=BOTH, expand=Y)
|
|
|
|
column_ids = list()
|
|
for i in range(1, len(self.columns_dicts)):
|
|
column_ids.append(self.columns_dicts[i]['id'])
|
|
# create the tree and scrollbars
|
|
self.tree = ttk.Treeview(columns=column_ids)
|
|
|
|
scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command=self.tree.yview)
|
|
scroll_bar_h = ttk.Scrollbar(
|
|
orient=HORIZONTAL, command=self.tree.xview)
|
|
self.tree['yscroll'] = scroll_bar_v.set
|
|
self.tree['xscroll'] = scroll_bar_h.set
|
|
|
|
# setup column headings and columns properties
|
|
for columns_dict in self.columns_dicts:
|
|
self.tree.heading(
|
|
columns_dict['id'],
|
|
text=columns_dict['text'],
|
|
anchor=columns_dict['anchor'])
|
|
self.tree.column(
|
|
columns_dict['id'],
|
|
stretch=columns_dict['stretch'])
|
|
|
|
# add tree and scrollbars to frame
|
|
self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW)
|
|
scroll_bar_v.grid(in_=frame, row=0, column=1, sticky=NS)
|
|
scroll_bar_h.grid(in_=frame, row=1, column=0, sticky=EW)
|
|
|
|
# set frame resizing priorities
|
|
frame.rowconfigure(0, weight=1)
|
|
frame.columnconfigure(0, weight=1)
|
|
|
|
# action to perform when a node is expanded
|
|
self.tree.bind('<<TreeviewOpen>>', self._update_tree)
|
|
|
|
def insert_items(self, parent_id, item_dicts):
|
|
for item_dict in item_dicts:
|
|
name = None
|
|
values = list()
|
|
first = True
|
|
for columns_dict in self.columns_dicts:
|
|
if first:
|
|
name = item_dict[columns_dict['id']]
|
|
first = False
|
|
else:
|
|
values.append(item_dict[columns_dict['id']])
|
|
item_id = self.tree.insert(parent_id, # root item has an empty name
|
|
END,
|
|
text=name,
|
|
values=values)
|
|
self.item_id_to_item_dict[item_id] = item_dict
|
|
if item_dict['children']:
|
|
self.tree.insert(item_id, END, text='dummy')
|
|
|
|
def _populate_root(self):
|
|
# use current directory as root node
|
|
self.insert_items('', self.delegate.get_child_item_dictionaries())
|
|
|
|
def _update_tree(self, event):
|
|
# user expanded a node - build the related directory
|
|
item_id = self.tree.focus() # the id of the expanded node
|
|
children = self.tree.get_children(item_id)
|
|
if len(children):
|
|
first_child = children[0]
|
|
# if the node only has a 'dummy' child, remove it and
|
|
# build new directory; skip if the node is already
|
|
# populated
|
|
if self.tree.item(first_child, option='text') == 'dummy':
|
|
self.tree.delete(first_child)
|
|
item_dict = self.item_id_to_item_dict[item_id]
|
|
item_dicts = item_dict[
|
|
'tree-item-delegate'].get_child_item_dictionaries()
|
|
self.insert_items(item_id, item_dicts)
|
|
|
|
|
|
@lldb.command("tk-variables")
|
|
def tk_variable_display(debugger, command, result, dict):
|
|
# needed for tree creation in TK library as it uses sys.argv...
|
|
sys.argv = ['tk-variables']
|
|
target = debugger.GetSelectedTarget()
|
|
if not target:
|
|
print >>result, "invalid target"
|
|
return
|
|
process = target.GetProcess()
|
|
if not process:
|
|
print >>result, "invalid process"
|
|
return
|
|
thread = process.GetSelectedThread()
|
|
if not thread:
|
|
print >>result, "invalid thread"
|
|
return
|
|
frame = thread.GetSelectedFrame()
|
|
if not frame:
|
|
print >>result, "invalid frame"
|
|
return
|
|
# Parse command line args
|
|
command_args = shlex.split(command)
|
|
column_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
|
|
{'id': 'typename', 'text': 'Type', 'anchor': W, 'stretch': 0},
|
|
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
|
|
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
|
|
tree = DelegateTree(
|
|
column_dicts,
|
|
FrameTreeItemDelegate(frame),
|
|
'Variables',
|
|
'lldb-tk-variables')
|
|
tree.mainloop()
|
|
|
|
|
|
@lldb.command("tk-process")
|
|
def tk_process_display(debugger, command, result, dict):
|
|
# needed for tree creation in TK library as it uses sys.argv...
|
|
sys.argv = ['tk-process']
|
|
target = debugger.GetSelectedTarget()
|
|
if not target:
|
|
print >>result, "invalid target"
|
|
return
|
|
process = target.GetProcess()
|
|
if not process:
|
|
print >>result, "invalid process"
|
|
return
|
|
# Parse command line args
|
|
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
|
|
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
|
|
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
|
|
command_args = shlex.split(command)
|
|
tree = DelegateTree(
|
|
columnd_dicts,
|
|
ProcessTreeItemDelegate(process),
|
|
'Process',
|
|
'lldb-tk-process')
|
|
tree.mainloop()
|
|
|
|
|
|
@lldb.command("tk-target")
|
|
def tk_target_display(debugger, command, result, dict):
|
|
# needed for tree creation in TK library as it uses sys.argv...
|
|
sys.argv = ['tk-target']
|
|
target = debugger.GetSelectedTarget()
|
|
if not target:
|
|
print >>result, "invalid target"
|
|
return
|
|
# Parse command line args
|
|
columnd_dicts = [{'id': '#0', 'text': 'Name', 'anchor': W, 'stretch': 0},
|
|
{'id': 'value', 'text': 'Value', 'anchor': W, 'stretch': 0},
|
|
{'id': 'summary', 'text': 'Summary', 'anchor': W, 'stretch': 1}]
|
|
command_args = shlex.split(command)
|
|
tree = DelegateTree(
|
|
columnd_dicts,
|
|
TargetTreeItemDelegate(target),
|
|
'Target',
|
|
'lldb-tk-target')
|
|
tree.mainloop()
|