ELF Relocation Notes

From Linux/Xtensa
Jump to navigation Jump to search

Note: macros and data structures that are mentioned below refer to uClibc source code, unless otherwise stated.

Xtensa Global Offset Table

The GOT has only one pointer entry. The link editor keeps in this GOT entry a pointer to the .dynamic section. At run-time the dynamic linker sets the same entry to point to the _dl_linux_resolve() routine. This pointer is later replicated to the beginning of each PLT chunk using the R_XTENSA_RTLD type 1 relocation (see below).

The "real" GOT is pointed at from and array of (offset, length) pairs (xtensa_got_location data type) at the .got.loc section. The offset and size of this array are kept in xtensa specific .dynamic section tags named DT_XTENSA_GOT_LOC_OFF and DT_XTENSA_GOT_LOC_SZ, respectively. This "real" GOT is part of .text section, and as such is flagged for read and execute only. However, xtensa specific macros (PERFORM_BOOTSTRAP_GOT at start-up time, INIT_GOT at run-time load [elf_machine_runtime_setup() in glibc]) use _dl_mprotect() to change the protection bits on the .text pages pointed from the .got.loc section, and allow write access.

Open questions:

  1. The sections .got.loc and .xt.lit look identical, why are both needed?
  2. The .got.loc section contains a short array of GOT locations at the beginning, and is mostly filled with zeros, why?
  3. Are .xt.lit and .xt.prop really needed at run-time?

Run-Time Relocations

Xtensa run-time relocations as implemented in _dl_do_reloc():

R_XTENSA_GLOB_DAT, R_XTENSA_JMP_SLOT
Relocate to symbol address + addend. In terms of the Intel psABI the calculation is 'S + A'.
R_XTENSA_RTLD
This includes two relocation types selected by the addend field. Type 1 inserts a pointer to the _dl_linux_resolve() routine (taken by the dynamic linker from the first (and only) entry of the .got section). Type 2 inserts a pointer to the per-module 'struct elf_resolve' data structure. According to the binutils elf_xtensa_finish_dynamic_sections() routine, this relocation is emitted at the beginning of each PLT "chunk". Each Chunk holds up to 254 PLT entries. The _dl_linux_resolve() pointer, and the link map pointer (struct elf_resolve) are the first two parameters of the initial PLT routine (elf_xtensa_le_plt_entry[]).
R_XTENSA_RELATIVE
Used to adjust internal pointers in the "real" GOT according to the current load address, mainly in shared libraries.