diff options
author | Greg Clayton <gclayton@apple.com> | 2017-11-16 17:14:48 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2017-11-16 17:14:48 +0000 |
commit | 0bc869a48812f7dea12b6f8a637e9f21b088fb73 (patch) | |
tree | 34e30251db165a6b60ee3be42b7349fdb018c6ae /lldb/examples | |
parent | be9295de971c3106f12324057230ca8e15e19b43 (diff) |
Fixed up to use a class for the commands, renamed the commands and added a way to just dump the compile unit full paths and optionally their support files with the new "dump-files"command.
Diffstat (limited to 'lldb/examples')
-rw-r--r-- | lldb/examples/python/lldb_module_utils.py | 249 |
1 files changed, 181 insertions, 68 deletions
diff --git a/lldb/examples/python/lldb_module_utils.py b/lldb/examples/python/lldb_module_utils.py index eb00a489ce0..006f232681f 100644 --- a/lldb/examples/python/lldb_module_utils.py +++ b/lldb/examples/python/lldb_module_utils.py @@ -7,72 +7,185 @@ import string import sys -def create_dump_module_line_tables_options(): - usage = "usage: dump_module_line_tables [options] MODULE1 [MODULE2 ...]" - description = '''Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.''' - parser = optparse.OptionParser( - description=description, - prog='start_gdb_log', - usage=usage) - parser.add_option( - '-v', - '--verbose', - action='store_true', - dest='verbose', - help='Display verbose output.', - default=False) - return parser - - -def dump_module_line_tables(debugger, command, result, dict): - '''Dumps all line tables from all compile units for any modules specified as arguments.''' - command_args = shlex.split(command) - - parser = create_dump_module_line_tables_options() - try: - (options, args) = parser.parse_args(command_args) - except: - return - if command_args: - target = debugger.GetSelectedTarget() - lldb.target = target - for module_name in command_args: - result.PutCString('Searching for module "%s"' % (module_name,)) - module_fspec = lldb.SBFileSpec(module_name, False) - module = target.FindModule(module_fspec) - if module: - for cu_idx in range(module.GetNumCompileUnits()): - cu = module.GetCompileUnitAtIndex(cu_idx) - result.PutCString("\n%s:" % (cu.file)) - for line_idx in range(cu.GetNumLineEntries()): - line_entry = cu.GetLineEntryAtIndex(line_idx) - start_file_addr = line_entry.addr.file_addr - end_file_addr = line_entry.end_addr.file_addr - # If the two addresses are equal, this line table entry - # is a termination entry - if options.verbose: - if start_file_addr != end_file_addr: - result.PutCString( - '[%#x - %#x): %s' % - (start_file_addr, end_file_addr, line_entry)) - else: - if start_file_addr == end_file_addr: - result.PutCString('%#x: END' % - (start_file_addr)) - else: - result.PutCString( - '%#x: %s' % - (start_file_addr, line_entry)) +class DumpLineTables: + command_name = "dump-line-tables" + short_decription = "Dumps full paths to compile unit files and optionally all line table files." + description = 'Dumps all line tables from all compile units for any modules specified as arguments. Specifying the --verbose flag will output address ranges for each line entry.' + usage = "usage: %prog [options] MODULE1 [MODULE2 ...]" + def create_options(self): + self.parser = optparse.OptionParser( + description=self.description, + prog=self.command_name, + usage=self.usage) + + self.parser.add_option( + '-v', + '--verbose', + action='store_true', + dest='verbose', + help='Display verbose output.', + default=False) + + def get_short_help(self): + return self.short_decription + + def get_long_help(self): + return self.help_string + + def __init__(self, debugger, unused): + self.create_options() + self.help_string = self.parser.format_help() + + def __call__(self, debugger, command, exe_ctx, result): + # Use the Shell Lexer to properly parse up command options just like a + # shell would + command_args = shlex.split(command) + + try: + (options, args) = self.parser.parse_args(command_args) + except: + # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit + # (courtesy of OptParse dealing with argument errors by throwing SystemExit) + result.SetError("option parsing failed") + return + + # Always get program state from the SBExecutionContext passed in as exe_ctx + target = exe_ctx.GetTarget() + if not target.IsValid(): + result.SetError("invalid target") + return + + for module_path in args: + module = target.module[module_path] + if not module: + result.SetError('no module found that matches "%s".' % (module_path)) + return + num_cus = module.GetNumCompileUnits() + print >>result, 'Module: "%s"' % (module.file.fullpath), + if num_cus == 0: + print >>result, 'no debug info.' + continue + print >>result, 'has %u compile units:' % (num_cus) + for cu_idx in range(num_cus): + cu = module.GetCompileUnitAtIndex(cu_idx) + print >>result, ' Compile Unit: %s' % (cu.file.fullpath) + for line_idx in range(cu.GetNumLineEntries()): + line_entry = cu.GetLineEntryAtIndex(line_idx) + start_file_addr = line_entry.addr.file_addr + end_file_addr = line_entry.end_addr.file_addr + # If the two addresses are equal, this line table entry + # is a termination entry + if options.verbose: + if start_file_addr != end_file_addr: + result.PutCString( + ' [%#x - %#x): %s' % + (start_file_addr, end_file_addr, line_entry)) + else: if start_file_addr == end_file_addr: - result.Printf("\n") - else: - result.PutCString("no module for '%s'" % module) - else: - result.PutCString("error: invalid target") - -parser = create_dump_module_line_tables_options() -dump_module_line_tables.__doc__ = parser.format_help() -lldb.debugger.HandleCommand( - 'command script add -f %s.dump_module_line_tables dump_module_line_tables' % - __name__) -print 'Installed "dump_module_line_tables" command' + result.PutCString(' %#x: END' % + (start_file_addr)) + else: + result.PutCString( + ' %#x: %s' % + (start_file_addr, line_entry)) + if start_file_addr == end_file_addr: + result.PutCString("\n") + + +class DumpFiles: + command_name = "dump-files" + short_description = "Dumps full paths to compile unit files and optionally all line table files." + usage = "usage: %prog [options] MODULE1 [MODULE2 ...]" + description = '''This class adds a dump-files command to the LLDB interpreter. + +This command will dump all compile unit file paths found for each source file +for the binaries specified as arguments in the current target. Specify the +--support-files or -s option to see all file paths that a compile unit uses in +its lines tables. This is handy for troubleshooting why breakpoints aren't +working in IDEs that specify full paths to source files when setting file and +line breakpoints. Sometimes symlinks cause the debug info to contain the symlink +path and an IDE will resolve the path to the actual file and use the resolved +path when setting breakpoints. +''' + def create_options(self): + # Pass add_help_option = False, since this keeps the command in line with lldb commands, + # and we wire up "help command" to work by providing the long & short help methods below. + self.parser = optparse.OptionParser( + description = self.description, + prog = self.command_name, + usage = self.usage, + add_help_option = False) + + self.parser.add_option( + '-s', + '--support-files', + action = 'store_true', + dest = 'support_files', + help = 'Dumps full paths to all files used in a compile unit.', + default = False) + + def get_short_help(self): + return self.short_description + + def get_long_help(self): + return self.help_string + + def __init__(self, debugger, unused): + self.create_options() + self.help_string = self.parser.format_help() + + def __call__(self, debugger, command, exe_ctx, result): + # Use the Shell Lexer to properly parse up command options just like a + # shell would + command_args = shlex.split(command) + + try: + (options, args) = self.parser.parse_args(command_args) + except: + # if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit + # (courtesy of OptParse dealing with argument errors by throwing SystemExit) + result.SetError("option parsing failed") + return + + # Always get program state from the SBExecutionContext passed in as exe_ctx + target = exe_ctx.GetTarget() + if not target.IsValid(): + result.SetError("invalid target") + return + + if len(args) == 0: + result.SetError("one or more executable paths must be specified") + return + + for module_path in args: + module = target.module[module_path] + if not module: + result.SetError('no module found that matches "%s".' % (module_path)) + return + num_cus = module.GetNumCompileUnits() + print >>result, 'Module: "%s"' % (module.file.fullpath), + if num_cus == 0: + print >>result, 'no debug info.' + continue + print >>result, 'has %u compile units:' % (num_cus) + for i in range(num_cus): + cu = module.GetCompileUnitAtIndex(i) + print >>result, ' Compile Unit: %s' % (cu.file.fullpath) + if options.support_files: + num_support_files = cu.GetNumSupportFiles() + for j in range(num_support_files): + path = cu.GetSupportFileAtIndex(j).fullpath + print >>result, ' file[%u]: %s' % (j, path) + + +def __lldb_init_module(debugger, dict): + # This initializer is being run from LLDB in the embedded command interpreter + + # Add any commands contained in this module to LLDB + debugger.HandleCommand( + 'command script add -c %s.DumpLineTables %s' % (__name__, + DumpLineTables.command_name)) + debugger.HandleCommand( + 'command script add -c %s.DumpFiles %s' % (__name__, DumpFiles.command_name)) + print 'The "%s" and "%s" commands have been installed.' % (DumpLineTables.command_name, + DumpFiles.command_name) |