This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] better assembly level debugging


(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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]