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
|
@ -1,3 +1,10 @@
|
||||||
|
2013-02-20 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.
|
||||||
|
|
||||||
2013-02-20 Jiong Wang <jiwang@tilera.com>
|
2013-02-20 Jiong Wang <jiwang@tilera.com>
|
||||||
|
|
||||||
* MAINTAINERS (Write After Approval): Add myself to the list.
|
* MAINTAINERS (Write After Approval): Add myself to the list.
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2013-02-20 Siva Chandra Reddy <sivachandra@google.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Architectures In Python): Add description about
|
||||||
|
the new method gdb.Architecture.disassemble.
|
||||||
|
|
||||||
2013-02-15 Pedro Alves <pedro@codesourcery.com>
|
2013-02-15 Pedro Alves <pedro@codesourcery.com>
|
||||||
Hafiz Abid Qadeer <abidh@codesourcery.com>
|
Hafiz Abid Qadeer <abidh@codesourcery.com>
|
||||||
|
|
||||||
|
|
|
@ -26040,6 +26040,42 @@ A @code{gdb.Architecture} class has the following methods:
|
||||||
Return the name (string value) of the architecture.
|
Return the name (string value) of the architecture.
|
||||||
@end defun
|
@end defun
|
||||||
|
|
||||||
|
@defun Architecture.disassemble (@var{start_pc} @r{[}, @var{end_pc} @r{[}, @var{count}@r{]]})
|
||||||
|
Return a list of disassembled instructions starting from the memory
|
||||||
|
address @var{start_pc}. The optional arguments @var{end_pc} and
|
||||||
|
@var{count} determine the number of instructions in the returned list.
|
||||||
|
If both the optional arguments @var{end_pc} and @var{count} are
|
||||||
|
specified, then a list of at most @var{count} disassembled instructions
|
||||||
|
whose start address falls in the closed memory address interval from
|
||||||
|
@var{start_pc} to @var{end_pc} are returned. If @var{end_pc} is not
|
||||||
|
specified, but @var{count} is specified, then @var{count} number of
|
||||||
|
instructions starting from the address @var{start_pc} are returned. If
|
||||||
|
@var{count} is not specified but @var{end_pc} is specified, then all
|
||||||
|
instructions whose start address falls in the closed memory address
|
||||||
|
interval from @var{start_pc} to @var{end_pc} are returned. If neither
|
||||||
|
@var{end_pc} nor @var{count} are specified, then a single instruction at
|
||||||
|
@var{start_pc} is returned. For all of these cases, each element of the
|
||||||
|
returned list is a Python @code{dict} with the following string keys:
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
|
||||||
|
@item addr
|
||||||
|
The value corresponding to this key is a Python long integer capturing
|
||||||
|
the memory address of the instruction.
|
||||||
|
|
||||||
|
@item asm
|
||||||
|
The value corresponding to this key is a string value which represents
|
||||||
|
the instruction with assembly language mnemonics. The assembly
|
||||||
|
language flavor used is the same as that specified by the current CLI
|
||||||
|
variable @code{disassembly-flavor}. @xref{Machine Code}.
|
||||||
|
|
||||||
|
@item length
|
||||||
|
The value corresponding to this key is the length (integer value) of the
|
||||||
|
instruction in bytes.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
@end defun
|
||||||
|
|
||||||
@node Python Auto-loading
|
@node Python Auto-loading
|
||||||
@subsection Python Auto-loading
|
@subsection Python Auto-loading
|
||||||
@cindex Python auto-loading
|
@cindex Python auto-loading
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "gdbarch.h"
|
#include "gdbarch.h"
|
||||||
#include "arch-utils.h"
|
#include "arch-utils.h"
|
||||||
|
#include "disasm.h"
|
||||||
#include "python-internal.h"
|
#include "python-internal.h"
|
||||||
|
|
||||||
typedef struct arch_object_type_object {
|
typedef struct arch_object_type_object {
|
||||||
|
@ -86,6 +87,145 @@ archpy_name (PyObject *self, PyObject *args)
|
||||||
return py_name;
|
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. */
|
/* Initializes the Architecture class in the gdb module. */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -105,6 +245,11 @@ static PyMethodDef arch_object_methods [] = {
|
||||||
{ "name", archpy_name, METH_NOARGS,
|
{ "name", archpy_name, METH_NOARGS,
|
||||||
"name () -> String.\n\
|
"name () -> String.\n\
|
||||||
Return the name of the architecture as a string value." },
|
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 */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
2013-02-20 Siva Chandra Reddy <sivachandra@google.com>
|
||||||
|
|
||||||
|
* gdb.python/py-arch.c: New test case
|
||||||
|
* gdb.python/py-arch.exp: New tests to test
|
||||||
|
gdb.Architecture.disassemble
|
||||||
|
* gdb.python/Makefile.in: Add py-arch to the list of
|
||||||
|
EXECUTABLES.
|
||||||
|
|
||||||
2013-02-18 Tom Tromey <tromey@redhat.com>
|
2013-02-18 Tom Tromey <tromey@redhat.com>
|
||||||
|
|
||||||
* gdb.dwarf2/subrange.exp: New file.
|
* gdb.dwarf2/subrange.exp: New file.
|
||||||
|
|
|
@ -6,7 +6,7 @@ EXECUTABLES = py-type py-value py-prettyprint py-template py-block \
|
||||||
py-shared python lib-types py-events py-evthreads py-frame \
|
py-shared python lib-types py-events py-evthreads py-frame \
|
||||||
py-mi py-pp-maint py-progspace py-section-script py-objfile \
|
py-mi py-pp-maint py-progspace py-section-script py-objfile \
|
||||||
py-finish-breakpoint py-finish-breakpoint2 py-value-cc py-explore \
|
py-finish-breakpoint py-finish-breakpoint2 py-value-cc py-explore \
|
||||||
py-explore-cc
|
py-explore-cc py-arch
|
||||||
|
|
||||||
MISCELLANEOUS = py-shared-sl.sl py-events-shlib.so py-events-shlib-nodebug.so
|
MISCELLANEOUS = py-shared-sl.sl py-events-shlib.so py-events-shlib-nodebug.so
|
||||||
|
|
||||||
|
|
23
gdb/testsuite/gdb.python/py-arch.c
Normal file
23
gdb/testsuite/gdb.python/py-arch.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
54
gdb/testsuite/gdb.python/py-arch.exp
Normal file
54
gdb/testsuite/gdb.python/py-arch.exp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Copyright 2013 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
standard_testfile
|
||||||
|
|
||||||
|
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Skip all tests if Python scripting is not enabled.
|
||||||
|
if { [skip_python_tests] } { continue }
|
||||||
|
|
||||||
|
if ![runto_main] {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_py_test_silent_cmd "python frame = gdb.selected_frame()" "get frame" 0
|
||||||
|
gdb_py_test_silent_cmd "python arch = frame.architecture()" "get arch" 0
|
||||||
|
gdb_py_test_silent_cmd "python pc = frame.pc()" "get pc" 0
|
||||||
|
gdb_py_test_silent_cmd "python insn_list1 = arch.disassemble(pc, pc, 1)" \
|
||||||
|
"disassemble" 0
|
||||||
|
gdb_py_test_silent_cmd "python insn_list2 = arch.disassemble(pc, pc)" \
|
||||||
|
"disassemble no count" 0
|
||||||
|
gdb_py_test_silent_cmd "python insn_list3 = arch.disassemble(pc, count=1)" \
|
||||||
|
"disassemble no end" 0
|
||||||
|
gdb_py_test_silent_cmd "python insn_list4 = arch.disassemble(pc)" \
|
||||||
|
"disassemble no end no count" 0
|
||||||
|
|
||||||
|
gdb_test "python print len(insn_list1)" "1" "test number of instructions 1"
|
||||||
|
gdb_test "python print len(insn_list2)" "1" "test number of instructions 2"
|
||||||
|
gdb_test "python print len(insn_list3)" "1" "test number of instructions 3"
|
||||||
|
gdb_test "python print len(insn_list4)" "1" "test number of instructions 4"
|
||||||
|
|
||||||
|
gdb_py_test_silent_cmd "python insn = insn_list1\[0\]" "get instruction" 0
|
||||||
|
|
||||||
|
gdb_test "python print \"addr\" in insn" "True" "test key addr"
|
||||||
|
gdb_test "python print \"asm\" in insn" "True" "test key asm"
|
||||||
|
gdb_test "python print \"length\" in insn" "True" "test key length"
|
||||||
|
|
||||||
|
# Negative test
|
||||||
|
gdb_test "python arch.disassemble(0, 0)" ".*gdb\.MemoryError.*" \
|
||||||
|
"test exception"
|
Loading…
Add table
Add a link
Reference in a new issue