[RFC - Python Scripting] New method gdb.Architecture.disassemble
Siva Chandra
sivachandra@google.com
Tue Feb 12 14:56:00 GMT 2013
On Fri, Feb 8, 2013 at 10:05 AM, Doug Evans <dje@google.com> wrote:
> On Tue, Feb 5, 2013 at 5:53 PM, Siva Chandra <sivachandra@google.com> wrote:
>> The only useful entry point currently available is gdb_disassembly and
>> I do not think it is a bad entry point. Other disassembly functions in
>> disasm.c are static.
>
> Well, it begs the question what entrypoint into libopcodes does
> gdb_disassembly use? :-)
> Anyways, my point is gdb_disassembly is a bit high level for the
> Python API for me.
Thanks for your detailed reply. I now have a patch which does not use
ui_out. Instead of calling gdb_disassembly, it essentially
re-implements disasm.c:dump_insns. The patch is attached.
2013-02-12 Siva Chandra Reddy <sivachandra@google.com>
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.
-------------- next part --------------
diff --git a/gdb/python/py-arch.c b/gdb/python/py-arch.c
index edd508f..dd50d78 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,137 @@ archpy_name (PyObject *self, PyObject *args)
return py_name;
}
+/* Implementation of gdb.Architecture.disassemble (self, low, high) -> List.
+ Returns a list of instructions in a memory address range. Each instruction
+ in the list is a dict object with the following string keys:
+
+ KEY VALUE TYPE DESCRIPTION
+ =============================================================================
+ 'addr' long integer The address of the instruction in target memory.
+ -----------------------------------------------------------------------------
+ 'asm' string The instruction depicted in its assembly
+ language. Will be set to 'unknown' if GDB is
+ unable to obtain this value.
+ -----------------------------------------------------------------------------
+ 'func' string Name of the function to which the instruction
+ belongs to. Will be set to '<unknown>' if GDB is
+ unable to obtain this value.
+ -----------------------------------------------------------------------------
+ 'length' integer Length of the instruction in bytes.
+ -----------------------------------------------------------------------------
+ 'offset' integer The byte offset of the instruction in the func
+ above. Will be set to -1 if GDB is unable to
+ obtain this value.
+*/
+
+static PyObject *
+archpy_disassemble (PyObject *self, PyObject *args, PyObject *kw)
+{
+ static char *keywords[] = { "low", "high", NULL };
+ CORE_ADDR low, high;
+ CORE_ADDR pc;
+ PyObject *result_list;
+ static char unknown_str[] = { '<', 'u', 'n', 'k', 'n', 'o', 'w', 'n', '>', '\0' };
+ struct gdbarch *gdbarch = arch_object_to_gdbarch (self);
+
+ if (!PyArg_ParseTupleAndKeywords (args, kw, GDB_PY_LLU_ARG GDB_PY_LLU_ARG,
+ keywords, &low, &high))
+ return NULL;
+
+ result_list = PyList_New (0);
+ if (!result_list)
+ {
+ PyErr_SetString (PyExc_MemoryError,
+ _("Unable to create a list of disassembled "
+ "instructions."));
+ return NULL;
+ }
+
+ for (pc = low; pc <= high;)
+ {
+ int line = -1, unmapped, offset = -1, insn_len = 0;
+ char *filename = NULL, *funcname = NULL, *asm_code = NULL;
+ struct ui_file *memfile = mem_fileopen ();
+ PyObject *insn_dict = PyDict_New ();
+ volatile struct gdb_exception except;
+
+ if (!insn_dict)
+ {
+ Py_DECREF (result_list);
+ PyErr_SetString (PyExc_MemoryError,
+ _("Unable to create a dict for instruction."));
+
+ return NULL;
+ }
+ if (PyList_Append (result_list, insn_dict))
+ {
+ Py_DECREF (result_list);
+ Py_DECREF (insn_dict);
+
+ return NULL; /* PyList_Append Sets the exception. */
+ }
+
+ TRY_CATCH (except, RETURN_MASK_ALL)
+ {
+ insn_len = gdb_print_insn (gdbarch, pc, memfile, NULL);
+ /* Even though filename, line and unmapped are passed as arguments,
+ they do not give us any meaningful values currently. */
+ build_address_symbolic (gdbarch, pc, 0, &funcname, &offset, &filename,
+ &line, &unmapped);
+ }
+ if (except.reason < 0)
+ {
+ Py_DECREF (result_list);
+ ui_file_delete (memfile);
+ if (funcname)
+ xfree (funcname);
+ if (filename)
+ xfree (filename);
+ if (asm_code)
+ xfree (asm_code);
+
+ return gdbpy_convert_exception (except);
+ }
+
+ asm_code = ui_file_xstrdup (memfile, NULL);
+ if (!asm_code)
+ asm_code = unknown_str;
+ if (!funcname)
+ funcname = unknown_str;
+ if (!filename)
+ filename = unknown_str;
+
+ if (PyDict_SetItemString (insn_dict, "addr",
+ gdb_py_long_from_ulongest (pc))
+ || PyDict_SetItemString (insn_dict, "asm",
+ PyString_FromString (asm_code))
+ || PyDict_SetItemString (insn_dict, "func",
+ PyString_FromString (funcname))
+ || PyDict_SetItemString (insn_dict, "length",
+ PyInt_FromLong (insn_len))
+ || PyDict_SetItemString (insn_dict, "offset",
+ PyInt_FromLong (offset)))
+ {
+ Py_DECREF (result_list);
+ PyErr_SetString (PyExc_MemoryError,
+ _("Unable to add fields to instruction dict."));
+
+ return NULL;
+ }
+
+ pc += insn_len;
+ ui_file_delete (memfile);
+ if (funcname && funcname != unknown_str)
+ xfree (funcname);
+ if (filename && filename != unknown_str)
+ xfree (filename);
+ if (asm_code && asm_code != unknown_str)
+ xfree (asm_code);
+ }
+
+ return result_list;
+}
+
/* Initializes the Architecture class in the gdb module. */
void
@@ -105,6 +237,10 @@ 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 (low, high) -> List.\n\
+Return the list of disassembled instructions from LOW to HIGH." },
{NULL} /* Sentinel */
};
More information about the Gdb-patches
mailing list