This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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] Making it easier to set breakpoints in gdb on pass->execute methods


A complaint I heard at Cauldron with the C++ification of GCC passes is
that it's become much more difficult to set breakpoints on the execute
hooks of a pass, now that the passes are classes within anonymous
namespaces.

When this was first done, the execute methods were trivial
implementations that called into the existing named functions, which are
still easy to put a breakpoint on by name (assuming you know the name of
the function), but some of these have now been converted so that the
"execute" method is the body of the pass.

I did some experimentation, on this box with
gdb-7.6.50.20130731-19.fc20.x86_64 and gcc trunk r212913 (the latter
from a week ago).

You *can* set a breakpoint by name on such an execute method, but it's
tedious to type:
(gdb) break '(anonymous namespace)::pass_expand::execute'
Breakpoint 7 at 0x655220: file ../../src/gcc/cfgexpand.c, line 

...since tab-completion doesn't work well:

(gdb) break '(a<TAB>
does tab complete to:
(gdb) break '(anonymous namespace)::

but typing anything else then hitting tab returns back to:
(gdb) break '(anonymous namespace)::

Is anyone else seeing this?

I had a go at implementing a workaround, for the lack of tab completion
(and the general verbosity) using gdbhooks.py.  

Attached is a patch to gdbhooks.py which adds a new command
"break-on-pass" to gdb; in particular, it locates and parses passes.def,
so that it can tab-complete on pass classnames:

Example of use from the script: putting a breakpoint on "final", i.e.
classname "pass_final":

  (gdb) break-on-pass
Press <TAB>; it autocompletes to "pass_":
  (gdb) break-on-pass pass_
Press <TAB>:
  Display all 219 possibilities? (y or n)
Press "n"; then type "f":
  (gdb) break-on-pass pass_f
Press <TAB> to autocomplete to pass classnames beginning with "pass_f":
  pass_fast_rtl_dce              pass_fold_builtins
  pass_feedback_split_functions  pass_forwprop
  pass_final                     pass_fre
  pass_fixup_cfg                 pass_free_cfg
Type "in<TAB>" to complete to "pass_final":
  (gdb) break-on-pass pass_final
...and hit <RETURN>:
  Breakpoint 6 at 0x8396ba: file ../../src/gcc/final.c, line 4526.
...and we have a breakpoint set; continue execution:
  (gdb) cont
  Continuing.
  Breakpoint 6, (anonymous namespace)::pass_final::execute (this=0x17fb990) at ../../src/gcc/final.c:4526
  4526	  virtual unsigned int execute (function *) { return rest_of_handle_final (); }

This assumes you've suitably enabled gdbhooks.py, as documented at the
top of that file.

Thoughts?
Dave

gcc/
	* gdbhooks.py (find_gcc_source_dir): New helper function.
	(class PassNames): New class, locating and parsing passes.def.
	(class BreakOnPass): New command "break-on-pass".

diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 85608dc..aeb9199 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -130,6 +130,7 @@ Instead (for now) you must access m_vecdata:
   (gdb) p bb->preds->m_vecdata[1]
   $21 = <edge 0x7ffff044d3b8 (4 -> 5)>
 """
+import os.path
 import re
 
 import gdb
@@ -476,4 +477,71 @@ gdb.printing.register_pretty_printer(
     gdb.current_objfile(),
     build_pretty_printer())
 
+def find_gcc_source_dir():
+    # Use location of global "g" to locate the source tree
+    sym_g = gdb.lookup_global_symbol('g')
+    path = sym_g.symtab.filename # e.g. '../../src/gcc/context.h'
+    srcdir = os.path.split(path)[0] # e.g. '../../src/gcc'
+    return srcdir
+
+class PassNames:
+    """Parse passes.def, gathering a list of pass class names"""
+    def __init__(self):
+        srcdir = find_gcc_source_dir()
+        self.names = []
+        with open(os.path.join(srcdir, 'passes.def')) as f:
+            for line in f:
+                m = re.match('\s*NEXT_PASS \((.+)\);', line)
+                if m:
+                    self.names.append(m.group(1))
+PassNames()
+
+class BreakOnPass(gdb.Command):
+    """
+    A custom command for putting breakpoints on the execute hook of passes.
+    This is largely a workaround for issues with tab-completion in gdb when
+    setting breakpoints on methods on classes within anonymous namespaces.
+
+    Example of use: putting a breakpoint on "final"
+      (gdb) break-on-pass
+    Press <TAB>; it autocompletes to "pass_":
+      (gdb) break-on-pass pass_
+    Press <TAB>:
+      Display all 219 possibilities? (y or n)
+    Press "n"; then type "f":
+      (gdb) break-on-pass pass_f
+    Press <TAB> to autocomplete to pass classnames beginning with "pass_f":
+      pass_fast_rtl_dce              pass_fold_builtins
+      pass_feedback_split_functions  pass_forwprop
+      pass_final                     pass_fre
+      pass_fixup_cfg                 pass_free_cfg
+    Type "in<TAB>" to complete to "pass_final":
+      (gdb) break-on-pass pass_final
+    ...and hit <RETURN>:
+      Breakpoint 6 at 0x8396ba: file ../../src/gcc/final.c, line 4526.
+    ...and we have a breakpoint set; continue execution:
+      (gdb) cont
+      Continuing.
+      Breakpoint 6, (anonymous namespace)::pass_final::execute (this=0x17fb990) at ../../src/gcc/final.c:4526
+      4526	  virtual unsigned int execute (function *) { return rest_of_handle_final (); }
+    """
+    def __init__(self):
+        gdb.Command.__init__(self, 'break-on-pass', gdb.COMMAND_BREAKPOINTS)
+        self.pass_names = None
+
+    def complete(self, text, word):
+        # Lazily load pass names:
+        if not self.pass_names:
+            self.pass_names = PassNames()
+
+        return [name
+                for name in sorted(self.pass_names.names)
+                if name.startswith(text)]
+
+    def invoke(self, arg, from_tty):
+        sym = '(anonymous namespace)::%s::execute' % arg
+        breakpoint = gdb.Breakpoint(sym)
+
+BreakOnPass()
+
 print('Successfully loaded GDB hooks for GCC')

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