Add -exec-abort command (MI); Don't exit on eStateExited

Summary:
Add -exec-abort command + test.

Also, I had fixed an error, when lldb-mi exits on eStateExited. With current patch we can re-run target:
```
-file-exec-and-symbols hello
^done
-exec-run
^running
*stopped,reason="breakpoint-hit"...
-exec-abort
^done
*stopped,reason="exited-normally"...    <- program exits
-exec-run                               <- run again
^running
*stopped,reason="breakpoint-hit"...
```

All tests pass on OS X.

Reviewers: zturner, emaste, abidh, clayborg

Reviewed By: abidh, clayborg

Subscribers: lldb-commits, emaste, zturner, clayborg, abidh

Differential Revision: http://reviews.llvm.org/D7794

llvm-svn: 230321
This commit is contained in:
Ilia K 2015-02-24 10:40:45 +00:00
parent 327b6f5942
commit 2f85244553
9 changed files with 132 additions and 25 deletions

View File

@ -12,7 +12,7 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
@lldbmi_test
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
@unittest2.skip("-exec-abort isn't implemented")
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
def test_lldbmi_exec_abort(self):
"""Test that 'lldb-mi --interpreter' works for -exec-abort."""

View File

@ -19,6 +19,7 @@
// CMICmdCmdExecFinish implementation.
// CMICmdCmdExecInterrupt implementation.
// CMICmdCmdExecArguments implementation.
// CMICmdCmdExecAbort implementation.
//
// Environment: Compilers: Visual C++ 12.
// gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
@ -1136,3 +1137,95 @@ CMICmdCmdExecArguments::CreateSelf(void)
{
return new CMICmdCmdExecArguments();
}
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdExecAbort constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdExecAbort::CMICmdCmdExecAbort(void)
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "exec-abort";
// Required by the CMICmdFactory when registering *this command
m_pSelfCreatorFn = &CMICmdCmdExecAbort::CreateSelf;
}
//++ ------------------------------------------------------------------------------------
// Details: CMICmdCmdExecAbort destructor.
// Type: Overrideable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmdCmdExecAbort::~CMICmdCmdExecAbort(void)
{
}
//++ ------------------------------------------------------------------------------------
// 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.
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmdCmdExecAbort::Execute(void)
{
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
if (!sbProcess.IsValid())
{
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str()));
return MIstatus::failure;
}
lldb::SBError sbError = sbProcess.Destroy();
if (sbError.Fail())
{
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), m_cmdData.strMiCmd.c_str(), sbError.GetCString()));
return MIstatus::failure;
}
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: The invoker requires this function. The command prepares a MI Record Result
// for the work carried out in the Execute().
// Type: Overridden.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmdCmdExecAbort::Acknowledge(void)
{
const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
m_miResultRecord = miRecordResult;
return MIstatus::success;
}
//++ ------------------------------------------------------------------------------------
// Details: Required by the CMICmdFactory when registering *this command. The factory
// calls this function to create an instance of *this command.
// Type: Static method.
// Args: None.
// Return: CMICmdBase * - Pointer to a new command.
// Throws: None.
//--
CMICmdBase *
CMICmdCmdExecAbort::CreateSelf(void)
{
return new CMICmdCmdExecAbort();
}

View File

@ -19,6 +19,7 @@
// CMICmdCmdExecFinish interface.
// CMICmdCmdExecInterrupt interface.
// CMICmdCmdExecArguments interface.
// CMICmdCmdExecAbort interface.
//
// To implement new MI commands derive a new command class from the command base
// class. To enable the new command for interpretation add the new command class
@ -340,3 +341,27 @@ class CMICmdCmdExecArguments : public CMICmdBase
private:
const CMIUtilString m_constStrArgArguments;
};
//++ ============================================================================
// Details: MI command class. MI commands derived from the command base class.
// *this class implements MI command "exec-abort".
//--
class CMICmdCmdExecAbort : public CMICmdBase
{
// Statics:
public:
// Required by the CMICmdFactory when registering *this command
static CMICmdBase *CreateSelf(void);
// Methods:
public:
/* ctor */ CMICmdCmdExecAbort(void);
// Overridden:
public:
// From CMICmdInvoker::ICmd
virtual bool Execute(void);
virtual bool Acknowledge(void);
// From CMICmnBase
/* dtor */ virtual ~CMICmdCmdExecAbort(void);
};

View File

@ -99,6 +99,7 @@ MICmnCommands::RegisterAll(void)
bOk &= Register<CMICmdCmdDataWriteMemory>();
bOk &= Register<CMICmdCmdEnablePrettyPrinting>();
bOk &= Register<CMICmdCmdEnvironmentCd>();
bOk &= Register<CMICmdCmdExecAbort>();
bOk &= Register<CMICmdCmdExecArguments>();
bOk &= Register<CMICmdCmdExecContinue>();
bOk &= Register<CMICmdCmdExecInterrupt>();

