forked from OSchip/llvm-project
Add -s/--source option support (MI)
Summary: This patch adds -s/--source option to execute source file with prepared command. For example: ``` $ cat start_script target create ~/p/hello process launch -s continue $ bin/lldb-mi -s start_script (gdb) target create ~/p/hello Current executable set to '~/p/hello' (x86_64). ^done (gdb) process launch -s =shlibs-added,shlib-info=[num="1",name="hello",dyld-addr="-",reason="dyld",path="/Users/IliaK/p/hello",loaded_addr="-",dsym-objpath="/Users/IliaK/p/hello.dSYM/Contents/Resources/DWARF/hello"] Process 33289 launched: '/Users/IliaK/p/hello' (x86_64) ^done (gdb) continue =thread-created,id="1",group-id="i1" =thread-selected,id="1" (gdb) Process 33289 resuming Process 33289 exited with status = 0 (0x00000000) ^done ``` Test Plan: ./dotest.py -v --executable $BUILDDIR/bin/lldb tools/lldb-mi/ Reviewers: abidh Reviewed By: abidh Subscribers: lldb-commits, abidh Differential Revision: http://reviews.llvm.org/D9278 llvm-svn: 236703
This commit is contained in:
parent
8913012ee9
commit
d3da77e84e
|
@ -127,6 +127,105 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
|
||||
# Test that lldb-mi is ready when executable was loaded
|
||||
self.expect(self.child_prompt, exactly = True)
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
def test_lldbmi_source_option_start_script(self):
|
||||
"""Test that 'lldb-mi --interpreter' can execute user's commands after initial commands were executed."""
|
||||
|
||||
# Prepared source file
|
||||
sourceFile = "start_script"
|
||||
|
||||
self.spawnLldbMi(args = "--source %s" % sourceFile)
|
||||
|
||||
# After '-file-exec-and-symbols a.out'
|
||||
self.expect("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# After '-break-insert -f main'
|
||||
self.expect("-break-insert -f main")
|
||||
self.expect("\^done,bkpt={number=\"1\"")
|
||||
|
||||
# After '-exec-run'
|
||||
self.expect("-exec-run")
|
||||
self.expect("\^running")
|
||||
|
||||
# After '-break-insert main.cpp:BP_return'
|
||||
line = line_number('main.cpp', '// BP_return')
|
||||
self.expect("-break-insert main.cpp:%d" % line)
|
||||
self.expect("\^done,bkpt={number=\"2\"")
|
||||
|
||||
# After '-exec-continue'
|
||||
self.expect("-exec-continue")
|
||||
self.expect("\^running")
|
||||
|
||||
# Test that lldb-mi is ready after execution of --source start_script
|
||||
self.expect(self.child_prompt, exactly = True)
|
||||
|
||||
# Try to evaluate 'a' expression
|
||||
self.runCmd("-data-evaluate-expression a")
|
||||
self.expect("\^done,value=\"10\"")
|
||||
self.expect(self.child_prompt, exactly = True)
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
def test_lldbmi_source_option_start_script_exit(self):
|
||||
"""Test that 'lldb-mi --interpreter' can execute a prepared file which passed via --source option."""
|
||||
|
||||
# Prepared source file
|
||||
sourceFile = "start_script_exit"
|
||||
|
||||
self.spawnLldbMi(args = "--source %s" % sourceFile)
|
||||
|
||||
# After '-file-exec-and-symbols a.out'
|
||||
self.expect("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# After '-break-insert -f main'
|
||||
self.expect("-break-insert -f main")
|
||||
self.expect("\^done,bkpt={number=\"1\"")
|
||||
|
||||
# After '-exec-run'
|
||||
self.expect("-exec-run")
|
||||
self.expect("\^running")
|
||||
|
||||
# After '-break-insert main.cpp:BP_return'
|
||||
line = line_number('main.cpp', '// BP_return')
|
||||
self.expect("-break-insert main.cpp:%d" % line)
|
||||
self.expect("\^done,bkpt={number=\"2\"")
|
||||
|
||||
# After '-exec-continue'
|
||||
self.expect("-exec-continue")
|
||||
self.expect("\^running")
|
||||
|
||||
# After '-data-evaluate-expression a'
|
||||
self.expect("-data-evaluate-expression a")
|
||||
self.expect("\^done,value=\"10\"")
|
||||
|
||||
# After '-gdb-exit'
|
||||
self.expect("-gdb-exit")
|
||||
self.expect("\^exit")
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
def test_lldbmi_source_option_start_script_error(self):
|
||||
"""Test that 'lldb-mi --interpreter' stops execution of initial commands in case of error."""
|
||||
|
||||
# Prepared source file
|
||||
sourceFile = "start_script_error"
|
||||
|
||||
self.spawnLldbMi(args = "--source %s" % sourceFile)
|
||||
|
||||
# After '-file-exec-and-symbols a.out'
|
||||
self.expect("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# After '-break-ins -f main'
|
||||
self.expect("-break-ins -f main")
|
||||
self.expect("\^error")
|
||||
|
||||
# Test that lldb-mi is ready after execution of --source start_script
|
||||
self.expect(self.child_prompt, exactly = True)
|
||||
|
||||
@lldbmi_test
|
||||
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
|
||||
|
|
|
@ -10,5 +10,6 @@
|
|||
int
|
||||
main(int argc, char const *argv[])
|
||||
{
|
||||
return 0;
|
||||
int a = 10;
|
||||
return 0; // BP_return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
-file-exec-and-symbols a.out
|
||||
-break-insert -f main
|
||||
-exec-run
|
||||
-break-insert main.cpp:14
|
||||
-exec-continue
|
|
@ -0,0 +1,2 @@
|
|||
-file-exec-and-symbols a.out
|
||||
-break-ins -f main
|
|
@ -0,0 +1,7 @@
|
|||
-file-exec-and-symbols a.out
|
||||
-break-insert -f main
|
||||
-exec-run
|
||||
-break-insert main.cpp:14
|
||||
-exec-continue
|
||||
-data-evaluate-expression a
|
||||
-gdb-exit
|
|
@ -8,6 +8,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Third party headers:
|
||||
#include <fstream>
|
||||
#include "lldb/API/SBError.h"
|
||||
|
||||
// In-house headers:
|
||||
|
@ -54,6 +55,7 @@ CMIDriver::CMIDriver(void)
|
|||
, m_eCurrentDriverState(eDriverState_NotRunning)
|
||||
, m_bHaveExecutableFileNamePathOnCmdLine(false)
|
||||
, m_bDriverDebuggingArgExecutable(false)
|
||||
, m_bHaveCommandFileNamePathOnCmdLine(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -407,20 +409,40 @@ CMIDriver::ParseArgs(const int argc, const char *argv[], FILE *vpStdOut, bool &v
|
|||
|
||||
if (bHaveArgs)
|
||||
{
|
||||
// Search right to left to look for the executable
|
||||
// Search right to left to look for filenames
|
||||
for (MIint i = argc - 1; i > 0; i--)
|
||||
{
|
||||
const CMIUtilString strArg(argv[i]);
|
||||
const CMICmdArgValFile argFile;
|
||||
|
||||
// Check for a filename
|
||||
if (argFile.IsFilePath(strArg) || CMICmdArgValString(true, false, true).IsStringArg(strArg))
|
||||
{
|
||||
// Is this the command file for the '-s' or '--source' options?
|
||||
const CMIUtilString strPrevArg(argv[i - 1]);
|
||||
if (strPrevArg.compare("-s") == 0 || strPrevArg.compare("--source") == 0)
|
||||
{
|
||||
m_strCmdLineArgCommandFileNamePath = strArg;
|
||||
m_bHaveCommandFileNamePathOnCmdLine = true;
|
||||
i--; // skip '-s' on the next loop
|
||||
continue;
|
||||
}
|
||||
// Else, must be the executable
|
||||
bHaveExecutableFileNamePath = true;
|
||||
m_strCmdLineArgExecuteableFileNamePath = strArg;
|
||||
m_bHaveExecutableFileNamePathOnCmdLine = true;
|
||||
}
|
||||
// This argument is also check for in CMIDriverMgr::ParseArgs()
|
||||
if (0 == strArg.compare("--executable")) // Used to specify that there is executable argument also on the command line
|
||||
{ // See fn description.
|
||||
// Report error if no command file was specified for the '-s' or '--source' options
|
||||
else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0)
|
||||
{
|
||||
vwbExiting = true;
|
||||
const CMIUtilString errMsg = CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strArg.c_str());
|
||||
errStatus.SetErrorString(errMsg.c_str());
|
||||
break;
|
||||
}
|
||||
// This argument is also checked for in CMIDriverMgr::ParseArgs()
|
||||
else if (strArg.compare("--executable") == 0) // Used to specify that there is executable argument also on the command line
|
||||
{ // See fn description.
|
||||
bHaveExecutableLongOption = true;
|
||||
}
|
||||
}
|
||||
|
@ -526,6 +548,13 @@ CMIDriver::DoMainLoop(void)
|
|||
// App is not quitting currently
|
||||
m_bExitApp = false;
|
||||
|
||||
// Handle source file
|
||||
if (m_bHaveCommandFileNamePathOnCmdLine)
|
||||
{
|
||||
const bool bAsyncMode = false;
|
||||
ExecuteCommandFile(bAsyncMode);
|
||||
}
|
||||
|
||||
// While the app is active
|
||||
while (bOk && !m_bExitApp)
|
||||
{
|
||||
|
@ -1228,6 +1257,74 @@ CMIDriver::IsDriverDebuggingArgExecutable(void) const
|
|||
return m_bDriverDebuggingArgExecutable;
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: Execute commands from prepared source file
|
||||
// Type: Method.
|
||||
// Args: vbAsyncMode - (R) True = execute commands in asynchronous mode, false = otherwise.
|
||||
// Return: MIstatus::success - Function succeeded.
|
||||
// MIstatus::failure - Function failed.
|
||||
// Throws: None.
|
||||
//--
|
||||
bool
|
||||
CMIDriver::ExecuteCommandFile(const bool vbAsyncMode)
|
||||
{
|
||||
std::ifstream ifsStartScript(m_strCmdLineArgCommandFileNamePath.c_str());
|
||||
if (!ifsStartScript.is_open())
|
||||
{
|
||||
const CMIUtilString errMsg(
|
||||
CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN), m_strCmdLineArgCommandFileNamePath.c_str()));
|
||||
SetErrorDescription(errMsg.c_str());
|
||||
const bool bForceExit = true;
|
||||
SetExitApplicationFlag(bForceExit);
|
||||
return MIstatus::failure;
|
||||
}
|
||||
|
||||
// Switch lldb to synchronous mode
|
||||
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
||||
const bool bAsyncSetting = rSessionInfo.GetDebugger().GetAsync();
|
||||
rSessionInfo.GetDebugger().SetAsync(vbAsyncMode);
|
||||
|
||||
// Execute commands from file
|
||||
bool bOk = MIstatus::success;
|
||||
CMIUtilString strCommand;
|
||||
while (!m_bExitApp && std::getline(ifsStartScript, strCommand))
|
||||
{
|
||||
// Print command
|
||||
bOk = CMICmnStreamStdout::TextToStdout(strCommand);
|
||||
|
||||
// Skip if it's a comment or empty line
|
||||
if (strCommand.empty() || strCommand[0] == '#')
|
||||
continue;
|
||||
|
||||
// Execute if no error
|
||||
if (bOk)
|
||||
{
|
||||
CMIUtilThreadLock lock(rSessionInfo.GetSessionMutex());
|
||||
bOk = InterpretCommand(strCommand);
|
||||
}
|
||||
|
||||
// Draw the prompt after command will be executed (if enabled)
|
||||
if (bOk && m_rStdin.GetEnablePrompt())
|
||||
bOk = m_rStdOut.WriteMIResponse(m_rStdin.GetPrompt());
|
||||
|
||||
// Exit if there is an error
|
||||
if (!bOk)
|
||||
{
|
||||
const bool bForceExit = true;
|
||||
SetExitApplicationFlag(bForceExit);
|
||||
break;
|
||||
}
|
||||
|
||||
// Wait while the handler thread handles incoming events
|
||||
CMICmnLLDBDebugger::Instance().WaitForHandleEvent();
|
||||
}
|
||||
|
||||
// Switch lldb back to initial mode
|
||||
rSessionInfo.GetDebugger().SetAsync(bAsyncSetting);
|
||||
|
||||
return bOk;
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: Gets called when lldb-mi gets a signal. Stops the process if it was SIGINT.
|
||||
//
|
||||
|
|
|
@ -137,6 +137,7 @@ class CMIDriver : public CMICmnBase,
|
|||
bool InitClientIDEToMIDriver(void) const;
|
||||
bool InitClientIDEEclipse(void) const;
|
||||
bool LocalDebugSessionStartupExecuteCommands(void);
|
||||
bool ExecuteCommandFile(const bool vbAsyncMode);
|
||||
|
||||
// Overridden:
|
||||
private:
|
||||
|
@ -161,4 +162,6 @@ class CMIDriver : public CMICmnBase,
|
|||
CMIUtilString m_strCmdLineArgExecuteableFileNamePath;
|
||||
bool m_bDriverDebuggingArgExecutable; // True = the MI Driver (MI mode) is debugging executable passed as argument,
|
||||
// false = running via a client (e.g. Eclipse)
|
||||
bool m_bHaveCommandFileNamePathOnCmdLine; // True = file with initial commands given as one of the parameters to the MI Driver, false = not found
|
||||
CMIUtilString m_strCmdLineArgCommandFileNamePath;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue