diff options
author | Xavier Roirand <roirand@adacore.com> | 2017-12-11 10:03:45 +0100 |
---|---|---|
committer | Xavier Roirand <roirand@adacore.com> | 2018-01-09 10:02:51 +0100 |
commit | b1dc1806fad00fc5b2589164e964646c02a700fa (patch) | |
tree | 58e4e01765fc82d844cdf5274d2dadce2766a985 /gdb/dwarf2read.c | |
parent | 6cef73f96f58ca3f0e0b2f594b324602c7590611 (diff) | |
download | gdb-b1dc1806fad00fc5b2589164e964646c02a700fa.zip gdb-b1dc1806fad00fc5b2589164e964646c02a700fa.tar.gz gdb-b1dc1806fad00fc5b2589164e964646c02a700fa.tar.bz2 |
Fix breakpoint add on inlined function using function name.
Using this Ada example:
package B is
procedure Read_Small with Inline_Always;
end B;
package body B is
Total : Natural := 0;
procedure Read_Small is
begin
Total := Total + 1;
end Read_Small;
end B;
and
with B;
procedure M is
begin
B.Read_Small;
end M;
% gnatmake -g -O0 -m m.adb -cargs -gnatn
% gdb m
Inserting a breakpoint on Read_Small inlined function does not work:
(gdb) b read_small
Breakpoint 1 at 0x40250e: file b.adb, line 5.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000040250e in b.doit at b.adb:5
(gdb)
In this exemple we should have two breakpoints set, one in package B and
the other one in the inlined instance inside procedure M), like below:
(gdb) b read_small
Breakpoint 1 at 0x40250e: b.adb:5. (2 locations)
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y <MULTIPLE>
1.1 y 0x000000000040250e in b.doit at b.adb:5
1.2 y 0x0000000000402540 in m at b.adb:5
(gdb)
Looking at the DWARF info for inlined instance of Read_Small:
<1><1526>: Abbrev Number: 2 (DW_TAG_subprogram)
<1527> DW_AT_name : ([...], offset: 0x1e82): b__read_small
<152b> DW_AT_decl_file : 2
<152c> DW_AT_decl_line : 3
<152d> DW_AT_inline : 3 (declared as inline and inlined)
[...]
<2><1547>: Abbrev Number: 4 (DW_TAG_inlined_subroutine)
<1548> DW_AT_abstract_origin: <0x1526>
<154c> DW_AT_low_pc : 0x402552
<1554> DW_AT_high_pc : 0x2b
<155c> DW_AT_call_file : 1
<155d> DW_AT_call_line : 5
<2><155e>: Abbrev Number: 0
During the parsing of DWARF info in order to produce partial DIE linked
list, the DW_TAG_inlined_subroutine were skipped thus not present in the
final partial dies.
Taking DW_TAG_inlined_subroutine in account during the parsing process
fixes the problem.
gdb/ChangeLog:
* dwarf2read.c (scan_partial_symbols, add_partial_symbol)
(add_partial_subprogram, load_partial_dies): Add
DW_TAG_inlined_subroutine handling.
gdb/testsuite/ChangeLog:
* gdb.ada/bp_inlined_func: New testcase.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 1330c37..20e57e0 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -9065,11 +9065,13 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, if (pdi->name != NULL || pdi->tag == DW_TAG_namespace || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type - || pdi->tag == DW_TAG_imported_unit) + || pdi->tag == DW_TAG_imported_unit + || pdi->tag == DW_TAG_inlined_subroutine) { switch (pdi->tag) { case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu); break; case DW_TAG_constant: @@ -9304,6 +9306,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) switch (pdi->tag) { + case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: addr = gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr); if (pdi->is_external || cu->language == language_ada) @@ -9501,12 +9504,12 @@ add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu); } -/* Read a partial die corresponding to a subprogram and create a partial - symbol for that subprogram. When the CU language allows it, this - routine also defines a partial symbol for each nested subprogram - that this subprogram contains. If SET_ADDRMAP is true, record the - covered ranges in the addrmap. Set *LOWPC and *HIGHPC to the lowest - and highest PC values found in PDI. +/* Read a partial die corresponding to a subprogram or an inlined + subprogram and create a partial symbol for that subprogram. + When the CU language allows it, this routine also defines a partial + symbol for each nested subprogram that this subprogram contains. + If SET_ADDRMAP is true, record the covered ranges in the addrmap. + Set *LOWPC and *HIGHPC to the lowest and highest PC values found in PDI. PDI may also be a lexical block, in which case we simply search recursively for subprograms defined inside that lexical block. @@ -9518,7 +9521,7 @@ add_partial_subprogram (struct partial_die_info *pdi, CORE_ADDR *lowpc, CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu) { - if (pdi->tag == DW_TAG_subprogram) + if (pdi->tag == DW_TAG_subprogram || pdi->tag == DW_TAG_inlined_subroutine) { if (pdi->has_pc_info) { @@ -9566,6 +9569,7 @@ add_partial_subprogram (struct partial_die_info *pdi, { fixup_partial_die (pdi, cu); if (pdi->tag == DW_TAG_subprogram + || pdi->tag == DW_TAG_inlined_subroutine || pdi->tag == DW_TAG_lexical_block) add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu); pdi = pdi->die_sibling; @@ -18409,6 +18413,7 @@ load_partial_dies (const struct die_reader_specs *reader, && abbrev->tag != DW_TAG_constant && abbrev->tag != DW_TAG_enumerator && abbrev->tag != DW_TAG_subprogram + && abbrev->tag != DW_TAG_inlined_subroutine && abbrev->tag != DW_TAG_lexical_block && abbrev->tag != DW_TAG_variable && abbrev->tag != DW_TAG_namespace |