https://sourceware.org/bugzilla/show_bug.cgi?id=34030

--- Comment #2 from Marek Pazúr <marekpazur1 at seznam dot cz> ---
(In reply to Mark Wielaard from comment #1)
> (In reply to Marek Pazúr from comment #0)
> > Would it make sense to add __versions to this list?
> 
> Yes, it might make sense to add __versions to that list.
> But the kernel seems to have been done this for at least 15 years.
> So this doesn't seem to be something recent.
> 
> I cannot immediately find a way to repoduce the issue though.
> Do you happen to have an full reproducer for the issue you are seeing?

Hi Mark,

apologies for my late response.

Here is the concrete dwfl setup that triggers the issue for me:

  callbacks.find_elf = dwfl_linux_kernel_find_elf;
  callbacks.find_debuginfo = dwfl_standard_find_debuginfo;
  callbacks.section_address = dwfl_linux_kernel_module_section_address;
  dwfl = dwfl_begin(&callbacks);
  dwfl_linux_kernel_report_kernel(dwfl);
  dwfl_linux_kernel_report_modules(dwfl);
  dwfl_report_end(dwfl, nullptr, nullptr);

With this setup, dwfl_linux_kernel_module_section_address() returns
DWARF_CB_ABORT for any kernel module that references __versions in its
relocations, since the section is not exported under
/sys/module/<name>/sections/. As a result, I am unable to retrieve any DIEs for
those modules. Kernel module debuginfo was installed via the distro package
manager.

The workaround I am currently using is wrapping the callback to intercept
__versions before delegating to the original, essentially mirroring how the
known absent sections are handled inside the callback.

Here is a minimal standalone reproducer demonstrating the issue for me:

  #include <iostream>
  #include <cstring>
  #include <elfutils/libdwfl.h>

  static int wrapper(Dwfl_Module *mod,
                                           void **userdata,
                                           const char *modname,
                                           Dwarf_Addr base,
                                           const char *secname,
                                           Elf32_Word shndx,
                                           const GElf_Shdr *shdr,
                                           Dwarf_Addr *addr)
  {
      // Ignore the missing __versions section
      if (std::strcmp(secname, "__versions") == 0) {
          *addr = (Dwarf_Addr)-1l;
          return DWARF_CB_OK;
      }
      return dwfl_linux_kernel_module_section_address(
          mod, userdata, modname, base, secname, shndx, shdr, addr);
  }

  static int section_log(Dwfl_Module *mod,
                                           void **userdata,
                                           const char *modname,
                                           Dwarf_Addr base,
                                           const char *secname,
                                           Elf32_Word shndx,
                                           const GElf_Shdr *shdr,
                                           Dwarf_Addr *addr)
  {
      int res;
      if ((res = dwfl_linux_kernel_module_section_address(
              mod, userdata, modname, base, secname, shndx, shdr, addr))
          != DWARF_CB_OK) {
          // Print missing section
          std::cout << "(Section " << secname << " error for " << modname <<
")\n";
      }
      return res;
  }

  static void run(bool workaround)
  {
      std::cout << (workaround ? "=== With wrapper ===" : "=== Without wrapper
===") << "\n";

      Dwfl_Callbacks callbacks = {
          .find_elf        = dwfl_linux_kernel_find_elf,
          .find_debuginfo  = dwfl_standard_find_debuginfo,
          .section_address = workaround ? wrapper
                                        : section_log,
      };
      Dwfl *dwfl = dwfl_begin(&callbacks);
      dwfl_linux_kernel_report_kernel(dwfl);
      dwfl_linux_kernel_report_modules(dwfl);
      dwfl_report_end(dwfl, nullptr, nullptr);

      Dwarf_Addr bias;
      Dwarf_Die *cudie = nullptr;
      int count = 0;
      const char *last_mod = nullptr;
      while ((cudie = dwfl_nextcu(dwfl, cudie, &bias)) != nullptr) {
          // Print present modules
          const char *modname = dwfl_module_info(dwfl_cumodule(cudie), NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
          if (!last_mod || std::strcmp(last_mod, modname) != 0) {
              std::cout << modname << "\n";
              last_mod = modname;
          }

          count++;

          // do some dwarf work
      }
      std::cout << "\nTotal CUs: " << count << std::endl;

      dwfl_end(dwfl);
  }

  int main(void)
  {
      run(false);
      run(true);
      return 0;
  }

Let me know if you need any additional information.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to