Message ID | 1406666669.2134.139.camel@surprise |
---|---|
State | New |
Headers | show |
On Tue, 2014-07-29 at 16:44 -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. > > 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? FWIW, this appears to be filed against gdb as: https://sourceware.org/bugzilla/show_bug.cgi?id=16874 [...snip discussion of workaround...]
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')
On Tue, Jul 29, 2014 at 10:44 PM, David Malcolm <dmalcolm@redhat.com> 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. > > 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? Yes, I filed a gdb bug about 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? Works for me though I'm not able to review python ;) Richard. > 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". >
On Wed, 2014-07-30 at 10:07 +0200, Richard Biener wrote: > On Tue, Jul 29, 2014 at 10:44 PM, David Malcolm <dmalcolm@redhat.com> 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. > > > > 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? > > Yes, I filed a gdb bug about 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? > > Works for me though I'm not able to review python ;) I've gone ahead and committed it to trunk as r213646; hope this reduces the pain somewhat. > Richard. > > > 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". > >
On Tue, Aug 05, 2014 at 05:02:57PM -0400, David Malcolm wrote: > On Wed, 2014-07-30 at 10:07 +0200, Richard Biener wrote: > > On Tue, Jul 29, 2014 at 10:44 PM, David Malcolm <dmalcolm@redhat.com> 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. > > > > > > 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? > > > > Yes, I filed a gdb bug about 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? > > > > Works for me though I'm not able to review python ;) > > I've gone ahead and committed it to trunk as r213646; hope this reduces > the pain somewhat. So, I was thinking about this more at some point. iirc the reason to put the classes in the anon namespace was to get stuff devirtualized. However I think we can just use __final if building with gcc to acomplish the same thing, and then remove the namespace {}s. It needs to be tested, but if it works it would be even better :-) Trev > > > Richard. > > > > > 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')