* load TLS segment for executable - while we can skip PT_LOAD for executable,
we still have to load TLS segment.
* set TCB address based on if elf is position independent
It seams that stdout of ld.so is not that much of an issue but actually
it unfortunately is. The major problem here is that sometimes programs
generate header files in stdout (./getmy_custom_headers > header.h) and
we need to keep that cleen. and this is very very popular in gcc.
This patch avoids collecting symbols, resolving relocs if they are
already done (usually for example libc.so during a dlopen for another
libfoo.so). This patch is purely for performance boost.
It is usually not optimal to load a library twice and for specifics,
it is **terrible** idea to load libc twice it was enough trouble
dealing with libc statically linked into ld.so. So What this patch does
it check for soname and if a library is already loaded it won't get
loaded again. Why soname ? because unfortunately some bins gets linked
againt libc.so while of their dependencies gets linked against
libc.so.6 while one is usually symbolic link for the other.
struct flock is posix defined locking mechanism on *nix platform
Example usage (copied from https://gavv.github.io/articles/file-locks/) :
#include <fcntl.h>
struct flock fl;
memset(&fl, 0, sizeof(fl));
// lock in shared mode
fl.l_type = F_RDLCK;
// lock entire file
fl.l_whence = SEEK_SET; // offset base is start of the file
fl.l_start = 0; // starting offset is zero
fl.l_len = 0; // len is zero, which is a special value representing end
// of file (no matter how large the file grows in future)
fl.l_pid = 0; // F_SETLK(W) ignores it; F_OFD_SETLK(W) requires it to be zero
// F_SETLKW specifies blocking mode
if (fcntl(fd, F_SETLKW, &fl) == -1) {
exit(1);
}
// atomically upgrade shared lock to exclusive lock, but only
// for bytes in range [10; 15)
//
// after this call, the process will hold three lock regions:
// [0; 10) - shared lock
// [10; 15) - exclusive lock
// [15; SEEK_END) - shared lock
fl.l_type = F_WRLCK;
fl.l_start = 10;
fl.l_len = 5;
// F_SETLKW specifies non-blocking mode
if (fcntl(fd, F_SETLK, &fl) == -1) {
exit(1);
}
// release lock for bytes in range [10; 15)
fl.l_type = F_UNLCK;
if (fcntl(fd, F_SETLK, &fl) == -1) {
exit(1);
}
// close file and release locks for all regions
// remember that locks are released when process calls close()
// on any descriptor for a lock file
close(fd);
It is fact that ld.so has libc statially linked into it.
Normally we wouldn't need ld.so functionality once the program is
finalyl loaded, but with the next few patches, we will have dlopen which
will reuse the same ld.so functionality.
The problem is that it seams that huge part of the code is possible not
referntially transparent. That is, it is not impossible that some of the
functions have internals states. So when using the struct Linker that is
initialized by ld.so's copy of libc. we must access it using the same
copy even if both copies are identical.
For example in dlopen if you do linker.load_library(..). That would
segfault because it is using the function from libc not ld.so
So I don't truly undestand why should this be needed, but after long
hours of being stuck I thought maybe.. maybe that is the issue and
indeed it turned out to be so.