1#!/usr/bin/python 2 3import lldb 4import shlex 5import sys 6from Tkinter import * 7import ttk 8 9class ValueTreeItemDelegate(object): 10 def __init__(self, value): 11 self.value = value 12 13 def get_item_dictionary(self): 14 name = self.value.name 15 if name is None: 16 name = '' 17 typename = self.value.type 18 if typename is None: 19 typename = '' 20 value = self.value.value 21 if value is None: 22 value = '' 23 summary = self.value.summary 24 if summary is None: 25 summary = '' 26 has_children = self.value.MightHaveChildren() 27 return { '#0' : name, 28 'typename' : typename, 29 'value' : value, 30 'summary' : summary, 31 'children' : has_children, 32 'tree-item-delegate' : self } 33 34 def get_child_item_dictionaries(self): 35 item_dicts = list() 36 for i in range(self.value.num_children): 37 item_delegate = ValueTreeItemDelegate(self.value.GetChildAtIndex(i)) 38 item_dicts.append(item_delegate.get_item_dictionary()) 39 return item_dicts 40 41class FrameTreeItemDelegate(object): 42 def __init__(self, frame): 43 self.frame = frame 44 45 def get_item_dictionary(self): 46 id = self.frame.GetFrameID() 47 name = 'frame #%u' % (id); 48 value = '0x%16.16x' % (self.frame.GetPC()) 49 stream = lldb.SBStream() 50 self.frame.GetDescription(stream) 51 summary = stream.GetData().split("`")[1] 52 return { '#0' : name, 53 'value': value, 54 'summary': summary, 55 'children' : self.frame.GetVariables(True, True, True, True).GetSize() > 0, 56 'tree-item-delegate' : self } 57 58 def get_child_item_dictionaries(self): 59 item_dicts = list() 60 variables = self.frame.GetVariables(True, True, True, True) 61 n = variables.GetSize() 62 for i in range(n): 63 item_delegate = ValueTreeItemDelegate(variables[i]) 64 item_dicts.append(item_delegate.get_item_dictionary()) 65 return item_dicts 66 67class ThreadTreeItemDelegate(object): 68 def __init__(self, thread): 69 self.thread = thread 70 71 def get_item_dictionary(self): 72 num_frames = self.thread.GetNumFrames() 73 name = 'thread #%u' % (self.thread.GetIndexID()) 74 value = '0x%x' % (self.thread.GetThreadID()) 75 summary = '%u frames' % (num_frames) 76 return { '#0' : name, 77 'value': value, 78 'summary': summary, 79 'children' : num_frames > 0, 80 'tree-item-delegate' : self } 81 82 def get_child_item_dictionaries(self): 83 item_dicts = list() 84 for frame in self.thread: 85 item_delegate = FrameTreeItemDelegate(frame) 86 item_dicts.append(item_delegate.get_item_dictionary()) 87 return item_dicts 88 89class ProcessTreeItemDelegate(object): 90 def __init__(self, process): 91 self.process = process 92 93 def get_item_dictionary(self): 94 id = self.process.GetProcessID() 95 num_threads = self.process.GetNumThreads() 96 value = str(self.process.GetProcessID()) 97 summary = self.process.target.executable.fullpath 98 return { '#0' : 'process', 99 'value': value, 100 'summary': summary, 101 'children' : num_threads > 0, 102 'tree-item-delegate' : self } 103 104 def get_child_item_dictionaries(self): 105 item_dicts = list() 106 for thread in self.process: 107 item_delegate = ThreadTreeItemDelegate(thread) 108 item_dicts.append(item_delegate.get_item_dictionary()) 109 return item_dicts 110 111class TargetTreeItemDelegate(object): 112 def __init__(self, target): 113 self.target = target 114 115 def get_item_dictionary(self): 116 value = str(self.target.triple) 117 summary = self.target.executable.fullpath 118 return { '#0' : 'target', 119 'value': value, 120 'summary': summary, 121 'children' : True, 122 'tree-item-delegate' : self } 123 124 def get_child_item_dictionaries(self): 125 item_dicts = list() 126 image_item_delegate = TargetImagesTreeItemDelegate(self.target) 127 item_dicts.append(image_item_delegate.get_item_dictionary()) 128 return item_dicts 129 130class TargetImagesTreeItemDelegate(object): 131 def __init__(self, target): 132 self.target = target 133 134 def get_item_dictionary(self): 135 value = str(self.target.triple) 136 summary = self.target.executable.fullpath 137 num_modules = self.target.GetNumModules() 138 return { '#0' : 'images', 139 'value': '', 140 'summary': '%u images' % num_modules, 141 'children' : num_modules > 0, 142 'tree-item-delegate' : self } 143 144 def get_child_item_dictionaries(self): 145 item_dicts = list() 146 for i in range(self.target.GetNumModules()): 147 module = self.target.GetModuleAtIndex(i) 148 image_item_delegate = ModuleTreeItemDelegate(self.target, module, i) 149 item_dicts.append(image_item_delegate.get_item_dictionary()) 150 return item_dicts 151 152class ModuleTreeItemDelegate(object): 153 def __init__(self, target, module, index): 154 self.target = target 155 self.module = module 156 self.index = index 157 158 def get_item_dictionary(self): 159 name = 'module %u' % (self.index) 160 value = self.module.file.basename 161 summary = self.module.file.dirname 162 return { '#0' : name, 163 'value': value, 164 'summary': summary, 165 'children' : True, 166 'tree-item-delegate' : self } 167 168 def get_child_item_dictionaries(self): 169 item_dicts = list() 170 sections_item_delegate = ModuleSectionsTreeItemDelegate(self.target, self.module) 171 item_dicts.append(sections_item_delegate.get_item_dictionary()) 172 173 symbols_item_delegate = ModuleSymbolsTreeItemDelegate(self.target, self.module) 174 item_dicts.append(symbols_item_delegate.get_item_dictionary()) 175 176 comp_units_item_delegate = ModuleCompileUnitsTreeItemDelegate(self.target, self.module) 177 item_dicts.append(comp_units_item_delegate.get_item_dictionary()) 178 return item_dicts 179 180class ModuleSectionsTreeItemDelegate(object): 181 def __init__(self, target, module): 182 self.target = target 183 self.module = module 184 185 def get_item_dictionary(self): 186 name = 'sections' 187 value = '' 188 summary = '%u sections' % (self.module.GetNumSections()) 189 return { '#0' : name, 190 'value': value, 191 'summary': summary, 192 'children' : True, 193 'tree-item-delegate' : self } 194 195 def get_child_item_dictionaries(self): 196 item_dicts = list() 197 num_sections = self.module.GetNumSections() 198 for i in range(num_sections): 199 section = self.module.GetSectionAtIndex(i) 200 image_item_delegate = SectionTreeItemDelegate(self.target, section) 201 item_dicts.append(image_item_delegate.get_item_dictionary()) 202 return item_dicts 203 204class SectionTreeItemDelegate(object): 205 def __init__(self, target, section): 206 self.target = target 207 self.section = section 208 209 def get_item_dictionary(self): 210 name = self.section.name 211 section_load_addr = self.section.GetLoadAddress(self.target) 212 if section_load_addr != lldb.LLDB_INVALID_ADDRESS: 213 value = '0x%16.16x' % (section_load_addr) 214 else: 215 value = '0x%16.16x *' % (self.section.file_addr) 216 summary = '' 217 return { '#0' : name, 218 'value': value, 219 'summary': summary, 220 'children' : self.section.GetNumSubSections() > 0, 221 'tree-item-delegate' : self } 222 223 def get_child_item_dictionaries(self): 224 item_dicts = list() 225 num_sections = self.section.GetNumSubSections() 226 for i in range(num_sections): 227 section = self.section.GetSubSectionAtIndex(i) 228 image_item_delegate = SectionTreeItemDelegate(self.target, section) 229 item_dicts.append(image_item_delegate.get_item_dictionary()) 230 return item_dicts 231 232class ModuleCompileUnitsTreeItemDelegate(object): 233 def __init__(self, target, module): 234 self.target = target 235 self.module = module 236 237 def get_item_dictionary(self): 238 name = 'compile units' 239 value = '' 240 summary = '%u compile units' % (self.module.GetNumSections()) 241 return { '#0' : name, 242 'value': value, 243 'summary': summary, 244 'children' : self.module.GetNumCompileUnits() > 0, 245 'tree-item-delegate' : self } 246 247 def get_child_item_dictionaries(self): 248 item_dicts = list() 249 num_cus = self.module.GetNumCompileUnits() 250 for i in range(num_cus): 251 cu = self.module.GetCompileUnitAtIndex(i) 252 image_item_delegate = CompileUnitTreeItemDelegate(self.target, cu) 253 item_dicts.append(image_item_delegate.get_item_dictionary()) 254 return item_dicts 255 256class CompileUnitTreeItemDelegate(object): 257 def __init__(self, target, cu): 258 self.target = target 259 self.cu = cu 260 261 def get_item_dictionary(self): 262 name = self.cu.GetFileSpec().basename 263 value = '' 264 num_lines = self.cu.GetNumLineEntries() 265 summary = '' 266 return { '#0' : name, 267 'value': value, 268 'summary': summary, 269 'children' : num_lines > 0, 270 'tree-item-delegate' : self } 271 272 def get_child_item_dictionaries(self): 273 item_dicts = list() 274 item_delegate = LineTableTreeItemDelegate(self.target, self.cu) 275 item_dicts.append(item_delegate.get_item_dictionary()) 276 return item_dicts 277 278class LineTableTreeItemDelegate(object): 279 def __init__(self, target, cu): 280 self.target = target 281 self.cu = cu 282 283 def get_item_dictionary(self): 284 name = 'line table' 285 value = '' 286 num_lines = self.cu.GetNumLineEntries() 287 summary = '%u line entries' % (num_lines) 288 return { '#0' : name, 289 'value': value, 290 'summary': summary, 291 'children' : num_lines > 0, 292 'tree-item-delegate' : self } 293 294 def get_child_item_dictionaries(self): 295 item_dicts = list() 296 num_lines = self.cu.GetNumLineEntries() 297 for i in range(num_lines): 298 line_entry = self.cu.GetLineEntryAtIndex(i) 299 item_delegate = LineEntryTreeItemDelegate(self.target, line_entry, i) 300 item_dicts.append(item_delegate.get_item_dictionary()) 301 return item_dicts 302 303class LineEntryTreeItemDelegate(object): 304 def __init__(self, target, line_entry, index): 305 self.target = target 306 self.line_entry = line_entry 307 self.index = index 308 309 def get_item_dictionary(self): 310 name = str(self.index) 311 address = self.line_entry.GetStartAddress() 312 load_addr = address.GetLoadAddress(self.target) 313 if load_addr != lldb.LLDB_INVALID_ADDRESS: 314 value = '0x%16.16x' % (load_addr) 315 else: 316 value = '0x%16.16x *' % (address.file_addr) 317 summary = self.line_entry.GetFileSpec().fullpath + ':' + str(self.line_entry.line) 318 return { '#0' : name, 319 'value': value, 320 'summary': summary, 321 'children' : False, 322 'tree-item-delegate' : self } 323 324 def get_child_item_dictionaries(self): 325 item_dicts = list() 326 return item_dicts 327 328class InstructionTreeItemDelegate(object): 329 def __init__(self, target, instr): 330 self.target = target 331 self.instr = instr 332 333 def get_item_dictionary(self): 334 address = self.instr.GetAddress() 335 load_addr = address.GetLoadAddress(self.target) 336 if load_addr != lldb.LLDB_INVALID_ADDRESS: 337 name = '0x%16.16x' % (load_addr) 338 else: 339 name = '0x%16.16x *' % (address.file_addr) 340 value = self.instr.GetMnemonic(self.target) + ' ' + self.instr.GetOperands(self.target) 341 summary = self.instr.GetComment(self.target) 342 return { '#0' : name, 343 'value': value, 344 'summary': summary, 345 'children' : False, 346 'tree-item-delegate' : self } 347 348class ModuleSymbolsTreeItemDelegate(object): 349 def __init__(self, target, module): 350 self.target = target 351 self.module = module 352 353 def get_item_dictionary(self): 354 name = 'symbols' 355 value = '' 356 summary = '%u symbols' % (self.module.GetNumSymbols()) 357 return { '#0' : name, 358 'value': value, 359 'summary': summary, 360 'children' : True, 361 'tree-item-delegate' : self } 362 363 def get_child_item_dictionaries(self): 364 item_dicts = list() 365 num_symbols = self.module.GetNumSymbols() 366 for i in range(num_symbols): 367 symbol = self.module.GetSymbolAtIndex(i) 368 image_item_delegate = SymbolTreeItemDelegate(self.target, symbol, i) 369 item_dicts.append(image_item_delegate.get_item_dictionary()) 370 return item_dicts 371 372class SymbolTreeItemDelegate(object): 373 def __init__(self, target, symbol, index): 374 self.target = target 375 self.symbol = symbol 376 self.index = index 377 378 def get_item_dictionary(self): 379 address = self.symbol.GetStartAddress() 380 name = '[%u]' % self.index 381 symbol_load_addr = address.GetLoadAddress(self.target) 382 if symbol_load_addr != lldb.LLDB_INVALID_ADDRESS: 383 value = '0x%16.16x' % (symbol_load_addr) 384 else: 385 value = '0x%16.16x *' % (address.file_addr) 386 summary = self.symbol.name 387 return { '#0' : name, 388 'value': value, 389 'summary': summary, 390 'children' : False, 391 'tree-item-delegate' : self } 392 393 def get_child_item_dictionaries(self): 394 item_dicts = list() 395 return item_dicts 396 397 398 399class DelegateTree(ttk.Frame): 400 401 def __init__(self, column_dicts, delegate, title, name): 402 ttk.Frame.__init__(self, name=name) 403 self.pack(expand=Y, fill=BOTH) 404 self.master.title(title) 405 self.delegate = delegate 406 self.columns_dicts = column_dicts 407 self.item_id_to_item_dict = dict() 408 frame = Frame(self) 409 frame.pack(side=TOP, fill=BOTH, expand=Y) 410 self._create_treeview(frame) 411 self._populate_root() 412 413 def _create_treeview(self, parent): 414 frame = ttk.Frame(parent) 415 frame.pack(side=TOP, fill=BOTH, expand=Y) 416 417 column_ids = list() 418 for i in range(1,len(self.columns_dicts)): 419 column_ids.append(self.columns_dicts[i]['id']) 420 # create the tree and scrollbars 421 self.tree = ttk.Treeview(columns=column_ids) 422 423 scroll_bar_v = ttk.Scrollbar(orient=VERTICAL, command= self.tree.yview) 424 scroll_bar_h = ttk.Scrollbar(orient=HORIZONTAL, command= self.tree.xview) 425 self.tree['yscroll'] = scroll_bar_v.set 426 self.tree['xscroll'] = scroll_bar_h.set 427 428 # setup column headings and columns properties 429 for columns_dict in self.columns_dicts: 430 self.tree.heading(columns_dict['id'], text=columns_dict['text'], anchor=columns_dict['anchor']) 431 self.tree.column(columns_dict['id'], stretch=columns_dict['stretch']) 432 433 # add tree and scrollbars to frame 434 self.tree.grid(in_=frame, row=0, column=0, sticky=NSEW) 435 scroll_bar_v.grid(in_=frame, row=0, column=1, sticky=NS) 436 scroll_bar_h.grid(in_=frame, row=1, column=0, sticky=EW) 437 438 # set frame resizing priorities 439 frame.rowconfigure(0, weight=1) 440 frame.columnconfigure(0, weight=1) 441 442 # action to perform when a node is expanded 443 self.tree.bind('<<TreeviewOpen>>', self._update_tree) 444 445 def insert_items(self, parent_id, item_dicts): 446 for item_dict in item_dicts: 447 name = None 448 values = list() 449 first = True 450 for columns_dict in self.columns_dicts: 451 if first: 452 name = item_dict[columns_dict['id']] 453 first = False 454 else: 455 values.append(item_dict[columns_dict['id']]) 456 item_id = self.tree.insert (parent_id, # root item has an empty name 457 END, 458 text=name, 459 values=values) 460 self.item_id_to_item_dict[item_id] = item_dict 461 if item_dict['children']: 462 self.tree.insert(item_id, END, text='dummy') 463 464 def _populate_root(self): 465 # use current directory as root node 466 self.insert_items('', self.delegate.get_child_item_dictionaries()) 467 468 def _update_tree(self, event): 469 # user expanded a node - build the related directory 470 item_id = self.tree.focus() # the id of the expanded node 471 children = self.tree.get_children (item_id) 472 if len(children): 473 first_child = children[0] 474 # if the node only has a 'dummy' child, remove it and 475 # build new directory; skip if the node is already 476 # populated 477 if self.tree.item(first_child, option='text') == 'dummy': 478 self.tree.delete(first_child) 479 item_dict = self.item_id_to_item_dict[item_id] 480 item_dicts = item_dict['tree-item-delegate'].get_child_item_dictionaries() 481 self.insert_items(item_id, item_dicts) 482 483@lldb.command("tk-variables") 484def tk_variable_display(debugger, command, result, dict): 485 sys.argv = ['tk-variables'] # needed for tree creation in TK library as it uses sys.argv... 486 target = debugger.GetSelectedTarget() 487 if not target: 488 print >>result, "invalid target" 489 return 490 process = target.GetProcess() 491 if not process: 492 print >>result, "invalid process" 493 return 494 thread = process.GetSelectedThread() 495 if not thread: 496 print >>result, "invalid thread" 497 return 498 frame = thread.GetSelectedFrame() 499 if not frame: 500 print >>result, "invalid frame" 501 return 502 # Parse command line args 503 command_args = shlex.split(command) 504 column_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 }, 505 { 'id' : 'typename', 'text' : 'Type' , 'anchor' : W , 'stretch' : 0 }, 506 { 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 }, 507 { 'id' : 'summary' , 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }] 508 tree = DelegateTree(column_dicts, FrameTreeItemDelegate(frame), 'Variables', 'lldb-tk-variables') 509 tree.mainloop() 510 511@lldb.command("tk-process") 512def tk_process_display(debugger, command, result, dict): 513 sys.argv = ['tk-process'] # needed for tree creation in TK library as it uses sys.argv... 514 target = debugger.GetSelectedTarget() 515 if not target: 516 print >>result, "invalid target" 517 return 518 process = target.GetProcess() 519 if not process: 520 print >>result, "invalid process" 521 return 522 # Parse command line args 523 columnd_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 }, 524 { 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 }, 525 { 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]; 526 command_args = shlex.split(command) 527 tree = DelegateTree(columnd_dicts, ProcessTreeItemDelegate(process), 'Process', 'lldb-tk-process') 528 tree.mainloop() 529 530@lldb.command("tk-target") 531def tk_target_display(debugger, command, result, dict): 532 sys.argv = ['tk-target'] # needed for tree creation in TK library as it uses sys.argv... 533 target = debugger.GetSelectedTarget() 534 if not target: 535 print >>result, "invalid target" 536 return 537 # Parse command line args 538 columnd_dicts = [{ 'id' : '#0' , 'text' : 'Name' , 'anchor' : W , 'stretch' : 0 }, 539 { 'id' : 'value' , 'text' : 'Value' , 'anchor' : W , 'stretch' : 0 }, 540 { 'id' : 'summary', 'text' : 'Summary', 'anchor' : W , 'stretch' : 1 }]; 541 command_args = shlex.split(command) 542 tree = DelegateTree(columnd_dicts, TargetTreeItemDelegate(target), 'Target', 'lldb-tk-target') 543 tree.mainloop() 544 545