https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103135

            Bug ID: 103135
           Summary: DW_AT_high_pc 0 offset for inlined functions with a
                    singled instruction
           Product: gcc
           Version: 11.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wcohen at redhat dot com
  Target Milestone: ---

Created attachment 51749
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51749&action=edit
Reproducer to show DW_AT_high_pc of 0 for an inlined function.

When reviewing the debuginfo for the linux kernel I found a large number of
inlined functions that had an offset of 0 for the DW_AT_high_pc.  This would
indicate that the inlined function has no instructions in it as the DWARF spec
in 2.17.2 Contiguous Address Range says: 

If the value of the DW_AT_high_pc is of class address, it is the address of the
first location past the last instruction associated with the entity; if it is
of class constant, the value is an unsigned integer offset which when added to
the low PC gives the address of the first location past the last instruction
associated with the entity.


I found inlined functions in the Fedora 34 linux-5.14.15 kernel that had
DW_AT_high_pc == 0 with the following command line using dwgrep
(https://pmachata.github.io/dwgrep/):

$  dwgrep /usr/lib/debug/lib/modules/5.14.15-200.fc34.x86_64/vmlinux -e '
let A := entry (?TAG_inlined_subroutine) ?AT_abstract_origin;
let LOW := ((A ?DW_AT_low_pc @DW_AT_low_pc) || (0xdeadbeef));
let HI := ((A ?DW_AT_high_pc @DW_AT_high_pc) || (0xdeadbeef));
let ENTRY := ((A ?DW_AT_low_pc @DW_AT_low_pc) || (A ?DW_AT_entry_pc
@DW_AT_entry_pc) || (0xdeadbeef));
(HI == 0) ([A name, LOW, HI, ENTRY ])' |grep \\[ | sort |more

I found that inlined functions with a single instruction to implement the
function were the ones with DW_AT_high_pc.  The kernel is rather large, so I
have a simple reproducer even-odd.c that has the function isodd that reduces to
a single instruction that demonstrates the problem when compiled with
gcc-11.2.1 and the following command line:

gcc -save-temps -g -O2 even-odd.c -o even-odd

In the output of "eu-readelf --debug-dump=info+ even-odd" see the info for the
inlined function isodd:


 [   31b]      inlined_subroutine   abbrev: 25
               abstract_origin      (ref4) [   3b3]
               entry_pc             (addr) 0x0000000000401070 <main+0x20>
               GNU_entry_view       (data1) 0
               low_pc               (addr) 0x0000000000401070 <main+0x20>
               high_pc              (data8) 0 (0x0000000000401070 <main+0x20>)
               call_file            (data1) even-odd.c (1)
               call_line            (data1) 13
               call_column          (data1) 6
               sibling              (ref4) [   34e]

Looking at the disassembled code is is the expected test of the lsb:


  401070:       40 f6 c6 01             test   $0x1,%sil
  401074:       74 13                   je     401089 <main+0x39>

Would have expected DW_AT_high_pc to be offset 4 not 0 for this example.

Reply via email to