abg-dwarf-reader: resolve relocation sections by index
authorMatthias Maennich <maennich@google.com>
Mon, 11 Nov 2019 21:48:10 +0000 (21:48 +0000)
committerMatthias Maennich <maennich@google.com>
Tue, 7 Jan 2020 09:21:30 +0000 (09:21 +0000)
Looking up relocation sections by name introduces a dependency to the
linker in use. Relocation sections might be named differently. For
instance, linking kernel modules with the bfd linker leads to a
.rela__ksymtab section corresponding to the __ksymtab section. Using lld
as a linker leads to .rela___ksymtab as section name. Both are valid.
When the kernel loads these, it simply applies all relocations from all
sections it finds. Tools should not depend on the concrete name (even
though I would prefer consistency among them). Libabigail hit an
assertion when trying to extract the ABI from a kernel module linked
with lld.

Hence, resolve the relocation sections for __ksymtab and __ksymtab_gpl
by iterating over the ELF sections, searching for relocation sections
and identifying the one that points to the respective ksymtab.

* src/abg-dwarf-reader.cc (find_relocation_section): New function.
(find_ksymtab_reloc_section): Use find_relocation_section to
resolve the ksymtab's relocation section.
(find_ksymtab_gpl_reloc_section): Likewise.

Fixes: e6870326e01a ("Support pre and post v4.19 ksymtabs for Linux kernel modules")
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Android Kernel Team <kernel-team@android.com>
Reviewed-by: Dodji Seketeli <dodji@seketeli.org>
Signed-off-by: Matthias Maennich <maennich@google.com>
src/abg-dwarf-reader.cc

index 69c3285..bb1ffc1 100644 (file)
@@ -6167,6 +6167,37 @@ public:
     return ksymtab_section_;
   }
 
+  /// Return the .rel{a,} section corresponding to a given section.
+  ///
+  /// @param target_section the section to search the relocation section for
+  ///
+  /// @return the .rel{a,} section if found, null otherwise.
+  Elf_Scn*
+  find_relocation_section(Elf_Scn* target_section) const
+  {
+    if (target_section)
+      {
+       // the relo section we are searching for has this index as sh_info
+       size_t target_index = elf_ndxscn(target_section);
+
+       // now iterate over all the sections, look for relocation sections and
+       // find the one that points to the section we are searching for
+       Elf_Scn*  section = 0;
+       GElf_Shdr header_mem, *header;
+       while ((section = elf_nextscn(elf_handle(), section)) != 0)
+         {
+           header = gelf_getshdr(section, &header_mem);
+           if (header == NULL
+               || (header->sh_type != SHT_RELA && header->sh_type != SHT_REL))
+             continue;
+
+           if (header->sh_info == target_index)
+             return section;
+         }
+      }
+    return NULL;
+  }
+
   /// Return the .rel{a,}__ksymtab section of a linux kernel ELF file (either
   /// a vmlinux binary or a kernel module).
   ///
@@ -6176,10 +6207,8 @@ public:
   {
     if (!ksymtab_reloc_section_)
       {
-        Elf_Scn *sec = find_section(elf_handle(), ".rela__ksymtab", SHT_RELA);
-       if (!sec)
-         sec = find_section(elf_handle(), ".rel__ksymtab", SHT_REL);
-       const_cast<read_context*>(this)->ksymtab_reloc_section_ = sec;
+       const_cast<read_context*>(this)->ksymtab_reloc_section_
+           = find_relocation_section(find_ksymtab_section());
       }
     return ksymtab_reloc_section_;
   }
@@ -6206,10 +6235,8 @@ public:
   {
     if (!ksymtab_gpl_reloc_section_)
       {
-       Elf_Scn *sec = find_section(elf_handle(), ".rela__ksymtab_gpl", SHT_RELA);
-       if (!sec)
-         sec = find_section(elf_handle(), ".rel__ksymtab_gpl", SHT_REL);
-       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_ = sec;
+       const_cast<read_context*>(this)->ksymtab_gpl_reloc_section_
+           = find_relocation_section(find_ksymtab_gpl_section());
       }
     return ksymtab_gpl_reloc_section_;
   }