summaryrefslogtreecommitdiffstats
path: root/lldb/examples/python/lldbtk.py
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/examples/python/lldbtk.py')
-rw-r--r--lldb/examples/python/lldbtk.py260
1 files changed, 260 insertions, 0 deletions
diff --git a/lldb/examples/python/lldbtk.py b/lldb/examples/python/lldbtk.py
new file mode 100644
index 00000000000..6c4dabb24a3
--- /dev/null
+++ b/lldb/examples/python/lldbtk.py
@@ -0,0 +1,260 @@
+#!/usr/bin/python
+
+import lldb
+import shlex
+import sys
+from Tkinter import *
+import ttk
+
+def get_item_dictionary_for_sbvalue(v, include_typename):
+ '''Given an lldb.SBValue, create an item dictionary for that value and return it
+
+ The dictionary must have the following key/value pairs:
+ 'values' - must be a list of string values for each column defined in self.get_column_definitions()
+ 'children' - a boolean value that indicates if an item has children or not
+ '''
+ name = v.name
+ if name is None:
+ name = ''
+ if include_typename:
+ typename = v.type
+ if typename is None:
+ typename = ''
+ value = v.value
+ if value is None:
+ value = ''
+ summary = v.summary
+ if summary is None:
+ summary = ''
+ if include_typename:
+ return { 'values' : [name, typename, value, summary],
+ 'children' : v.MightHaveChildren(),
+ 'type' : 'SBValue',
+ 'object' : v }
+ else:
+ return { 'values' : [name, value, summary],
+ 'children' : v.MightHaveChildren(),
+ 'type' : 'SBValue',
+ 'object' : v }
+
+
+def get_item_dictionary_for_process(process):
+ id = process.GetProcessID()
+ num_threads = process.GetNumThreads()
+ value = str(process.GetProcessID())
+ summary = process.target.executable.fullpath
+ return { 'values' : ['process', value, summary],
+ 'children' : num_threads > 0,
+ 'type' : 'SBProcess',
+ 'object' : process }
+
+def get_item_dictionary_for_thread(thread):
+ num_frames = thread.GetNumFrames()
+ value = '0x%x' % (thread.GetThreadID())
+ summary = '%u frames' % (num_frames)
+ return { 'values' : ['thread #%u' % (thread.GetIndexID()), value, summary],
+ 'children' : num_frames > 0,
+ 'type' : 'SBThread',
+ 'object' : thread }
+
+def get_item_dictionary_for_frame(frame):
+ id = frame.GetFrameID()
+ value = '0x%16.16x' % (frame.GetPC())
+ stream = lldb.SBStream()
+ frame.GetDescription(stream)
+ summary = stream.GetData().split("`")[1]
+ return { 'values' : ['frame #%u' % (id), value, summary],
+ 'children' : frame.GetVariables(True, True, True, True).GetSize() > 0,
+ 'type' : 'SBFrame',
+ 'object' : frame }
+
+class ProcessTreeDelegate(object):
+ def __init__(self, process):
+ self.process = process
+
+ def get_column_definitions(self):
+ '''Return an array of column definition dictionaries'''
+ return [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 },
+ { 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 },
+ { 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]
+
+ def get_item_dictionary(self, sbvalue):
+ '''Given an lldb.SBValue, create an item dictionary for that value and return it
+
+ The dictionary must have the following key/value pairs:
+ 'values' - must be a list of string values for each column defined in self.get_column_definitions()
+ 'children' - a boolean value that indicates if an item has children or not
+ '''
+
+ def get_child_item_dictionaries(self, parent_item_dict):
+ '''Given an lldb.SBValue, create an item dictionary for that value and return it'''
+ item_dicts = list()
+ if parent_item_dict is None:
+ # Create root items if parent_item_dict is None
+ item_dicts.append(get_item_dictionary_for_process(self.process))
+ else:
+ # Get children for a specified item given its item dictionary
+ item_type = parent_item_dict['type']
+ if item_type == 'SBProcess':
+ for thread in parent_item_dict['object']:
+ item_dicts.append(get_item_dictionary_for_thread(thread))
+ elif item_type == 'SBThread':
+ for frame in parent_item_dict['object']:
+ item_dicts.append(get_item_dictionary_for_frame(frame))
+ elif item_type == 'SBFrame':
+ frame = parent_item_dict['object']
+ variables = frame.GetVariables(True, True, True, True)
+ n = variables.GetSize()
+ for i in range(n):
+ item_dicts.append(get_item_dictionary_for_sbvalue(variables[i], False))
+ elif item_type == 'SBValue':
+ sbvalue = parent_item_dict['object']
+ if sbvalue.IsValid():
+ for i in range(sbvalue.num_children):
+ item_dicts.append(get_item_dictionary_for_sbvalue(sbvalue.GetChildAtIndex(i), False))
+ return item_dicts
+
+class VariableTreeDelegate(object):
+ def __init__(self, frame):
+ self.frame = frame
+
+ def get_column_definitions(self):
+ '''Return an array of column definition dictionaries'''
+ return [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 },
+ { 'id' : 'type' , 'text' : 'Type' , 'anchor' : W , 'stretch' : 0 },
+ { 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 },
+ { 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]
+
+ def get_child_item_dictionaries(self, parent_item_dict):
+ '''Given an lldb.SBValue, create an item dictionary for that value and return it'''
+ item_dicts = list()
+ if parent_item_dict is None:
+ # Create root items if parent_item_dict is None
+ variables = self.frame.GetVariables(True, True, True, True)
+ n = variables.GetSize()
+ for i in range(n):
+ item_dicts.append(get_item_dictionary_for_sbvalue(variables[i], True))
+ else:
+ # Get children for a specified item given its item dictionary
+ sbvalue = parent_item_dict['object']
+ if sbvalue.IsValid():
+ for i in range(sbvalue.num_children):
+ item_dicts.append(get_item_dictionary_for_sbvalue(sbvalue.GetChildAtIndex(i), True))
+ return item_dicts
+
+class DelegateTree(ttk.Frame):
+
+ def __init__(self, delegate, title, name):
+ ttk.Frame.__init__(self, name=name)
+ self.pack(expand=Y, fill=BOTH)
+ self.master.title(title)
+ self.delegate = delegate
+ 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)
+
+ columns_dicts = self.delegate.get_column_definitions()
+ column_ids = list()
+ for i in range(1,len(columns_dicts)):
+ column_ids.append(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 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:
+ values = item_dict['values']
+ item_id = self.tree.insert (parent_id, # root item has an empty name
+ END,
+ text=values[0],
+ values=values[1:])
+ 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(None))
+
+ 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_dicts = self.delegate.get_child_item_dictionaries(self.item_id_to_item_dict[item_id])
+ self.insert_items(item_id, item_dicts)
+
+@lldb.command("tk-variables")
+def tk_variable_display(debugger, command, result, dict):
+ sys.argv = ['tk-variables'] # needed for tree creation in TK library as it uses sys.argv...
+ 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)
+
+ tree = DelegateTree(VariableTreeDelegate(frame), 'Variables', 'lldb-tk-variables')
+ tree.mainloop()
+
+@lldb.command("tk-process")
+def tk_process_display(debugger, command, result, dict):
+ sys.argv = ['tk-process'] # needed for tree creation in TK library as it uses sys.argv...
+ 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
+ command_args = shlex.split(command)
+ tree = DelegateTree(ProcessTreeDelegate(process), 'Process', 'lldb-tk-process')
+ tree.mainloop()
+
OpenPOWER on IntegriCloud