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.""" 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(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: 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(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/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(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/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/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"},