With target board readnow and test-case gdb.dwarf2/dw2-align.exp, I have: ... (gdb) run ^M Starting program: dw2-align ^M ^M Breakpoint 1, 0x00000000004004ab in main ()^M (gdb) set lang c++^M Warning: the current language does not match this frame.^M (gdb) FAIL: gdb.dwarf2/dw2-align.exp: set lang c++ ...
Adding a "show lang" gives us more info: ... +gdb_test "show lang" gdb_test_no_output "set lang c++" ... With readnow: ... (gdb) run ^M Starting program: dw2-align ^M ^M Breakpoint 1, 0x00000000004004ab in main ()^M (gdb) show lang^M The current source language is "auto; currently asm".^M (gdb) PASS: gdb.dwarf2/dw2-align.exp: show lang set lang c++^M Warning: the current language does not match this frame.^M (gdb) FAIL: gdb.dwarf2/dw2-align.exp: set lang c++ ... Normal run: ... (gdb) run ^M Starting program: dw2-align ^M ^M Breakpoint 1, 0x00000000004004ab in main ()^M (gdb) show lang^M The current source language is "auto; currently c".^M (gdb) PASS: gdb.dwarf2/dw2-align.exp: show lang set lang c++^M (gdb) PASS: gdb.dwarf2/dw2-align.exp: set lang c++ ... So, the question seems to be, why is the language asm in the readnow case. In other words: ... $ gdb -batch ./outputs/gdb.dwarf2/dw2-align/dw2-align -ex start -ex "show language" Temporary breakpoint 1 at 0x4004ab Temporary breakpoint 1, 0x00000000004004ab in main () The current source language is "auto; currently c". ... vs: ... $ gdb -batch ./outputs/gdb.dwarf2/dw2-align/dw2-align -ex start -ex "show language" -readnow Temporary breakpoint 1 at 0x4004ab Temporary breakpoint 1, 0x00000000004004ab in main () The current source language is "auto; currently asm". ...
The problem happens when select_frame is called, which calls find_pc_compunit_symtab (pc) with a pc of 0x4004ab, which corresponds to main_label: ... 00000000004004a7 <main>: 4004a7: 55 push %rbp 4004a8: 48 89 e5 mov %rsp,%rbp 00000000004004ab <main_label>: 4004ab: b8 00 00 00 00 mov $0x0,%eax 4004b0: 5d pop %rbp 4004b1: c3 retq 4004b2: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 4004b9: 00 00 00 4004bc: 0f 1f 40 00 nopl 0x0(%rax) ... In the normal case, find_pc_compunit_symtab (pc) == NULL. In the readnow case, we have: ... (gdb) p *cust $2 = {next = 0x2089ba0, objfile = 0x1fe9ce0, name = 0x2088290 "crtn.S", filetabs = 0x20882a0, last_filetab = 0x20882a0, debugformat = 0xe16d98 "DWARF 2", producer = 0x1ff6cd5 "GNU AS 2.32.0", dirname = 0x20884d0 "/home/abuild/rpmbuild/BUILD/glibc-2.26/csu", blockvector = 0x20883c0, block_line_section = 11, locations_valid = 0, epilogue_unwind_valid = 0, call_site_htab = 0x0, macro_table = 0x0, includes = 0x0, user = 0x0} ...
In find_pc_sect_compunit_symtab, we iterate to find the best match: ... for (objfile *obj_file : current_program_space->objfiles ()) { for (compunit_symtab *cust : obj_file->compunits ()) { ... And the global block for crtn.S matches, because the address 0x4004ab fits in the range: ... (gdb) p /x b.startaddr $6 = 0x4003c2 (gdb) p /x b.endaddr $7 = 0x40053d ... The crtn.S CU has a DW_AT_ranges attribute: ... <0><2e7>: Abbrev Number: 1 (DW_TAG_compile_unit) <2e8> DW_AT_stmt_list : 0x1a3 <2ec> DW_AT_ranges : 0x40 <2f0> DW_AT_name : ../sysdeps/x86_64/crtn.S ... which corresponds to: ... 00000040 ffffffffffffffff 0000000000000000 (base address) 00000040 00000000004003c2 00000000004003c7 00000040 0000000000400538 000000000040053d 00000040 <End of list> ... So, the global block correctly describes the outer limits of the address range of the crtn.S CU, but 0x4004ab is not part of the address range. The idea behind the algorithm is that a CU should be found with a narrower match for 0x4004ab, which will then be classified as the better match. The problem is that the algorithm doesn't take into account the case that a narrower match is not present, and the best match is still inaccurate. To get an accurate match, we can use f.i. the address map found in the block vector: ... (gdb) p addrmap_find (bv.map, pc) $26 = (void *) 0x0 ... Alternatively, also the static block seems to have accurate info: .... (gdb) p /x bv.block[1].ranges.range[0] $37 = {startaddr = 0x4003c2, endaddr = 0x4003c7} (gdb) p /x bv.block[1].ranges.range[1] $38 = {startaddr = 0x400538, endaddr = 0x40053d} ...
This patch uses the addrmap: ... diff --git a/gdb/symtab.c b/gdb/symtab.c index a4f8239a8a..1148527f68 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -2920,10 +2920,20 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *sec tion) bv = COMPUNIT_BLOCKVECTOR (cust); b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); - if (BLOCK_START (b) <= pc - && BLOCK_END (b) > pc - && (distance == 0 - || BLOCK_END (b) - BLOCK_START (b) < distance)) + bool in_range_p = BLOCK_START (b) <= pc && pc < BLOCK_END (b); + if (!in_range_p) + continue; + + if (BLOCKVECTOR_MAP (bv)) + { + if (addrmap_find (BLOCKVECTOR_MAP (bv), pc) == nullptr) + continue; + + return cust; + } + + if (distance == 0 + || BLOCK_END (b) - BLOCK_START (b) < distance) { /* For an objfile that has its functions reordered, find_pc_psymtab will find the proper partial symbol table ... such that we have: ... $ gdb -batch ./outputs/gdb.dwarf2/dw2-align/dw2-align -ex start -ex "show language" -readnow Temporary breakpoint 1 at 0x4004ab Temporary breakpoint 1, 0x00000000004004ab in main () The current source language is "auto; currently c". ...
Btw, this is on openSUSE Leap 15.2. This doesn't reproduce on f.i. ubuntu 18.04.5, since there there's no debug info for crtn.S.
Patch submitted at https://sourceware.org/pipermail/gdb-patches/2020-October/172733.html
*** Bug 25858 has been marked as a duplicate of this bug. ***
The master branch has been updated by Tom de Vries <vries@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1b00ef063f8230a1f110cc5aeef04d3dc1338358 commit 1b00ef063f8230a1f110cc5aeef04d3dc1338358 Author: Tom de Vries <tdevries@suse.de> Date: Wed Oct 28 21:04:12 2020 +0100 [gdb/symtab] Fix language of frame without debug info On openSUSE Leap 15.2, I run into this FAIL with target board readnow and test-case gdb.dwarf2/dw2-align.exp: ... (gdb) set lang c++^M Warning: the current language does not match this frame.^M (gdb) FAIL: gdb.dwarf2/dw2-align.exp: set lang c++ ... Adding some extra debugging shows that the current language differs without and with readnow: ... Breakpoint 1, 0x00000000004004ab in main ()^M (gdb) show lang^M -The current source language is "auto; currently c".^M +The current source language is "auto; currently asm".^M ... This is explained by find_pc_compunit_symtab (0x4004ab) called from select_frame, which: - without readnow: returns NULL, and - with readnow: returns the symtab for the CU crtn.S, wich has language "MIPS assembler". In the former case, the symtab for crtn.S is not expanded, and find_pc_compunit_symtab hits the default NULL return. In the latter case, the symtab for crtn.S is expanded, and the "best match" loop in find_pc_compunit_symtab returns that symtab as its best match. The GLOBAL_BLOCK for crtn.S has these outer limits of the address range: ... (gdb) p /x b.startaddr $6 = 0x4003c2 (gdb) p /x b.endaddr $7 = 0x40053d ... and 0x4004ab indeed fits in that range, which explains why the CU is considered a match. However, the actual address ranges for the CU are: ... 00000040 ffffffffffffffff 0000000000000000 (base address) 00000040 00000000004003c2 00000000004003c7 00000040 0000000000400538 000000000040053d 00000040 <End of list> ... which confirms that the CU should not be considered a match. The problem is that the "best match" loop is based on the assumption that a symtab with a better match will be found, but in this case we don't find a better match because there's no debug info describing main. Fix this by preferring to use the addres map in the "best match" loop, which will accurately tell us that addrmap_find (bv.map, 0x4004ab) == NULL. Tested on x86_64-linux (that is, openSUSE Leap 15.2), with and without readnow. In the case of a readnow run, brings down the number of unexpected failures from 66 to 38. The FAIL does not reproduce on f.i. Ubuntu 18.04.5, because there the exec does not contain debug info for crtn.S. The dwarf assembly test-case mimics the scenario described above, and reproduces the FAIL with and without -readnow, for both mentioned OS configurations. Also fixes PR25980 - "Overlapping Dwarf Compile Units with non-overlapping subranges gives incorrect line information". gdb/ChangeLog: 2020-10-28 Tom de Vries <tdevries@suse.de> PR symtab/26772 * symtab.c (find_pc_sect_compunit_symtab): In case there's an address map, check it in the "best match" loop. gdb/testsuite/ChangeLog: 2020-10-28 Tom de Vries <tdevries@suse.de> PR symtab/26772 * gdb.dwarf2/dw2-ranges-overlap.c: New test. * gdb.dwarf2/dw2-ranges-overlap.exp: New file.
Patch with test-case committed, marking resolved-fixed.
*** Bug 25980 has been marked as a duplicate of this bug. ***