diff options
author | Siva Chandra Reddy <sivachandra@sourceware.org> | 2013-02-21 01:46:57 +0000 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@sourceware.org> | 2013-02-21 01:46:57 +0000 |
commit | 9f44fbc03496a470cf661d011d9bcdcf21859726 (patch) | |
tree | 9fd2d9e47afdc5718ea6dcb017ca812df8bcb30e /gdb/python/py-arch.c | |
parent | d373aa7be9bbd3d47988652ba59496db34b0d246 (diff) | |
download | gdb-9f44fbc03496a470cf661d011d9bcdcf21859726.zip gdb-9f44fbc03496a470cf661d011d9bcdcf21859726.tar.gz gdb-9f44fbc03496a470cf661d011d9bcdcf21859726.tar.bz2 |
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.
Diffstat (limited to 'gdb/python/py-arch.c')
-rw-r--r-- | gdb/python/py-arch.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c index edd508f..b41de06 100644 --- a/gdb/python/py-arch.c +++ b/gdb/python/py-arch.c @@ -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 */ }; |