KLapshin created this revision.
KLapshin added reviewers: dawn, ki.stfu, abidh.
KLapshin added a subscriber: lldb-commits.
KLapshin set the repository for this revision to rL LLVM.
In some cases debugger user may want to get debugged process stopped at very
early point - at first instruction.
With lldb command line interpreter this may be done easily with exisiting
option to "process launch" command:
process launch -s
Currently, if lldb-mi user want to use pure MI only - important for IDEs -
there is no possibility to run debugged process and getting it stopped right on
first instruction.
This patch is implementation of such option with additional boolean flag set by
-gdb-set and launch program in -exec-run handler with checking this flag.
-gdb-set/show option, patch for -exec-run handler and lldb-mi tests for added
-gdb-set/show option.
Example:
-gdb-set process-stopatentry on/off
-exec-run
...
Repository:
rL LLVM
http://reviews.llvm.org/D12977
Files:
test/tools/lldb-mi/TestMiGdbSetShow.py
tools/lldb-mi/MICmdCmdExec.cpp
tools/lldb-mi/MICmdCmdGdbSet.cpp
tools/lldb-mi/MICmdCmdGdbSet.h
tools/lldb-mi/MICmdCmdGdbShow.cpp
tools/lldb-mi/MICmdCmdGdbShow.h
tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
tools/lldb-mi/MICmnResources.cpp
tools/lldb-mi/MICmnResources.h
Index: tools/lldb-mi/MICmnResources.h
===================================================================
--- tools/lldb-mi/MICmnResources.h
+++ tools/lldb-mi/MICmnResources.h
@@ -266,6 +266,7 @@
IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH,
IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS,
IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION,
+ IDS_CMD_ERR_GDBSET_OPT_PROCESS_STOPATENTRY, // LLDB_EMBARCADERO_MI_STOPATENTRY
IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS,
IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION,
IDS_CMD_ERR_EXPR_INVALID,
Index: tools/lldb-mi/MICmnResources.cpp
===================================================================
--- tools/lldb-mi/MICmnResources.cpp
+++ tools/lldb-mi/MICmnResources.cpp
@@ -249,6 +249,7 @@
{IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH, "'solib-search-path' requires at least one argument"},
{IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS, "'print' expects option-name and \"on\" or \"off\""},
{IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION, "'print' error. The option '%s' not found"},
+ {IDS_CMD_ERR_GDBSET_OPT_PROCESS_STOPATENTRY, "'process-stopatentry' expects \"on\" or \"off\""}, // LLDB_EMBARCADERO_MI_STOPATENTRY
{IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS, "'print' expects option-name and \"on\" or \"off\""},
{IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, "'print' error. The option '%s' not found"},
{IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"},
Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
===================================================================
--- tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
+++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.h
@@ -182,6 +182,7 @@
const CMIUtilString m_constStrPrintCharArrayAsString;
const CMIUtilString m_constStrPrintExpandAggregates;
const CMIUtilString m_constStrPrintAggregateFieldNames;
+ const CMIUtilString m_constStrProcessStopAtEntry; // LLDB_EMBARCADERO_MI_STOPATENTRY
// Typedefs:
private:
Index: tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
===================================================================
--- tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -42,6 +42,7 @@
, m_constStrSharedDataSolibPath("Solib Path")
, m_constStrPrintCharArrayAsString("Print CharArrayAsString")
, m_constStrPrintExpandAggregates("Print ExpandAggregates")
+ , m_constStrProcessStopAtEntry("Process StopAtEntry") // LLDB_EMBARCADERO_MI_STOPATENTRY
, m_constStrPrintAggregateFieldNames("Print AggregateFieldNames")
{
}
Index: tools/lldb-mi/MICmdCmdGdbShow.h
===================================================================
--- tools/lldb-mi/MICmdCmdGdbShow.h
+++ tools/lldb-mi/MICmdCmdGdbShow.h
@@ -70,6 +70,7 @@
bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords);
bool OptionFnLanguage(const CMIUtilString::VecString_t &vrWords);
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
+ bool OptionFnProcessStopAtEntry(const CMIUtilString::VecString_t &vrWords); // LLDB_EMBARCADERO_MI_STOPATENTRY
// Attributes:
private:
Index: tools/lldb-mi/MICmdCmdGdbShow.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdGdbShow.cpp
+++ tools/lldb-mi/MICmdCmdGdbShow.cpp
@@ -27,6 +27,7 @@
// Instantiations:
const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbShow::ms_mapGdbOptionNameToFnGdbOptionPtr = {
{"target-async", &CMICmdCmdGdbShow::OptionFnTargetAsync},
+ {"process-stopatentry", &CMICmdCmdGdbShow::OptionFnProcessStopAtEntry}, // LLDB_EMBARCADERO_MI_STOPATENTRY
{"print", &CMICmdCmdGdbShow::OptionFnPrint},
{"language", &CMICmdCmdGdbShow::OptionFnLanguage},
{"fallback", &CMICmdCmdGdbShow::OptionFnFallback}};
@@ -246,6 +247,31 @@
}
//++ ------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB show option 'process-stopatentry' to prepare
+// and send back the requested information.
+// Type: Method.
+// Args: vrWords - (R) List of additional parameters used by this option.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdGdbShow::OptionFnProcessStopAtEntry(const CMIUtilString::VecString_t &vrWords)
+{
+ MIunused(vrWords);
+
+ CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
+
+ bool bProcessMustStopAtEntry = false;
+
+ // Get current process stopatentry flag value and set result string
+ m_strValue = (rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrProcessStopAtEntry, bProcessMustStopAtEntry)
+ && bProcessMustStopAtEntry) ? "on" : "off";
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: Carry out work to complete the GDB show option 'print' to prepare and send
// back the requested information.
// Type: Method.
Index: tools/lldb-mi/MICmdCmdGdbSet.h
===================================================================
--- tools/lldb-mi/MICmdCmdGdbSet.h
+++ tools/lldb-mi/MICmdCmdGdbSet.h
@@ -71,6 +71,7 @@
bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords);
bool OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords);
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
+ bool OptionFnProcessStopAtEntry(const CMIUtilString::VecString_t &vrWords); // LLDB_EMBARCADERO_MI_STOPATENTRY
// Attributes:
private:
Index: tools/lldb-mi/MICmdCmdGdbSet.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdGdbSet.cpp
+++ tools/lldb-mi/MICmdCmdGdbSet.cpp
@@ -21,6 +21,7 @@
// Instantiations:
const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t CMICmdCmdGdbSet::ms_mapGdbOptionNameToFnGdbOptionPtr = {
{"target-async", &CMICmdCmdGdbSet::OptionFnTargetAsync},
+ {"process-stopatentry", &CMICmdCmdGdbSet::OptionFnProcessStopAtEntry}, // LLDB_EMBARCADERO_MI_STOPATENTRY
{"print", &CMICmdCmdGdbSet::OptionFnPrint},
// { "auto-solib-add", &CMICmdCmdGdbSet::OptionFnAutoSolibAdd }, // Example code if need to implement GDB set other options
{"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix},
@@ -336,7 +337,45 @@
return MIstatus::success;
}
+// LLDB_EMBARCADERO_MI_STOPATENTRY
//++ ------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB set option 'process-stopatentry' to prepare
+// and send back information asked for.
+// Type: Method.
+// Args: vrWords - (R) List of additional parameters used by this option.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool
+CMICmdCmdGdbSet::OptionFnProcessStopAtEntry(const CMIUtilString::VecString_t &vrWords)
+{
+ const bool bEmptyArg(vrWords.empty());
+ const bool bArgOn(bEmptyArg || CMIUtilString::Compare(vrWords[0], "on"));
+ const bool bArgOff(!bEmptyArg && CMIUtilString::Compare(vrWords[0], "off"));
+ if (!bArgOn && !bArgOff)
+ {
+ m_bGbbOptionFnHasError = true;
+ m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PROCESS_STOPATENTRY);
+ return MIstatus::failure;
+ }
+
+ // Save process stopatentry launch flag
+ const bool bProcessStopAtEntry = bArgOn;
+
+ // Add process stopatentry flag to the shared data list
+ const CMIUtilString &rStrKeyProcessStopAtEntry(m_rLLDBDebugSessionInfo.m_constStrProcessStopAtEntry);
+ if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(rStrKeyProcessStopAtEntry, bProcessStopAtEntry))
+ {
+ m_bGbbOptionFnHasError = false;
+ SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyProcessStopAtEntry.c_str()));
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++ ------------------------------------------------------------------------------------
// Details: Carry out work to complete the GDB set option 'output-radix' to prepare
// and send back information asked for.
// Type: Method.
Index: tools/lldb-mi/MICmdCmdExec.cpp
===================================================================
--- tools/lldb-mi/MICmdCmdExec.cpp
+++ tools/lldb-mi/MICmdCmdExec.cpp
@@ -82,13 +82,44 @@
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBError error;
lldb::SBStream errMsg;
- lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo();
- launchInfo.SetListener(rSessionInfo.GetListener());
- lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error);
- if ((!process.IsValid()) || (error.Fail()))
+ lldb::SBProcess process;
+ bool bProcessMustStopAtEntry = false;
+
+ bProcessMustStopAtEntry = (rSessionInfo.SharedDataRetrieve<bool>(rSessionInfo.m_constStrProcessStopAtEntry, bProcessMustStopAtEntry)
+ && bProcessMustStopAtEntry);
{
- SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str(), errMsg.GetData()));
- return MIstatus::failure;
+ const char *pCmd = bProcessMustStopAtEntry ? "process launch -s" : "process launch";
+ const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult);
+ MIunused(rtn);
+
+ if (!rSessionInfo.GetProcess().IsValid())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
+ m_cmdData.strMiCmd.c_str(), errMsg.GetData()));
+ return MIstatus::failure;
+ }
+
+ if (m_lldbResult.GetErrorSize() == 0)
+ {
+ if (!CMIDriver::Instance().SetDriverStateRunningDebugging())
+ {
+ const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE),
+ m_cmdData.strMiCmd.c_str(), rErrMsg.c_str()));
+ return MIstatus::failure;
+ }
+ }
+ else
+ {
+ // FIXME: Re-evaluate if this is required when the application is near finished
+ // as this parses the LLDB error message which is a hack and is brittle
+ const char *pLldbErr = m_lldbResult.GetError();
+ const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine());
+ if (strLldbMsg == "error: Process must be launched.")
+ {
+ CMIDriver::Instance().SetExitApplicationFlag(true);
+ }
+ }
}
if (!CMIDriver::Instance().SetDriverStateRunningDebugging())
Index: test/tools/lldb-mi/TestMiGdbSetShow.py
===================================================================
--- test/tools/lldb-mi/TestMiGdbSetShow.py
+++ test/tools/lldb-mi/TestMiGdbSetShow.py
@@ -144,10 +144,49 @@
self.runCmd("-gdb-show unknown")
self.expect("\^error")
+ # LLDB_EMBARCADERO_MI_STOPATENTRY
+ @lldbmi_test
+ @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+ @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
+ def test_lldbmi_gdb_set_process_stopatentry_on(self):
+ """Test that 'lldb-mi --interpreter' can stop at entry."""
+ self.spawnLldbMi(args = None)
+
+ # Test that -gdb-set can set process-stopatentry flag
+ self.runCmd("-gdb-set process-stopatentry on")
+ self.expect("\^done")
+ self.runCmd("-gdb-show process-stopatentry")
+ self.expect("\^done,value=\"on\"")
+
+ # 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")
+ 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)
+
+ # LLDB_EMBARCADERO_MI_STOPATENTRY
@lldbmi_test
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
+ def test_lldbmi_gdb_show_process_stopatentry(self):
+ """Test that 'lldb-mi --interpreter' starts without process-stopatentry by default."""
+
+ self.spawnLldbMi(args = None)
+
+ # Test that default process-stopatentry value is "off"
+ self.runCmd("-gdb-show process-stopatentry")
+ self.expect("\^done,value=\"off\"")
+
+ @lldbmi_test
+ @expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
+ @skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfLinux # llvm.org/pr22841: lldb-mi tests fail on all Linux buildbots
def test_lldbmi_gdb_set_ouptut_radix(self):
"""Test that 'lldb-mi --interpreter' works for -gdb-set output-radix."""
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits