diff options
Diffstat (limited to 'tools/lldb-mi/MICmdCmdSymbol.cpp')
-rw-r--r-- | tools/lldb-mi/MICmdCmdSymbol.cpp | 136 |
1 files changed, 112 insertions, 24 deletions
diff --git a/tools/lldb-mi/MICmdCmdSymbol.cpp b/tools/lldb-mi/MICmdCmdSymbol.cpp index 2649389d76862..d99ceef22498f 100644 --- a/tools/lldb-mi/MICmdCmdSymbol.cpp +++ b/tools/lldb-mi/MICmdCmdSymbol.cpp @@ -19,6 +19,7 @@ #include "MICmnMIResultRecord.h" #include "MICmnMIValueList.h" #include "MICmnMIValueTuple.h" +#include "MIUtilParse.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdSymbolListLines constructor. @@ -27,7 +28,7 @@ // Return: None. // Throws: None. //-- -CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines(void) +CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines() : m_constStrArgNameFile("file") { // Command factory matches this name with that received from the stdin stream @@ -44,7 +45,7 @@ CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines(void) // Return: None. // Throws: None. //-- -CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines(void) +CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines() { } @@ -58,10 +59,10 @@ CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines(void) // Throws: None. //-- bool -CMICmdCmdSymbolListLines::ParseArgs(void) +CMICmdCmdSymbolListLines::ParseArgs() { - bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNameFile, true, true))); - return (bOk && ParseValidateCmdOptions()); + m_setCmdArgs.Add(new CMICmdArgValFile(m_constStrArgNameFile, true, true)); + return ParseValidateCmdOptions(); } //++ ------------------------------------------------------------------------------------ @@ -76,11 +77,15 @@ CMICmdCmdSymbolListLines::ParseArgs(void) // Throws: None. //-- bool -CMICmdCmdSymbolListLines::Execute(void) +CMICmdCmdSymbolListLines::Execute() { 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())); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); @@ -91,6 +96,77 @@ CMICmdCmdSymbolListLines::Execute(void) } //++ ------------------------------------------------------------------------------------ +// Details: Helper function for parsing the header returned from lldb for the command: +// target modules dump line-table <file> +// where the header is of the format: +// Line table for /path/to/file in `/path/to/module +// Args: input - (R) Input string to parse. +// file - (W) String representing the file. +// Return: bool - True = input was parsed successfully, false = input could not be parsed. +// Throws: None. +//-- +static bool +ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) +{ + // Match LineEntry using regex. + static MIUtilParse::CRegexParser g_lineentry_header_regex( + "^ *Line table for (.+) in `(.+)$"); + // ^1=file ^2=module + + MIUtilParse::CRegexParser::Match match(3); + + const bool ok = g_lineentry_header_regex.Execute(input, match); + if (ok) + file = match.GetMatchAtIndex(1); + return ok; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Helper function for parsing a line entry returned from lldb for the command: +// target modules dump line-table <file> +// where the line entry is of the format: +// 0x0000000100000e70: /path/to/file:3002[:4] +// addr file line column(opt) +// Args: input - (R) Input string to parse. +// addr - (W) String representing the pc address. +// file - (W) String representing the file. +// line - (W) String representing the line. +// Return: bool - True = input was parsed successfully, false = input could not be parsed. +// Throws: None. +//-- +static bool +ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr, + CMIUtilString &file, CMIUtilString &line) +{ + // Note: Ambiguities arise because the column is optional, and + // because : can appear in filenames or as a byte in a multibyte + // UTF8 character. We keep those cases to a minimum by using regex + // to work on the string from both the left and right, so that what + // is remains is assumed to be the filename. + + // Match LineEntry using regex. + static MIUtilParse::CRegexParser g_lineentry_nocol_regex( + "^ *(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) + + MIUtilParse::CRegexParser::Match match(5); + + // First try matching the LineEntry with the column, + // then try without the column. + const bool ok = g_lineentry_col_regex.Execute(input, match) || + g_lineentry_nocol_regex.Execute(input, match); + if (ok) + { + addr = match.GetMatchAtIndex(1); + file = match.GetMatchAtIndex(2); + line = match.GetMatchAtIndex(3); + } + return ok; +} + +//++ ------------------------------------------------------------------------------------ // Details: The invoker requires this function. The command prepares a MI Record Result // for the work carried out in the Execute(). // Type: Overridden. @@ -100,7 +176,7 @@ CMICmdCmdSymbolListLines::Execute(void) // Throws: None. //-- bool -CMICmdCmdSymbolListLines::Acknowledge(void) +CMICmdCmdSymbolListLines::Acknowledge() { if (m_lldbResult.GetErrorSize() > 0) { @@ -117,36 +193,48 @@ CMICmdCmdSymbolListLines::Acknowledge(void) const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); const MIuint nLines(strLldbMsg.SplitLines(vecLines)); + // Parse the file from the header. + const CMIUtilString &rWantFile(vecLines[0]); + CMIUtilString strWantFile; + if (!ParseLLDBLineAddressHeader(rWantFile.c_str(), strWantFile)) + { + // Unexpected error - parsing failed. + // MI print "%s^error,msg=\"Command '-symbol-list-lines'. Error: Line address header is absent or has an unknown format.\"" + const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "Line address header is absent or has an unknown format.")); + const CMICmnMIValueResult miValueResult("msg", miValueConst); + const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); + m_miResultRecord = miRecordResult; + + return MIstatus::success; + } + + // Parse the line address entries. CMICmnMIValueList miValueList(true); for (MIuint i = 1; i < nLines; ++i) { // String looks like: // 0x0000000100000e70: /path/to/file:3[:4] const CMIUtilString &rLine(vecLines[i]); + CMIUtilString strAddr; + CMIUtilString strFile; + CMIUtilString strLine; + + if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine)) + continue; + + // Skip entries which don't match the desired source. + if (strWantFile != strFile) + continue; - // 0x0000000100000e70: /path/to/file:3[:4] - // ^^^^^^^^^^^^^^^^^^ -- pc - const size_t nAddrEndPos = rLine.find(':'); - const CMIUtilString strAddr(rLine.substr(0, nAddrEndPos).c_str()); const CMICmnMIValueConst miValueConst(strAddr); const CMICmnMIValueResult miValueResult("pc", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); - // 0x0000000100000e70: /path/to/file:3[:4] - // ^ -- line - const size_t nLineOrColumnStartPos = rLine.rfind(':'); - const CMIUtilString strLineOrColumn(rLine.substr(nLineOrColumnStartPos + 1).c_str()); - const size_t nPathOrLineStartPos = rLine.rfind(':', nLineOrColumnStartPos - 1); - const size_t nPathOrLineLen = nLineOrColumnStartPos - nPathOrLineStartPos - 1; - const CMIUtilString strPathOrLine(rLine.substr(nPathOrLineStartPos + 1, nPathOrLineLen).c_str()); - const CMIUtilString strLine(strPathOrLine.IsNumber() ? strPathOrLine : strLineOrColumn); const CMICmnMIValueConst miValueConst2(strLine); const CMICmnMIValueResult miValueResult2("line", miValueConst2); - bool bOk = miValueTuple.Add(miValueResult2); + miValueTuple.Add(miValueResult2); - bOk = bOk && miValueList.Add(miValueTuple); - if (!bOk) - return MIstatus::failure; + miValueList.Add(miValueTuple); } // MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]" @@ -167,7 +255,7 @@ CMICmdCmdSymbolListLines::Acknowledge(void) // Throws: None. //-- CMICmdBase * -CMICmdCmdSymbolListLines::CreateSelf(void) +CMICmdCmdSymbolListLines::CreateSelf() { return new CMICmdCmdSymbolListLines(); } |