forked from OSchip/llvm-project
[lldb-mi] Fix implementation for a few mi commands
Summary: Some of the mi commands implemented in lldb-mi are incomplete/not confirming to the spec. - `gdb-show` and `gdb-set` doesn't support getting/setting `disassembly-flavor` - `environment-cd` should also change the working directory for inferior - debugger CLI output should be printed as console-stream-output record, rather than being dumped directly to stdout - `target-select` should provide inner error message in mi response Related bug report: - https://llvm.org/bugs/show_bug.cgi?id=28026 - https://llvm.org/bugs/show_bug.cgi?id=28718 - https://llvm.org/bugs/show_bug.cgi?id=30265 Reviewers: ki.stfu, abidh Subscribers: abidh, ki.stfu, lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D24711 llvm-svn: 291104
This commit is contained in:
parent
763f1c453b
commit
5e9bfc671b
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
Test lldb-mi -environment-cd command.
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
import lldbmi_testcase
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class MiEnvironmentCdTestCase(lldbmi_testcase.MiTestCaseBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
|
||||
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
|
||||
def test_lldbmi_environment_cd(self):
|
||||
"""Test that 'lldb-mi --interpreter' changes working directory for inferior."""
|
||||
|
||||
self.spawnLldbMi(args=None)
|
||||
|
||||
# Load executable
|
||||
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# cd to a different directory
|
||||
self.runCmd("-environment-cd /tmp")
|
||||
self.expect("\^done")
|
||||
|
||||
# Run to the end
|
||||
self.runCmd("-exec-run")
|
||||
self.expect("\^running")
|
||||
self.expect("@\"cwd: /tmp\\r\\n\"", exactly=True)
|
|
@ -208,3 +208,44 @@ class MiGdbSetShowTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
self.expect("\^done")
|
||||
self.runCmd("-var-evaluate-expression var_a")
|
||||
self.expect("\^done,value=\"10\"")
|
||||
|
||||
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
|
||||
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
|
||||
@expectedFailureAll(
|
||||
bugnumber="llvm.org/pr31485: data-disassemble doesn't follow flavor settings")
|
||||
def test_lldbmi_gdb_set_disassembly_flavor(self):
|
||||
"""Test that 'lldb-mi --interpreter' works for -gdb-set disassembly-flavor."""
|
||||
|
||||
self.spawnLldbMi(args=None)
|
||||
|
||||
# Load executable
|
||||
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.expect("\^done")
|
||||
|
||||
# Run to BP_printf
|
||||
line = line_number('main.cpp', '// BP_printf')
|
||||
self.runCmd("-break-insert main.cpp:%d" % line)
|
||||
self.expect("\^done,bkpt={number=\"1\"")
|
||||
self.runCmd("-exec-run")
|
||||
self.expect("\^running")
|
||||
self.expect("\*stopped,reason=\"breakpoint-hit\".+addr=\"(0x[0-9a-f]+)\"")
|
||||
|
||||
# Get starting and ending address from $pc
|
||||
pc = int(self.child.match.group(1), base=16)
|
||||
s_addr, e_addr = pc, pc + 1
|
||||
|
||||
# Test default output (att)
|
||||
self.runCmd("-data-disassemble -s %d -e %d -- 0" % (s_addr, e_addr))
|
||||
self.expect("movl ")
|
||||
|
||||
# Test intel style
|
||||
self.runCmd("-gdb-set disassembly-flavor intel")
|
||||
self.expect("\^done")
|
||||
self.runCmd("-data-disassemble -s %d -e %d -- 0" % (s_addr, e_addr))
|
||||
self.expect("mov ")
|
||||
|
||||
# Test AT&T style
|
||||
self.runCmd("-gdb-set disassembly-flavor intel")
|
||||
self.expect("\^done")
|
||||
self.runCmd("-data-disassemble -s %d -e %d -- 0" % (s_addr, e_addr))
|
||||
self.expect("movl ")
|
||||
|
|
|
@ -111,24 +111,25 @@ class MiExecTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
self.expect("\*stopped,reason=\"breakpoint-hit\"")
|
||||
|
||||
# Check argc and argv to see if arg passed
|
||||
# Note that exactly=True is needed to avoid extra escaping for re
|
||||
self.runCmd("-data-evaluate-expression argc")
|
||||
self.expect("\^done,value=\"5\"")
|
||||
#self.runCmd("-data-evaluate-expression argv[1]")
|
||||
# self.expect("\^done,value=\"--arg1\"")
|
||||
self.runCmd("-interpreter-exec command \"print argv[1]\"")
|
||||
self.expect("\"--arg1\"")
|
||||
self.expect("\\\"--arg1\\\"", exactly=True)
|
||||
#self.runCmd("-data-evaluate-expression argv[2]")
|
||||
#self.expect("\^done,value=\"2nd arg\"")
|
||||
self.runCmd("-interpreter-exec command \"print argv[2]\"")
|
||||
self.expect("\"2nd arg\"")
|
||||
self.expect("\\\"2nd arg\\\"", exactly=True)
|
||||
#self.runCmd("-data-evaluate-expression argv[3]")
|
||||
# self.expect("\^done,value=\"third_arg\"")
|
||||
self.runCmd("-interpreter-exec command \"print argv[3]\"")
|
||||
self.expect("\"third_arg\"")
|
||||
self.expect("\\\"third_arg\\\"", exactly=True)
|
||||
#self.runCmd("-data-evaluate-expression argv[4]")
|
||||
#self.expect("\^done,value=\"fourth=\\\\\\\"4th arg\\\\\\\"\"")
|
||||
self.runCmd("-interpreter-exec command \"print argv[4]\"")
|
||||
self.expect("\"fourth=\\\\\\\"4th arg\\\\\\\"\"")
|
||||
self.expect("\\\"fourth=\\\\\\\"4th arg\\\\\\\"\\\"", exactly=True)
|
||||
|
||||
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
|
||||
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
|
||||
|
|
|
@ -9,11 +9,25 @@
|
|||
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#define getcwd _getcwd // suppress "deprecation" warning
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char const *argv[])
|
||||
{
|
||||
int a = 10;
|
||||
int a = 10;
|
||||
|
||||
char buf[512];
|
||||
char *ans = getcwd(buf, sizeof(buf));
|
||||
if (ans) {
|
||||
printf("cwd: %s\n", ans);
|
||||
}
|
||||
|
||||
printf("argc=%d\n", argc); // BP_printf
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase):
|
|||
|
||||
# Run all commands simultaneously
|
||||
self.runCmd("-unknown-command")
|
||||
self.runCmd("-interpreter-exec command help")
|
||||
self.runCmd("-file-exec-and-symbols %s" % self.myexe)
|
||||
self.runCmd("-break-insert -f main")
|
||||
self.runCmd("-gdb-set target-async off")
|
||||
|
|
|
@ -94,6 +94,13 @@ bool CMICmdCmdEnvironmentCd::Execute() {
|
|||
m_cmdData.strMiCmd.c_str(),
|
||||
"SetCurrentPlatformSDKRoot()"));
|
||||
|
||||
lldb::SBTarget sbTarget = m_rLLDBDebugSessionInfo.GetTarget();
|
||||
if (sbTarget.IsValid()) {
|
||||
lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo();
|
||||
sbLaunchInfo.SetWorkingDirectory(strWkDir.c_str());
|
||||
sbTarget.SetLaunchInfo(sbLaunchInfo);
|
||||
}
|
||||
|
||||
return bOk;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t
|
|||
// Example code if need to implement GDB set other options
|
||||
{"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix},
|
||||
{"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath},
|
||||
{"disassembly-flavor", &CMICmdCmdGdbSet::OptionFnDisassemblyFlavor},
|
||||
{"fallback", &CMICmdCmdGdbSet::OptionFnFallback}};
|
||||
|
||||
//++
|
||||
|
@ -397,6 +398,39 @@ bool CMICmdCmdGdbSet::OptionFnOutputRadix(
|
|||
return MIstatus::success;
|
||||
}
|
||||
|
||||
//++
|
||||
//------------------------------------------------------------------------------------
|
||||
// Details: Carry out work to complete the GDB set option 'disassembly-flavor'
|
||||
// to prepare
|
||||
// and send back information asked for.
|
||||
// Type: Method.
|
||||
// Args: vrWords - (R) List of additional parameters used by this option.
|
||||
// Return: MIstatus::success - Functional succeeded.
|
||||
// MIstatus::failure - Functional failed.
|
||||
// Throws: None.
|
||||
//--
|
||||
bool CMICmdCmdGdbSet::OptionFnDisassemblyFlavor(
|
||||
const CMIUtilString::VecString_t &vrWords) {
|
||||
// Check we have at least one argument
|
||||
if (vrWords.size() < 1) {
|
||||
m_bGbbOptionFnHasError = true;
|
||||
// m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH);
|
||||
return MIstatus::failure;
|
||||
}
|
||||
const CMIUtilString &rStrValDisasmFlavor(vrWords[0]);
|
||||
|
||||
lldb::SBDebugger &rDbgr = m_rLLDBDebugSessionInfo.GetDebugger();
|
||||
lldb::SBError error = lldb::SBDebugger::SetInternalVariable(
|
||||
"target.x86-disassembly-flavor", rStrValDisasmFlavor.c_str(),
|
||||
rDbgr.GetInstanceName());
|
||||
if (error.Fail()) {
|
||||
m_strGdbOptionFnError = error.GetCString();
|
||||
return MIstatus::failure;
|
||||
}
|
||||
|
||||
return MIstatus::success;
|
||||
}
|
||||
|
||||
//++
|
||||
//------------------------------------------------------------------------------------
|
||||
// Details: Carry out work to complete the GDB set option to prepare and send
|
||||
|
|
|
@ -79,6 +79,7 @@ private:
|
|||
bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
|
||||
|
||||
// Attributes:
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "lldb/API/SBCompileUnit.h"
|
||||
#include "lldb/API/SBFrame.h"
|
||||
#include "lldb/API/SBLanguageRuntime.h"
|
||||
#include "lldb/API/SBStringList.h"
|
||||
#include "lldb/API/SBThread.h"
|
||||
|
||||
// In-house headers:
|
||||
|
@ -30,6 +31,7 @@ const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t
|
|||
{"target-async", &CMICmdCmdGdbShow::OptionFnTargetAsync},
|
||||
{"print", &CMICmdCmdGdbShow::OptionFnPrint},
|
||||
{"language", &CMICmdCmdGdbShow::OptionFnLanguage},
|
||||
{"disassembly-flavor", &CMICmdCmdGdbShow::OptionFnDisassemblyFlavor},
|
||||
{"fallback", &CMICmdCmdGdbShow::OptionFnFallback}};
|
||||
|
||||
//++
|
||||
|
@ -325,6 +327,26 @@ bool CMICmdCmdGdbShow::OptionFnLanguage(
|
|||
return MIstatus::success;
|
||||
}
|
||||
|
||||
//++
|
||||
//------------------------------------------------------------------------------------
|
||||
// Details: Carry out work to complete the GDB show option 'disassembly-flavor' 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::OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t &vrWords) {
|
||||
MIunused(vrWords);
|
||||
|
||||
// Get current disassembly flavor
|
||||
lldb::SBDebugger &rDbgr = m_rLLDBDebugSessionInfo.GetDebugger();
|
||||
m_strValue = lldb::SBDebugger::GetInternalVariableValue("target.x86-disassembly-flavor",
|
||||
rDbgr.GetInstanceName()).GetStringAtIndex(0);
|
||||
return MIstatus::success;
|
||||
}
|
||||
|
||||
//++
|
||||
//------------------------------------------------------------------------------------
|
||||
// Details: Carry out work to complete the GDB show option to prepare and send
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
bool OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnPrint(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnLanguage(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t &vrWords);
|
||||
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
|
||||
|
||||
// Attributes:
|
||||
|
|
|
@ -496,14 +496,22 @@ bool CMICmdCmdInterpreterExec::Execute() {
|
|||
//--
|
||||
bool CMICmdCmdInterpreterExec::Acknowledge() {
|
||||
if (m_lldbResult.GetOutputSize() > 0) {
|
||||
CMIUtilString strMsg(m_lldbResult.GetOutput());
|
||||
strMsg = strMsg.StripCREndOfLine();
|
||||
CMICmnStreamStdout::TextToStdout(strMsg);
|
||||
const CMIUtilString line(m_lldbResult.GetOutput());
|
||||
const bool bEscapeQuotes(true);
|
||||
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
|
||||
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ConsoleStreamOutput, miValueConst);
|
||||
const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
|
||||
if (!bOk)
|
||||
return MIstatus::failure;
|
||||
}
|
||||
if (m_lldbResult.GetErrorSize() > 0) {
|
||||
CMIUtilString strMsg(m_lldbResult.GetError());
|
||||
strMsg = strMsg.StripCREndOfLine();
|
||||
CMICmnStreamStderr::LLDBMsgToConsole(strMsg);
|
||||
const CMIUtilString line(m_lldbResult.GetError());
|
||||
const bool bEscapeQuotes(true);
|
||||
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
|
||||
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_LogStreamOutput, miValueConst);
|
||||
const bool bOk = CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString());
|
||||
if (!bOk)
|
||||
return MIstatus::failure;
|
||||
}
|
||||
|
||||
const CMICmnMIResultRecord miRecordResult(
|
||||
|
|
|
@ -123,6 +123,7 @@ bool CMICmdCmdTargetSelect::Execute() {
|
|||
|
||||
// Verify that we have managed to connect successfully
|
||||
lldb::SBStream errMsg;
|
||||
error.GetDescription(errMsg);
|
||||
if (!process.IsValid()) {
|
||||
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN),
|
||||
m_cmdData.strMiCmd.c_str(),
|
||||
|
|
|
@ -48,6 +48,10 @@ MapOutOfBandToText(CMICmnMIOutOfBandRecord::OutOfBand_e veType) {
|
|||
return "library-unloaded";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput:
|
||||
return "";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_ConsoleStreamOutput:
|
||||
return "";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_LogStreamOutput:
|
||||
return "";
|
||||
}
|
||||
assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e");
|
||||
return NULL;
|
||||
|
@ -86,6 +90,10 @@ MapOutOfBandToToken(CMICmnMIOutOfBandRecord::OutOfBand_e veType) {
|
|||
return "=";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput:
|
||||
return "@";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_ConsoleStreamOutput:
|
||||
return "~";
|
||||
case CMICmnMIOutOfBandRecord::eOutOfBand_LogStreamOutput:
|
||||
return "&";
|
||||
}
|
||||
assert(false && "unknown CMICmnMIOutofBandRecord::OutOfBand_e");
|
||||
return NULL;
|
||||
|
|
|
@ -65,7 +65,9 @@ public:
|
|||
eOutOfBand_ThreadSelected,
|
||||
eOutOfBand_TargetModuleLoaded,
|
||||
eOutOfBand_TargetModuleUnloaded,
|
||||
eOutOfBand_TargetStreamOutput
|
||||
eOutOfBand_TargetStreamOutput,
|
||||
eOutOfBand_ConsoleStreamOutput,
|
||||
eOutOfBand_LogStreamOutput
|
||||
};
|
||||
|
||||
// Methods:
|
||||
|
|
Loading…
Reference in New Issue