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

            Bug ID: 97713
           Summary: [gsplit-dwarf] label generated for .debug_abbrev.dwo
                    offset, corresponding relocation ignored by objcopy
                    --extract-dwo
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vries at gcc dot gnu.org
  Target Milestone: ---

I.

Consider a simple hello.c, compiled with debug info:
...
$ gcc-11 -g ~/hello.c -dA -save-temps
...

In a-hello.s, in the CU header we have a label .Ldebug_abbrev0:
...
        .section        .debug_info,"",@progbits
.Ldebug_info0:
        .long   0x87    # Length of Compilation Unit Info
        .value  0x4     # DWARF version number
        .long   .Ldebug_abbrev0 # Offset Into Abbrev. Section
....
referring here:
...
        .section        .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
        .uleb128 0x1    # (abbrev code)
        .uleb128 0x11   # (TAG: DW_TAG_compile_unit)
...

In a-hello.o, we find a zero at the abbrev offset:
...
Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x87 (32-bit)
   Version:       4
   Abbrev Offset: 0x0
   Pointer Size:  8
...
but there's a related relocation in place:
...
Relocation section '.rela.debug_info' at offset 0x4c8 contains 16 entries:
  Offset          Info           Type           Sym. Value    Sym. Name +
Addend
000000000006  00070000000a R_X86_64_32       0000000000000000 .debug_abbrev + 0
...
and in the a.out, we end up with:
...
  Compilation Unit @ offset 0xc7:
   Length:        0x87 (32-bit)
   Version:       4
   Abbrev Offset: 0x64
...


II.

Now cp a-hello.s to hello.s and modify like this:
...
$ diff -u a-hello.s hello.s
--- a-hello.s   2020-11-04 13:04:03.325633204 +0100
+++ hello.s     2020-11-04 13:04:17.001509687 +0100
@@ -102,6 +102,7 @@
                        # DW_AT_GNU_all_tail_call_sites
        .byte   0       # end of children of DIE 0xb
        .section        .debug_abbrev,"",@progbits
+       .uleb128 0x0    # (abbrev code)
 .Ldebug_abbrev0:
        .uleb128 0x1    # (abbrev code)
        .uleb128 0x11   # (TAG: DW_TAG_compile_unit)
...
and recompile:
...
$ gcc-11 -g hello.s -save-temps
...

We can see that we've indeed moved the label by 1 byte:
...
$ llvm-dwarfdump -debug-abbrev a-hello.o
a-hello.o:      file format ELF64-x86-64

.debug_abbrev contents:
Abbrev table for offset: 0x00000000
Abbrev table for offset: 0x00000001
[1] DW_TAG_compile_unit DW_CHILDREN_yes
...
and likewise, the relocation:
...
Relocation section '.rela.debug_info' at offset 0x4c8 contains 16 entries:
  Offset          Info           Type           Sym. Value    Sym. Name +
Addend
000000000006  00070000000a R_X86_64_32       0000000000000000 .debug_abbrev + 1
...
and likewise, in the a.out:
...
  Compilation Unit @ offset 0xc7:
   Length:        0x87 (32-bit)
   Version:       4
   Abbrev Offset: 0x65
...


III.

Now, let's try the same with in .debug_abbrev.dwo.  We compile with
-gsplit-dwarf:
...
$ gcc-11 ~/hello.c -g -gsplit-dwarf -dA -save-temps
...
and copy to hello.s and modify:
...
$ diff -u a-hello.s hello.s
--- a-hello.s   2020-11-04 13:12:57.188966796 +0100
+++ hello.s     2020-11-04 13:14:48.632059272 +0100
@@ -156,6 +156,7 @@
        .byte   0
        .byte   0       # end of skeleton .debug_abbrev
        .section        .debug_abbrev.dwo,"e",@progbits
+       .uleb128 0x0    # (abbrev code)
 .Ldebug_abbrev0:
        .uleb128 0x1    # (abbrev code)
        .uleb128 0x11   # (TAG: DW_TAG_compile_unit)
...

We can see that we indeed added the entry to .debug_abbrev.dwo:
...
$ llvm-dwarfdump -debug-abbrev a-hello.dwo 
a-hello.dwo:    file format ELF64-x86-64

.debug_abbrev.dwo contents:
Abbrev table for offset: 0x00000000
Abbrev table for offset: 0x00000001
[1] DW_TAG_compile_unit DW_CHILDREN_yes
...

The abbrev offset is 0:
...
Contents of the .debug_info.dwo section:

  Compilation Unit @ offset 0x0:
   Length:        0x50 (32-bit)
   Version:       4
   Abbrev Offset: 0x0
...
but there's no related relocation so the CU is interpreted using the empty
abbrev table at offset 0, and we run into:
...
 <0><b>: Abbrev Number: 1
readelf: Warning: DIE at offset 0xb refers to abbreviation number 1 which does
not exist
...

The split into .o/.dwo is done like this:
...
 /usr/lib64/gcc/x86_64-suse-linux/11/../../../../x86_64-suse-linux/bin/as
--gdwarf2 -v --64 -o a-hello.o hello.s
 objcopy --extract-dwo a-hello.o a-hello.dwo
 objcopy --strip-dwo a-hello.o
...
so we can recreate the original a-hello.o, and find the relocation:
...
Relocation section '.rela.debug_info.dwo' at offset 0x710 contains 1 entry:
  Offset          Info           Type           Sym. Value    Sym. Name +
Addend
000000000006  000a0000000a R_X86_64_32       0000000000000000 .debug_abbrev.dwo
+ 1
...

So, objcopy --extract-dwo (silently) drops the relocation rather than implement
it.

Now, should objcopy implement the relocation?

Note that llvm emits a '0' as abbrev offset instead of a label.

Reply via email to