Hi Stephen,

Thanks for reporting the issue and patch. Please check if I understood
you correctly. The correct output you are expecting in your case is:

    crash> sym ata_dummy_port_ops
    ffffffffc0a71580 (?) ata_dummy_port_ops [libata]
    crash> mod -s libata
         MODULE       NAME                      TEXT_BASE         SIZE
 OBJECT FILE
    ffffffffc0a7b640  libata                 ffffffffc0a47000   520192
    
/usr/lib/debug/lib/modules/6.12.0-0.11.8.el9uek.x86_64/kernel/drivers/ata/libata.ko.debug
    crash> sym ata_dummy_port_ops
    ffffffffc0a71580 (B) ata_dummy_port_ops [libata]
    crash> p/x &ata_dummy_port_ops
    $1 = 0xffffffffc0a6fe80 <<-------- should be 0xffffffffc0a71580,
same as sym's output, right?

If that is the case, then after applied your patch, the issue still
exists on my machine:

crash> sym fuse_miscdevice
ffffffffc05f7fe0 (?) fuse_miscdevice [fuse]
crash> mod -s fuse
     MODULE       NAME                             TEXT_BASE
SIZE  OBJECT FILE
ffffffffc05f8dc0  fuse                          ffffffffc05da000
233472  
/usr/lib/debug/lib/modules/6.11.5-300.fc41.x86_64/kernel/fs/fuse/fuse.ko.debug
crash> sym fuse_miscdevice
ffffffffc05f7fe0 (b) fuse_miscdevice [fuse]
crash> p/x &fuse_miscdevice
$1 = 0xffffffffc05daf20 << ------ unmatch with the previous value.

The .data section of fuse.ko.debug have non-zero address:

$ readelf -S 
/usr/lib/debug/lib/modules/6.11.5-300.fc41.x86_64/kernel/fs/fuse/fuse.ko.debug
Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
...
[50] .data             NOBITS           0000000000000e20  00000100
       000000000000080f  0000000000000000  WA       0     0     32

Could you please re-check your patch for this, or is there something
I'm missing?

Thanks,
Tao Liu

