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