diff options
author | Jim Ingham <jingham@apple.com> | 2010-08-20 01:17:07 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2010-08-20 01:17:07 +0000 |
commit | 5466e751f0c911815fe62684164667bd659f60d2 (patch) | |
tree | cef37c06f9a2dcb35182f7498b6ae7ebe06b623d /lldb/source/Commands | |
parent | 64b931c1e1490e6cca2b3020c1c97f4ec622df0e (diff) | |
download | bcm5719-llvm-5466e751f0c911815fe62684164667bd659f60d2.tar.gz bcm5719-llvm-5466e751f0c911815fe62684164667bd659f60d2.zip |
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
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r-- | lldb/source/Commands/CommandObjectSource.cpp | 269 |
1 files changed, 247 insertions, 22 deletions
diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index 2fd0f9c7b28..d905bcb0756 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -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) + { + 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.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; - if (sc_list.GetContextAtIndex(0, 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) { - 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); - + 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 } }; |