Support pre and post v4.19 ksymtabs for Linux kernel modules
authorJessica Yu <jeyu@kernel.org>
Tue, 3 Sep 2019 15:35:14 +0000 (17:35 +0200)
committerDodji Seketeli <dodji@redhat.com>
Tue, 17 Sep 2019 15:53:12 +0000 (17:53 +0200)
commite6870326e01ab4cebccf7e15a40a7656557ab3aa
treeb7b4ff99938d9e4baf52beb3f791bfa41cfd9099
parentbc2d2ce660d3d28bcedb76f3cde30280c9b667a2
Support pre and post v4.19 ksymtabs for Linux kernel modules

As described in commit ad8c2531fb9, the format of the Linux kernel
ksymtab changed in v4.19 to use relative references instead of absolute
references. This changes the type of relocations emitted for ksymtab
sections to be place-relative 32-bit relocations instead of absolute
relocations. One side-effect of this is that libdwfl will not relocate
the ksymtab sections due to the PC-relative relocations. This breaks
load_kernel_symbol_table() for kernel modules because it only reads in
zeros from the unrelocated ksymtab section and is subsequently unable to
determine what exported symbols it refers to. Since a vmlinux binary is
already fully linked and relocated (and therefore we can read its
ksymtab section just fine), this problem is only relevant to Linux
kernel modules.

To work around this, we utilize the ksymtab relocation sections to
determine which symbols the ksymtab entries refer to. We do this by
inspecting each relocation's r_info field for the symbol table index and
from there we are able to read each symbol's value and subsequently add
that to the set of exported symbols.

In addition, for Linux kernel modules, we can utilize relocation types
to implement a new heuristic to determine the ksymtab format we have.
The presence of PC-relative relocations suggest the new v4.19 format,
and absolute relocation types suggest the old pre v4.19 format.

        * include/abg-ir.h (elf_symbol::{elf_symbol, create}): Take new
symbol value and shndx parameters.
        (elf_symbol::{get_value, get_shndx}): Declare new accessors.
        * src/abg-ir.cc (elf_symbol::priv::{value_, shndx_}): New data
members.
        (elf_symbol::priv::priv): Adjust.
        (elf_symbol::elf_symbol): Take new value and is_linux_string_cst
parameters.
        (elf_symbol::create): Likewise.
        (elf_symbol::{get_value, get_is_linux_string_cst}): Define new
accessors.
        * src/abg-reader.cc (build_elf_symbol): Adjust.
        * src/abg-dwarf-reader.cc (binary_is_linux_kernel)
(binary_is_linux_kernel): New static functions.
(lookup_symbol_from_sysv_hash_tab)
        (lookup_symbol_from_gnu_hash_tab)
        (lookup_symbol_from_symtab): Adjust.
        (read_context::{ksymtab_reloc_section_,
ksymtab_gpl_reloc_section_, ksymtab_strings_section_}): New data
members.
        (read_context::read_context): Initialize ksymtab_reloc_section_,
ksymtab_gpl_reloc_section_, ksymtab_strings_section_.
        (read_context::{find_ksymtab_reloc_section,
find_ksymtab_gpl_reloc_section, find_ksymtab_strings_section,
find_any_ksymtab_reloc_section, get_ksymtab_format_module,
populate_symbol_map_from_ksymtab,
populate_symbol_map_from_ksymtab_reloc, is_linux_kernel_module}):
New member functions.
        (read_context::load_kernel_symbol_table): Adjust to call either
populate_symbol_map_from_ksymtab{_reloc,} depending on ksymtab
format.
        (read_context::get_ksymtab_format): Adjust to call
get_ksymtab_format_module for linux kernel modules.
        (read_context::lookup_elf_symbol_from_index): Adjust.
        (create_default_var_sym, create_default_fn_sym): Adjust.

Signed-off-by: Jessica Yu <jeyu@kernel.org>
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
include/abg-ir.h
src/abg-dwarf-reader.cc
src/abg-ir.cc
src/abg-reader.cc