aboutsummaryrefslogtreecommitdiff
path: root/gdb/python/py-arch.c
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@sourceware.org>2013-02-21 01:46:57 +0000
committerSiva Chandra Reddy <sivachandra@sourceware.org>2013-02-21 01:46:57 +0000
commit9f44fbc03496a470cf661d011d9bcdcf21859726 (patch)
tree9fd2d9e47afdc5718ea6dcb017ca812df8bcb30e /gdb/python/py-arch.c
parentd373aa7be9bbd3d47988652ba59496db34b0d246 (diff)
downloadgdb-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.c145
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 */
};