I have added a function to SBTarget that allows
clients to disassemble a series of raw bytes as
demonstrated by a new testcase.
In the future, this API will also allow clients
to provide a callback that adds comments for
addresses in the disassembly.
I also modified the SWIG harness to ensure that
Python ByteArrays work as well as strings as
sources of raw data.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@146611 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/API/SBInstructionList.h b/include/lldb/API/SBInstructionList.h
index 7fecd52..0d336d4 100644
--- a/include/lldb/API/SBInstructionList.h
+++ b/include/lldb/API/SBInstructionList.h
@@ -58,6 +58,7 @@
protected:
friend class SBFunction;
friend class SBSymbol;
+ friend class SBTarget;
void
SetDisassembler (const lldb::DisassemblerSP &opaque_sp);
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 7ac46c8..7aad795 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -494,6 +494,12 @@
SBSourceManager
GetSourceManager();
+
+ lldb::SBInstructionList
+ GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size);
+
+ lldb::SBInstructionList
+ GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size);
#ifndef SWIG
bool
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h
index 126a411..719e069 100644
--- a/include/lldb/Core/Disassembler.h
+++ b/include/lldb/Core/Disassembler.h
@@ -261,6 +261,13 @@
const char *plugin_name,
const ExecutionContext &exe_ctx,
const AddressRange &disasm_range);
+
+ static lldb::DisassemblerSP
+ DisassembleBytes (const ArchSpec &arch,
+ const char *plugin_name,
+ const Address &start,
+ const void *bytes,
+ size_t length);
static bool
Disassemble (Debugger &debugger,
diff --git a/scripts/Python/interface/SBTarget.i b/scripts/Python/interface/SBTarget.i
index 04dcfbf..676a6c0 100644
--- a/scripts/Python/interface/SBTarget.i
+++ b/scripts/Python/interface/SBTarget.i
@@ -470,7 +470,10 @@
lldb::SBBroadcaster
GetBroadcaster () const;
-
+
+ lldb::SBInstructionList
+ GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size);
+
bool
GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level);
};
diff --git a/scripts/Python/python-typemaps.swig b/scripts/Python/python-typemaps.swig
index 55f2819..86ce7af 100644
--- a/scripts/Python/python-typemaps.swig
+++ b/scripts/Python/python-typemaps.swig
@@ -69,30 +69,48 @@
// typemap for an outgoing buffer
// See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len).
%typemap(in) (const char *cstr, uint32_t cstr_len) {
- if (!PyString_Check($input)) {
- PyErr_SetString(PyExc_ValueError, "Expecting a string");
- return NULL;
+ if (PyString_Check($input)) {
+ $1 = (char *) PyString_AsString($input);
+ $2 = PyString_Size($input);
}
- $1 = (char *) PyString_AsString($input);
- $2 = PyString_Size($input);
+ else if(PyByteArray_Check($input)) {
+ $1 = (char *) PyByteArray_AsString($input);
+ $2 = PyByteArray_Size($input);
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "Expecting a string");
+ return NULL;
+ }
}
// Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len).
%typemap(in) (const char *src, size_t src_len) {
- if (!PyString_Check($input)) {
- PyErr_SetString(PyExc_ValueError, "Expecting a string");
- return NULL;
+ if (PyString_Check($input)) {
+ $1 = (char *) PyString_AsString($input);
+ $2 = PyString_Size($input);
}
- $1 = (char *) PyString_AsString($input);
- $2 = PyString_Size($input);
+ else if(PyByteArray_Check($input)) {
+ $1 = (char *) PyByteArray_AsString($input);
+ $2 = PyByteArray_Size($input);
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "Expecting a string");
+ return NULL;
+ }
}
// And SBProcess::WriteMemory.
%typemap(in) (const void *buf, size_t size) {
- if (!PyString_Check($input)) {
- PyErr_SetString(PyExc_ValueError, "Expecting a string");
- return NULL;
+ if (PyString_Check($input)) {
+ $1 = (void *) PyString_AsString($input);
+ $2 = PyString_Size($input);
}
- $1 = (void *) PyString_AsString($input);
- $2 = PyString_Size($input);
+ else if(PyByteArray_Check($input)) {
+ $1 = (void *) PyByteArray_AsString($input);
+ $2 = PyByteArray_Size($input);
+ }
+ else {
+ PyErr_SetString(PyExc_ValueError, "Expecting a string");
+ return NULL;
+ }
}
// typemap for an incoming buffer
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 179cb93..b922d2a 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -1285,6 +1285,33 @@
return source_manager;
}
+lldb::SBInstructionList
+SBTarget::GetInstructions (lldb::SBAddress base_addr, const void *buf, size_t size)
+{
+ SBInstructionList sb_instructions;
+
+ if (m_opaque_sp)
+ {
+ Address addr;
+
+ if (base_addr.get())
+ addr = *base_addr.get();
+
+ sb_instructions.SetDisassembler (Disassembler::DisassembleBytes (m_opaque_sp->GetArchitecture(),
+ NULL,
+ addr,
+ buf,
+ size));
+ }
+
+ return sb_instructions;
+}
+
+lldb::SBInstructionList
+SBTarget::GetInstructions (lldb::addr_t base_addr, const void *buf, size_t size)
+{
+ return GetInstructions (ResolveLoadAddress(base_addr), buf, size);
+}
SBError
SBTarget::SetSectionLoadAddress (lldb::SBSection section,
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index 1628f3a..fe044a6 100644
--- a/source/Core/Disassembler.cpp
+++ b/source/Core/Disassembler.cpp
@@ -230,6 +230,37 @@
return disasm_sp;
}
+lldb::DisassemblerSP
+Disassembler::DisassembleBytes
+(
+ const ArchSpec &arch,
+ const char *plugin_name,
+ const Address &start,
+ const void *bytes,
+ size_t length
+)
+{
+ lldb::DisassemblerSP disasm_sp;
+
+ if (bytes)
+ {
+ disasm_sp.reset(Disassembler::FindPlugin(arch, plugin_name));
+
+ if (disasm_sp)
+ {
+ DataExtractor data(bytes, length, arch.GetByteOrder(), arch.GetAddressByteSize());
+
+ (void)disasm_sp->DecodeInstructions (start,
+ data,
+ 0,
+ UINT32_MAX,
+ false);
+ }
+ }
+
+ return disasm_sp;
+}
+
bool
Disassembler::Disassemble
diff --git a/test/api/disassemble-raw-data/TestDisassembleRawData.py b/test/api/disassemble-raw-data/TestDisassembleRawData.py
new file mode 100644
index 0000000..d9d35d0
--- /dev/null
+++ b/test/api/disassemble-raw-data/TestDisassembleRawData.py
@@ -0,0 +1,40 @@
+"""
+Use lldb Python API to disassemble raw machine code bytes
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class DisassembleRawDataTestCase(TestBase):
+
+ mydir = os.path.join("api", "disassemble-raw-data")
+
+ @python_api_test
+ def test_disassemble_raw_data(self):
+ """Test disassembling raw bytes with the API."""
+ self.disassemble_raw_data()
+
+ def disassemble_raw_data(self):
+ """Test disassembling raw bytes with the API."""
+ # Create a target from the debugger.
+
+ target = self.dbg.CreateTargetWithFileAndTargetTriple ("", "x86_64-apple-darwin")
+ self.assertTrue(target, VALID_TARGET)
+
+ raw_bytes = bytearray([0x48, 0x89, 0xe5])
+
+ insts = target.GetInstructions(lldb.SBAddress(), raw_bytes)
+
+ inst = insts.GetInstructionAtIndex(0)
+
+ self.assertTrue (inst.GetMnemonic(target) == "movq")
+ self.assertTrue (inst.GetOperands(target) == '%' + "rsp, " + '%' + "rbp")
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()