On Wed, Apr 2, 2025 at 11:41 AM Stephen Brennan
<stephen.s.bren...@oracle.com> wrote:
>
> A user reported that crash was reporting the address for certain module
> variables incorrectly. I was able to track it down specifically to
> variables which were located in the .data section of a kernel module.
> While the "sym" command gave the correct value, printing the address of
> the variable or expressions based on it with "p" would give an incorrect
> value. For example, the variable "ata_dummy_port_ops" variable is
> included in the .data section of libata.ko when built as a module:
>
>     $ sudo grep '\bata_dummy_port_ops\b' /proc/kallsyms
>     ffffffffc0a71580 d ata_dummy_port_ops   [libata]
>     $ sudo crash /usr/lib/debug/lib/modules/$(uname -r)/vmlinux /proc/kcore
>     crash> sym ata_dummy_port_ops
>     ffffffffc0a71580 (?) ata_dummy_port_ops [libata]
>     crash> mod -s libata
>          MODULE       NAME                      TEXT_BASE         SIZE  
> OBJECT FILE
>     ffffffffc0a7b640  libata                 ffffffffc0a47000   520192
>     
> /usr/lib/debug/lib/modules/6.12.0-0.11.8.el9uek.x86_64/kernel/drivers/ata/libata.ko.debug
>     crash> sym ata_dummy_port_ops
>     ffffffffc0a71580 (B) ata_dummy_port_ops [libata]
>     crash> p/x &ata_dummy_port_ops
>     $1 = 0xffffffffc0a6fe80
>
> The symbol value (from kallsyms) is correct, but its address provided by
> GDB is incorrect. It turns out that the .data section has an sh_addr
> which is non-zero. The result of this is that calculate_load_order_6_4()
> incorrectly calculates the base address for the .data section. This
> patch fixes the base address which is later provided to GDB via
> add-symbol-file.
>
> The impact here is interesting. Only variables within sections that have
> a non-zero sh_addr are impacted. It turns out that this is relatively
> common since Linux kernel commit 22d407b164ff7 ("lib: add allocation
> tagging support for memory allocation profiling"), which was merged in
> 6.10. That commit added an entry to the scripts/module.lds.S linker
> script, without specifying a base address of zero. I believe that is the
> reason for the non-zero base addresses.
>
> I was able to verify that, in addition to the Oracle Linux kernel where
> we initially noticed the issue, kernel modules on Arch Linux and Fedora
> also have non-zero .data sh_addr values. This is likely the case for
> most non-clang kernels since 6.10, but those were the only two distros I
> checked. While my reading of the module.lds.S seems to indicate that
> kernels built with CONFIG_LTO_CLANG=y should also have non-zero .data,
> .bss, and .rodata section addresses, I haven't been able to reproduce
> this with clang LTO kernels. Regardless, crash should properly handle
> non-zero sh_addr since it exists in the real world now.
>
> The core of the issue is that the symbol value returned by BFD includes
> the sh_addr of the section containing the symbol. For example, suppose
> a symbol with address 0 is located within a section with virtual address
> 0xa00. Then, the resulting symbol value will be 0xa00, not 0.
>
> calculate_load_order_6_4() computes the base address of each section by
> using a kallsyms symbol known to be within that section, and then
> subtracting the value of the symbol from the object file. This
> implicitly assumes that the section sh_addr is zero, and thus the symbol
> value is just an offset. To fix the computation, add in the section base
> address, to account for cases where it is non-zero.
>
> Signed-off-by: Stephen Brennan <stephen.s.bren...@oracle.com>
> ---
>  symbols.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/symbols.c b/symbols.c
> index 5adbc30..e30fafe 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -12808,6 +12808,7 @@ calculate_load_order_6_4(struct load_module *lm, bfd 
> *bfd, int dynamic,
>         asymbol *store;
>         asymbol *sym;
>         symbol_info syminfo;
> +       bfd_vma secaddr;
>         char *secname;
>         int i, t;
>
> @@ -12860,6 +12861,7 @@ calculate_load_order_6_4(struct load_module *lm, bfd 
> *bfd, int dynamic,
>                                 }
>                                 if (strcmp(syminfo.name, s1->name) == 0) {
>                                         secname = (char 
> *)bfd_section_name(sym->section);
> +                                       secaddr = 
> bfd_section_vma(sym->section);
>                                         break;
>                                 }
>
> @@ -12890,14 +12892,14 @@ calculate_load_order_6_4(struct load_module *lm, 
> bfd *bfd, int dynamic,
>                         }
>
>                         /* Update the offset information for the section */
> -                       sec_start = s1->value - syminfo.value;
> +                       sec_start = s1->value - syminfo.value + secaddr;
>                         /* keep the address instead of offset */
>                         lm->mod_section_data[i].addr = sec_start;
>                         lm->mod_section_data[i].flags |= SEC_FOUND;
>
>                         if (CRASHDEBUG(2))
> -                               fprintf(fp, "update sec offset sym %s @ %lx  
> val %lx  section %s\n",
> -                                       s1->name, s1->value, 
> (ulong)syminfo.value, secname);
> +                               fprintf(fp, "update sec offset sym %s @ %lx  
> val %lx  section %s @ %lx\n",
> +                                       s1->name, s1->value, 
> (ulong)syminfo.value, secname, secaddr);
>
>                         if (strcmp(secname, ".text") == 0)
>                                 lm->mod_text_start = sec_start;
> --
> 2.43.5
> --
> Crash-utility mailing list -- devel@lists.crash-utility.osci.io
> To unsubscribe send an email to devel-le...@lists.crash-utility.osci.io
> https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
> Contribution Guidelines: https://github.com/crash-utility/crash/wiki
--
Crash-utility mailing list -- devel@lists.crash-utility.osci.io
To unsubscribe send an email to devel-le...@lists.crash-utility.osci.io
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to