forked from OSchip/llvm-project
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.
llvm-svn: 318424
This commit is contained in:
parent
cebbfacc9e
commit
84a7333a61
|
@ -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
|
||||
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 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)
|
||||
def get_short_help(self):
|
||||
return self.short_decription
|
||||
|
||||
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))
|
||||
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")
|
||||
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")
|
||||
|
||||
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'
|
||||
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue