forked from OSchip/llvm-project
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. llvm-svn: 146611
This commit is contained in:
parent
75d7d5e988
commit
50952e9571
|
@ -58,6 +58,7 @@ public:
|
|||
protected:
|
||||
friend class SBFunction;
|
||||
friend class SBSymbol;
|
||||
friend class SBTarget;
|
||||
|
||||
void
|
||||
SetDisassembler (const lldb::DisassemblerSP &opaque_sp);
|
||||
|
|
|
@ -494,6 +494,12 @@ public:
|
|||
|
||||
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
|
||||
|
|
|
@ -261,6 +261,13 @@ public:
|
|||
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,
|
||||
|
|
|
@ -470,7 +470,10 @@ public:
|
|||
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
else if(PyByteArray_Check($input)) {
|
||||
$1 = (char *) PyByteArray_AsString($input);
|
||||
$2 = PyByteArray_Size($input);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting a string");
|
||||
return NULL;
|
||||
}
|
||||
$1 = (char *) PyString_AsString($input);
|
||||
$2 = PyString_Size($input);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
else if(PyByteArray_Check($input)) {
|
||||
$1 = (char *) PyByteArray_AsString($input);
|
||||
$2 = PyByteArray_Size($input);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting a string");
|
||||
return NULL;
|
||||
}
|
||||
$1 = (char *) PyString_AsString($input);
|
||||
$2 = PyString_Size($input);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
else if(PyByteArray_Check($input)) {
|
||||
$1 = (void *) PyByteArray_AsString($input);
|
||||
$2 = PyByteArray_Size($input);
|
||||
}
|
||||
else {
|
||||
PyErr_SetString(PyExc_ValueError, "Expecting a string");
|
||||
return NULL;
|
||||
}
|
||||
$1 = (void *) PyString_AsString($input);
|
||||
$2 = PyString_Size($input);
|
||||
}
|
||||
|
||||
// typemap for an incoming buffer
|
||||
|
|
|
@ -1285,6 +1285,33 @@ SBTarget::GetSourceManager()
|
|||
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,
|
||||
|
|
|
@ -230,6 +230,37 @@ Disassembler::DisassembleRange
|
|||
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
|
||||
|
|
|
@ -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()
|
Loading…
Reference in New Issue