forked from OSchip/llvm-project
Added "source list -n" so you can list by symbol name. Moved "--count" from "-n" to "-c". Added a -s option so you can restrict the source listing to a particular shared library.
llvm-svn: 111608
This commit is contained in:
parent
64b931c1e1
commit
5466e751f0
|
@ -172,7 +172,7 @@ class CommandObjectSourceList : public CommandObject
|
|||
error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
case 'c':
|
||||
num_lines = Args::StringToUInt32 (option_arg, 0);
|
||||
if (num_lines == 0)
|
||||
error.SetErrorStringWithFormat("Invalid line count: '%s'.\n", option_arg);
|
||||
|
@ -181,7 +181,14 @@ class CommandObjectSourceList : public CommandObject
|
|||
case 'f':
|
||||
file_name = option_arg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
symbol_name = option_arg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
m_modules.push_back (std::string (option_arg));
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
|
||||
break;
|
||||
|
@ -197,8 +204,10 @@ class CommandObjectSourceList : public CommandObject
|
|||
|
||||
file_spec.Clear();
|
||||
file_name.clear();
|
||||
symbol_name.clear();
|
||||
start_line = 0;
|
||||
num_lines = 10;
|
||||
m_modules.clear();
|
||||
}
|
||||
|
||||
const lldb::OptionDefinition*
|
||||
|
@ -211,9 +220,10 @@ class CommandObjectSourceList : public CommandObject
|
|||
// Instance variables to hold the values for command options.
|
||||
FileSpec file_spec;
|
||||
std::string file_name;
|
||||
std::string symbol_name;
|
||||
uint32_t start_line;
|
||||
uint32_t num_lines;
|
||||
|
||||
STLStringArray m_modules;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -253,7 +263,155 @@ public:
|
|||
}
|
||||
|
||||
ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
|
||||
if (m_options.file_name.empty())
|
||||
|
||||
if (!m_options.symbol_name.empty())
|
||||
{
|
||||
// Displaying the source for a symbol:
|
||||
Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("invalid target, set executable file using 'file' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
SymbolContextList sc_list;
|
||||
ConstString name(m_options.symbol_name.c_str());
|
||||
bool append = true;
|
||||
size_t num_matches = 0;
|
||||
|
||||
if (m_options.m_modules.size() > 0)
|
||||
{
|
||||
ModuleList matching_modules;
|
||||
for (int i = 0; i < m_options.m_modules.size(); i++)
|
||||
{
|
||||
FileSpec module_spec(m_options.m_modules[i].c_str());
|
||||
if (module_spec)
|
||||
{
|
||||
matching_modules.Clear();
|
||||
target->GetImages().FindModules (&module_spec, NULL, NULL, NULL, matching_modules);
|
||||
num_matches += matching_modules.FindFunctions (name, eFunctionNameTypeBase, append, sc_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num_matches = target->GetImages().FindFunctions (name, eFunctionNameTypeBase, append, sc_list);
|
||||
}
|
||||
|
||||
SymbolContext sc;
|
||||
|
||||
if (num_matches == 0)
|
||||
{
|
||||
result.AppendErrorWithFormat("Could not find function named: \"%s\".\n", m_options.symbol_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
sc_list.GetContextAtIndex (0, sc);
|
||||
FileSpec start_file;
|
||||
uint32_t start_line;
|
||||
uint32_t end_line;
|
||||
FileSpec end_file;
|
||||
if (sc.function != NULL)
|
||||
{
|
||||
sc.function->GetStartLineSourceInfo (start_file, start_line);
|
||||
if (start_line == 0)
|
||||
{
|
||||
result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", m_options.symbol_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
sc.function->GetEndLineSourceInfo (end_file, end_line);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_matches > 1)
|
||||
{
|
||||
// This could either be because there are multiple functions of this name, in which case
|
||||
// we'll have to specify this further... Or it could be because there are multiple inlined instances
|
||||
// of one function. So run through the matches and if they all have the same file & line then we can just
|
||||
// list one.
|
||||
|
||||
bool found_multiple = false;
|
||||
|
||||
for (size_t i = 1; i < num_matches; i++)
|
||||
{
|
||||
SymbolContext scratch_sc;
|
||||
sc_list.GetContextAtIndex (i, scratch_sc);
|
||||
if (scratch_sc.function != NULL)
|
||||
{
|
||||
FileSpec scratch_file;
|
||||
uint32_t scratch_line;
|
||||
scratch_sc.function->GetStartLineSourceInfo (scratch_file, scratch_line);
|
||||
if (scratch_file != start_file
|
||||
|| scratch_line != start_line)
|
||||
{
|
||||
found_multiple = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found_multiple)
|
||||
{
|
||||
StreamString s;
|
||||
for (size_t i = 0; i < num_matches; i++)
|
||||
{
|
||||
SymbolContext scratch_sc;
|
||||
sc_list.GetContextAtIndex (i, scratch_sc);
|
||||
if (scratch_sc.function != NULL)
|
||||
{
|
||||
s.Printf("\n%d: ", i);
|
||||
scratch_sc.function->Dump (&s, true);
|
||||
}
|
||||
}
|
||||
result.AppendErrorWithFormat("Multiple functions found matching: %s: \n%s\n",
|
||||
m_options.symbol_name.c_str(),
|
||||
s.GetData());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This is a little hacky, but the first line table entry for a function points to the "{" that
|
||||
// starts the function block. It would be nice to actually get the function
|
||||
// declaration in there too. So back up a bit, but not further than what you're going to display.
|
||||
size_t lines_to_back_up = m_options.num_lines >= 10 ? 5 : m_options.num_lines/2;
|
||||
uint32_t line_no;
|
||||
if (start_line <= lines_to_back_up)
|
||||
line_no = 1;
|
||||
else
|
||||
line_no = start_line - lines_to_back_up;
|
||||
|
||||
// For fun, if the function is shorter than the number of lines we're supposed to display,
|
||||
// only display the function...
|
||||
if (end_line != 0)
|
||||
{
|
||||
if (m_options.num_lines > end_line - line_no)
|
||||
m_options.num_lines = end_line - line_no;
|
||||
}
|
||||
|
||||
char path_buf[PATH_MAX+1];
|
||||
start_file.GetPath(path_buf, PATH_MAX);
|
||||
result.AppendMessageWithFormat("File: %s.\n", path_buf);
|
||||
interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
|
||||
line_no,
|
||||
0,
|
||||
m_options.num_lines,
|
||||
"",
|
||||
&result.GetOutputStream());
|
||||
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
return true;
|
||||
|
||||
}
|
||||
else if (m_options.file_name.empty())
|
||||
{
|
||||
// Last valid source manager context, or the current frame if no
|
||||
// valid last context in source manager.
|
||||
|
@ -294,32 +452,96 @@ public:
|
|||
|
||||
bool check_inlines = false;
|
||||
SymbolContextList sc_list;
|
||||
size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
|
||||
0,
|
||||
check_inlines,
|
||||
eSymbolContextModule | eSymbolContextCompUnit,
|
||||
sc_list);
|
||||
if (num_matches > 0)
|
||||
size_t num_matches = 0;
|
||||
|
||||
if (m_options.m_modules.size() > 0)
|
||||
{
|
||||
SymbolContext sc;
|
||||
if (sc_list.GetContextAtIndex(0, sc))
|
||||
ModuleList matching_modules;
|
||||
for (int i = 0; i < m_options.m_modules.size(); i++)
|
||||
{
|
||||
if (sc.comp_unit)
|
||||
FileSpec module_spec(m_options.m_modules[i].c_str());
|
||||
if (module_spec)
|
||||
{
|
||||
interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
|
||||
m_options.start_line, // Line to display
|
||||
0, // Lines before line to display
|
||||
m_options.num_lines, // Lines after line to display
|
||||
"", // Don't mark "line"
|
||||
&result.GetOutputStream());
|
||||
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
|
||||
matching_modules.Clear();
|
||||
target->GetImages().FindModules (&module_spec, NULL, NULL, NULL, matching_modules);
|
||||
num_matches += matching_modules.ResolveSymbolContextForFilePath (filename,
|
||||
0,
|
||||
check_inlines,
|
||||
eSymbolContextModule | eSymbolContextCompUnit,
|
||||
sc_list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
|
||||
0,
|
||||
check_inlines,
|
||||
eSymbolContextModule | eSymbolContextCompUnit,
|
||||
sc_list);
|
||||
}
|
||||
|
||||
if (num_matches == 0)
|
||||
{
|
||||
result.AppendErrorWithFormat("Could not find source file \"%s\".\n",
|
||||
m_options.file_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_matches > 1)
|
||||
{
|
||||
SymbolContext sc;
|
||||
bool got_multiple = false;
|
||||
FileSpec *test_cu_spec = NULL;
|
||||
|
||||
for (int i = 0; i < num_matches; i++)
|
||||
{
|
||||
sc_list.GetContextAtIndex(i, sc);
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
if (test_cu_spec)
|
||||
{
|
||||
if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit))
|
||||
got_multiple = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
test_cu_spec = sc.comp_unit;
|
||||
}
|
||||
}
|
||||
if (got_multiple)
|
||||
{
|
||||
result.AppendErrorWithFormat("Multiple source files found matching: \"%s.\"\n",
|
||||
m_options.file_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SymbolContext sc;
|
||||
if (sc_list.GetContextAtIndex(0, sc))
|
||||
{
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
interpreter.GetDebugger().GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
|
||||
m_options.start_line,
|
||||
0,
|
||||
m_options.num_lines,
|
||||
"",
|
||||
&result.GetOutputStream());
|
||||
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat("No comp unit found for: \"%s.\"\n",
|
||||
m_options.file_name.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
|
@ -336,9 +558,12 @@ protected:
|
|||
lldb::OptionDefinition
|
||||
CommandObjectSourceList::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
|
||||
{ LLDB_OPT_SET_ALL, false, "count", 'c', required_argument, NULL, 0, "<count>", "The number of source lines to display."},
|
||||
{ LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
|
||||
"Look up the source file in the given shared library."},
|
||||
{ LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>", "The file from which to display source."},
|
||||
{ LLDB_OPT_SET_1, false, "count", 'n', required_argument, NULL, 0, "<count>", "The number of source lines to display."},
|
||||
{ LLDB_OPT_SET_1, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
|
||||
{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<symbol>", "The name of a function whose source to display."},
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue