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