forked from OSchip/llvm-project
[lldb-mi] Add support for StopAtEntry in MI via "-exec-run --start".
This patch adds a --start option to the lldb-mi -exec-run command for getting process stopped at entry point after launch. It is equivelent to the -s option in the lldb command line interpreter: process launch -s and is therefore not supported on all hosts and/or targets. To check if the --start option is supported, see if the corresponding feature "exec-run-start-option" is in the list of options reported by the lldb-mi "-list-features" command. Patch from engineer.developer@gmail.com (Kirill Lapshin) Reviewed by: ki.stfu Subscribers: lldb-commits Differential Revision: http://reviews.llvm.org/D12977 llvm-svn: 249072
This commit is contained in:
parent
52bf0ebfdf
commit
8587212085
|
@ -10,6 +10,26 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@lldbmi_test
|
||||
@skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
|
||||
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
|
||||
@expectedFailureLinux # llvm.org/pr25000: lldb-mi does not receive broadcasted notification from Core/Process about process stopped
|
||||
def test_lldbmi_exec_run(self):
|
||||
"""Test that 'lldb-mi --interpreter' can stop at entry."""
|
||||
|
||||
self.spawnLldbMi(args = None)
|
||||
|
||||
# Load executable
|
||||
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# Test that program is stopped at entry
|
||||
self.runCmd("-exec-run --start")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",.*?thread-id=\"1\",stopped-threads=\"all\"")
|
||||
# Test that lldb-mi is ready to execute next commands
|
||||
self.expect(self.child_prompt, exactly = True)
|
||||
|
||||
@lldbmi_test
|
||||
@skipIfWindows #llvm.org/pr24452: Get lldb-mi tests working on Windows
|
||||
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
// Throws: None.
|
||||
//--
|
||||
CMICmdCmdExecRun::CMICmdCmdExecRun()
|
||||
: m_constStrArgStart("start")
|
||||
{
|
||||
// Command factory matches this name with that received from the stdin stream
|
||||
m_strMiCmd = "exec-run";
|
||||
|
@ -67,6 +68,23 @@ CMICmdCmdExecRun::~CMICmdCmdExecRun()
|
|||
{
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: The invoker requires this function. It parses the command line options'
|
||||
// arguments to extract values for each of those arguments.
|
||||
// Type: Overridden.
|
||||
// Args: None.
|
||||
// Return: MIstatus::success - Functional succeeded.
|
||||
// MIstatus::failure - Functional failed.
|
||||
// Throws: None.
|
||||
//--
|
||||
bool
|
||||
CMICmdCmdExecRun::ParseArgs()
|
||||
{
|
||||
m_setCmdArgs.Add(
|
||||
new CMICmdArgValOptionLong(m_constStrArgStart, false, true, CMICmdArgValListBase::eArgValType_OptionLong, 0));
|
||||
return ParseValidateCmdOptions();
|
||||
}
|
||||
|
||||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: The invoker requires this function. The command does work in this function.
|
||||
// The command is likely to communicate with the LLDB SBDebugger in here.
|
||||
|
@ -84,6 +102,14 @@ CMICmdCmdExecRun::Execute()
|
|||
lldb::SBStream errMsg;
|
||||
lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo();
|
||||
launchInfo.SetListener(rSessionInfo.GetListener());
|
||||
|
||||
// Run to first instruction or main() requested?
|
||||
CMICMDBASE_GETOPTION(pArgStart, OptionLong, m_constStrArgStart);
|
||||
if (pArgStart->GetFound())
|
||||
{
|
||||
launchInfo.SetLaunchFlags(launchInfo.GetLaunchFlags() | lldb::eLaunchFlagStopAtEntry);
|
||||
}
|
||||
|
||||
lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error);
|
||||
if ((!process.IsValid()) || (error.Fail()))
|
||||
{
|
||||
|
@ -103,6 +129,7 @@ CMICmdCmdExecRun::Execute()
|
|||
//++ ------------------------------------------------------------------------------------
|
||||
// Details: The invoker requires this function. The command prepares a MI Record Result
|
||||
// for the work carried out in the Execute().
|
||||
// Called only if Execute() set status as successful on completion.
|
||||
// Type: Overridden.
|
||||
// Args: None.
|
||||
// Return: MIstatus::success - Functional succeeded.
|
||||
|
@ -112,31 +139,21 @@ CMICmdCmdExecRun::Execute()
|
|||
bool
|
||||
CMICmdCmdExecRun::Acknowledge()
|
||||
{
|
||||
if (m_lldbResult.GetErrorSize() > 0)
|
||||
{
|
||||
const CMICmnMIValueConst miValueConst(m_lldbResult.GetError());
|
||||
const CMICmnMIValueResult miValueResult("message", miValueConst);
|
||||
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult);
|
||||
m_miResultRecord = miRecordResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
|
||||
m_miResultRecord = miRecordResult;
|
||||
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running);
|
||||
m_miResultRecord = miRecordResult;
|
||||
|
||||
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
||||
lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
|
||||
// Give the client '=thread-group-started,id="i1" pid="xyz"'
|
||||
m_bHasResultRecordExtra = true;
|
||||
const CMICmnMIValueConst miValueConst2("i1");
|
||||
const CMICmnMIValueResult miValueResult2("id", miValueConst2);
|
||||
const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
|
||||
const CMICmnMIValueConst miValueConst(strPid);
|
||||
const CMICmnMIValueResult miValueResult("pid", miValueConst);
|
||||
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
|
||||
miOutOfBand.Add(miValueResult);
|
||||
m_miResultRecordExtra = miOutOfBand.GetString();
|
||||
}
|
||||
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
||||
lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID();
|
||||
// Give the client '=thread-group-started,id="i1" pid="xyz"'
|
||||
m_bHasResultRecordExtra = true;
|
||||
const CMICmnMIValueConst miValueConst2("i1");
|
||||
const CMICmnMIValueResult miValueResult2("id", miValueConst2);
|
||||
const CMIUtilString strPid(CMIUtilString::Format("%lld", pid));
|
||||
const CMICmnMIValueConst miValueConst(strPid);
|
||||
const CMICmnMIValueResult miValueResult("pid", miValueConst);
|
||||
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2);
|
||||
miOutOfBand.Add(miValueResult);
|
||||
m_miResultRecordExtra = miOutOfBand.GetString();
|
||||
|
||||
return MIstatus::success;
|
||||
}
|
||||
|
|
|
@ -55,11 +55,13 @@ class CMICmdCmdExecRun : public CMICmdBase
|
|||
// From CMICmdInvoker::ICmd
|
||||
bool Execute() override;
|
||||
bool Acknowledge() override;
|
||||
bool ParseArgs() override;
|
||||
// From CMICmnBase
|
||||
/* dtor */ ~CMICmdCmdExecRun() override;
|
||||
|
||||
// Attributes:
|
||||
private:
|
||||
const CMIUtilString m_constStrArgStart; // StopAtEntry - run to first instruction or main() if specified
|
||||
lldb::SBCommandReturnObject m_lldbResult;
|
||||
};
|
||||
|
||||
|
|
|
@ -71,8 +71,13 @@ CMICmdCmdSupportListFeatures::Execute()
|
|||
bool
|
||||
CMICmdCmdSupportListFeatures::Acknowledge()
|
||||
{
|
||||
const CMICmnMIValueConst miValueConst("data-read-memory-bytes");
|
||||
const CMICmnMIValueList miValueList(miValueConst);
|
||||
// Declare supported features here
|
||||
const CMICmnMIValueConst miValueConst1("data-read-memory-bytes");
|
||||
const CMICmnMIValueConst miValueConst2("exec-run-start-option");
|
||||
// Some features may depend on host and/or target, decide what to add below
|
||||
CMICmnMIValueList miValueList(true);
|
||||
miValueList.Add(miValueConst1);
|
||||
miValueList.Add(miValueConst2);
|
||||
const CMICmnMIValueResult miValueResult("features", miValueList);
|
||||
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult);
|
||||
m_miResultRecord = miRecordResult;
|
||||
|
|
Loading…
Reference in New Issue