On Tue, Jul 29, 2014 at 04:44:29PM -0400, David Malcolm wrote: > 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.
Well, its a big annoyance of anonymous namespaces in general. > 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. The same holds for the gate method, but those are probably less important in general. > 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). I don't think anonymous namespaces ever worked well with gdb, and afaik it hasn't been fixed. > Thoughts? ugh, why can somebody just fix gdb is my first reaction, but if its useful maybe its worth hacks. Trev > 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')