gdb: Add support for DW_LNS_set_prologue_end in line-table
authorLancelot SIX <lancelot.six@amd.com>
Fri, 25 Feb 2022 23:41:47 +0000 (23:41 +0000)
committerLancelot SIX <lancelot.six@amd.com>
Mon, 4 Apr 2022 22:03:32 +0000 (23:03 +0100)
commitcc96ae7f8839bd63a943751d52af94db3b956c1f
tree52e84b6b5ac798fdc470e8011bc8bb050804bf46
parent6cacd78ba5bb705e127d60478c71955b37914c53
gdb: Add support for DW_LNS_set_prologue_end in line-table

Add support for DW_LNS_set_prologue_end when building line-tables.  This
attribute can be set by the compiler to indicate that an instruction is
an adequate place to set a breakpoint just after the prologue of a
function.

The compiler might set multiple prologue_end, but considering how
current skip_prologue_using_sal works, this commit modifies it to accept
the first instruction with this marker (if any) to be the place where a
breakpoint should be placed to be at the end of the prologue.

The need for this support came from a problematic usecase generated by
hipcc (i.e. clang).  The problem is as follows:  There's a function
(lets call it foo) which covers PC from 0xa800 to 0xa950.  The body of
foo begins with a call to an inlined function, covering from 0xa800 to
0xa94c.   The issue is that when placing a breakpoint at 'foo', GDB
inserts the breakpoint at 0xa818.  The 0x18 offset is what GDB thinks is
foo's first address past the prologue.

Later, when hitting the breakpoint, GDB reports the stop within the
inlined function because the PC falls in its range while the user
expects to stop in FOO.

Looking at the line-table for this location, we have:

    INDEX  LINE   ADDRESS            IS-STMT
    [...]
    14     293    0x000000000000a66c Y
    15     END    0x000000000000a6e0 Y
    16     287    0x000000000000a800 Y
    17     END    0x000000000000a818 Y
    18     287    0x000000000000a824 Y
    [...]

For comparison, let's look at llvm-dwarfdump's output for this CU:

    Address            Line   Column File   ISA Discriminator Flags
    ------------------ ------ ------ ------ --- ------------- -------------
    [...]
    0x000000000000a66c    293     12      2   0             0  is_stmt
    0x000000000000a6e0     96     43     82   0             0  is_stmt
    0x000000000000a6f8    102     18     82   0             0  is_stmt
    0x000000000000a70c    102     24     82   0             0
    0x000000000000a710    102     18     82   0             0
    0x000000000000a72c    101     16     82   0             0  is_stmt
    0x000000000000a73c   2915     50     83   0             0  is_stmt
    0x000000000000a74c    110      1      1   0             0  is_stmt
    0x000000000000a750    110      1      1   0             0  is_stmt end_sequence
    0x000000000000a800    107      0      1   0             0  is_stmt
    0x000000000000a800    287     12      2   0             0  is_stmt prologue_end
    0x000000000000a818    114     59     81   0             0  is_stmt
    0x000000000000a824    287     12      2   0             0  is_stmt
    0x000000000000a828    100     58     82   0             0  is_stmt
    [...]

The main difference we are interested in here is that llvm-dwarfdump's
output tells us that 0xa800 is an adequate place to place a breakpoint
past a function prologue.  Since we know that foo covers from 0xa800 to
0xa94c, 0xa800 is the address at which the breakpoint should be placed
if the user wants to break in foo.

This commit proposes to add support for the prologue_end flag in the
line-program processing.

The processing of this prologue_end flag is made in skip_prologue_sal,
before it calls gdbarch_skip_prologue_noexcept.  The intent is that if
the compiler gave information on where the prologue ends, we should use
this information and not try to rely on architecture dependent logic to
guess it.

The testsuite have been executed using this patch on GNU/Linux x86_64.
Testcases have been compiled with both gcc/g++ (verison 9.4.0) and
clang/clang++ (version 10.0.0) since at the time of writing GCC does not
set the prologue_end marker.  Tests done with GCC 11.2.0 (not over the
entire testsuite) show that it does not emit this flag either.

No regression have been observed with GCC or Clang.  Note that when
using Clang, this patch fixes a failure in
gdb.opt/inline-small-func.exp.

Change-Id: I720449a8a9b2e1fb45b54c6095d3b1e9da9152f8
13 files changed:
gdb/NEWS
gdb/buildsym.c
gdb/buildsym.h
gdb/doc/gdb.texinfo
gdb/dwarf2/read.c
gdb/symmisc.c
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp
gdb/testsuite/gdb.dwarf2/dw2-prologue-end.c [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp [new file with mode: 0644]
gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp
gdb/testsuite/lib/dwarf.exp