Changeset View
Changeset View
Standalone View
Standalone View
lldb/trunk/tools/lldb-mi/MICmdCmdSymbol.cpp
Show First 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
// Throws: None. | // Throws: None. | ||||
//-- | //-- | ||||
bool | bool | ||||
CMICmdCmdSymbolListLines::Execute() | CMICmdCmdSymbolListLines::Execute() | ||||
{ | { | ||||
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile); | CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile); | ||||
const CMIUtilString &strFilePath(pArgFile->GetValue()); | const CMIUtilString &strFilePath(pArgFile->GetValue()); | ||||
// FIXME: this won't work for header files! To try and use existing | const CMIUtilString strCmd(CMIUtilString::Format("source info --file \"%s\"", strFilePath.AddSlashes().c_str())); | ||||
// 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()); | CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); | ||||
const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult); | const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult); | ||||
MIunused(rtn); | MIunused(rtn); | ||||
return MIstatus::success; | return MIstatus::success; | ||||
} | } | ||||
//++ ------------------------------------------------------------------------------------ | //++ ------------------------------------------------------------------------------------ | ||||
// Details: Helper function for parsing the header returned from lldb for the command: | // Details: Helper function for parsing the header returned from lldb for the command: | ||||
// target modules dump line-table <file> | // target modules dump line-table <file> | ||||
// where the header is of the format: | // where the header is of the format: | ||||
// Line table for /path/to/file in `/path/to/module | // Line table for /path/to/file in `/path/to/module | ||||
// Args: input - (R) Input string to parse. | // Args: input - (R) Input string to parse. | ||||
// file - (W) String representing the file. | // file - (W) String representing the file. | ||||
// Return: bool - True = input was parsed successfully, false = input could not be parsed. | // Return: bool - True = input was parsed successfully, false = input could not be parsed. | ||||
// Throws: None. | // Throws: None. | ||||
//-- | //-- | ||||
static bool | static bool | ||||
ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) | ParseLLDBLineAddressHeader(const char *input, CMIUtilString &file) | ||||
{ | { | ||||
// Match LineEntry using regex. | // Match LineEntry using regex. | ||||
static MIUtilParse::CRegexParser g_lineentry_header_regex( | static MIUtilParse::CRegexParser g_lineentry_header_regex( | ||||
"^ *Line table for (.+) in `(.+)$"); | "^ *Lines for file (.+) in compilation unit (.+) in `(.+)$"); | ||||
// ^1=file ^2=module | // ^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); | const bool ok = g_lineentry_header_regex.Execute(input, match); | ||||
if (ok) | if (ok) | ||||
file = match.GetMatchAtIndex(1); | file = match.GetMatchAtIndex(1); | ||||
return ok; | return ok; | ||||
} | } | ||||
//++ ------------------------------------------------------------------------------------ | //++ ------------------------------------------------------------------------------------ | ||||
Show All 16 Lines | ParseLLDBLineAddressEntry(const char *input, CMIUtilString &addr, | ||||
// Note: Ambiguities arise because the column is optional, and | // Note: Ambiguities arise because the column is optional, and | ||||
// because : can appear in filenames or as a byte in a multibyte | // because : can appear in filenames or as a byte in a multibyte | ||||
// UTF8 character. We keep those cases to a minimum by using regex | // 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 | // to work on the string from both the left and right, so that what | ||||
// is remains is assumed to be the filename. | // is remains is assumed to be the filename. | ||||
// Match LineEntry using regex. | // Match LineEntry using regex. | ||||
static MIUtilParse::CRegexParser g_lineentry_nocol_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( | static MIUtilParse::CRegexParser g_lineentry_col_regex( | ||||
"^ *(0x[0-9a-fA-F]+): (.+):([0-9]+):[0-9]+$"); | "^ *\\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$"); | ||||
// ^1=addr ^2=f ^3=line ^4=:col(opt) | // ^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, | // First try matching the LineEntry with the column, | ||||
// then try without the column. | // then try without the column. | ||||
const bool ok = g_lineentry_col_regex.Execute(input, match) || | const bool ok = g_lineentry_col_regex.Execute(input, match) || | ||||
g_lineentry_nocol_regex.Execute(input, match); | g_lineentry_nocol_regex.Execute(input, match); | ||||
if (ok) | if (ok) | ||||
{ | { | ||||
addr = match.GetMatchAtIndex(1); | addr = match.GetMatchAtIndex(1); | ||||
file = match.GetMatchAtIndex(2); | file = match.GetMatchAtIndex(3); | ||||
line = match.GetMatchAtIndex(3); | line = match.GetMatchAtIndex(4); | ||||
} | } | ||||
return ok; | return ok; | ||||
} | } | ||||
//++ ------------------------------------------------------------------------------------ | //++ ------------------------------------------------------------------------------------ | ||||
// Details: The invoker requires this function. The command prepares a MI Record Result | // Details: The invoker requires this function. The command prepares a MI Record Result | ||||
// for the work carried out in the Execute(). | // for the work carried out in the Execute(). | ||||
// Type: Overridden. | // Type: Overridden. | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | else | ||||
const CMIUtilString &rLine(vecLines[i]); | const CMIUtilString &rLine(vecLines[i]); | ||||
CMIUtilString strAddr; | CMIUtilString strAddr; | ||||
CMIUtilString strFile; | CMIUtilString strFile; | ||||
CMIUtilString strLine; | CMIUtilString strLine; | ||||
if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine)) | if (!ParseLLDBLineAddressEntry(rLine.c_str(), strAddr, strFile, strLine)) | ||||
continue; | continue; | ||||
// Skip entries which don't match the desired source. | |||||
if (strWantFile != strFile) | |||||
continue; | |||||
const CMICmnMIValueConst miValueConst(strAddr); | const CMICmnMIValueConst miValueConst(strAddr); | ||||
const CMICmnMIValueResult miValueResult("pc", miValueConst); | const CMICmnMIValueResult miValueResult("pc", miValueConst); | ||||
CMICmnMIValueTuple miValueTuple(miValueResult); | CMICmnMIValueTuple miValueTuple(miValueResult); | ||||
const CMICmnMIValueConst miValueConst2(strLine); | const CMICmnMIValueConst miValueConst2(strLine); | ||||
const CMICmnMIValueResult miValueResult2("line", miValueConst2); | const CMICmnMIValueResult miValueResult2("line", miValueConst2); | ||||
miValueTuple.Add(miValueResult2); | miValueTuple.Add(miValueResult2); | ||||
Show All 25 Lines |