4

https://linux-audit.com/elf-binaries-on-linux-understanding-and-analysis/ says

The type field tells us what the purpose of the file is. There are a few common file types.

CORE (value 4)
DYN (Shared object file), for libraries (value 3)
EXEC (Executable file), for binaries (value 2)
REL (Relocatable file), before linked into an executable file (value 1)

https://unix.stackexchange.com/a/476157/674 shows that a kernel module is REL. Why is it REL not DYN?

What is the difference between DYN and REL?

Thanks.

2 Answers 2

4

See the System V ABI, which contains the specifications of the ELF format. It says

Relocation entries for different object files have slightly different interpretations for the r_offset member.

  • In relocatable files, r_offset holds a section offset. That is, the relocation section itself describes how to modify another section in the file; relocation offsets designate a storage unit within the second section.

  • In executable and shared object files, r_offset holds a virtual address. To make these files’ relocation entries more useful for the dynamic linker, the section offset (file interpretation) gives way to a virtual address (memory interpretation).

Relocatable files are still fully relocatable, whereas shared objects are one step further along the linking process and have been largely relocated. Shared objects are only relocatable if their code is position-independent (e.g. it was built with GCC’s -fPIC option).

Kernel modules need to be relocatable without being position-independent, so they are shipped as relocatable files.

7
  • Thanks. Is a static library REL or DYN? I guess REL not DYN
    – Tim
    Oct 18, 2018 at 17:11
  • (1) Is it correct that static linking translates relocatable address to virtual address, and dynamic linking accepts virtual address and doesn't output different address or translates place holder to virtual address? (2) Do static and dynamic loading perform some address translation? (3) Do loading (be it static and dynamic) always happen before linking (be it static or dynamic)?
    – Tim
    Oct 18, 2018 at 17:19
  • people.cs.pitt.edu/~xianeizhang/notes/Linking.html says "shared obj file. A special type of relocatable obj file that can be loaded into mem and linked dynamically, at either load time or run time. Compilers and assemblers generate relocatable obj files (including shared obj files)." I am confused that shared library file contains relocatable address or virtual address?
    – Tim
    Oct 18, 2018 at 17:48
  • Thanks. Is it correct that a shared library file contains virtual addresses by default, and relocatable addresses if it was built with GCC’s -fPIC option?
    – Tim
    Oct 18, 2018 at 19:23
  • No, it’s not correct. There’s not enough room in comments to address your questions here. Oct 18, 2018 at 21:19
2

Linux does not use the ELF methods for dynamic objects in the kernel, Linux instead still uses a basic method to load drivers that is from the mid 1980s and that worked already with the a.out format. There are relocatable files (similar to .o files) that are linked for the kernel and then loaded.

The method that has been introduced in the mid 1980s work this way, either by calling a program that does the following or by having a user space daemon that does the following:

  • Take the driver .o file or a file linked from several .o files via ld -o driver -r *.o and perform a final link step (using ld) that links that driver to load address 0. This is needed since the COMMON variables do not show up in the size output.

  • Now call sizeon the resulting file to get the size needed by the driver.

  • Open a module loading driver and use an ioctl to tell that driver the size of the module.

  • The module loading driver calls kmem_alloc() in the kernel for text, data and bss segments and returns the addresses returned by kmem_alloc() in the result structure of the ioctl.

  • Call the linker (ld) again but now link the driver to the addresses that have been returned by the module loading driver.

  • Use another call to the module loading driver that tells this driver to slurp in the driver variant that has been linked to the addresses allocated by the kernel and puts the driver content to the allocated space.

  • The loaded driver is now usable

If you like to look at a kernel that uses the ELF methods, I recommend to look at the Solaris kernel.

The first file that is loaded for Solaris is e.g. /platform/i86pc/kernel/amd64/unix and this file is marked as an excutable that depends on two shared "libraries". You can list this with the standard ELF tool dump:

dump -Lv /platform/i86pc/kernel/amd64/unix  

/platform/i86pc/kernel/amd64/unix:

  **** DYNAMIC SECTION INFORMATION ****
.dynamic:
[INDEX] Tag         Value
[1]     NEEDED          genunix
[2]     NEEDED          dtracestubs
[3]     HASH            0xfffffffffb8c1040
[4]     STRTAB          0xfffffffffb8e4e10
[5]     STRSZ           0xf584
[6]     SYMTAB          0xfffffffffb8c9fc0
[7]     SYMENT          0x18
[8]     CHECKSUM        0x4445
[9]     TEXTREL         0
[10]    RELA            0xfffffffffb8f4398
[11]    RELASZ          0x16470
[12]    RELAENT         0x18
[13]    FEATURE_1       PARINIT
[14]    SUNW_CAP        0xfffffffffb8a37a8
[15]    FLAGS           TEXTREL
[16]    FLAGS_1         [ NOHDR ]
[17]    SUNW_STRPAD     0x200
[18]    SUNW_LDMACH     EM_AMD64

file /platform/i86pc/kernel/unix        
/platform/i86pc/kernel/unix:       ELF 32-bit LSB executable 80386 Version 1, dynamically linked, not stripped, no debugging information available

As you see here, the shared libraries, the basic kernel depends on are: genunix and dtracestubs.

So if you like to boot a Solaris kernel, you need to have a bootloader that knows about ELF and is able to load and link the shared objects, the kernel depends on.

BTW: Solaris has an in-kernel dynamic linker, so dynamically loading a driver takes less steps.

3
  • You may find it interesting to see what load_module does in the Linux kernel, it doesn’t match what you describe here (along with its init_module and finit_module syscalls). Oct 20, 2018 at 19:10
  • It may be that Linux meanwhile implemented an in kernel linker. I would need to check this if I have more time.
    – schily
    Oct 20, 2018 at 20:31
  • Yes, Linux 2.6 added an in-kernel linker. Oct 20, 2018 at 20:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .