dawn created this revision.
dawn added reviewers: clayborg, ki.stfu, abidh.
dawn added a subscriber: lldb-commits.
dawn set the repository for this revision to rL LLVM.
This adds support for the new command:
target modules dump line-entries <file>
which dumps the line entries found for 'file' for all CUs in all modules.
This command is used to fix the MI command:
-symbol-list-lines <file>
which didn't work for header files because it called:
target modules dump line-table <file>
which only dumps line tables for a compilation unit.
Repository:
rL LLVM
http://reviews.llvm.org/D15593
Files:
packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py
packages/Python/lldbsuite/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
source/Commands/CommandObjectTarget.cpp
tools/lldb-mi/MICmdCmdSymbol.cpp
Index: tools/lldb-mi/MICmdCmdSymbol.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdSymbol.cpp
+++ tools/lldb-mi/MICmdCmdSymbol.cpp
@@ -82,11 +82,7 @@
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
const CMIUtilString &strFilePath(pArgFile->GetValue());
- // FIXME: this won't work for header files! To try and use existing
- // commands to get this to work for header files would be too slow.
- // Instead, this code should be rewritten to use APIs and/or support
- // should be added to lldb which would work for header files.
- const CMIUtilString strCmd(CMIUtilString::Format("target modules dump line-table \"%s\"", strFilePath.AddSlashes().c_str()));
+ const CMIUtilString strCmd(CMIUtilString::Format("target modules dump line-entries \"%s\"", strFilePath.AddSlashes().c_str()));
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
@@ -110,10 +106,10 @@
{
// Match LineEntry using regex.
static MIUtilParse::CRegexParser g_lineentry_header_regex(
- "^ *Line table for (.+) in `(.+)$");
- // ^1=file ^2=module
+ "^ *Lines for file (.+) in compilation unit (.+) in `(.+)$");
+ // ^1=file ^2=cu ^3=module
- MIUtilParse::CRegexParser::Match match(3);
+ MIUtilParse::CRegexParser::Match match(4);
const bool ok = g_lineentry_header_regex.Execute(input, match);
if (ok)
@@ -146,12 +142,12 @@
// Match LineEntry using regex.
static MIUtilParse::CRegexParser g_lineentry_nocol_regex(
- "^ *(0x[0-9a-fA-F]+): (.+):([0-9]+)$");
+ "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$");
static MIUtilParse::CRegexParser g_lineentry_col_regex(
- "^ *(0x[0-9a-fA-F]+): (.+):([0-9]+):[0-9]+$");
- // ^1=addr ^2=f ^3=line ^4=:col(opt)
+ "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$");
+ // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt)
- MIUtilParse::CRegexParser::Match match(5);
+ MIUtilParse::CRegexParser::Match match(6);
// First try matching the LineEntry with the column,
// then try without the column.
@@ -160,8 +156,8 @@
if (ok)
{
addr = match.GetMatchAtIndex(1);
- file = match.GetMatchAtIndex(2);
- line = match.GetMatchAtIndex(3);
+ file = match.GetMatchAtIndex(3);
+ line = match.GetMatchAtIndex(4);
}
return ok;
}
@@ -222,10 +218,6 @@
if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine))
continue;
- // Skip entries which don't match the desired source.
- if (strWantFile != strFile)
- continue;
-
const CMICmnMIValueConst miValueConst(strAddr);
const CMICmnMIValueResult miValueResult("pc", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -1524,6 +1524,91 @@
return num_matches;
}
+static uint32_t
+DumpFileLineEntries (CommandInterpreter &interpreter,
+ Stream &strm,
+ Module *module,
+ const FileSpec &file_spec,
+ bool load_addresses)
+{
+ uint32_t num_matches = 0;
+ if (module)
+ {
+ // Look through all the compilation units (CUs) for ones that contain
+ // lines of code from this source file.
+ assert(file_spec.GetFilename().AsCString());
+ bool has_path = (file_spec.GetDirectory().AsCString() != 0);
+ int ncus = module->GetNumCompileUnits();
+ for (int i = 0; i < ncus; i++)
+ {
+ // Look for a matching source file in this CU.
+ CompUnitSP cu_sp(module->GetCompileUnitAtIndex(i));
+ if (!cu_sp)
+ continue;
+ CompileUnit *cu = cu_sp.get();
+ const FileSpecList &cu_file_list = cu->GetSupportFiles();
+ size_t file_idx = cu_file_list.FindFileIndex(0, file_spec, has_path);
+ if (file_idx == UINT32_MAX)
+ // No such file in this CU.
+ continue;
+
+ // Update the file to how it appears in the CU.
+ const FileSpec &cu_file_spec = cu_file_list.GetFileSpecAtIndex(file_idx);
+
+ // Dump all the line entries for the file in the CU.
+ const ConstString &file_spec_name = file_spec.GetFilename();
+ const ConstString &module_file_name = module->GetFileSpec().GetFilename();
+ uint32_t line = 0;
+ bool cu_header_printed = false;
+ while (true)
+ {
+ LineEntry line_entry;
+
+ // Find the lowest index of a line entry with a line equal to
+ // or higher than 'line'.
+ uint32_t start_idx = 0;
+ start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec,
+ /*exact=*/false, &line_entry);
+ if (start_idx == UINT32_MAX)
+ // No more line entries for our file in this CU.
+ break;
+
+ // Loop through to find any other entries for this line, dumping each.
+ line = line_entry.line;
+ do
+ {
+ assert(lldb_private::FileSpec::Equal(cu_file_spec, line_entry.file, has_path));
+ if (cu_header_printed == false)
+ {
+ if (num_matches > 0)
+ strm << "\n\n";
+ strm << "Lines for file " << file_spec_name
+ << " in compilation unit " << cu->GetFilename()
+ << " in `" << module_file_name << "\n";
+ cu_header_printed = true;
+ }
+ line_entry.GetDescription(&strm,
+ lldb::eDescriptionLevelBrief,
+ cu,
+ interpreter.GetExecutionContext().GetTargetPtr(),
+ /*show_address_only=*/false);
+ strm << "\n";
+ num_matches++;
+
+ // Anymore after this one?
+ start_idx++;
+ start_idx = cu->FindLineEntry(start_idx, line, &cu_file_spec,
+ /*exact=*/true, &line_entry);
+ } while (start_idx != UINT32_MAX);
+
+ // Try the next higher line, starting over at start_idx 0.
+ line++;
+ }
+ }
+ }
+ return num_matches;
+}
+
static void
DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
{
@@ -2622,6 +2707,80 @@
}
};
+class CommandObjectTargetModulesDumpLineEntries : public CommandObjectTargetModulesSourceFileAutoComplete
+{
+public:
+ CommandObjectTargetModulesDumpLineEntries (CommandInterpreter &interpreter) :
+ CommandObjectTargetModulesSourceFileAutoComplete (interpreter,
+ "target modules dump line-entries",
+ "Dump the line entries for one or more files.",
+ NULL,
+ eCommandRequiresTarget)
+ {
+ }
+
+ ~CommandObjectTargetModulesDumpLineEntries () override
+ {
+ }
+
+protected:
+ bool
+ DoExecute (Args& command, CommandReturnObject &result) override
+ {
+ Target *target = m_exe_ctx.GetTargetPtr();
+ uint32_t total_num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec file_spec(arg_cstr, false);
+
+ const ModuleList &target_modules = target->GetImages();
+ Mutex::Locker modules_locker(target_modules.GetMutex());
+ const size_t num_modules = target_modules.GetSize();
+ if (num_modules > 0)
+ {
+ uint32_t num_dumped = 0;
+ for (uint32_t i = 0; i<num_modules; ++i)
+ {
+ if (DumpFileLineEntries (m_interpreter,
+ result.GetOutputStream(),
+ target_modules.GetModulePointerAtIndexUnlocked(i),
+ file_spec,
+ m_exe_ctx.GetProcessPtr() && m_exe_ctx.GetProcessRef().IsAlive()))
+ num_dumped++;
+ }
+ if (num_dumped == 0)
+ result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
+ else
+ total_num_dumped += num_dumped;
+ }
+ }
+ }
+
+ if (total_num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no source filenames matched any command arguments");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
#pragma mark CommandObjectTargetModulesDump
@@ -2645,6 +2804,7 @@
LoadSubCommand ("sections", CommandObjectSP (new CommandObjectTargetModulesDumpSections (interpreter)));
LoadSubCommand ("symfile", CommandObjectSP (new CommandObjectTargetModulesDumpSymfile (interpreter)));
LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter)));
+ LoadSubCommand ("line-entries", CommandObjectSP (new CommandObjectTargetModulesDumpLineEntries (interpreter)));
}
~CommandObjectTargetModulesDump() override
Index: packages/Python/lldbsuite/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
+++ packages/Python/lldbsuite/test/tools/lldb-mi/symbol/symbol_list_lines_inline_test.h
@@ -2,7 +2,7 @@
{
inline int
ifunc(int i)
-{
+{ // FUNC_ifunc
return i;
}
struct S
@@ -17,7 +17,7 @@
int
mfunc()
{
- return a + b;
+ return a + b; // FUNC_mfunc
}
};
extern S s;
Index: packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py
===================================================================
--- packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py
+++ packages/Python/lldbsuite/test/tools/lldb-mi/symbol/TestMiSymbol.py
@@ -48,12 +48,19 @@
eline = line_number('symbol_list_lines_inline_test2.cpp', '// END_gfunc2')
self.runCmd("-symbol-list-lines symbol_list_lines_inline_test2.cpp")
self.expect("\^done,lines=\[\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"3\d\"\})*,\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"3\d\"\})*\]" % (sline, eline))
- ##FIXME: This doesn't work for symbol_list_lines_inline_test.cpp due to clang bug llvm.org/pr24716
+ ##FIXME: This doesn't work for symbol_list_lines_inline_test.cpp due to clang bug llvm.org/pr24716 (fixed in newer versions of clang)
##sline = line_number('symbol_list_lines_inline_test.cpp', '// FUNC_gfunc')
##eline = line_number('symbol_list_lines_inline_test.cpp', '// STRUCT_s')
##self.runCmd("-symbol-list-lines symbol_list_lines_inline_test.cpp")
##self.expect("\^done,lines=\[\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"3\d\"\})*,\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}\]" % (sline, eline))
+ # Test that -symbol-list-lines works on header files by checking the first
+ # and last line, and making sure the other lines are under 29.
+ sline = line_number('symbol_list_lines_inline_test.h', '// FUNC_ifunc')
+ eline = line_number('symbol_list_lines_inline_test.h', '// FUNC_mfunc')
+ self.runCmd("-symbol-list-lines symbol_list_lines_inline_test.h")
+ self.expect("\^done,lines=\[\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"\d\"\})*(,\{pc=\"0x[0-9a-f]+\",line=\"1\d\"\})*,\{pc=\"0x[0-9a-f]+\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"2\d\"\})*\]" % (sline, eline))
+
# Test that -symbol-list-lines fails when file doesn't exist
self.runCmd("-symbol-list-lines unknown_file")
self.expect("\^error,message=\"warning: No source filenames matched 'unknown_file'\. error: no source filenames matched any command arguments \"")
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits