> Basic tk-frames and tk-variables tk-process and tk-variables, rather...
On Tue, Sep 23, 2014 at 11:01 AM, Todd Fiala <tfi...@google.com> wrote: > Basic tk-frames and tk-variables functionality seems to be working fine on > Linux FWIW in a couple simple cases I tried. > > -Todd > > On Mon, Sep 22, 2014 at 3:06 PM, Greg Clayton <gclay...@apple.com> wrote: > >> Author: gclayton >> Date: Mon Sep 22 17:06:41 2014 >> New Revision: 218279 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=218279&view=rev >> Log: >> Played around with TK UI a bit this weekend. >> >> If you "command script import" this file, then you will have two new >> commands: >> >> (lldb) tk-variables >> (lldb) tk-process >> >> Not sure how this will work on all other systems, but on MacOSX, you will >> get a window with a tree view that allows you to inspect your local >> variables by expanding variables to see the child values. >> >> The "tk-process" allows you to inspect the currently selected process by >> expanding the process to see the threads, the threads to see the frames, >> and the frames to see the variables. Very handy if you want to view >> variables for all frames simultaneously. >> >> >> Added: >> lldb/trunk/examples/python/lldbtk.py >> >> Added: lldb/trunk/examples/python/lldbtk.py >> URL: >> http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/lldbtk.py?rev=218279&view=auto >> >> ============================================================================== >> --- lldb/trunk/examples/python/lldbtk.py (added) >> +++ lldb/trunk/examples/python/lldbtk.py Mon Sep 22 17:06:41 2014 >> @@ -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() >> + >> >> >> _______________________________________________ >> lldb-commits mailing list >> lldb-commits@cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits >> > > > > -- > Todd Fiala | Software Engineer | tfi...@google.com | 650-943-3180 > -- Todd Fiala | Software Engineer | tfi...@google.com | 650-943-3180
_______________________________________________ lldb-commits mailing list lldb-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits