Add a new method 'disassemble' to gdb.Architecture class.
* python/py-arch.c (archpy_disassmble): Implementation of the new method gdb.Architecture.disassemble. (arch_object_methods): Add entry for the new method. * doc/gdb.texinfo (Architectures In Python): Add description about the new method gdb.Architecture.disassemble. * testsuite/gdb.python/py-arch.c: New test case * testsuite/gdb.python/py-arch.exp: New tests to test gdb.Architecture.disassemble * testsuite/gdb.python/Makefile.in: Add py-arch to the list of EXECUTABLES.
This commit is contained in:
parent
d373aa7be9
commit
9f44fbc034
8 changed files with 279 additions and 1 deletions
|
@ -20,6 +20,7 @@
|
|||
#include "defs.h"
|
||||
#include "gdbarch.h"
|
||||
#include "arch-utils.h"
|
||||
#include "disasm.h"
|
||||
#include "python-internal.h"
|
||||
|
||||
typedef struct arch_object_type_object {
|
||||
|
@ -86,6 +87,145 @@ archpy_name (PyObject *self, PyObject *args)
|
|||
return py_name;
|
||||
}
|
||||
|
||||
/* Implementation of
|
||||
gdb.Architecture.disassemble (self, start_pc [, end_pc [,count]]) -> List.
|
||||
Returns a list of instructions in a memory address range. Each instruction
|
||||
in the list is a Python dict object.
|
||||
*/
|
||||
|
||||
static PyObject *
|
||||
archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
static char *keywords[] = { "start_pc", "end_pc", "count", NULL };
|
||||
CORE_ADDR start, end = 0;
|
||||
CORE_ADDR pc;
|
||||
gdb_py_ulongest start_temp;
|
||||
long count = 0, i;
|
||||
PyObject *result_list, *end_obj = NULL, *count_obj = NULL;
|
||||
struct gdbarch *gdbarch = arch_object_to_gdbarch (self);
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords (args, kw, GDB_PY_LLU_ARG "|OO", keywords,
|
||||
&start_temp, &end_obj, &count_obj))
|
||||
return NULL;
|
||||
|
||||
start = start_temp;
|
||||
if (end_obj)
|
||||
{
|
||||
if (PyObject_TypeCheck (end_obj, &PyInt_Type))
|
||||
/* If the end_pc value is specified without a trailing 'L', end_obj will
|
||||
be an integer and not a long integer. */
|
||||
end = PyInt_AsLong (end_obj);
|
||||
else if (PyObject_TypeCheck (end_obj, &PyLong_Type))
|
||||
end = PyLong_AsUnsignedLongLong (end_obj);
|
||||
else
|
||||
{
|
||||
Py_DECREF (end_obj);
|
||||
Py_XDECREF (count_obj);
|
||||
PyErr_SetString (PyExc_TypeError,
|
||||
_("Argument 'end_pc' should be a (long) integer."));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (end < start)
|
||||
{
|
||||
Py_DECREF (end_obj);
|
||||
Py_XDECREF (count_obj);
|
||||
PyErr_SetString (PyExc_ValueError,
|
||||
_("Argument 'end_pc' should be greater than or "
|
||||
"equal to the argument 'start_pc'."));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (count_obj)
|
||||
{
|
||||
count = PyInt_AsLong (count_obj);
|
||||
if (PyErr_Occurred () || count < 0)
|
||||
{
|
||||
Py_DECREF (count_obj);
|
||||
Py_XDECREF (end_obj);
|
||||
PyErr_SetString (PyExc_TypeError,
|
||||
_("Argument 'count' should be an non-negative "
|
||||
"integer."));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
result_list = PyList_New (0);
|
||||
if (result_list == NULL)
|
||||
return NULL;
|
||||
|
||||
for (pc = start, i = 0;
|
||||
/* All args are specified. */
|
||||
(end_obj && count_obj && pc <= end && i < count)
|
||||
/* end_pc is specified, but no count. */
|
||||
|| (end_obj && count_obj == NULL && pc <= end)
|
||||
/* end_pc is not specified, but a count is. */
|
||||
|| (end_obj == NULL && count_obj && i < count)
|
||||
/* Both end_pc and count are not specified. */
|
||||
|| (end_obj == NULL && count_obj == NULL && pc == start);)
|
||||
{
|
||||
int insn_len = 0;
|
||||
char *as = NULL;
|
||||
struct ui_file *memfile = mem_fileopen ();
|
||||
PyObject *insn_dict = PyDict_New ();
|
||||
volatile struct gdb_exception except;
|
||||
|
||||
if (insn_dict == NULL)
|
||||
{
|
||||
Py_DECREF (result_list);
|
||||
ui_file_delete (memfile);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
if (PyList_Append (result_list, insn_dict))
|
||||
{
|
||||
Py_DECREF (result_list);
|
||||
Py_DECREF (insn_dict);
|
||||
ui_file_delete (memfile);
|
||||
|
||||
return NULL; /* PyList_Append Sets the exception. */
|
||||
}
|
||||
|
||||
TRY_CATCH (except, RETURN_MASK_ALL)
|
||||
{
|
||||
insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
|
||||
}
|
||||
if (except.reason < 0)
|
||||
{
|
||||
Py_DECREF (result_list);
|
||||
ui_file_delete (memfile);
|
||||
|
||||
return gdbpy_convert_exception (except);
|
||||
}
|
||||
|
||||
as = ui_file_xstrdup (memfile, NULL);
|
||||
if (PyDict_SetItemString (insn_dict, "addr",
|
||||
gdb_py_long_from_ulongest (pc))
|
||||
|| PyDict_SetItemString (insn_dict, "asm",
|
||||
PyString_FromString (*as ? as : "<unknown>"))
|
||||
|| PyDict_SetItemString (insn_dict, "length",
|
||||
PyInt_FromLong (insn_len)))
|
||||
{
|
||||
Py_DECREF (result_list);
|
||||
|
||||
ui_file_delete (memfile);
|
||||
xfree (as);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pc += insn_len;
|
||||
i++;
|
||||
ui_file_delete (memfile);
|
||||
xfree (as);
|
||||
}
|
||||
|
||||
return result_list;
|
||||
}
|
||||
|
||||
/* Initializes the Architecture class in the gdb module. */
|
||||
|
||||
void
|
||||
|
@ -105,6 +245,11 @@ static PyMethodDef arch_object_methods [] = {
|
|||
{ "name", archpy_name, METH_NOARGS,
|
||||
"name () -> String.\n\
|
||||
Return the name of the architecture as a string value." },
|
||||
{ "disassemble", (PyCFunction) archpy_disassemble,
|
||||
METH_VARARGS | METH_KEYWORDS,
|
||||
"disassemble (start_pc [, end_pc [, count]]) -> List.\n\
|
||||
Return a list of at most COUNT disassembled instructions from START_PC to\n\
|
||||
END_PC." },
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue