public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* DWARF Debug Info Relocations (.debug_str STRP references)
@ 2020-11-30 19:18 Bill Messmer
  2020-11-30 20:16 ` Mark Wielaard
  0 siblings, 1 reply; 7+ messages in thread
From: Bill Messmer @ 2020-11-30 19:18 UTC (permalink / raw)
  To: gcc

Hello!

I am trying to understand something unexpected I am seeing in the relocations placed into a compiled Linux kernel for the .debug_info section.  Those relocations seem to change the names of various entries in the debug info:

      [65] .debug_info       PROGBITS         0000000000000000  02c284e0
           000000000c458644  0000000000000000           0     0     1
      [66] .rela.debug_info  RELA             0000000000000000  16081790
           000000001288ae68  0000000000000018   I      78    65     8
      [72] .debug_str        PROGBITS         0000000000000000  10b451e8
           00000000002bef2e  0000000000000001  MS       0     0     1

Dumping the DWARF information for one of the CUs in the compiled image (with standard tooling) shows me:

0x0000002d: DW_TAG_compile_unit
              DW_AT_producer    ("GNU C89 8.3.1 20191121 (Red Hat 8.3.1-5) -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -mfentry -march=x86-64 -g -gdwarf-4 -O2 -std=gnu90 -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -falign-jumps=1 -falign-loops=1 -funit-at-a-time -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fstack-protector-strong -fno-inline-functions-called-once -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fstack-check=no -fconserve-stack --param allow-store-data-races=0")
              DW_AT_language    (DW_LANG_C89)
              DW_AT_name        ("arch/x86/kernel/head64.c")
              DW_AT_comp_dir    ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64")
              DW_AT_ranges      (0x000009d0
                 [0xffffffff81002000, 0xffffffff81002008)
                 [0xffffffff82977172, 0xffffffff829771c0)
                 [0xffffffff829771c0, 0xffffffff8297727a)
                 [0xffffffff8297727a, 0xffffffff829774f8)
                 [0xffffffff829774f8, 0xffffffff82977518)
                 [0xffffffff82977518, 0xffffffff8297759f)
                 [0xffffffff81000200, 0xffffffff810005b9)
                 [0xffffffff8297759f, 0xffffffff829775bc))
              DW_AT_low_pc      (0x0000000000000000)
              DW_AT_stmt_list   (0x00000126)

            0x00000d84:   DW_TAG_structure_type [55] *
                            DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0023ff94] = "task_struct")
                            DW_AT_byte_size [DW_FORM_data2] (0x2480)
                            DW_AT_alignment [DW_FORM_data1] (0x40)
                            DW_AT_decl_file [DW_FORM_data1] ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64/./include/linux/sched.h")
                            DW_AT_decl_line [DW_FORM_data2] (589)
                            DW_AT_decl_column [DW_FORM_data1]       (0x08)
                            DW_AT_sibling [DW_FORM_ref4]    (cu + 0x19cc => {0x000019ee})

As I'd expect, the name of the structure with the DWARF DIE at offset 0xd84 is "task_struct".  A hex dump of this part of .debug_info within the compiled image confirms the 0x23ff94 offset into the string table:

    02c29260  47 0d 00 00 37 **94 ff 23  00** 80 24 40 22 4d 02 08  |G...7..#..$@"M..|

    02c29270  cc 19 00 00 02 28 a5 19  00 22 53 02 16 bb 49 00  |.....(..."S...I.|
    02c29280  00 00 02 77 0a 11 00 22  56 02 12 bd 01 00 00 10  |...w..."V.......|
    02c29290  02 c6 07 15 00 22 5e 02  0b 8b 05 00 00 18 02 26  |....."^........&|

And dumping this area of .debug_str shows the name I'd expect (0x23ff94 within .debug_str is 0x10d8517c)

    10d85168  61 73 6b 5f 73 74 72 75  63 74 00 61 72 63 68 5f  |ask_struct.arch_|

    10d85178  64 75 70 5f **74 61 73 6b  5f 73 74 72 75 63 74 00 ** |dup_task_struct.|

    10d85188  5f 5f 6b 73 79 6d 74 61  62 5f 5f 5f 70 75 74 5f  |__ksymtab___put_|
    10d85198  74 61 73 6b 5f 73 74 72  75 63 74 00 5f 5f 6b 73  |task_struct.__ks|

The relocations within .rela.debug_info, however, change the STRP reference for the "task_struct" DIE to something else:

    Relocation section '.rela.debug_info' at offset 0x16081790 contains 12956143 entries:
      Offset          Info           Type           Sym. Value    Sym. Name + Addend
    000000000d85  002a0000000a R_X86_64_32       0000000000000000 .debug_str + 66d60

Looking at offset 0x66d60 into .debug_str shows the middle of some other random name (0x66d60 in would be 0x10babf48): "ksymtab_power_supply_get_drvdata" in this case.

    10babf38  76 5f 67 65 74 5f 64 72  76 64 61 74 61 00 5f 5f  |v_get_drvdata.__|

    10babf48  6b 73 79 6d 74 61 62 5f  70 6f 77 65 72 5f 73 75  |ksymtab_power_su|

    10babf58  70 70 6c 79 5f 67 65 74  5f 64 72 76 64 61 74 61  |pply_get_drvdata|
    10babf68  00 5f 5f 6b 73 74 72 74  61 62 5f 70 6f 77 65 72  |.__kstrtab_power|

Have I misunderstood something fundamental here about the relocation data in .rela.debug_info and its application...?  Or is the relocation data in this .rela.debug_info bad...?

If there is a better mailing list for me to ask such a question, I'd be happy for a redirect.

Sincerely,

Bill Messmer

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-11-30 19:18 DWARF Debug Info Relocations (.debug_str STRP references) Bill Messmer
@ 2020-11-30 20:16 ` Mark Wielaard
  2020-11-30 22:22   ` [EXTERNAL] " Bill Messmer
  0 siblings, 1 reply; 7+ messages in thread
From: Mark Wielaard @ 2020-11-30 20:16 UTC (permalink / raw)
  To: Bill Messmer; +Cc: gcc

Hi Bill,

On Mon, Nov 30, 2020 at 07:18:50PM +0000, Bill Messmer via Gcc wrote:
> I am trying to understand something unexpected I am seeing in the relocations placed into a compiled Linux kernel for the .debug_info section.  Those relocations seem to change the names of various entries in the debug info:
> 
>       [65] .debug_info       PROGBITS         0000000000000000  02c284e0
>            000000000c458644  0000000000000000           0     0     1
>       [66] .rela.debug_info  RELA             0000000000000000  16081790
>            000000001288ae68  0000000000000018   I      78    65     8
>       [72] .debug_str        PROGBITS         0000000000000000  10b451e8
>            00000000002bef2e  0000000000000001  MS       0     0     1

Note that you are only seeing relocations against .debug sections
because the kernel and kernel modules are only partially linked (so in
theory they can be relinked again against more/other object files).

The relocations tell where the strings (and some other entities) are
relative to the start of the .debug_ sections, so when other pieces of
.debug sections are merged later the relocations can be used/updated
to show where they are now.

But since we know these relocations are "final" they can actually be
resolved (which means, apply the relications directly to the target
section). For example if you have the elfutils tools installed you can
use eu-strip, which has two different ways to get rid of them (one
while stripping the .debug sections into a separate .debug file, one
to remove the reloations "in-place"):

      --reloc-debug-sections Resolve all trivial relocations between debug
                             sections if the removed sections are placed in a
                             debug file (only relevant for ET_REL files,
                             operation is not reversable, needs -f)
      --reloc-debug-sections-only
                             Similar to --reloc-debug-sections, but resolve all
                             trivial relocations between debug sections in
                             place.  No other stripping is performed (operation
                             is not reversable, incompatible with -f, -g,
                             --remove-comment and --remove-section)

That can save a couple of hunder megabytes of relocations.

> Dumping the DWARF information for one of the CUs in the compiled image (with standard tooling) shows me:
> 
> 0x0000002d: DW_TAG_compile_unit
>               DW_AT_producer    ("GNU C89 8.3.1 20191121 (Red Hat 8.3.1-5) -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -mfentry -march=x86-64 -g -gdwarf-4 -O2 -std=gnu90 -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -falign-jumps=1 -falign-loops=1 -funit-at-a-time -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fstack-protector-strong -fno-inline-functions-called-once -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fstack-check=no -fconserve-stack --param allow-store-data-races=0")
>               DW_AT_language    (DW_LANG_C89)
>               DW_AT_name        ("arch/x86/kernel/head64.c")
>               DW_AT_comp_dir    ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64")
>               DW_AT_ranges      (0x000009d0
>                  [0xffffffff81002000, 0xffffffff81002008)
>                  [0xffffffff82977172, 0xffffffff829771c0)
>                  [0xffffffff829771c0, 0xffffffff8297727a)
>                  [0xffffffff8297727a, 0xffffffff829774f8)
>                  [0xffffffff829774f8, 0xffffffff82977518)
>                  [0xffffffff82977518, 0xffffffff8297759f)
>                  [0xffffffff81000200, 0xffffffff810005b9)
>                  [0xffffffff8297759f, 0xffffffff829775bc))
>               DW_AT_low_pc      (0x0000000000000000)
>               DW_AT_stmt_list   (0x00000126)
> 
>             0x00000d84:   DW_TAG_structure_type [55] *
>                             DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0023ff94] = "task_struct")
>                             DW_AT_byte_size [DW_FORM_data2] (0x2480)
>                             DW_AT_alignment [DW_FORM_data1] (0x40)
>                             DW_AT_decl_file [DW_FORM_data1] ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64/./include/linux/sched.h")
>                             DW_AT_decl_line [DW_FORM_data2] (589)
>                             DW_AT_decl_column [DW_FORM_data1]       (0x08)
>                             DW_AT_sibling [DW_FORM_ref4]    (cu + 0x19cc => {0x000019ee})
> 
> As I'd expect, the name of the structure with the DWARF DIE at offset 0xd84 is "task_struct".  A hex dump of this part of .debug_info within the compiled image confirms the 0x23ff94 offset into the string table:
> 
>     02c29260  47 0d 00 00 37 **94 ff 23  00** 80 24 40 22 4d 02 08  |G...7..#..$@"M..|
> 
>     02c29270  cc 19 00 00 02 28 a5 19  00 22 53 02 16 bb 49 00  |.....(..."S...I.|
>     02c29280  00 00 02 77 0a 11 00 22  56 02 12 bd 01 00 00 10  |...w..."V.......|
>     02c29290  02 c6 07 15 00 22 5e 02  0b 8b 05 00 00 18 02 26  |....."^........&|

I think the tool you are using is showing you the data with the relocations already applied.

> And dumping this area of .debug_str shows the name I'd expect (0x23ff94 within .debug_str is 0x10d8517c)
> 
>     10d85168  61 73 6b 5f 73 74 72 75  63 74 00 61 72 63 68 5f  |ask_struct.arch_|
> 
>     10d85178  64 75 70 5f **74 61 73 6b  5f 73 74 72 75 63 74 00 ** |dup_task_struct.|
> 
>     10d85188  5f 5f 6b 73 79 6d 74 61  62 5f 5f 5f 70 75 74 5f  |__ksymtab___put_|
>     10d85198  74 61 73 6b 5f 73 74 72  75 63 74 00 5f 5f 6b 73  |task_struct.__ks|
> 
> The relocations within .rela.debug_info, however, change the STRP reference for the "task_struct" DIE to something else:
> 
>     Relocation section '.rela.debug_info' at offset 0x16081790 contains 12956143 entries:
>       Offset          Info           Type           Sym. Value    Sym. Name + Addend
>     000000000d85  002a0000000a R_X86_64_32       0000000000000000 .debug_str + 66d60
> 
> Looking at offset 0x66d60 into .debug_str shows the middle of some other random name (0x66d60 in would be 0x10babf48): "ksymtab_power_supply_get_drvdata" in this case.
> 
>     10babf38  76 5f 67 65 74 5f 64 72  76 64 61 74 61 00 5f 5f  |v_get_drvdata.__|
> 
>     10babf48  6b 73 79 6d 74 61 62 5f  70 6f 77 65 72 5f 73 75  |ksymtab_power_su|
> 
>     10babf58  70 70 6c 79 5f 67 65 74  5f 64 72 76 64 61 74 61  |pply_get_drvdata|
>     10babf68  00 5f 5f 6b 73 74 72 74  61 62 5f 70 6f 77 65 72  |.__kstrtab_power|
> 
> Have I misunderstood something fundamental here about the relocation data in .rela.debug_info and its application...?  Or is the relocation data in this .rela.debug_info bad...?

I would be very surprised if the relocations generated by GCC are
bad. I don't know whether the tools you are using to dump the data
apply the relocations already or not. Which could explain why applying
the relocation again might seem wrong.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-11-30 20:16 ` Mark Wielaard
@ 2020-11-30 22:22   ` Bill Messmer
  2020-12-01  2:39     ` Mark Wielaard
  0 siblings, 1 reply; 7+ messages in thread
From: Bill Messmer @ 2020-11-30 22:22 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: gcc

Mark,

Much appreciate the response.

I'm still a bit confused here.  And the reason I ask this is because I open this particular vmlinux image with an OSS ELF/DWARF library...  which gives me the *WRONG* names for various DWARF DIEs.  I stepped through the library...  and the reason the names are wrong is because the library applies all of the relocations in .rela.debug_info to the sections it opens.  I thought there might be a bug in the library somewhere, so I started down looking at the DWARF data with standard Linux tools and in hex dumps...  and it seemed incorrect to my -- admittedly limited -- understanding...

Yes, I am using llvm-dwarfdump to textualize the DWARF data (llvm-dwarfdump-10 --verbose vmlinux) and I would assume(?) this applies the relocations as necessary.  And I am using readelf to get the section data (readelf -S vmlinux) and the relocation data (readelf -r vmlinuix); however, the hex data I show is just a flat hexdump of the image (hexdump -C vmlinux -n ... -s ...).

The headers via "readelf -S vmlinux":

      [65] .debug_info       PROGBITS         0000000000000000  02c284e0
           000000000c458644  0000000000000000           0     0     1
      [66] .rela.debug_info  RELA             0000000000000000  16081790
           000000001288ae68  0000000000000018   I      78    65     8
      [72] .debug_str        PROGBITS         0000000000000000  10b451e8
           00000000002bef2e  0000000000000001  MS       0     0     1

For the DIE I am looking at (0xd84) via "llvm-dwarfdump-10 --verbose vmlinux"

        vmlinux:        file format ELF64-x86-64
        Abbrev table for offset: 0x00000012

    [1 byte ]    [55] DW_TAG_structure_type      DW_CHILDREN_yes
    [4 bytes]            DW_AT_name      DW_FORM_strp
    [2 bytes]            DW_AT_byte_size DW_FORM_data2
    [1 byte ]            DW_AT_alignment DW_FORM_data1
    [1 byte ]            DW_AT_decl_file DW_FORM_data1
    [2 bytes]            DW_AT_decl_line DW_FORM_data2
    [1 byte ]            DW_AT_decl_column       DW_FORM_data1
    [4 bytes]            DW_AT_sibling   DW_FORM_ref4
    [16 bytes]

    0x00000d84:   DW_TAG_structure_type [55] *
                    DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0023ff94] = "task_struct")
                    DW_AT_byte_size [DW_FORM_data2] (0x2480)
                    DW_AT_alignment [DW_FORM_data1] (0x40)
                    DW_AT_decl_file [DW_FORM_data1] ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64/./include/linux/sched.h")
                    DW_AT_decl_line [DW_FORM_data2] (589)
                    DW_AT_decl_column [DW_FORM_data1]       (0x08)
                    DW_AT_sibling [DW_FORM_ref4]    (cu + 0x19cc => {0x000019ee})

The **RAW IMAGE DATA** for that DIE via "hexdump -C -n 16 -s 0x2c29264 vmlinux" (0x2c29264 is the section offset for .debug_info 0x2c284e0 + DIE offset of 0xd84):

    02c29264  37 94 ff 23 00 80 24 40  22 4d 02 08 cc 19 00 00  |7..#..$@"M......|

Breaking that down:

    02c29264  (abbrev code) 37    (name STRP) 94 ff 23 00     (byte_size DATA2) 80 24     (align DATA1) 40     (decl_file DATA1) 22     (decl_line DATA2) 4d 02     (decl_column DATA1) 08     (sibling REF4) cc 19 00 00  |7..#..$@"M......|

    2c29264: [1 byte] Abbrev Code --> 0x37 == [55]
    2c29265: [4 bytes] DW_AT_name (STRP reference) --> 0x0023ff94
    2c29269: [2 bytes] DW_AT_byte_size (data2) --> 0x2480
    2c2926b: [1 byte] DW_AT_alignment (data1) --> 0x40
    2c2926c: [1 byte] DW_AT_decl_file (data1) --> 0x22
    2c2926d: [2 bytes] DW_AT_decl_line (data2) --> 0x24d == 589
    2c2926f: [1 byte] DW_AT_decl_column (data1) --> 0x08
    2c29270: [4 bytes] DW_AT_sibling (data4) --> 0x000019cc == [cu + 0x19cc]

The relocations via "readelf -r vmlinux":

    Relocation section '.rela.debug_info' at offset 0x16081790 contains 12956143 entries:
      Offset          Info           Type           Sym. Value    Sym. Name + Addend
    <234 entries>
    000000000d85  002a0000000a R_X86_64_32       0000000000000000 .debug_str + 66d60
    <many entries>

64-bit ELF RELA relocations are 0x18 bytes.  .rela.debug_info's section offset is 0x16081790.  That puts this relocation at 0x16081790 + 234 * 0x18 == 0x16082d80.

That relocation's binary data via "hexdump -C -n 24 -s 0x16082d80 vmlinux":

    16082d80  85 0d 00 00 00 00 00 00  0a 00 00 00 2a 00 00 00  |............*...|
    16082d90  60 6d 06 00 00 00 00 00                           |`m......|

Breaking that down:

    16082d80  (r_offset) 85 0d 00 00 00 00 00 00      (r_info) 0a 00 00 00 2a 00 00 00  |............*...|
    16082d90  (r_addend) 60 6d 06 00 00 00 00 00                           |`m......|

    r_offset == 0xd85 (which points at the DW_AT_name STRP reference in .debug_info)
    r_info == 0x0000002a0000000a
        ELF32_R_SYM(r_info) == 0x2a
        ELF32_R_TYPE(r_info) == 0x0a (for x86-64 is R_X86_64_32)
    r_addend == 0x066d60

Looking at where that ELF32_R_SYM of 0x2a == 42 points via "readelf -s vmlinux":

    Symbol table '.symtab' contains 106815 entries:
    42: 0000000000000000     0 SECTION LOCAL  DEFAULT   72

Section 72 is:

      [72] .debug_str        PROGBITS         0000000000000000  10b451e8
           00000000002bef2e  0000000000000001  MS       0     0     1

The relocation does literally say "replace the DWORD 0xd85 bytes into .debug_info with a reference 0x66d60 into .debug_str" and, again, a hex dump of .debug_str (section offset == 0x10b451e8) at this offset (0x66d60) via "hexdump -C -n 128 -s 0x10babf48 vmlinux":

    10babf48  6b 73 79 6d 74 61 62 5f  70 6f 77 65 72 5f 73 75  |ksymtab_power_su|
    10babf58  70 70 6c 79 5f 67 65 74  5f 64 72 76 64 61 74 61  |pply_get_drvdata|
    10babf68  00 5f 5f 6b 73 74 72 74  61 62 5f 70 6f 77 65 72  |.__kstrtab_power|
    10babf78  5f 73 75 70 70 6c 79 5f  67 65 74 5f 64 72 76 64  |_supply_get_drvd|
    10babf88  61 74 61 00 68 69 64 5f  73 65 74 5f 64 72 76 64  |ata.hid_set_drvd|
    10babf98  61 74 61 00 74 79 70 65  63 5f 61 6c 74 6d 6f 64  |ata.typec_altmod|
    10babfa8  65 5f 73 65 74 5f 64 72  76 64 61 74 61 00 70 63  |e_set_drvdata.pc|
    10babfb8  69 5f 73 65 74 5f 64 72  76 64 61 74 61 00 70 6c  |i_set_drvdata.pl|

And indeed, if I open this image with the OSS library I'm using and do:

    if (dwarf_offdie_b(dwarf, dieOffset, true, &die, &err) == DW_DLV_OK)
    {
        Dwarf_Attribute atName;
        char *name;
        if (dwarf_attr(die, DW_AT_name, &atName, &err) == DW_DLV_OK &&
            dwarf_formstring(atName, &name, &err) == DW_DLV_OK)
        {
            //
            // Indeed, I get "ksymtab_power_supply_get_drvdata" as the name here
            //
        }
    }

I get the completely wrong "ksymtab_power_supply_get_drvdata" name instead of the "task_struct" name which is expected.

Either both that library and my understanding are incorrect, there is something wrong with that relocation data, or it flat isn't supposed to be applied...

I also tried what you suggested "eu-strip -- reloc-debug-sections vmlinux -f stripped" and looked at the resulting output:

"readelf -S stripped" still shows the reloc sections:

      [65] .debug_info       PROGBITS         0000000000000000  00059e50
           000000000c458644  0000000000000000           0     0     1
      [66] .rela.debug_info  RELA             0000000000000000  0c4b2498
           000000001288ae68  0000000000000018   I      78    65     8

And that relocation is still there via "readelf -r stripped":

    Relocation section '.rela.debug_info' at offset 0xc4b2498 contains 12956143 entries:
    000000000d85  002a0000000a R_X86_64_32       0000000000000000 .debug_str + 66d60

Any other thoughts?

Sincerely,

Bill Messmer

-----Original Message-----
From: Mark Wielaard <mark@klomp.org> 
Sent: Monday, November 30, 2020 12:17 PM
To: Bill Messmer <wmessmer@microsoft.com>
Cc: gcc@gcc.gnu.org
Subject: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)

Hi Bill,

On Mon, Nov 30, 2020 at 07:18:50PM +0000, Bill Messmer via Gcc wrote:
> I am trying to understand something unexpected I am seeing in the relocations placed into a compiled Linux kernel for the .debug_info section.  Those relocations seem to change the names of various entries in the debug info:
> 
>       [65] .debug_info       PROGBITS         0000000000000000  02c284e0
>            000000000c458644  0000000000000000           0     0     1
>       [66] .rela.debug_info  RELA             0000000000000000  16081790
>            000000001288ae68  0000000000000018   I      78    65     8
>       [72] .debug_str        PROGBITS         0000000000000000  10b451e8
>            00000000002bef2e  0000000000000001  MS       0     0     1

Note that you are only seeing relocations against .debug sections because the kernel and kernel modules are only partially linked (so in theory they can be relinked again against more/other object files).

The relocations tell where the strings (and some other entities) are relative to the start of the .debug_ sections, so when other pieces of .debug sections are merged later the relocations can be used/updated to show where they are now.

But since we know these relocations are "final" they can actually be resolved (which means, apply the relications directly to the target section). For example if you have the elfutils tools installed you can use eu-strip, which has two different ways to get rid of them (one while stripping the .debug sections into a separate .debug file, one to remove the reloations "in-place"):

      --reloc-debug-sections Resolve all trivial relocations between debug
                             sections if the removed sections are placed in a
                             debug file (only relevant for ET_REL files,
                             operation is not reversable, needs -f)
      --reloc-debug-sections-only
                             Similar to --reloc-debug-sections, but resolve all
                             trivial relocations between debug sections in
                             place.  No other stripping is performed (operation
                             is not reversable, incompatible with -f, -g,
                             --remove-comment and --remove-section)

That can save a couple of hunder megabytes of relocations.

> Dumping the DWARF information for one of the CUs in the compiled image (with standard tooling) shows me:
> 
> 0x0000002d: DW_TAG_compile_unit
>               DW_AT_producer    ("GNU C89 8.3.1 20191121 (Red Hat 8.3.1-5) -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mno-80387 -mno-fp-ret-in-387 -mpreferred-stack-boundary=3 -mskip-rax-setup -mtune=generic -mno-red-zone -mcmodel=kernel -mindirect-branch=thunk-extern -mindirect-branch-register -mrecord-mcount -mfentry -march=x86-64 -g -gdwarf-4 -O2 -std=gnu90 -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -falign-jumps=1 -falign-loops=1 -funit-at-a-time -fno-asynchronous-unwind-tables -fno-jump-tables -fno-delete-null-pointer-checks -fstack-protector-strong -fno-inline-functions-called-once -fno-strict-overflow -fno-merge-all-constants -fmerge-constants -fstack-check=no -fconserve-stack --param allow-store-data-races=0")
>               DW_AT_language    (DW_LANG_C89)
>               DW_AT_name        ("arch/x86/kernel/head64.c")
>               DW_AT_comp_dir    ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64")
>               DW_AT_ranges      (0x000009d0
>                  [0xffffffff81002000, 0xffffffff81002008)
>                  [0xffffffff82977172, 0xffffffff829771c0)
>                  [0xffffffff829771c0, 0xffffffff8297727a)
>                  [0xffffffff8297727a, 0xffffffff829774f8)
>                  [0xffffffff829774f8, 0xffffffff82977518)
>                  [0xffffffff82977518, 0xffffffff8297759f)
>                  [0xffffffff81000200, 0xffffffff810005b9)
>                  [0xffffffff8297759f, 0xffffffff829775bc))
>               DW_AT_low_pc      (0x0000000000000000)
>               DW_AT_stmt_list   (0x00000126)
> 
>             0x00000d84:   DW_TAG_structure_type [55] *
>                             DW_AT_name [DW_FORM_strp]       ( .debug_str[0x0023ff94] = "task_struct")
>                             DW_AT_byte_size [DW_FORM_data2] (0x2480)
>                             DW_AT_alignment [DW_FORM_data1] (0x40)
>                             DW_AT_decl_file [DW_FORM_data1] ("/usr/src/debug/kernel-4.18.0-193.el8/linux-4.18.0-193.el8.x86_64/./include/linux/sched.h")
>                             DW_AT_decl_line [DW_FORM_data2] (589)
>                             DW_AT_decl_column [DW_FORM_data1]       (0x08)
>                             DW_AT_sibling [DW_FORM_ref4]    (cu + 0x19cc => {0x000019ee})
> 
> As I'd expect, the name of the structure with the DWARF DIE at offset 0xd84 is "task_struct".  A hex dump of this part of .debug_info within the compiled image confirms the 0x23ff94 offset into the string table:
> 
>     02c29260  47 0d 00 00 37 **94 ff 23  00** 80 24 40 22 4d 02 08  
> |G...7..#..$@"M..|
> 
>     02c29270  cc 19 00 00 02 28 a5 19  00 22 53 02 16 bb 49 00  |.....(..."S...I.|
>     02c29280  00 00 02 77 0a 11 00 22  56 02 12 bd 01 00 00 10  |...w..."V.......|
>     02c29290  02 c6 07 15 00 22 5e 02  0b 8b 05 00 00 18 02 26  
> |....."^........&|

I think the tool you are using is showing you the data with the relocations already applied.

> And dumping this area of .debug_str shows the name I'd expect 
> (0x23ff94 within .debug_str is 0x10d8517c)
> 
>     10d85168  61 73 6b 5f 73 74 72 75  63 74 00 61 72 63 68 5f  
> |ask_struct.arch_|
> 
>     10d85178  64 75 70 5f **74 61 73 6b  5f 73 74 72 75 63 74 00 ** 
> |dup_task_struct.|
> 
>     10d85188  5f 5f 6b 73 79 6d 74 61  62 5f 5f 5f 70 75 74 5f  |__ksymtab___put_|
>     10d85198  74 61 73 6b 5f 73 74 72  75 63 74 00 5f 5f 6b 73  
> |task_struct.__ks|
> 
> The relocations within .rela.debug_info, however, change the STRP reference for the "task_struct" DIE to something else:
> 
>     Relocation section '.rela.debug_info' at offset 0x16081790 contains 12956143 entries:
>       Offset          Info           Type           Sym. Value    Sym. Name + Addend
>     000000000d85  002a0000000a R_X86_64_32       0000000000000000 .debug_str + 66d60
> 
> Looking at offset 0x66d60 into .debug_str shows the middle of some other random name (0x66d60 in would be 0x10babf48): "ksymtab_power_supply_get_drvdata" in this case.
> 
>     10babf38  76 5f 67 65 74 5f 64 72  76 64 61 74 61 00 5f 5f  
> |v_get_drvdata.__|
> 
>     10babf48  6b 73 79 6d 74 61 62 5f  70 6f 77 65 72 5f 73 75  
> |ksymtab_power_su|
> 
>     10babf58  70 70 6c 79 5f 67 65 74  5f 64 72 76 64 61 74 61  |pply_get_drvdata|
>     10babf68  00 5f 5f 6b 73 74 72 74  61 62 5f 70 6f 77 65 72  
> |.__kstrtab_power|
> 
> Have I misunderstood something fundamental here about the relocation data in .rela.debug_info and its application...?  Or is the relocation data in this .rela.debug_info bad...?

I would be very surprised if the relocations generated by GCC are bad. I don't know whether the tools you are using to dump the data apply the relocations already or not. Which could explain why applying the relocation again might seem wrong.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-11-30 22:22   ` [EXTERNAL] " Bill Messmer
@ 2020-12-01  2:39     ` Mark Wielaard
  2020-12-01 16:26       ` Bill Messmer
  2020-12-01 17:03       ` H.J. Lu
  0 siblings, 2 replies; 7+ messages in thread
From: Mark Wielaard @ 2020-12-01  2:39 UTC (permalink / raw)
  To: Bill Messmer; +Cc: gcc

Hi Bill,

On Mon, Nov 30, 2020 at 10:22:34PM +0000, Bill Messmer wrote:

> I'm still a bit confused here.  And the reason I ask this is because
> I open this particular vmlinux image with an OSS ELF/DWARF
> library...  which gives me the *WRONG* names for various DWARF DIEs.
> I stepped through the library...  and the reason the names are wrong
> is because the library applies all of the relocations in
> .rela.debug_info to the sections it opens.  I thought there might be
> a bug in the library somewhere, so I started down looking at the
> DWARF data with standard Linux tools and in hex dumps...  and it
> seemed incorrect to my -- admittedly limited -- understanding...
>
> Yes, I am using llvm-dwarfdump to textualize the DWARF data
> (llvm-dwarfdump-10 --verbose vmlinux) and I would assume(?) this
> applies the relocations as necessary.  And I am using readelf to get
> the section data (readelf -S vmlinux) and the relocation data
> (readelf -r vmlinuix); however, the hex data I show is just a flat
> hexdump of the image (hexdump -C vmlinux -n ... -s ...).

I traced your steps and did the same on a local vmlinux copy and got
the same results as you. That didn't make sense to me. Till I realized
my original assumption, that the vmlinux image, like kernel modules
were partially linked and so ET_REL files that still needed relocation
applied, seemed wrong. The vmlinux file isn't actually ET_REL, but it
is ET_EXEC (see readelf -h vmlinux). In which case other tools don't
apply the relocations. And so your observation is correct. The offset
to the .debug_str table is right in the .debug_info section, the
relocations are meaningless. That is surprising.

> Either both that library and my understanding are incorrect, there
> is something wrong with that relocation data, or it flat isn't
> supposed to be applied...

It is the last thing, the aren't supposed to be applied because it is
an ET_EXEC file (which isn't supposed to have .rela.debug sections,
but apparently has).

> I also tried what you suggested "eu-strip -- reloc-debug-sections vmlinux -f stripped" and looked at the resulting output:
> 
> "readelf -S stripped" still shows the reloc sections:
> 
>       [65] .debug_info       PROGBITS         0000000000000000  00059e50
>            000000000c458644  0000000000000000           0     0     1
>       [66] .rela.debug_info  RELA             0000000000000000  0c4b2498
>            000000001288ae68  0000000000000018   I      78    65     8
> 
> And that relocation is still there via "readelf -r stripped":

Which now also makes sense, because as the --help text says "only
relevant for ET_REL files".

So you did find a real mystery, for some reason the way the vmlinux
image is created does get relocations correctly applied, but they (or
at least some) are still left behind in the ELF image even though they
are no longer needed (and if you do try to use/apply them, you get
wrong results). We should probably find out if this happened during
the upstream build or during distro packaging.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-12-01  2:39     ` Mark Wielaard
@ 2020-12-01 16:26       ` Bill Messmer
  2020-12-03 17:05         ` Michael Matz
  2020-12-01 17:03       ` H.J. Lu
  1 sibling, 1 reply; 7+ messages in thread
From: Bill Messmer @ 2020-12-01 16:26 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: gcc

Mark,

Thank you very much for the help.  I was so fixated on the fact that the .rela.debug* sections were there that I didn't pay attention to the e_type in the ELF header.  Apparently, neither did the library that I was using to parse the DWARF data.

Interestingly, I have seen other non-RedHat kernel debug images where the kernel is ET_EXEC and there are still .rela.debug* sections present in the image.  Though the effect of applying those relocs has always been nil (the data in the original .debug* section is already the same as what the .rela.debug* section indicates to alter).

Sincerely,

Bill Messmer

-----Original Message-----
From: Mark Wielaard <mark@klomp.org> 
Sent: Monday, November 30, 2020 6:39 PM
To: Bill Messmer <wmessmer@microsoft.com>
Cc: gcc@gcc.gnu.org
Subject: Re: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)

Hi Bill,

On Mon, Nov 30, 2020 at 10:22:34PM +0000, Bill Messmer wrote:

> I'm still a bit confused here.  And the reason I ask this is because I 
> open this particular vmlinux image with an OSS ELF/DWARF library...  
> which gives me the *WRONG* names for various DWARF DIEs.
> I stepped through the library...  and the reason the names are wrong 
> is because the library applies all of the relocations in 
> .rela.debug_info to the sections it opens.  I thought there might be a 
> bug in the library somewhere, so I started down looking at the DWARF 
> data with standard Linux tools and in hex dumps...  and it seemed 
> incorrect to my -- admittedly limited -- understanding...
>
> Yes, I am using llvm-dwarfdump to textualize the DWARF data
> (llvm-dwarfdump-10 --verbose vmlinux) and I would assume(?) this 
> applies the relocations as necessary.  And I am using readelf to get 
> the section data (readelf -S vmlinux) and the relocation data (readelf 
> -r vmlinuix); however, the hex data I show is just a flat hexdump of 
> the image (hexdump -C vmlinux -n ... -s ...).

I traced your steps and did the same on a local vmlinux copy and got the same results as you. That didn't make sense to me. Till I realized my original assumption, that the vmlinux image, like kernel modules were partially linked and so ET_REL files that still needed relocation applied, seemed wrong. The vmlinux file isn't actually ET_REL, but it is ET_EXEC (see readelf -h vmlinux). In which case other tools don't apply the relocations. And so your observation is correct. The offset to the .debug_str table is right in the .debug_info section, the relocations are meaningless. That is surprising.

> Either both that library and my understanding are incorrect, there is 
> something wrong with that relocation data, or it flat isn't supposed 
> to be applied...

It is the last thing, the aren't supposed to be applied because it is an ET_EXEC file (which isn't supposed to have .rela.debug sections, but apparently has).

> I also tried what you suggested "eu-strip -- reloc-debug-sections vmlinux -f stripped" and looked at the resulting output:
> 
> "readelf -S stripped" still shows the reloc sections:
> 
>       [65] .debug_info       PROGBITS         0000000000000000  00059e50
>            000000000c458644  0000000000000000           0     0     1
>       [66] .rela.debug_info  RELA             0000000000000000  0c4b2498
>            000000001288ae68  0000000000000018   I      78    65     8
> 
> And that relocation is still there via "readelf -r stripped":

Which now also makes sense, because as the --help text says "only relevant for ET_REL files".

So you did find a real mystery, for some reason the way the vmlinux image is created does get relocations correctly applied, but they (or at least some) are still left behind in the ELF image even though they are no longer needed (and if you do try to use/apply them, you get wrong results). We should probably find out if this happened during the upstream build or during distro packaging.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-12-01  2:39     ` Mark Wielaard
  2020-12-01 16:26       ` Bill Messmer
@ 2020-12-01 17:03       ` H.J. Lu
  1 sibling, 0 replies; 7+ messages in thread
From: H.J. Lu @ 2020-12-01 17:03 UTC (permalink / raw)
  To: Mark Wielaard; +Cc: Bill Messmer, gcc

On Mon, Nov 30, 2020 at 6:41 PM Mark Wielaard <mark@klomp.org> wrote:
>
> Hi Bill,
>
> On Mon, Nov 30, 2020 at 10:22:34PM +0000, Bill Messmer wrote:
>
> > I'm still a bit confused here.  And the reason I ask this is because
> > I open this particular vmlinux image with an OSS ELF/DWARF
> > library...  which gives me the *WRONG* names for various DWARF DIEs.
> > I stepped through the library...  and the reason the names are wrong
> > is because the library applies all of the relocations in
> > .rela.debug_info to the sections it opens.  I thought there might be
> > a bug in the library somewhere, so I started down looking at the
> > DWARF data with standard Linux tools and in hex dumps...  and it
> > seemed incorrect to my -- admittedly limited -- understanding...
> >
> > Yes, I am using llvm-dwarfdump to textualize the DWARF data
> > (llvm-dwarfdump-10 --verbose vmlinux) and I would assume(?) this
> > applies the relocations as necessary.  And I am using readelf to get
> > the section data (readelf -S vmlinux) and the relocation data
> > (readelf -r vmlinuix); however, the hex data I show is just a flat
> > hexdump of the image (hexdump -C vmlinux -n ... -s ...).
>
> I traced your steps and did the same on a local vmlinux copy and got
> the same results as you. That didn't make sense to me. Till I realized
> my original assumption, that the vmlinux image, like kernel modules
> were partially linked and so ET_REL files that still needed relocation
> applied, seemed wrong. The vmlinux file isn't actually ET_REL, but it
> is ET_EXEC (see readelf -h vmlinux). In which case other tools don't
> apply the relocations. And so your observation is correct. The offset
> to the .debug_str table is right in the .debug_info section, the
> relocations are meaningless. That is surprising.
>
> > Either both that library and my understanding are incorrect, there
> > is something wrong with that relocation data, or it flat isn't
> > supposed to be applied...
>
> It is the last thing, the aren't supposed to be applied because it is
> an ET_EXEC file (which isn't supposed to have .rela.debug sections,
> but apparently has).
>
> > I also tried what you suggested "eu-strip -- reloc-debug-sections vmlinux -f stripped" and looked at the resulting output:
> >
> > "readelf -S stripped" still shows the reloc sections:
> >
> >       [65] .debug_info       PROGBITS         0000000000000000  00059e50
> >            000000000c458644  0000000000000000           0     0     1
> >       [66] .rela.debug_info  RELA             0000000000000000  0c4b2498
> >            000000001288ae68  0000000000000018   I      78    65     8
> >
> > And that relocation is still there via "readelf -r stripped":
>
> Which now also makes sense, because as the --help text says "only
> relevant for ET_REL files".
>
> So you did find a real mystery, for some reason the way the vmlinux
> image is created does get relocations correctly applied, but they (or
> at least some) are still left behind in the ELF image even though they
> are no longer needed (and if you do try to use/apply them, you get
> wrong results). We should probably find out if this happened during
> the upstream build or during distro packaging.

Check if CONFIG_X86_NEED_RELOCS is enabled for your kernel.

-- 
H.J.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
  2020-12-01 16:26       ` Bill Messmer
@ 2020-12-03 17:05         ` Michael Matz
  0 siblings, 0 replies; 7+ messages in thread
From: Michael Matz @ 2020-12-03 17:05 UTC (permalink / raw)
  To: Bill Messmer; +Cc: Mark Wielaard, gcc

Hello,

On Tue, 1 Dec 2020, Bill Messmer via Gcc wrote:

> Thank you very much for the help.  I was so fixated on the fact that the 
> .rela.debug* sections were there that I didn't pay attention to the 
> e_type in the ELF header.  Apparently, neither did the library that I 
> was using to parse the DWARF data.
> 
> Interestingly, I have seen other non-RedHat kernel debug images where 
> the kernel is ET_EXEC

vmlinux is always final-linked.

> and there are still .rela.debug* sections present 
> in the image.

Depending on configuration vmlinux is linked with --emit-relocs, which 
causes all relocations, no matter if applied or not, to also be emitted in 
a final link.  That has its uses, but it also confuses most tools, as 
they blindly apply relocations again, even if they aren't from loadable 
segments.

As not much other software uses --emit-relocs, and even in linux it's 
optional and non-default you see these confused tools occuring in the wild 
instead of being fixed.


Ciao,
Michael.

> Though the effect of applying those relocs has always 
> been nil (the data in the original .debug* section is already the same 
> as what the .rela.debug* section indicates to alter).
> 
> Sincerely,
> 
> Bill Messmer
> 
> -----Original Message-----
> From: Mark Wielaard <mark@klomp.org> 
> Sent: Monday, November 30, 2020 6:39 PM
> To: Bill Messmer <wmessmer@microsoft.com>
> Cc: gcc@gcc.gnu.org
> Subject: Re: [EXTERNAL] Re: DWARF Debug Info Relocations (.debug_str STRP references)
> 
> Hi Bill,
> 
> On Mon, Nov 30, 2020 at 10:22:34PM +0000, Bill Messmer wrote:
> 
> > I'm still a bit confused here.  And the reason I ask this is because I 
> > open this particular vmlinux image with an OSS ELF/DWARF library...  
> > which gives me the *WRONG* names for various DWARF DIEs.
> > I stepped through the library...  and the reason the names are wrong 
> > is because the library applies all of the relocations in 
> > .rela.debug_info to the sections it opens.  I thought there might be a 
> > bug in the library somewhere, so I started down looking at the DWARF 
> > data with standard Linux tools and in hex dumps...  and it seemed 
> > incorrect to my -- admittedly limited -- understanding...
> >
> > Yes, I am using llvm-dwarfdump to textualize the DWARF data
> > (llvm-dwarfdump-10 --verbose vmlinux) and I would assume(?) this 
> > applies the relocations as necessary.  And I am using readelf to get 
> > the section data (readelf -S vmlinux) and the relocation data (readelf 
> > -r vmlinuix); however, the hex data I show is just a flat hexdump of 
> > the image (hexdump -C vmlinux -n ... -s ...).
> 
> I traced your steps and did the same on a local vmlinux copy and got the same results as you. That didn't make sense to me. Till I realized my original assumption, that the vmlinux image, like kernel modules were partially linked and so ET_REL files that still needed relocation applied, seemed wrong. The vmlinux file isn't actually ET_REL, but it is ET_EXEC (see readelf -h vmlinux). In which case other tools don't apply the relocations. And so your observation is correct. The offset to the .debug_str table is right in the .debug_info section, the relocations are meaningless. That is surprising.
> 
> > Either both that library and my understanding are incorrect, there is 
> > something wrong with that relocation data, or it flat isn't supposed 
> > to be applied...
> 
> It is the last thing, the aren't supposed to be applied because it is an ET_EXEC file (which isn't supposed to have .rela.debug sections, but apparently has).
> 
> > I also tried what you suggested "eu-strip -- reloc-debug-sections vmlinux -f stripped" and looked at the resulting output:
> > 
> > "readelf -S stripped" still shows the reloc sections:
> > 
> >       [65] .debug_info       PROGBITS         0000000000000000  00059e50
> >            000000000c458644  0000000000000000           0     0     1
> >       [66] .rela.debug_info  RELA             0000000000000000  0c4b2498
> >            000000001288ae68  0000000000000018   I      78    65     8
> > 
> > And that relocation is still there via "readelf -r stripped":
> 
> Which now also makes sense, because as the --help text says "only relevant for ET_REL files".
> 
> So you did find a real mystery, for some reason the way the vmlinux image is created does get relocations correctly applied, but they (or at least some) are still left behind in the ELF image even though they are no longer needed (and if you do try to use/apply them, you get wrong results). We should probably find out if this happened during the upstream build or during distro packaging.
> 
> Cheers,
> 
> Mark
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-12-03 17:05 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-30 19:18 DWARF Debug Info Relocations (.debug_str STRP references) Bill Messmer
2020-11-30 20:16 ` Mark Wielaard
2020-11-30 22:22   ` [EXTERNAL] " Bill Messmer
2020-12-01  2:39     ` Mark Wielaard
2020-12-01 16:26       ` Bill Messmer
2020-12-03 17:05         ` Michael Matz
2020-12-01 17:03       ` H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).