This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] better assembly level debugging
- From: Francois <rigault dot francois at gmail dot com>
- To: pmuldoon at redhat dot com
- Cc: gdb-patches at sourceware dot org
- Date: Fri, 6 May 2011 17:56:56 +0200
- Subject: [PATCH] better assembly level debugging
- References: <BANLkTi=NhwR2_F584nsxVhvDtTuxPMB0Ag@mail.gmail.com> <m3tydd9j3u.fsf@redhat.com>
(continuing http://sourceware.org/ml/gdb/2011-05/msg00009.html)
I've made a proof of concept patch to pretty print addresses. I
believe it can already greatly improve the task of reading assembly
code, although it is not yet ready for delivery, I'd love some
feedback.
I'm finally able to display:
=> 0x400680 <main+4>: sub $0x10,%rsp
0x400684 <main+8>: mov 0x1003fd(%rip),%rax # 0x500a88 [<wprintf>]
0x40068b <main+15>: mov %rax,-0x10(%rbp)
0x40068f <main+19>: lea 0x106(%rip),%rax # 0x40079c [L"foo 42"]
Examining the stack:
0x7fffffffdd00 [<wprintf>]: 0x7ffff7371920 <wprintf>
0x40079c [L"foo 42"]
where a Python pretty printer is used to
- show method name (here 0x500a88 comes from .rela.dyn and is not
matching any symbol)
- show strings (0x40079c points to a wide char string)
For that purpose, I've made 2 changes:
- a gdb.probe_address Python function is called by the print_insn
routine to check if operands can be pretty printed. If yes, the # is
added on the right of the instruction and the print_address_func is
called
- a gdb.print_address Python function is called by
print_address_symbolic if no symbolic address could be created for
this address by the C code.
There are a couple of issues with this first draft :
- you need to define 2 Python functions, if gdb.probe_address returns
an address but print_address is not able to print something pretty,
you will have the same address within the operand and within the
#-block on the right. I'd like to have a single function but I don't
know how I should store it's result...
- the C code takes precedence. The python function is not even called
if (for example) a symbol already exists for this address.
- the output can be uglier sometime (see for example when examining
the stack above : the address on the left repeats the content of data)
- the code is not safe yet and I did the changes only for i386-dis.
Hoping for some feedback
cheers
Francois
diff -r -u1 -d gdb-7.3.50.20110503/gdb/disasm.c new/gdb/disasm.c
--- gdb-7.3.50.20110503/gdb/disasm.c 2011-02-03 15:45:36.000000000 +0100
+++ new/gdb/disasm.c 2011-05-06 15:39:10.000089000 +0200
@@ -28,2 +28,3 @@
#include "dis-asm.h"
+#include "python/python.h"
@@ -396,2 +397,3 @@
di.application_data = gdbarch;
+ di.probe_address_func = (bfd_vma ( *) (char* , void* )) py_probe_address;
disassemble_init_for_target (&di);
diff -r -u1 -d gdb-7.3.50.20110503/gdb/printcmd.c new/gdb/printcmd.c
--- gdb-7.3.50.20110503/gdb/printcmd.c 2011-03-22 15:39:40.000000000 +0100
+++ new/gdb/printcmd.c 2011-05-06 15:41:31.000626000 +0200
@@ -52,2 +52,3 @@
#include "cli/cli-utils.h"
+#include "python/python.h"
@@ -594,2 +595,4 @@
{
+ /* failed: try the python pretty printer */
+ apply_addr_pretty_printer(addr, stream, gdbarch);
do_cleanups (cleanup_chain);
diff -r -u1 -d gdb-7.3.50.20110503/gdb/python/py-prettyprint.c
new/gdb/python/py-prettyprint.c
--- gdb-7.3.50.20110503/gdb/python/py-prettyprint.c 2011-03-31
18:25:41.000000000 +0200
+++ new/gdb/python/py-prettyprint.c 2011-05-06 15:37:34.002309000 +0200
@@ -676,2 +676,67 @@
+/* Calls Python function gdb.probe_address.
+ The input string is usually an operand (like $0x401000) that could
+ represent an address.
+ Returns 0 if this string does not represent an address..
+ Returns the address that could match this string otherwise. */
+
+CORE_ADDR
+py_probe_address (char* bufm, struct gdbarch *gdbarch)
+{
+ PyObject *probe_func, *result, *value;
+ CORE_ADDR ret = 0;
+ struct cleanup *cleanups = ensure_python_env (gdbarch, current_language);
+
+ if (!PyObject_HasAttrString(gdb_module, "probe_address"))
+ goto done;
+
+ probe_func = PyObject_GetAttrString(gdb_module, "probe_address");
+ value = PyString_FromString(bufm);
+ result = PyObject_CallFunctionObjArgs (probe_func, value, NULL);
+ if (result)
+ ret = (CORE_ADDR) PyInt_AsLong(result);
+ Py_DECREF(value);
+ Py_DECREF(probe_func);
+ Py_XDECREF(result);
+done:
+ do_cleanups(cleanups);
+ return ret;
+
+}
+
+/*
+ Pretty print address on stream, by calling the gdb.print_address Python
+ function. gdb.print_address should return the string to pretty print or
+ an empty string. */
+
+int
+apply_addr_pretty_printer (CORE_ADDR address,
+ struct ui_file *stream,
+ struct gdbarch *gdbarch)
+{
+
+ PyObject *probe_func, *result, *value;
+ char* ret;
+ struct cleanup *cleanups = ensure_python_env (gdbarch, current_language);
+
+ if (!PyObject_HasAttrString(gdb_module, "print_address"))
+ goto done;
+
+ probe_func = PyObject_GetAttrString(gdb_module, "print_address");
+ value = PyInt_FromLong(address);
+ result = PyObject_CallFunctionObjArgs (probe_func, value, NULL);
+ if (result) {
+ ret = PyString_AsString(result);
+ if (strlen(ret) > 0)
+ fprintf_filtered (stream, " [%s]", ret);
+ Py_DECREF(result);
+ }
+ Py_DECREF(value);
+ Py_DECREF(probe_func);
+done:
+ do_cleanups(cleanups);
+
+ return 0;
+}
+
int
diff -r -u1 -d gdb-7.3.50.20110503/gdb/python/python.h new/gdb/python/python.h
--- gdb-7.3.50.20110503/gdb/python/python.h 2011-03-14 17:09:54.000000000 +0100
+++ new/gdb/python/python.h 2011-05-06 14:52:25.000638000 +0200
@@ -49,2 +49,8 @@
+CORE_ADDR py_probe_address(char* buf, struct gdbarch *gdbarch);
+
+int apply_addr_pretty_printer (CORE_ADDR address,
+ struct ui_file *stream,
+ struct gdbarch *gdbarch);
+
#endif /* GDB_PYTHON_H */
diff -r -u1 -d gdb-7.3.50.20110503/include/dis-asm.h new/include/dis-asm.h
--- gdb-7.3.50.20110503/include/dis-asm.h 2010-06-29 06:17:27.000000000 +0200
+++ new/include/dis-asm.h 2011-05-06 16:00:28.002916000 +0200
@@ -212,2 +212,6 @@
+
+ /* 0 or the address corresponding to operand_txt we want to print */
+ bfd_vma (* probe_address_func) (char* operand_txt, void* application_data);
+
/* Command line options specific to the target disassembler. */
diff -r -u1 -d gdb-7.3.50.20110503/opcodes/i386-dis.c new/opcodes/i386-dis.c
--- gdb-7.3.50.20110503/opcodes/i386-dis.c 2011-02-09 19:43:41.000000000 +0100
+++ new/opcodes/i386-dis.c 2011-05-06 14:48:44.000988000 +0200
@@ -11831,2 +11831,3 @@
+ needcomma = 0;
for (i = 0; i < MAX_OPERANDS; i++)
@@ -11834,2 +11835,3 @@
{
+ needcomma = 1;
(*info->fprintf_func) (info->stream, " # ");
@@ -11839,2 +11841,20 @@
}
+
+ for (i = 0; i < MAX_OPERANDS; i++)
+ if (*op_txt[i] && (op_index[i] == -1))
+ {
+ bfd_vma probed_address = (*info->probe_address_func) (op_txt[i],
+ info->application_data);
+ if (probed_address)
+ {
+ if (needcomma)
+ (*info->fprintf_func)(info->stream, ",");
+ else
+ (*info->fprintf_func)(info->stream, " # ");
+
+ (*info->print_address_func) (probed_address, info);
+ needcomma = 1;
+ }
+ }
+
return codep - priv.the_buffer;
Cheers
Francois