Skip to content

Commit c12d88d

Browse files
committedFeb 20, 2015
Add -symbol-list-lines command (MI)
Summary: Add -symbol-list-lines command + test. All test passed on OS X. Reviewers: emaste, abidh, clayborg Reviewed By: clayborg Subscribers: lldb-commits, clayborg, abidh, emaste Differential Revision: http://reviews.llvm.org/D7768 llvm-svn: 230008
1 parent 7329636 commit c12d88d

File tree

8 files changed

+329
-1
lines changed

8 files changed

+329
-1
lines changed
 
+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
Test that the lldb-mi driver works with -symbol-xxx commands
3+
"""
4+
5+
import lldbmi_testcase
6+
from lldbtest import *
7+
import unittest2
8+
9+
class MiSymbolTestCase(lldbmi_testcase.MiTestCaseBase):
10+
11+
@lldbmi_test
12+
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
13+
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
14+
@skipIfLinux # llvm.org/pr22411: Failure presumably due to known thread races
15+
def test_lldbmi_symbol_list_lines_file(self):
16+
"""Test that 'lldb-mi --interpreter' works for -symbol-list-lines when file exists."""
17+
18+
self.spawnLldbMi(args = None)
19+
20+
# Load executable
21+
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
22+
self.expect("\^done")
23+
24+
# Run to main
25+
self.runCmd("-break-insert -f main")
26+
self.expect("\^done,bkpt={number=\"1\"")
27+
self.runCmd("-exec-run")
28+
self.expect("\^running")
29+
self.expect("\*stopped,reason=\"breakpoint-hit\"")
30+
31+
# Get address of main
32+
self.runCmd("-data-evaluate-expression main")
33+
self.expect("\^done,value=\"0x[0-9a-f]+\"")
34+
main_addr = int(self.child.after.split("\"")[1], 16)
35+
main_line = line_number('main.c', '//FUNC_main')
36+
37+
# Test that -symbol-list-lines works on valid data
38+
self.runCmd("-symbol-list-lines main.c")
39+
self.expect("\^done,lines=\[\{pc=\"0x0*%x\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"\d+\"\})+\]" % (main_addr, main_line))
40+
41+
# Test that -symbol-list-lines fails when file doesn't exist
42+
self.runCmd("-symbol-list-lines unknown_file")
43+
self.expect("\^error,message=\"warning: No source filenames matched 'unknown_file'. error: no source filenames matched any command arguments \"")
44+
45+
# Test that -symbol-list-lines fails when file is specified using relative path
46+
self.runCmd("-symbol-list-lines ./main.c")
47+
self.expect("\^error,message=\"warning: No source filenames matched './main.c'. error: no source filenames matched any command arguments \"")
48+
49+
# Test that -symbol-list-lines works when file is specified using absolute path
50+
import os
51+
main_file = os.path.join(os.getcwd(), "main.c")
52+
self.runCmd("-symbol-list-lines \"%s\"" % main_file)
53+
self.expect("\^done,lines=\[\{pc=\"0x0*%x\",line=\"%d\"\}(,\{pc=\"0x[0-9a-f]+\",line=\"\d+\"\})+\]" % (main_addr, main_line))
54+
55+
# Test that -symbol-list-lines fails when file doesn't exist
56+
self.runCmd("-symbol-list-lines unknown_dir/main.c")
57+
self.expect("\^error,message=\"warning: No source filenames matched 'unknown_dir/main.c'. error: no source filenames matched any command arguments \"")
58+
59+
if __name__ == '__main__':
60+
unittest2.main()

‎lldb/test/tools/lldb-mi/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ static int s_MyVar = 4;
1919
const char s_RawData[] = "\x12\x34\x56\x78"; //FIXME static const char s_RawData[] = "\x12\x34\x56\x78";
2020

2121
int main (int argc, char const *argv[])
22-
{
22+
{ //FUNC_main
2323
int a, b;
2424
printf("argc=%d\n", argc); //BP_printf_call
2525
//BP_argctest

‎lldb/tools/lldb-mi/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_lldb_executable(lldb-mi
3030
MICmdCmdStack.cpp
3131
MICmdCmdSupportInfo.cpp
3232
MICmdCmdSupportList.cpp
33+
MICmdCmdSymbol.cpp
3334
MICmdCmdTarget.cpp
3435
MICmdCmdThread.cpp
3536
MICmdCmdTrace.cpp
@@ -111,6 +112,7 @@ add_lldb_executable(lldb-mi
111112
MICmdCmdStack.cpp
112113
MICmdCmdSupportInfo.cpp
113114
MICmdCmdSupportList.cpp
115+
MICmdCmdSymbol.cpp
114116
MICmdCmdTarget.cpp
115117
MICmdCmdThread.cpp
116118
MICmdCmdTrace.cpp

‎lldb/tools/lldb-mi/MICmdCmdSymbol.cpp

+183
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
//===-- MICmdCmdSymbol.cpp --------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
//++
11+
// File: MICmdCmdSymbol.cpp
12+
//
13+
// Overview: CMICmdCmdSymbolListLines implementation.
14+
//
15+
// Environment: Compilers: Visual C++ 12.
16+
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
17+
// Libraries: See MIReadmetxt.
18+
//
19+
// Copyright: None.
20+
//--
21+
22+
// Third Party Headers:
23+
#include <lldb/API/SBCommandInterpreter.h>
24+
25+
// In-house headers:
26+
#include "MICmdArgValFile.h"
27+
#include "MICmdCmdSymbol.h"
28+
#include "MICmnLLDBDebugSessionInfo.h"
29+
#include "MICmnMIResultRecord.h"
30+
#include "MICmnMIValueList.h"
31+
#include "MICmnMIValueTuple.h"
32+
33+
//++ ------------------------------------------------------------------------------------
34+
// Details: CMICmdCmdSymbolListLines constructor.
35+
// Type: Method.
36+
// Args: None.
37+
// Return: None.
38+
// Throws: None.
39+
//--
40+
CMICmdCmdSymbolListLines::CMICmdCmdSymbolListLines(void)
41+
: m_constStrArgNameFile("file")
42+
{
43+
// Command factory matches this name with that received from the stdin stream
44+
m_strMiCmd = "symbol-list-lines";
45+
46+
// Required by the CMICmdFactory when registering *this command
47+
m_pSelfCreatorFn = &CMICmdCmdSymbolListLines::CreateSelf;
48+
}
49+
50+
//++ ------------------------------------------------------------------------------------
51+
// Details: CMICmdCmdSymbolListLines destructor.
52+
// Type: Overrideable.
53+
// Args: None.
54+
// Return: None.
55+
// Throws: None.
56+
//--
57+
CMICmdCmdSymbolListLines::~CMICmdCmdSymbolListLines(void)
58+
{
59+
}
60+
61+
//++ ------------------------------------------------------------------------------------
62+
// Details: The invoker requires this function. The parses the command line options
63+
// arguments to extract values for each of those arguments.
64+
// Type: Overridden.
65+
// Args: None.
66+
// Return: MIstatus::success - Functional succeeded.
67+
// MIstatus::failure - Functional failed.
68+
// Throws: None.
69+
//--
70+
bool
71+
CMICmdCmdSymbolListLines::ParseArgs(void)
72+
{
73+
bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValFile(m_constStrArgNameFile, true, true)));
74+
return (bOk && ParseValidateCmdOptions());
75+
}
76+
77+
//++ ------------------------------------------------------------------------------------
78+
// Details: The invoker requires this function. The command does work in this function.
79+
// The command is likely to communicate with the LLDB SBDebugger in here.
80+
// Synopsis: -symbol-list-lines file
81+
// Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Symbol-Query.html#GDB_002fMI-Symbol-Query
82+
// Type: Overridden.
83+
// Args: None.
84+
// Return: MIstatus::success - Functional succeeded.
85+
// MIstatus::failure - Functional failed.
86+
// Throws: None.
87+
//--
88+
bool
89+
CMICmdCmdSymbolListLines::Execute(void)
90+
{
91+
CMICMDBASE_GETOPTION(pArgFile, File, m_constStrArgNameFile);
92+
93+
const CMIUtilString &strFilePath(pArgFile->GetValue());
94+
const CMIUtilString strCmd(CMIUtilString::Format("target modules dump line-table \"%s\"", strFilePath.c_str()));
95+
96+
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
97+
const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult);
98+
MIunused(rtn);
99+
100+
return MIstatus::success;
101+
}
102+
103+
//++ ------------------------------------------------------------------------------------
104+
// Details: The invoker requires this function. The command prepares a MI Record Result
105+
// for the work carried out in the Execute().
106+
// Type: Overridden.
107+
// Args: None.
108+
// Return: MIstatus::success - Functional succeeded.
109+
// MIstatus::failure - Functional failed.
110+
// Throws: None.
111+
//--
112+
bool
113+
CMICmdCmdSymbolListLines::Acknowledge(void)
114+
{
115+
if (m_lldbResult.GetErrorSize() > 0)
116+
{
117+
const MIchar *pLldbErr = m_lldbResult.GetError();
118+
const CMIUtilString strMsg(CMIUtilString(pLldbErr).StripCRAll());
119+
const CMICmnMIValueConst miValueConst(strMsg);
120+
const CMICmnMIValueResult miValueResult("message", miValueConst);
121+
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
122+
m_miResultRecord = miRecordResult;
123+
}
124+
else
125+
{
126+
CMIUtilString::VecString_t vecLines;
127+
const CMIUtilString strLldbMsg(m_lldbResult.GetOutput());
128+
const MIuint nLines(strLldbMsg.SplitLines(vecLines));
129+
130+
CMICmnMIValueList miValueList(true);
131+
for (MIuint i = 1; i < nLines; ++i)
132+
{
133+
// String looks like:
134+
// 0x0000000100000e70: /path/to/file:3[:4]
135+
const CMIUtilString &rLine(vecLines[i]);
136+
137+
// 0x0000000100000e70: /path/to/file:3[:4]
138+
// ^^^^^^^^^^^^^^^^^^ -- pc
139+
const MIuint nAddrEndPos = rLine.find(':');
140+
const CMIUtilString strAddr(rLine.substr(0, nAddrEndPos).c_str());
141+
const CMICmnMIValueConst miValueConst(strAddr);
142+
const CMICmnMIValueResult miValueResult("pc", miValueConst);
143+
CMICmnMIValueTuple miValueTuple(miValueResult);
144+
145+
// 0x0000000100000e70: /path/to/file:3[:4]
146+
// ^ -- line
147+
const MIuint nLineOrColumnStartPos = rLine.rfind(':');
148+
const CMIUtilString strLineOrColumn(rLine.substr(nLineOrColumnStartPos + 1).c_str());
149+
const MIuint nPathOrLineStartPos = rLine.rfind(':', nLineOrColumnStartPos - 1);
150+
const MIuint nPathOrLineLen = nLineOrColumnStartPos - nPathOrLineStartPos - 1;
151+
const CMIUtilString strPathOrLine(rLine.substr(nPathOrLineStartPos + 1, nPathOrLineLen).c_str());
152+
const CMIUtilString strLine(strPathOrLine.IsNumber() ? strPathOrLine : strLineOrColumn);
153+
const CMICmnMIValueConst miValueConst2(strLine);
154+
const CMICmnMIValueResult miValueResult2("line", miValueConst2);
155+
bool bOk = miValueTuple.Add(miValueResult2);
156+
157+
bOk = bOk && miValueList.Add(miValueTuple);
158+
if (!bOk)
159+
return MIstatus::failure;
160+
}
161+
162+
// MI print "%s^done,lines=[{pc=\"%d\",line=\"%d\"}...]"
163+
const CMICmnMIValueResult miValueResult("lines", miValueList);
164+
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
165+
m_miResultRecord = miRecordResult;
166+
}
167+
168+
return MIstatus::success;
169+
}
170+
171+
//++ ------------------------------------------------------------------------------------
172+
// Details: Required by the CMICmdFactory when registering *this command. The factory
173+
// calls this function to create an instance of *this command.
174+
// Type: Static method.
175+
// Args: None.
176+
// Return: CMICmdBase * - Pointer to a new command.
177+
// Throws: None.
178+
//--
179+
CMICmdBase *
180+
CMICmdCmdSymbolListLines::CreateSelf(void)
181+
{
182+
return new CMICmdCmdSymbolListLines();
183+
}

‎lldb/tools/lldb-mi/MICmdCmdSymbol.h

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
//===-- MICmdCmdSymbol.h ----------------------------------------*- C++ -*-===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
//++
11+
// File: MICmdCmdSymbol.h
12+
//
13+
// Overview: CMICmdCmdSymbolListLines interface.
14+
//
15+
// To implement new MI commands derive a new command class from the command base
16+
// class. To enable the new command for interpretation add the new command class
17+
// to the command factory. The files of relevance are:
18+
// MICmdCommands.cpp
19+
// MICmdBase.h / .cpp
20+
// MICmdCmd.h / .cpp
21+
// For an introduction to adding a new command see CMICmdCmdSupportInfoMiCmdQuery
22+
// command class as an example.
23+
//
24+
// Environment: Compilers: Visual C++ 12.
25+
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
26+
// Libraries: See MIReadmetxt.
27+
//
28+
// Copyright: None.
29+
//--
30+
31+
#pragma once
32+
33+
// Third party headers:
34+
#include <lldb/API/SBCommandReturnObject.h>
35+
36+
// In-house headers:
37+
#include "MICmdBase.h"
38+
39+
//++ ============================================================================
40+
// Details: MI command class. MI commands derived from the command base class.
41+
// *this class implements MI command "symbol-list-lines".
42+
//--
43+
class CMICmdCmdSymbolListLines : public CMICmdBase
44+
{
45+
// Statics:
46+
public:
47+
// Required by the CMICmdFactory when registering *this command
48+
static CMICmdBase *CreateSelf(void);
49+
50+
// Methods:
51+
public:
52+
/* ctor */ CMICmdCmdSymbolListLines(void);
53+
54+
// Overridden:
55+
public:
56+
// From CMICmdInvoker::ICmd
57+
virtual bool Execute(void);
58+
virtual bool Acknowledge(void);
59+
virtual bool ParseArgs(void);
60+
// From CMICmnBase
61+
/* dtor */ virtual ~CMICmdCmdSymbolListLines(void);
62+
63+
// Attributes:
64+
private:
65+
lldb::SBCommandReturnObject m_lldbResult;
66+
const CMIUtilString m_constStrArgNameFile;
67+
};

‎lldb/tools/lldb-mi/MICmdCommands.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "MICmdCmdStack.h"
4343
#include "MICmdCmdSupportInfo.h"
4444
#include "MICmdCmdSupportList.h"
45+
#include "MICmdCmdSymbol.h"
4546
#include "MICmdCmdTarget.h"
4647
#include "MICmdCmdThread.h"
4748
#include "MICmdCmdTrace.h"
@@ -123,6 +124,7 @@ MICmnCommands::RegisterAll(void)
123124
bOk &= Register<CMICmdCmdStackListLocals>();
124125
bOk &= Register<CMICmdCmdStackSelectFrame>();
125126
bOk &= Register<CMICmdCmdSupportListFeatures>();
127+
bOk &= Register<CMICmdCmdSymbolListLines>();
126128
bOk &= Register<CMICmdCmdTargetSelect>();
127129
bOk &= Register<CMICmdCmdThreadInfo>();
128130
bOk &= Register<CMICmdCmdVarAssign>();

‎lldb/tools/lldb-mi/MIUtilString.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,19 @@ CMIUtilString::SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t
307307
return vwVecSplits.size();
308308
}
309309

310+
//++ ------------------------------------------------------------------------------------
311+
// Details: Split string into lines using \n and return an array of strings.
312+
// Type: Method.
313+
// Args: vwVecSplits - (W) Container of splits found in string data.
314+
// Return: MIuint - Number of splits found in the string data.
315+
// Throws: None.
316+
//--
317+
MIuint
318+
CMIUtilString::SplitLines(VecString_t &vwVecSplits) const
319+
{
320+
return Split("\n", vwVecSplits);
321+
}
322+
310323
//++ ------------------------------------------------------------------------------------
311324
// Details: Remove '\n' from the end of string if found. It does not alter
312325
// *this string.

‎lldb/tools/lldb-mi/MIUtilString.h

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class CMIUtilString : public std::string
6363
CMIUtilString RemoveRepeatedCharacters(const MIchar vChar);
6464
MIuint Split(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const;
6565
MIuint SplitConsiderQuotes(const CMIUtilString &vDelimiter, VecString_t &vwVecSplits) const;
66+
MIuint SplitLines(VecString_t &vwVecSplits) const;
6667
CMIUtilString StripCREndOfLine(void) const;
6768
CMIUtilString StripCRAll(void) const;
6869
CMIUtilString Trim(void) const;

0 commit comments

Comments
 (0)
Please sign in to comment.