Message ID | 1499740601-15957-1-git-send-email-keiths@redhat.com |
---|---|
State | New |
Headers | show |
> From: Keith Seitz <keiths@redhat.com> > Date: Mon, 10 Jul 2017 19:36:40 -0700 > > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index c167a86..58cdc1a 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -26755,6 +26755,14 @@ known. If not known, this field is not present. > The line number at which this breakpoint appears, if known. > If not known, this field is not present. > > +@item call-site-func > +@item call-site-file > +@item call-site-fullname > +@item call-site-line All but the first of these should be @itemx. Does this warrant a NEWS entry? OK for the documentation part, thanks.
Hi Keith, with attached file on Fedora 25 x86_64 'gcc -g' (not any -O): ------------------------------------------------------------------------------ (gdb) b g Breakpoint 1 at 0x4004ce: file inlined5.c, line 12. (gdb) r Starting program: inlined5 Breakpoint 1, g (a=1) at inlined5.c:12 12 f (a); (gdb) bt #0 g (a=1) at inlined5.c:12 #1 h (a=1) at inlined5.c:20 #2 main () at inlined5.c:28 (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004004ce in g at inlined5.c:10 inlined in main at inlined5.c:20 breakpoint already hit 1 time (gdb) ------------------------------------------------------------------------------ I think g is inlined into h which is inlined into main. Personally I think it would be enough to say "in g" as the rest is a toolchain implementation detail. But if it tries to describe the code layout then it should match the reality. The MI attributes would also need to be adjusted for multi-level inlines. Jan int e; static __attribute__ ((__noinline__)) void f (int a) { e = a; } static __attribute__ ((__always_inline__)) void g (int a) { f (a); e = a; } static __attribute__ ((__always_inline__)) void h (int a) { g (a); e = a; } int main (void) { h (1); return 0; }
On 07/11/2017 03:36 AM, Keith Seitz wrote: > I have chosen to record the actual symbol that we found during the parse > in the SaL. Later that information is copied into the bp_location. At some point I think we'll just make bp_location hold a SaL. :-) > From > there, print_breakpoint_location can use this information to ascertain > that the symbol is really an inlined function, and it can report the > real symbol (foo) and inform the user of the actual call site (where the > breakpoint is really set): > > (gdb) i b > Num Type Disp Enb Address What > 1 breakpoint keep y 0x0000000000400434 in foo at 1228556.c:3 > inlined in main > at 1228556.c:10 > > I have reported this information through to MI so that UI writers can inform > their users as well: > > (gdb) interpreter-exec mi -break-info > ^done,BreakpointTable={nr_rows="1",nr_cols="6",hdr=[{width="7",alignment="-1",col_name="number",colhdr="Num"},{width="14",alignment="-1",col_name="type",colhdr="Type"},{width="4",alignment="-1",col_name="disp",colhdr="Disp"},{width="3",alignment="-1",col_name="enabled",colhdr="Enb"},{width="18",alignment="-1",col_name="addr",colhdr="Address"},{width="40",alignment="2",col_name="what",colhdr="What"}],body=[bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x0000000000400434",func="foo",file="1228556.c",fullname="/home/keiths/tmp/1228556.c",line="3",call-site-func="main",call-site-file="1228556.c",call-site-fullname="/home/keiths/tmp/1228556.c",call-site-line="10",thread-groups=["i1"],times="0",original-location="foo"}]} > > Here you can see the new call-site-func, call-site-file, call-site-fullname, > and call-site-line. The non-inlined call site seems sufficient info to me, at least for the CLI. I'm not sure whether "call-site" is sufficiently clear that it's referring to that vs the immediate potential inlined-too caller though. I think at least the docs need such a clarification. > --- a/gdb/breakpoint.c > +++ b/gdb/breakpoint.c > @@ -6153,24 +6153,73 @@ print_breakpoint_location (struct breakpoint *b, > uiout->field_string ("what", event_location_to_string (b->location.get ())); > else if (loc && loc->symtab) > { > - struct symbol *sym > - = find_pc_sect_function (loc->address, loc->section); > - if (sym) > + /* If a location is associated with an inlined symbol, print out > + information about its call site, too. */ > + if (loc->symbol != NULL && SYMBOL_INLINED (loc->symbol)) > { > + struct inlined_symbol *isym = (struct inlined_symbol *) (loc->symbol); > + struct symbol *sym > + = find_pc_sect_function (loc->address, loc->section); > + > + /* ISYM contains information about the inlined function, and > + LOC->SYMBOL describes the call site. */ > uiout->text ("in "); > - uiout->field_string ("func", SYMBOL_PRINT_NAME (sym)); > + uiout->field_string ("func", SYMBOL_PRINT_NAME (loc->symbol)); > uiout->text (" "); > uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); > uiout->text ("at "); > + > + const char *s = symtab_to_filename_for_display (isym->decl_file); > + uiout->field_string ("file", s); > + > + uiout->text (":"); > + if (uiout->is_mi_like_p ()) > + { > + uiout->field_string ("fullname", > + symtab_to_fullname (isym->decl_file)); > + } Isn't there a good deal of duplication between the above and the else branch? > + uiout->field_int ("line", isym->decl_line); > + uiout->text (" "); > + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); > + uiout->text ("inlined in "); > + if (sym != NULL) > + uiout->field_string ("call-site-func", SYMBOL_PRINT_NAME (sym)); > + uiout->text (" "); > + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); > + uiout->text ("at "); > + s = symtab_to_filename_for_display (symbol_symtab (loc->symbol)); > + uiout->field_string ("call-site-file", s); > + > + uiout->text (":"); > + if (uiout->is_mi_like_p ()) > + { > + s = symtab_to_fullname (symbol_symtab (loc->symbol)); > + uiout->field_string ("call-site-fullname", s); > + } > + uiout->field_int ("call-site-line", SYMBOL_LINE (loc->symbol)); > } > - uiout->field_string ("file", > - symtab_to_filename_for_display (loc->symtab)); > - uiout->text (":"); > + else > + { > + struct symbol *sym > + = find_pc_sect_function (loc->address, loc->section); > I wonder whether the else branch could use loc->symbol now that you have it, instead of looking it up. > - if (uiout->is_mi_like_p ()) > - uiout->field_string ("fullname", symtab_to_fullname (loc->symtab)); > + if (sym) > + { > + uiout->text ("in "); > + uiout->field_string ("func", SYMBOL_PRINT_NAME (sym)); > + uiout->text (" "); > + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); > + uiout->text ("at "); > + } > + uiout->field_string ("file", > + symtab_to_filename_for_display (loc->symtab)); > + uiout->text (":"); > + > + if (uiout->is_mi_like_p ()) > + uiout->field_string ("fullname", symtab_to_fullname (loc->symtab)); > > - uiout->field_int ("line", loc->line_number); > + uiout->field_int ("line", loc->line_number); > + } > } > else if (loc) > { > @@ -8986,6 +9035,7 @@ add_location_to_breakpoint (struct breakpoint *b, > loc->gdbarch = loc_gdbarch; > loc->line_number = sal->line; > loc->symtab = sal->symtab; > + loc->symbol = sal->symbol; > > set_breakpoint_location_function (loc, > sal->explicit_pc || sal->explicit_line); > diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h > index d955184..2f10c3b 100644 > --- a/gdb/breakpoint.h > +++ b/gdb/breakpoint.h > @@ -484,6 +484,11 @@ public: > to find the corresponding source file name. */ > > struct symtab *symtab = NULL; > + > + /* The symbol found by the location parser, if any. This may be used to > + ascertain when an event location was set at a different location than > + the one originally selected by parsing, e.g., inlined symbols. */ > + const struct symbol *symbol = NULL; > }; > > /* The possible return values for print_bpstat, print_it_normal, > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index c167a86..58cdc1a 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -26755,6 +26755,14 @@ known. If not known, this field is not present. > The line number at which this breakpoint appears, if known. > If not known, this field is not present. > > +@item call-site-func > +@item call-site-file > +@item call-site-fullname > +@item call-site-line > +These fields describe the call site for a breakpoint set on an inlined function. > +The fields are analogous to those fields of the same name for normal breakpoint > +locations. IMO, the non-inlined call site is sufficient info, at least for the CLI. I'm not sure whether "call-site" is sufficiently clear that it's referring to that vs the immediate potential inlined-too caller though. I think at least the docs need that clarified. > + > @item at > If the source file is not known, this field may be provided. If > provided, this holds the address of the breakpoint, possibly followed > diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c > index 0fdcd42..3b3193b 100644 > --- a/gdb/dwarf2read.c > +++ b/gdb/dwarf2read.c > @@ -11470,6 +11470,35 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) > do_cleanups (cleanups); > } > > +/* Get the symtab representing the KIND of file of DIE in CU or NULL > + if no such file exists. KIND is any valid DWARF file attribute such as > + DW_AT_decl_file or DW_AT_call_file. */ > + > +static struct symtab * > +dwarf2_file_symtab (unsigned int kind, struct die_info *die, > + struct dwarf2_cu *cu) > +{ > + struct attribute *attr = dwarf2_attr (die, kind, cu); > + > + if (attr != NULL) > + { > + file_name_index file_index = (file_name_index) DW_UNSND (attr); > + struct file_entry *fe; > + > + if (cu->line_header != NULL) > + fe = cu->line_header->file_name_at (file_index); > + else > + fe = NULL; > + > + if (fe == NULL) > + complaint (&symfile_complaints, _("file index out of range")); > + else > + return fe->symtab; > + } > + > + return NULL; > +} > + > static void > read_func_scope (struct die_info *die, struct dwarf2_cu *cu) > { > @@ -11486,6 +11515,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) > int inlined_func = (die->tag == DW_TAG_inlined_subroutine); > VEC (symbolp) *template_args = NULL; > struct template_symbol *templ_func = NULL; > + struct inlined_symbol *isym = NULL; > + struct symbol *symbol_storage = NULL; > > if (inlined_func) > { > @@ -11540,13 +11571,28 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) > { > templ_func = allocate_template_symbol (objfile); > templ_func->base.is_cplus_template_function = 1; > + symbol_storage = (struct symbol *) templ_func; > break; > } > } > > + /* If we have an inlined symbol, we must also allocate a different > + symbol. */ How does this work when you have an (inlined) template function? Like e.g.,: template<typename T> static T inline_func (T val) { return val * 2; } int not_inline_func (int val) { return inline_func (val * 2); } <1><31>: Abbrev Number: 2 (DW_TAG_subprogram) <32> DW_AT_name : (indirect string, offset: 0x929): inline_func<int> <36> DW_AT_decl_file : 1 <37> DW_AT_decl_line : 2 <38> DW_AT_type : <0x54> <3c> DW_AT_inline : 1 (inlined) <3d> DW_AT_sibling : <0x54> > + if (inlined_func) > + { > + isym = allocate_inlined_symbol (objfile); > + isym->decl_file = dwarf2_file_symtab (DW_AT_decl_file, die, cu); > + > + attr = dwarf2_attr (die, DW_AT_decl_line, cu); > + if (attr != NULL) > + isym->decl_line = DW_UNSND (attr); > + > + symbol_storage = (struct symbol *) isym; > + } > + > newobj = push_context (0, lowpc); > newobj->name = new_symbol_full (die, read_type_die (die, cu), cu, > - (struct symbol *) templ_func); > + symbol_storage); > > /* If there is a location expression for DW_AT_frame_base, record > it. */ > @@ -18948,25 +18994,11 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, > SYMBOL_LINE (sym) = DW_UNSND (attr); > } > > /* See symtab.h. */ > > struct objfile * > diff --git a/gdb/symtab.h b/gdb/symtab.h > index 341deca..a70ed54 100644 > --- a/gdb/symtab.h > +++ b/gdb/symtab.h > @@ -910,6 +910,21 @@ struct template_symbol > struct symbol **template_arguments; > }; > > +/* A superclass of struct symbol used to represent an inlined symbol. > + A symbol is really of this type if SYMBOL_INLINED is true. */ > + > +struct inlined_symbol > +{ > + /* The base class. */ > + struct symbol base; Couldn't this be real C++ inheritance? struct inlined_symbol : symbol { ... }; I ran out of time ... more later. Thanks, Pedro Alves
[My reply seems not to have made it to sourceware, so I'm resending.] On 07/18/2017 12:05 PM, Pedro Alves wrote: > On 07/11/2017 03:36 AM, Keith Seitz wrote: >> >> Here you can see the new call-site-func, call-site-file, call-site-fullname, >> and call-site-line. > > The non-inlined call site seems sufficient info to me, at least for > the CLI. I'm not sure whether "call-site" is sufficiently clear that > it's referring to that vs the immediate potential inlined-too > caller though. I think at least the docs need such a clarification. There seems to be consensus on the (lack of) utility of this call-site info, so in the next revision (to follow), I've chosen to remove it all. I think that pretty much resolves (by deletion!) most of your concerns/comments. I've also removed the inlined_symbol proposal since that is also no longer necessary. >> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c >> index 0fdcd42..3b3193b 100644 >> --- a/gdb/dwarf2read.c >> +++ b/gdb/dwarf2read.c >> @@ -11540,13 +11571,28 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) >> { >> templ_func = allocate_template_symbol (objfile); >> templ_func->base.is_cplus_template_function = 1; >> + symbol_storage = (struct symbol *) templ_func; >> break; >> } >> } >> >> + /* If we have an inlined symbol, we must also allocate a different >> + symbol. */ > > How does this work when you have an (inlined) template function? > Like e.g.,: > > template<typename T> > static T inline_func (T val) > { > return val * 2; > } > > int > not_inline_func (int val) > { > return inline_func (val * 2); > } > I realize this was asked in relation to the proposed (and now deleted) inline_symbol, but to be clear, the above example works: (gdb) b inline_func<int> Breakpoint 1 at 0x4004c0: file inline-t.cc, line 9. (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x00000000004004c0 in inline_func<int> at inline-t.cc:9 Keith
On 10/20/2017 07:46 PM, Keith Seitz wrote: > [My reply seems not to have made it to sourceware, so I'm resending.] > > On 07/18/2017 12:05 PM, Pedro Alves wrote: >> On 07/11/2017 03:36 AM, Keith Seitz wrote: >>> >>> Here you can see the new call-site-func, call-site-file, call-site-fullname, >>> and call-site-line. >> >> The non-inlined call site seems sufficient info to me, at least for >> the CLI. I'm not sure whether "call-site" is sufficiently clear that >> it's referring to that vs the immediate potential inlined-too >> caller though. I think at least the docs need such a clarification. > > There seems to be consensus on the (lack of) utility of this call-site info, so in the next revision (to follow), I've chosen to remove it all. I think that pretty much resolves (by deletion!) most of your concerns/comments. I've also removed the inlined_symbol proposal since that is also no longer necessary. I think my observations in <https://sourceware.org/ml/gdb-patches/2017-03/msg00382.html> still make sense, and I don't know about consensus, but OK, let's move on. I'll take a look at the new version. > >>> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c >>> index 0fdcd42..3b3193b 100644 >>> --- a/gdb/dwarf2read.c >>> +++ b/gdb/dwarf2read.c >>> @@ -11540,13 +11571,28 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) >>> { >>> templ_func = allocate_template_symbol (objfile); >>> templ_func->base.is_cplus_template_function = 1; >>> + symbol_storage = (struct symbol *) templ_func; >>> break; >>> } >>> } >>> >>> + /* If we have an inlined symbol, we must also allocate a different >>> + symbol. */ >> >> How does this work when you have an (inlined) template function? >> Like e.g.,: >> >> template<typename T> >> static T inline_func (T val) >> { >> return val * 2; >> } >> >> int >> not_inline_func (int val) >> { >> return inline_func (val * 2); >> } >> > > I realize this was asked in relation to the proposed (and now deleted) inline_symbol, but to be clear, the above example works: > > (gdb) b inline_func<int> > Breakpoint 1 at 0x4004c0: file inline-t.cc, line 9. > (gdb) i b > Num Type Disp Enb Address What > 1 breakpoint keep y 0x00000000004004c0 in inline_func<int> > at inline-t.cc:9 OK, it seems like a DIE can't be both DW_TAG_inlined_subroutine and a template (kind of makes sense), so you couldn't ever end up calling both allocate_template_symbol and allocate_inlined_symbol for the same symbol (which is what I was worrying about, because the code didn't consider/guard against that). Thanks, Pedro Alves
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 053ccef..c283ec0 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -6153,24 +6153,73 @@ print_breakpoint_location (struct breakpoint *b, uiout->field_string ("what", event_location_to_string (b->location.get ())); else if (loc && loc->symtab) { - struct symbol *sym - = find_pc_sect_function (loc->address, loc->section); - if (sym) + /* If a location is associated with an inlined symbol, print out + information about its call site, too. */ + if (loc->symbol != NULL && SYMBOL_INLINED (loc->symbol)) { + struct inlined_symbol *isym = (struct inlined_symbol *) (loc->symbol); + struct symbol *sym + = find_pc_sect_function (loc->address, loc->section); + + /* ISYM contains information about the inlined function, and + LOC->SYMBOL describes the call site. */ uiout->text ("in "); - uiout->field_string ("func", SYMBOL_PRINT_NAME (sym)); + uiout->field_string ("func", SYMBOL_PRINT_NAME (loc->symbol)); uiout->text (" "); uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); uiout->text ("at "); + + const char *s = symtab_to_filename_for_display (isym->decl_file); + uiout->field_string ("file", s); + + uiout->text (":"); + if (uiout->is_mi_like_p ()) + { + uiout->field_string ("fullname", + symtab_to_fullname (isym->decl_file)); + } + uiout->field_int ("line", isym->decl_line); + uiout->text (" "); + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); + uiout->text ("inlined in "); + if (sym != NULL) + uiout->field_string ("call-site-func", SYMBOL_PRINT_NAME (sym)); + uiout->text (" "); + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); + uiout->text ("at "); + s = symtab_to_filename_for_display (symbol_symtab (loc->symbol)); + uiout->field_string ("call-site-file", s); + + uiout->text (":"); + if (uiout->is_mi_like_p ()) + { + s = symtab_to_fullname (symbol_symtab (loc->symbol)); + uiout->field_string ("call-site-fullname", s); + } + uiout->field_int ("call-site-line", SYMBOL_LINE (loc->symbol)); } - uiout->field_string ("file", - symtab_to_filename_for_display (loc->symtab)); - uiout->text (":"); + else + { + struct symbol *sym + = find_pc_sect_function (loc->address, loc->section); - if (uiout->is_mi_like_p ()) - uiout->field_string ("fullname", symtab_to_fullname (loc->symtab)); + if (sym) + { + uiout->text ("in "); + uiout->field_string ("func", SYMBOL_PRINT_NAME (sym)); + uiout->text (" "); + uiout->wrap_hint (wrap_indent_at_field (uiout, "what")); + uiout->text ("at "); + } + uiout->field_string ("file", + symtab_to_filename_for_display (loc->symtab)); + uiout->text (":"); + + if (uiout->is_mi_like_p ()) + uiout->field_string ("fullname", symtab_to_fullname (loc->symtab)); - uiout->field_int ("line", loc->line_number); + uiout->field_int ("line", loc->line_number); + } } else if (loc) { @@ -8986,6 +9035,7 @@ add_location_to_breakpoint (struct breakpoint *b, loc->gdbarch = loc_gdbarch; loc->line_number = sal->line; loc->symtab = sal->symtab; + loc->symbol = sal->symbol; set_breakpoint_location_function (loc, sal->explicit_pc || sal->explicit_line); diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index d955184..2f10c3b 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -484,6 +484,11 @@ public: to find the corresponding source file name. */ struct symtab *symtab = NULL; + + /* The symbol found by the location parser, if any. This may be used to + ascertain when an event location was set at a different location than + the one originally selected by parsing, e.g., inlined symbols. */ + const struct symbol *symbol = NULL; }; /* The possible return values for print_bpstat, print_it_normal, diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c167a86..58cdc1a 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -26755,6 +26755,14 @@ known. If not known, this field is not present. The line number at which this breakpoint appears, if known. If not known, this field is not present. +@item call-site-func +@item call-site-file +@item call-site-fullname +@item call-site-line +These fields describe the call site for a breakpoint set on an inlined function. +The fields are analogous to those fields of the same name for normal breakpoint +locations. + @item at If the source file is not known, this field may be provided. If provided, this holds the address of the breakpoint, possibly followed diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 0fdcd42..3b3193b 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -11470,6 +11470,35 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) do_cleanups (cleanups); } +/* Get the symtab representing the KIND of file of DIE in CU or NULL + if no such file exists. KIND is any valid DWARF file attribute such as + DW_AT_decl_file or DW_AT_call_file. */ + +static struct symtab * +dwarf2_file_symtab (unsigned int kind, struct die_info *die, + struct dwarf2_cu *cu) +{ + struct attribute *attr = dwarf2_attr (die, kind, cu); + + if (attr != NULL) + { + file_name_index file_index = (file_name_index) DW_UNSND (attr); + struct file_entry *fe; + + if (cu->line_header != NULL) + fe = cu->line_header->file_name_at (file_index); + else + fe = NULL; + + if (fe == NULL) + complaint (&symfile_complaints, _("file index out of range")); + else + return fe->symtab; + } + + return NULL; +} + static void read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { @@ -11486,6 +11515,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) int inlined_func = (die->tag == DW_TAG_inlined_subroutine); VEC (symbolp) *template_args = NULL; struct template_symbol *templ_func = NULL; + struct inlined_symbol *isym = NULL; + struct symbol *symbol_storage = NULL; if (inlined_func) { @@ -11540,13 +11571,28 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { templ_func = allocate_template_symbol (objfile); templ_func->base.is_cplus_template_function = 1; + symbol_storage = (struct symbol *) templ_func; break; } } + /* If we have an inlined symbol, we must also allocate a different + symbol. */ + if (inlined_func) + { + isym = allocate_inlined_symbol (objfile); + isym->decl_file = dwarf2_file_symtab (DW_AT_decl_file, die, cu); + + attr = dwarf2_attr (die, DW_AT_decl_line, cu); + if (attr != NULL) + isym->decl_line = DW_UNSND (attr); + + symbol_storage = (struct symbol *) isym; + } + newobj = push_context (0, lowpc); newobj->name = new_symbol_full (die, read_type_die (die, cu), cu, - (struct symbol *) templ_func); + symbol_storage); /* If there is a location expression for DW_AT_frame_base, record it. */ @@ -18948,25 +18994,11 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, SYMBOL_LINE (sym) = DW_UNSND (attr); } - attr = dwarf2_attr (die, - inlined_func ? DW_AT_call_file : DW_AT_decl_file, - cu); - if (attr) - { - file_name_index file_index = (file_name_index) DW_UNSND (attr); - struct file_entry *fe; - - if (cu->line_header != NULL) - fe = cu->line_header->file_name_at (file_index); - else - fe = NULL; - - if (fe == NULL) - complaint (&symfile_complaints, - _("file index out of range")); - else - symbol_set_symtab (sym, fe->symtab); - } + struct symtab *symtab + = dwarf2_file_symtab (inlined_func ? DW_AT_call_file : DW_AT_decl_file, + die, cu); + if (symtab != NULL) + symbol_set_symtab (sym, symtab); switch (die->tag) { diff --git a/gdb/symtab.c b/gdb/symtab.c index 497d520..55bfc93 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3472,6 +3472,7 @@ find_function_start_sal (struct symbol *sym, int funfirstline) fixup_symbol_section (sym, NULL); section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym); sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0); + sal.symbol = sym; if (funfirstline && sal.symtab != NULL && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab)) @@ -5998,6 +5999,19 @@ allocate_template_symbol (struct objfile *objfile) return result; } +/* See description in symtab.h. */ + +struct inlined_symbol * +allocate_inlined_symbol (struct objfile *objfile) +{ + struct inlined_symbol *result; + + result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct inlined_symbol); + initialize_objfile_symbol_1 (&result->base); + + return result; +} + /* See symtab.h. */ struct objfile * diff --git a/gdb/symtab.h b/gdb/symtab.h index 341deca..a70ed54 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -910,6 +910,21 @@ struct template_symbol struct symbol **template_arguments; }; +/* A superclass of struct symbol used to represent an inlined symbol. + A symbol is really of this type if SYMBOL_INLINED is true. */ + +struct inlined_symbol +{ + /* The base class. */ + struct symbol base; + + /* The inlined symbol's symtab. */ + struct symtab *decl_file; + + /* Line number of the inlined symbol. */ + int decl_line; +}; + /* Each item represents a line-->pc (or the reverse) mapping. This is somewhat more wasteful of space than one might wish, but since only @@ -1436,6 +1451,9 @@ struct symtab_and_line /* If PROBE is not NULL, then this is the objfile in which the probe originated. */ struct objfile *objfile; + + /* The symbol for which this SaL was created. */ + struct symbol *symbol; }; extern void init_sal (struct symtab_and_line *sal); @@ -1676,4 +1694,6 @@ void initialize_objfile_symbol (struct symbol *); struct template_symbol *allocate_template_symbol (struct objfile *); +extern struct inlined_symbol *allocate_inlined_symbol (struct objfile *); + #endif /* !defined(SYMTAB_H) */ diff --git a/gdb/testsuite/gdb.opt/inline-break.exp b/gdb/testsuite/gdb.opt/inline-break.exp index 7be3a34..91766d4 100644 --- a/gdb/testsuite/gdb.opt/inline-break.exp +++ b/gdb/testsuite/gdb.opt/inline-break.exp @@ -24,6 +24,76 @@ if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ return -1 } +# Return a string that may be used to match the output of "info break NUM". +# +# Optional arguments: +# +# source - the name of the source file +# func - the name of the function +# disp - the event disposition +# enabled - enable state +# locs - number of locations +# line - source line number (ignored without -source) +# inlined - add inlined list, argument is a list of regexps to match +# *per location* (e.g., [list "" "foo at $source:$line"] will yield +# no inline for first location, and "inlined in foo at ..." for +# the second location) + +proc break_info_1 {num args} { + global decimal + + # Column delimiter + set c {[\t ]+} + + # Row delimiter + set end {[\r\n \t]+} + + # Table header + set header "[join [list Num Type Disp Enb Address What] ${c}]" + + # Get/configure any optional parameters. + parse_args [list {source ""} {func ".*"} {disp "keep"} \ + {enabled "y"} {locs 1} [list line $decimal] \ + {inlined {}} {type "breakpoint"}] + + if {$source != ""} { + set source "/$source:$line" + } + + # Result starts with the standard header. + set result "$header${end}" + + # Set up for multi-location breakpoint marker. + if {$locs == 1} { + set multi ".*" + } else { + set multi "<MULTIPLE>${end}" + } + append result "[join [list $num $type $disp $enabled $multi] $c]" + + # Add location info. + for {set i 1} {$i <= $locs} {incr i} { + if {$locs > 1} { + append result "[join [list $num.$i $enabled] $c].*" + } + + # Add function/source file info. + append result "in $func at .*$source${end}" + + # Add inline, if requested. + if {$i <= [llength $inlined]} { + set inlined_regexp [lindex $inlined [expr $i - 1]] + } else { + set inlined_regexp "" + } + if {$inlined_regexp != ""} { + append result ".*inlined in $inlined_regexp${end}" + } + } + + return $result +} + # # func1 is a static inlined function that is called once. # The result should be a single-location breakpoint. @@ -111,3 +181,34 @@ gdb_test "print func1" \ # gdb_test "print func2" \ "\\\$.* = {int \\(int\\)} .* <func2>" + +# Test that "info break" reports the location of the breakpoints "inside" +# the inlined functions + +set results(1) [break_info_1 1 -source $srcfile -func "func1" \ + -inlined [list "main at .*"]] +set results(2) [break_info_1 2 -locs 2 -source $srcfile -func "func2" \ + -inlined [list "" "main at .*"]] +set results(3) [break_info_1 3 -source $srcfile -func "func3b" \ + -inlined [list "main at .*"]] +set results(4) [break_info_1 4 -locs 2 -source $srcfile -func "func4b" \ + -inlined [list "func4a at .*" "main at .*"]] +set results(5) [break_info_1 5 -locs 2 -source $srcfile -func "func5b" \ + -inlined [list "" ".*"]] +set results(6) [break_info_1 6 -locs 3 -source $srcfile -func "func6b" \ + -inlined [list "" ".*"]] +set results(7) [break_info_1 7 -locs 2 -source $srcfile -func "func7b" \ + -inlined [list ".*" ".*"]] +set results(8) [break_info_1 8 -locs 3 -source $srcfile -func "func8b"\ + -inlined [list "" ".*" ".*"]] + +for {set i 1} {$i <= [llength [array names results]]} {incr i} { + send_log "Expecting: $results($i)\n" + gdb_test "info break $i" $results($i) +} + +# A quick check that MI is outputting new call-site parameters. +gdb_test "interpreter-exec mi -break-info 1" \ + ".*,call-site-func=\"main\",call-site-file=\".*\",call-site-fullname=\".*\",call-site-line=\".*\".*" + +unset -nocomplain results