View File

@ -663,13 +663,12 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive)
m_pLog->WriteLog(CMIUtilString::Format("##### An event occurred: %s", event.GetBroadcasterClass()));
bool bHandledEvent = false;
bool bExitAppEvent = false;
bool bOk = false;
{
// Lock Mutex before handling events so that we don't disturb a running cmd
CMIUtilThreadLock lock(CMICmnLLDBDebugSessionInfo::Instance().GetSessionMutex());
bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent, bExitAppEvent);
bOk = CMICmnLLDBDebuggerHandleEvents::Instance().HandleEvent(event, bHandledEvent);
}
if (!bHandledEvent)
{
@ -681,15 +680,6 @@ CMICmnLLDBDebugger::MonitorSBListenerEvents(bool &vrbIsAlive)
m_pLog->WriteLog(CMICmnLLDBDebuggerHandleEvents::Instance().GetErrorDescription());
}
if (bExitAppEvent)
{
// Set the application to shutdown
m_pClientDriver->SetExitApplicationFlag(true);
// Kill *this thread
vrbIsAlive = false;
}
return bOk;
}

View File

@ -126,22 +126,20 @@ CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// vrbHandledEvent - (W) True - event handled, false = not handled.
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent)
CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent)
{
bool bOk = MIstatus::success;
vrbHandledEvent = false;
vrbExitAppEvent = false;
if (lldb::SBProcess::EventIsProcessEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent);
bOk = HandleEventSBProcess(vEvent);
}
else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
{
@ -161,13 +159,12 @@ CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &v
// Details: Handle a LLDB SBProcess event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent)
{
bool bOk = MIstatus::success;
@ -183,7 +180,7 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent
break;
case lldb::SBProcess::eBroadcastBitStateChanged:
pEventType = "eBroadcastBitStateChanged";
bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent);
bOk = HandleProcessEventBroadcastBitStateChanged(vEvent);
break;
case lldb::SBProcess::eBroadcastBitSTDERR:
pEventType = "eBroadcastBitSTDERR";
@ -627,13 +624,12 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEv
// Details: Handle SBProcess event eBroadcastBitStateChanged.
// Type: Method.
// Args: vEvent - (R) An LLDB event object.
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent)
{
bool bOk = ChkForStateChanges();
bOk = bOk && GetProcessStdout();
@ -693,8 +689,8 @@ CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const
pEventType = "eStateDetached";
break;
case lldb::eStateExited:
// Don't exit from lldb-mi here. We should be able to re-run target.
pEventType = "eStateExited";
vrbExitAppEvent = true;
bOk = HandleProcessEventStateExited();
break;
default:

View File

@ -50,7 +50,7 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool Initialize(void);
bool Shutdown(void);
//
bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent);
bool HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent);
// Methods:
private:
@ -65,12 +65,12 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent);
bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent);
bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent);
bool HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent);
bool HandleEventSBProcess(const lldb::SBEvent &vEvent);
bool HandleEventSBThread(const lldb::SBEvent &vEvent);
bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent);
bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent);
bool HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent);
bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent);
bool HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent);
bool HandleProcessEventStateRunning(void);
bool HandleProcessEventStateExited(void);
bool HandleProcessEventStateStopped(bool &vwrbShouldBrk);

View File

@ -225,6 +225,7 @@ const CMICmnResources::SRsrcTextData CMICmnResources::ms_pResourceId2TextData[]
{IDS_CMD_ERR_FNFAILED, "Command '%s'. Fn '%s' failed"},
{IDS_CMD_ERR_SHARED_DATA_NOT_FOUND, "Command '%s'. Shared data '%s' not found"},
{IDS_CMD_ERR_LLDBPROCESS_DETACH, "Command '%s'. Process detach failed. '%s'"},
{IDS_CMD_ERR_LLDBPROCESS_DESTROY, "Command '%s'. Process destroy failed. '%s'"},
{IDS_CMD_ERR_SETWKDIR, "Command '%s'. Failed to set working directory '%s'"},
{IDS_CMD_ERR_INVALID_TARGET, "Command '%s'. Target binary '%s' is invalid. %s"},
{IDS_CMD_ERR_INVALID_TARGET_CURRENT, "Command '%s'. Current SBTarget is invalid"},

View File

@ -241,6 +241,7 @@ enum
IDS_CMD_ERR_FNFAILED,
IDS_CMD_ERR_SHARED_DATA_NOT_FOUND,
IDS_CMD_ERR_LLDBPROCESS_DETACH,
IDS_CMD_ERR_LLDBPROCESS_DESTROY,
IDS_CMD_ERR_SETWKDIR,
IDS_CMD_ERR_INVALID_TARGET,
IDS_CMD_ERR_INVALID_TARGET_CURRENT,