ELF object files can contain program sections which are not supposed
to be loaded into memory (e.g. .comment). Normally the static linker
uses these flags to decide which sections are allocated to loadable
program segments in ELF binaries and shared objects (including kernels
and DSO-styleon all architectures and kernel modules on architectures other than
amd64).
Mapping ELF object files (such as amd64 kernel modules) into memory
directly is a bit of a grey area. ELF object files are intended to be used as
inputs to the static linker. As a result, there is not a standardized definition
for what the memory layout of an ELF object should be (none of the section
headers have valid virtual memory addresses for example).
The kernel and loader were not checking the SHF_ALLOC flag but loading
any program sections with certain types meaning that when kernelsuch as SHT_PROGBITS. As a result,
modules for amd64 werethe kernel and loader would loaded, extra memory was used to hold unneeded into RAM some sections that weren't marked
data such as the contents ofwith SHF_ALLOC such as .comment and a few other sections. Withthat are not loaded into RAM for kernel
GNU BFD linker this was mostly harmless (aside from wasting a smallmodules on other architectures (which are implemented as ELF shared objects).
amount of RAM) since all of these unallocated sections were placed atAside from possibly requiring slightly more RAM to hold a kernel module this
the end of the file. LLD does not sortdoes not affect runtime correctness as the sections, so unallocatedkernel relocates symbols based on
sections were mixed in with allocated sections. Since the kernel wasthe layout it uses.
Debuggers such as gdb and lldb do not extract symbol tables from a running process
consistent about applying symbol relocationsor kernel. Instead, having this extra datathey replicate the memory layout of ELF executables and
mixed in between allocated sections did not result in any runtimeshared objects and use that to construct their own symbol tables. For executables
failuresand shared objects this works fine. However, it does confuse other tools that read the ELFFor ELF objects the current logic in kgdb (and
headers of kernel modules to determine how a module's memory is laidprobably lldb based on a simple reading) assumes that only sections with SHF_ALLOC
out (that is, debuggers)are memory resident when constructing a memory layout. In particular, kgdb was computing differentIf the debugger constructs
offsets for symbols and not displaying the correct data to the usera different memory layout than the kernel, then it will compute different addresses for
for any sections loaded after an unallocated section. mdb happened tosymbols causing symbols in the debugger to appear to have the wrong values (though
be immune from this because I copied the same bug from link_elf_obj.cthe kernel itself is working fine). The current port of mdb does not check SHF_ALLOC
into mdb but will be fixed. A kernel-aware lldb would also probablyas it replicates the kernel's logic in its existing kernel support.
The bfd linker sorts the sections in ELF object files such that all of the allocated sections
be confused(sections with SHF_ALLOCATED) are placed first followed by unallocated sections. As
a result, when kgdb composed a memory layout using only the allocated sections, this
layout happened to match the layout used by the kernel and loader. The lld linker does
not sort the sections in ELF object files and mixed allocated and unallocated sections.
This resulted in kgdb composing a different memory layout than the kernel and loader.
We could either patch kgdb (and possibly in the future lldb) to use custom handling when
generating memory layouts for kernel modules that are ELF objects, or we could change
the kernel and loader to check SHF_ALLOCATED. I chose the latter as I feel we shouldn't
be loading things into RAM that the module won't use. This should mostly be a NOP when
linking with bfd but will allow the existing kgdb to work with amd64 kernel modules linked
with lld.
Note that we only require SHF_ALLOC for "program" sections for types
like SHT_PROGBITS and SHT_NOBITS. Other section types such as symbol
tables, string tables, and relocations must also be loaded and are not
marked with SHF_ALLOC.