Some Interesting Facts
查资料时看到的一些有趣的细节。
- Glibc 2.27 Supports -static-pie
- Linus's Opinion Toward R_X86_64_PLT32
- RPATH or RUNPATH?
- Sections: Loadable or Allocatable?
- .symtab and .dynsym
- Who Has the Procedure Linkage Table?
- .got or .got.plt?
- We Must Lazy-Load?
Here are some interestion facts about linking, relocation, libraries, elf sections and lazy-loading.
Glibc 2.27 Supports -static-pie
URL: https://gcc.gnu.org/viewcvs?rev=252034&root=gcc&view=rev
Log: Add -static-pie to GCC driver to create static PIE This patch adds -static-pie to GCC driver to create static PIE. A static position independent executable (PIE) is similar to static executable, but can be loaded at any address without a dynamic linker. All linker input files must be compiled with -fpie or -fPIE and linker must support --no-dynamic-linker to avoid linking with dynamic linker. "-z text" is also needed to prevent dynamic relocations in read-only segments.
Linus's Opinion Toward R_X86_64_PLT32
URL: https://gitlab.freedesktop.org/panfrost/linux/commit/b21ebf2fb4cde1618915a97cc773e287ff49173e
x86: Treat R_X86_64_PLT32 as R_X86_64_PC32 On i386, there are 2 types of PLTs, PIC and non-PIC. PIE and shared objects must use PIC PLT. To use PIC PLT, you need to load GLOBAL_OFFSET_TABLE into EBX first. There is no need for that on x86-64 since x86-64 uses PC-relative PLT. On x86-64, for 32-bit PC-relative branches, we can generate PLT32 relocation, instead of PC32 relocation, which can also be used as a marker for 32-bit PC-relative branches. Linker can always reduce PLT32 relocation to PC32 if function is defined locally. Local functions should use PC32 relocation. As far as Linux kernel is concerned, R_X86_64_PLT32 can be treated the same as R_X86_64_PC32 since Linux kernel doesn't use PLT. R_X86_64_PLT32 for 32-bit PC-relative branches has been enabled in binutils master branch which will become binutils 2.31. [ hjl is working on having better documentation on this all, but a few more notes from him: "PLT32 relocation is used as marker for PC-relative branches. Because of EBX, it looks odd to generate PLT32 relocation on i386 when EBX doesn't have GOT. As for symbol resolution, PLT32 and PC32 relocations are almost interchangeable. But when linker sees PLT32 relocation against a protected symbol, it can resolved locally at link-time since it is used on a branch instruction. Linker can't do that for PC32 relocation" but for the kernel use, the two are basically the same, and this commit gets things building and working with the current binutils master - Linus ]
RPATH or RUNPATH?
URL: https://stackoverflow.com/questions/52018092/how-to-set-rpath-and-runpath-with-gcc-ld
--enable-new-dtags --disable-new-dtags This linker can create the new dynamic tags in ELF. But the older ELF systems may not understand them. If you specify --enable-new-dtags, the new dynamic tags will be created as needed and older dynamic tags will be omitted. If you specify --disable-new-dtags, no new dynamic tags will be created. By default, the new dynamic tags are not created. Note that those options are only available for ELF systems.
That means that when you are using -Wl,-rpath=
option
when linking a shared object, the linker will add a entrypoint whose
d_tag
is RUNPATH
into dynamic section in the
newer versions. You can use the --disable-new-dtags
to tell
linker you want a RPATH
, which has better
compatibility.
Sections: Loadable or Allocatable?
Each section in an object file has a name and a size. Most sections also have an associated block of data, known as the section contents. A section may be marked as loadable, which mean that the contents should be loaded into memory when the output file is run. A section with no contents may be allocatable, which means that an area in memory should be set aside, but nothing in particular should be loaded there (in some cases this memory must be zeroed out). A section which is neither loadable nor allocatable typically contains some sort of debugging information.
.symtab and .dynsym
We know that .symtab
is generated by the compiler and
used only by linker. So we can use the command strip
to
strip it from a ELF file without damaging it. However, why do we need
.dynsym
sections? SOURCE: System V Application Binary
Interface AMD64 Architecture Processor Supplement Draft Version
0.99.7
To allow comparisons of function addresses to work as expected, if an exe- cutable file references a function defined in a shared object, the link editor will place the address of the procedure linkage table entry for that function in its as- sociated symbol table entry. This will result in symbol table entries with section index of SHN_UNDEF but a type of STT_FUNC and a non-zero st_value. A reference to the address of a function from within a shared library will be satisfied by such a definition in the executable.
Who Has the Procedure Linkage Table?
SOURCE: System V Application Binary Interface AMD64 Architecture Processor Supplement Draft Version 0.99.7
Executable files and shared object files have separate procedure linkage tables. Unlike Intel386 ABI, this ABI uses the same procedure linkage table for both programs and shared objects.
.got or .got.plt?
.got is for relocations regarding global 'variables' while .got.plt is a auxiliary section to act together with .plt when resolving procedures absolute addresses.
We Must Lazy-Load?
An environment virable determines whether the dynamic linker user lazy-loading strategy. SOURCE: System V Application Binary Interface AMD64 Architecture Processor Supplement Draft Version 0.99.7
The LD_BIND_NOW environment variable can change the dynamic linking behavior. If its value is non-null, the dynamic linker evaluates procedure linkage table entries before transferring control to the program. That is, the dynamic linker processes relocation entries of type R_X86_64_JUMP_SLOT during process initialization. Otherwise, the dynamic linker evaluates procedure linkage table entries lazily, delaying symbol resolution and relocation until the first execution of a table entry.