[Lldb-commits] [lldb] r236694 - Fix LLDB-MI -data-read-memory-bytes command to comply with GDB/MI spec
Bruce Mitchener
bruce.mitchener at gmail.com
Wed May 6 22:32:14 PDT 2015
Author: brucem
Date: Thu May 7 00:32:13 2015
New Revision: 236694
URL: http://llvm.org/viewvc/llvm-project?rev=236694&view=rev
Log:
Fix LLDB-MI -data-read-memory-bytes command to comply with GDB/MI spec
Summary:
- The address argument can now be an expression (e.g. &array), it's no longer restricted to being just a number literal.
- The -o (offset) option is now properly handled, not just silently ignored.
- The --thread option is now properly handled.
- A new --frame option has been added for consistency with GDB.
- Added a new test to verify old and new functionality.
Patch by Vadim Macagon. Thanks!
Test Plan: ./dotest.py -A x86_64 -C clang --executable $BUILDDIR/bin/lldb tools/lldb-mi/data
Reviewers: domipheus, abidh, ki.stfu
Reviewed By: abidh, ki.stfu
Subscribers: brucem, lldb-commits
Differential Revision: http://reviews.llvm.org/D9470
Modified:
lldb/trunk/test/tools/lldb-mi/data/TestMiData.py
lldb/trunk/test/tools/lldb-mi/data/main.cpp
lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
lldb/trunk/tools/lldb-mi/MICmdCmdData.h
lldb/trunk/tools/lldb-mi/MICmnResources.cpp
lldb/trunk/tools/lldb-mi/MICmnResources.h
lldb/trunk/tools/lldb-mi/MIExtensions.txt
Modified: lldb/trunk/test/tools/lldb-mi/data/TestMiData.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/data/TestMiData.py?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/data/TestMiData.py (original)
+++ lldb/trunk/test/tools/lldb-mi/data/TestMiData.py Thu May 7 00:32:13 2015
@@ -41,9 +41,9 @@ class MiDataTestCase(lldbmi_testcase.MiT
@lldbmi_test
@expectedFailureWindows("llvm.org/pr22274: need a pexpect replacement for windows")
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
- @unittest2.skip("-data-evaluate-expression doesn't work") #FIXME: the global case worked before refactoring
- def test_lldbmi_data_read_memory_bytes(self):
- """Test that 'lldb-mi --interpreter' works for -data-read-memory-bytes."""
+ @unittest2.skip("-data-evaluate-expression doesn't work on globals") #FIXME: the global case worked before refactoring
+ def test_lldbmi_data_read_memory_bytes_global(self):
+ """Test that -data-read-memory-bytes can access global buffers."""
self.spawnLldbMi(args = None)
@@ -80,6 +80,114 @@ class MiDataTestCase(lldbmi_testcase.MiT
@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_data_read_memory_bytes_local(self):
+ """Test that -data-read-memory-bytes can access local buffers."""
+
+ self.spawnLldbMi(args = None)
+ self.expect(self.child_prompt, exactly = True)
+
+ # Load executable
+ self.runCmd('-file-exec-and-symbols %s' % self.myexe)
+ self.expect(r'\^done')
+
+ # Run to BP_local_array_test_inner
+ line = line_number('main.cpp', '// BP_local_array_test_inner')
+ self.runCmd('-break-insert main.cpp:%d' % line)
+ self.expect(r'\^done,bkpt=\{number="1"')
+ self.runCmd('-exec-run')
+ self.expect(r'\^running')
+ self.expect(r'\*stopped,reason="breakpoint-hit"')
+
+ # Get address of local char[]
+ self.runCmd('-data-evaluate-expression &array')
+ self.expect(r'\^done,value="0x[0-9a-f]+"')
+ addr = int(self.child.after.split('"')[1], 16)
+ size = 4
+
+ # Test that an unquoted hex literal address works
+ self.runCmd('-data-read-memory-bytes %#x %d' % (addr, size))
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # Test that a double-quoted hex literal address works
+ self.runCmd('-data-read-memory-bytes "%#x" %d' % (addr, size))
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # Test that unquoted expressions work
+ self.runCmd('-data-read-memory-bytes &array %d' % size)
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # This doesn't work, and perhaps that makes sense, but it does work on GDB
+ self.runCmd('-data-read-memory-bytes array 4')
+ self.expect(r'\^error')
+ #self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ self.runCmd('-data-read-memory-bytes &array[2] 2')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="0304"\}\]' % (addr + 2, addr + size))
+
+ self.runCmd('-data-read-memory-bytes first_element_ptr %d' % size)
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # Test that double-quoted expressions work
+ self.runCmd('-data-read-memory-bytes "&array" %d' % size)
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ self.runCmd('-data-read-memory-bytes "&array[0] + 1" 3')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="020304"\}\]' % (addr + 1, addr + size))
+
+ self.runCmd('-data-read-memory-bytes "first_element_ptr + 1" 3')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="020304"\}\]' % (addr + 1, addr + size))
+
+ # Test the -o (offset) option
+ self.runCmd('-data-read-memory-bytes -o 1 &array 3')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="020304"\}\]' % (addr + 1, addr + size))
+
+ # Test the --thread option
+ self.runCmd('-data-read-memory-bytes --thread 1 &array 4')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # Test the --thread option with an invalid value
+ self.runCmd('-data-read-memory-bytes --thread 999 &array 4')
+ self.expect(r'\^error')
+
+ # Test the --frame option (current frame)
+ self.runCmd('-data-read-memory-bytes --frame 0 &array 4')
+ self.expect(r'\^done,memory=\[\{begin="0x0*%x",offset="0x0+",end="0x0*%x",contents="01020304"\}\]' % (addr, addr + size))
+
+ # Test the --frame option (outer frame)
+ self.runCmd('-data-read-memory-bytes --frame 1 &array 4')
+ self.expect(r'\^done,memory=\[\{begin="0x[0-9a-f]+",offset="0x0+",end="0x[0-9a-f]+",contents="05060708"\}\]')
+
+ # Test the --frame option with an invalid value
+ self.runCmd('-data-read-memory-bytes --frame 999 &array 4')
+ self.expect(r'\^error')
+
+ # Test all the options at once
+ self.runCmd('-data-read-memory-bytes --thread 1 --frame 1 -o 2 &array 2')
+ self.expect(r'\^done,memory=\[\{begin="0x[0-9a-f]+",offset="0x0+",end="0x[0-9a-f]+",contents="0708"\}\]')
+
+ # Test that an expression that references undeclared variables doesn't work
+ self.runCmd('-data-read-memory-bytes "&undeclared_array1 + undeclared_array2[1]" 2')
+ self.expect(r'\^error')
+
+ # Test that the address argument is required
+ self.runCmd('-data-read-memory-bytes')
+ self.expect(r'\^error')
+
+ # Test that the count argument is required
+ self.runCmd('-data-read-memory-bytes &array')
+ self.expect(r'\^error')
+
+ # Test that the address argument is required when other options are present
+ self.runCmd('-data-read-memory-bytes --thread 1')
+ self.expect(r'\^error')
+
+ # Test that the count argument is required when other options are present
+ self.runCmd('-data-read-memory-bytes --thread 1 &array')
+ self.expect(r'\^error')
+
+ @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_data_list_register_names(self):
"""Test that 'lldb-mi --interpreter' works for -data-list-register-names."""
Modified: lldb/trunk/test/tools/lldb-mi/data/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/tools/lldb-mi/data/main.cpp?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/test/tools/lldb-mi/data/main.cpp (original)
+++ lldb/trunk/test/tools/lldb-mi/data/main.cpp Thu May 7 00:32:13 2015
@@ -10,8 +10,27 @@
const char g_CharArray[] = "\x10\x11\x12\x13";
static const char s_CharArray[] = "\x20\x21\x22\x23";
+void
+local_array_test_inner()
+{
+ char array[] = { 0x01, 0x02, 0x03, 0x04 };
+ char *first_element_ptr = &array[0];
+ // BP_local_array_test_inner
+ return;
+}
+
+void
+local_array_test()
+{
+ char array[] = { 0x05, 0x06, 0x07, 0x08 };
+ // BP_local_array_test
+ local_array_test_inner();
+ return;
+}
+
int
main(int argc, char const *argv[])
{ // FUNC_main
+ local_array_test();
return 0;
}
Modified: lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmdCmdData.cpp Thu May 7 00:32:13 2015
@@ -517,13 +517,13 @@ CMICmdCmdDataDisassemble::CreateSelf(voi
//--
CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes(void)
: m_constStrArgThread("thread")
+ , m_constStrArgFrame("frame")
, m_constStrArgByteOffset("o")
- , m_constStrArgAddrStart("address")
+ , m_constStrArgAddrExpr("address")
, m_constStrArgNumBytes("count")
, m_pBufferMemory(nullptr)
, m_nAddrStart(0)
, m_nAddrNumBytesToRead(0)
- , m_nAddrOffset(0)
{
// Command factory matches this name with that received from the stdin stream
m_strMiCmd = "data-read-memory-bytes";
@@ -561,11 +561,13 @@ bool
CMICmdCmdDataReadMemoryBytes::ParseArgs(void)
{
bool bOk =
- m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)));
+ m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgThread, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
+ bOk = bOk &&
+ m_setCmdArgs.Add(*(new CMICmdArgValOptionLong(m_constStrArgFrame, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
bOk =
bOk &&
m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)));
- bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgAddrStart, true, true, CMICmdArgValNumber::eArgValNumberFormat_Auto)));
+ bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)));
bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)));
return (bOk && ParseValidateCmdOptions());
}
@@ -575,21 +577,108 @@ CMICmdCmdDataReadMemoryBytes::ParseArgs(
// The command is likely to communicate with the LLDB SBDebugger in here.
// Type: Overridden.
// Args: None.
-// Return: MIstatus::success - Functional succeeded.
-// MIstatus::failure - Functional failed.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
// Throws: None.
//--
bool
CMICmdCmdDataReadMemoryBytes::Execute(void)
{
- CMICMDBASE_GETOPTION(pArgAddrStart, Number, m_constStrArgAddrStart);
- CMICMDBASE_GETOPTION(pArgAddrOffset, Number, m_constStrArgByteOffset);
+ CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
+ CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
+ CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
+ CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
- const MIuint64 nAddrStart = pArgAddrStart->GetValue();
+ // get the --thread option value
+ MIuint64 nThreadId = UINT64_MAX;
+ if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId))
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
+ m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str()));
+ return MIstatus::failure;
+ }
+
+ // get the --frame option value
+ MIuint64 nFrame = UINT64_MAX;
+ if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame))
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
+ m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str()));
+ return MIstatus::failure;
+ }
+
+ // get the -o option value
+ MIuint64 nAddrOffset = 0;
+ if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset))
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
+ m_cmdData.strMiCmd.c_str(), m_constStrArgByteOffset.c_str()));
+ return MIstatus::failure;
+ }
+
+ // FIXME: shouldn't have to ensure mandatory arguments are present, that should've been handled
+ // in ParseArgs(), unfortunately that seems kinda sorta broken right now if options are provided
+ // but mandatory arguments are missing, so here we go...
+ if (!pArgAddrExpr->GetFound())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY), m_constStrArgAddrExpr.c_str()));
+ return MIstatus::failure;
+ }
+
+ if (!pArgNumBytes->GetFound())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY), m_constStrArgNumBytes.c_str()));
+ return MIstatus::failure;
+ }
+
+ 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::SBThread thread = (nThreadId != UINT64_MAX) ?
+ sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread();
+ if (!thread.IsValid())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str()));
+ return MIstatus::failure;
+ }
+
+ lldb::SBFrame frame = (nFrame != UINT64_MAX) ?
+ thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame();
+ if (!frame.IsValid())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str()));
+ return MIstatus::failure;
+ }
+
+ const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
+ lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
+ lldb::SBError error = addrExprValue.GetError();
+ if (error.Fail())
+ {
+ SetError(error.GetCString());
+ return MIstatus::failure;
+ }
+ else if (!addrExprValue.IsValid())
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
+ return MIstatus::failure;
+ }
+
+ MIuint64 nAddrStart = 0;
+ if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart))
+ {
+ SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str()));
+ return MIstatus::failure;
+ }
+
+ nAddrStart += nAddrOffset;
const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
- if (pArgAddrOffset->GetFound())
- m_nAddrOffset = pArgAddrOffset->GetValue();
m_pBufferMemory = new MIuchar[nAddrNumBytes];
if (m_pBufferMemory == nullptr)
@@ -598,9 +687,6 @@ CMICmdCmdDataReadMemoryBytes::Execute(vo
return MIstatus::failure;
}
- CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
- lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
- lldb::SBError error;
const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error);
if (nReadBytes != nAddrNumBytes)
{
@@ -640,7 +726,8 @@ CMICmdCmdDataReadMemoryBytes::Acknowledg
const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
const CMICmnMIValueResult miValueResult("begin", miValueConst);
CMICmnMIValueTuple miValueTuple(miValueResult);
- const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, m_nAddrOffset));
+ const MIuint64 nAddrOffset = 0;
+ const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
miValueTuple.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
Modified: lldb/trunk/tools/lldb-mi/MICmdCmdData.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmdCmdData.h?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmdCmdData.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmdCmdData.h Thu May 7 00:32:13 2015
@@ -150,14 +150,14 @@ class CMICmdCmdDataReadMemoryBytes : pub
// Attributes:
private:
- const CMIUtilString m_constStrArgThread; // Not specified in MI spec but Eclipse gives this option. Not handled by command.
+ const CMIUtilString m_constStrArgThread; // Not in the MI spec but implemented by GDB.
+ const CMIUtilString m_constStrArgFrame; // Not in the MI spec but implemented by GDB.
const CMIUtilString m_constStrArgByteOffset;
- const CMIUtilString m_constStrArgAddrStart;
+ const CMIUtilString m_constStrArgAddrExpr;
const CMIUtilString m_constStrArgNumBytes;
MIuchar *m_pBufferMemory;
MIuint64 m_nAddrStart;
MIuint64 m_nAddrNumBytesToRead;
- MIuint64 m_nAddrOffset;
};
//++ ============================================================================
Modified: lldb/trunk/tools/lldb-mi/MICmnResources.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnResources.cpp?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnResources.cpp (original)
+++ lldb/trunk/tools/lldb-mi/MICmnResources.cpp Thu May 7 00:32:13 2015
@@ -249,7 +249,8 @@ const CMICmnResources::SRsrcTextData CMI
{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_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_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION, "'print' error. The option '%s' not found"},
+ {IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"}};
//++ ------------------------------------------------------------------------------------
// Details: CMICmnResources constructor.
Modified: lldb/trunk/tools/lldb-mi/MICmnResources.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MICmnResources.h?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MICmnResources.h (original)
+++ lldb/trunk/tools/lldb-mi/MICmnResources.h Thu May 7 00:32:13 2015
@@ -267,7 +267,8 @@ enum
IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS,
IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION,
IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS,
- IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION
+ IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION,
+ IDS_CMD_ERR_EXPR_INVALID
};
//++ ============================================================================
Modified: lldb/trunk/tools/lldb-mi/MIExtensions.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/lldb-mi/MIExtensions.txt?rev=236694&r1=236693&r2=236694&view=diff
==============================================================================
--- lldb/trunk/tools/lldb-mi/MIExtensions.txt (original)
+++ lldb/trunk/tools/lldb-mi/MIExtensions.txt Thu May 7 00:32:13 2015
@@ -32,6 +32,55 @@ Example:
-data-info-line hello.cpp:15
^done,start="0x0000000100000f80",end="0x0000000100000f94",file="/Users/IliaK/p/hello.cpp",line="15"
+# -data-read-memory-bytes
+
+Synopsis
+
+ -data-read-memory-bytes [--thread <thread-id>] [--frame <frame-index>] [-o <byte-offset>] <address> <count>
+
+Where:
+
+ `address`
+ An expression specifying the start of the memory range to read.
+ `count`
+ Number of bytes to read.
+ `byte-offset`
+ Relative offset in bytes from `address` where reading should start.
+ `thread-id`
+ Integer identifier of the thread within which the expression should be evaluated,
+ if this option is omitted the currently selected thread will be used.
+ This option is not in the MI specification but is implemented by GDB.
+ `frame-index`
+ Index of the frame within which the expression should be evaluated,
+ if this option is omitted the currently selected frame will be used.
+ This option is not in the MI specification but is implemented by GDB.
+
+Reads a block of memory from the specified range.
+
+Note that currently this command works in an all-or-nothing fashion where it either reads the entire
+block of memory successfully and returns it as a single block, or it returns an error. This doesn't
+quite match up with the MI specification that says that subsets of the specified range may be
+returned as individual blocks if only some of the memory within the specified range is accessible.
+
+The result record for this command may contain one or more tuples representing the blocks of memory
+that were read, where each tuple has the following fields:
+
+ `begin`
+ The start of the address range for this block (in hex notation).
+ `end`
+ The end of the address range for this block (in hex notation).
+ `offset`
+ Offset of this block from `address` (that was passed in as an argument).
+ `contents`
+ The actual data in this block (in hex notation).
+
+Example:
+
+ (gdb)
+ -data-read-memory-bytes &array 4
+ ^done,memory=[{begin="0x00007fffffffeccc",offset="0x0000000000000000",end="0x00007fffffffecd0",contents="01020304"}]
+ (gdb)
+
# =library-loaded notification
The =library-loaded notification has 3 extra fields:
More information about the lldb-commits
mailing list