Age | Commit message (Collapse) | Author |
|
|
|
|
|
While profiling I realized that this member is unused, so the
StringBuilder and String allocation are completely un-necessary.
|
|
|
|
The DT_RELR relocation is a relatively new relocation encoding designed
to achieve space-efficient relative relocations in PIE programs.
The description of the format is available here:
https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/Pi9aSwwABgAJ
It works by using a bitmap to store the offsets which need to be
relocated. Even entries are *address* entries: they contain an address
(relative to the base of the executable) which needs to be relocated.
Subsequent even entries are *bitmap* entries: "1" bits encode offsets
(in word size increments) relative to the last address entry which need
to be relocated.
This is in contrast to the REL/RELA format, where each entry takes up
2/3 machine words. Certain kinds of relocations store useful data in
that space (like the name of the referenced symbol), so not everything
can be encoded in this format. But as position-independent executables
and shared libraries tend to have a lot of relative relocations, a
specialized encoding for them absolutely makes sense.
The authors of the format suggest an overall 5-20% reduction in the file
size of various programs. Due to our extensive use of dynamic linking
and us not stripping debug info, relative relocations don't make up such
a large portion of the binary's size, so the measurements will tend to
skew to the lower side of the spectrum.
The following measurements were made with the x86-64 Clang toolchain:
- The kernel contains 290989 relocations. Enabling RELR decreased its
size from 30 MiB to 23 MiB.
- LibUnicodeData contains 190262 relocations, almost all of them
relative. Its file size changed from 17 MiB to 13 MiB.
- /bin/WebContent contains 1300 relocations, 66% of which are relative
relocations. With RELR, its size changed from 832 KiB to 812 KiB.
This change was inspired by the following blog post:
https://maskray.me/blog/2021-10-31-relative-relocations-and-relr
|
|
Now that m_tls_offset points to the start of the TLS block the argument
order makes more sense this way.
|
|
This makes it unnecessary to track the symbol size which just isn't
available for unexported symbols (e.g. for 'static __thread').
|
|
|
|
|
|
This changes the TLS offset calculation logic to be based on the
symbol's size instead of the total size of the TLS.
Because of this change, we no longer need to pipe "m_tls_size" to so
many functions.
Also, After this patch, the TLS data of the main program exists at the
"end" of the TLS block (Highest addresses).
This fixes a part of #6609.
|
|
Previously, TLS data was always zero-initialized.
To support initializing the values of TLS data, sys$allocate_tls now
receives a buffer with the desired initial data, and copies it to the
master TLS region of the process.
The DynamicLinker gathers the initial TLS image and passes it to
sys$allocate_tls.
We also now require the size passed to sys$allocate_tls to be
page-aligned, to make things easier. Note that this doesn't waste memory
as the TLS data has to be allocated in separate pages anyway.
|
|
|
|
|
|
This implements more of the dlfcn functionality. Most notably:
* It's now possible to dlopen() libraries which were already
loaded at program startup time. This does not cause those
libraries to be loaded twice.
* Errors are reported via dlerror() rather than by crashing
the program.
* Calls to the dl*() functions are thread-safe.
|
|
SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
|
|
Having unresolved weak symbols is allowed and we should initialize
them to zero.
|
|
This helper is used by libgcc_s to figure out where the .eh_frame sections
are located for all loaded shared objects.
|
|
This enables loading executables with multiple data and text segments. Also
it fixes loading executables where the text segment has a non-zero offset.
Example:
$ echo "main () {}" > test.c
$ gcc -Wl,-z,separate-code -o test test.c
$ objdump -p test
test: file format elf32-i386
Program Header:
PHDR off 0x00000034 vaddr 0x00000034 paddr 0x00000034 align 2**2
filesz 0x000000e0 memsz 0x000000e0 flags r--
INTERP off 0x00000114 vaddr 0x00000114 paddr 0x00000114 align 2**0
filesz 0x00000013 memsz 0x00000013 flags r--
LOAD off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**12
filesz 0x000003c4 memsz 0x000003c4 flags r--
LOAD off 0x00001000 vaddr 0x00001000 paddr 0x00001000 align 2**12
filesz 0x00000279 memsz 0x00000279 flags r-x
LOAD off 0x00002000 vaddr 0x00002000 paddr 0x00002000 align 2**12
filesz 0x00000004 memsz 0x00000004 flags r--
LOAD off 0x00002004 vaddr 0x00003004 paddr 0x00003004 align 2**12
filesz 0x00000100 memsz 0x00000124 flags rw-
DYNAMIC off 0x00002014 vaddr 0x00003014 paddr 0x00003014 align 2**2
filesz 0x000000c8 memsz 0x000000c8 flags rw-
|
|
Merge the load_elf() and commit_elf() functions into a single
load_main_executable() function that takes care of both things.
Also split "stage 3" into two separate stages, keeping the lazy
relocations in stage 3, and adding a stage 4 for calling library
initialization functions.
We also make sure to map the main executable before dealing with
any of its dependencies, to ensure that non-PIE executables get
loaded at their desired address.
|
|
Also simplify it by removing an unreachable code path.
|
|
Remove a bunch of unused code, unnecessary const, and make some
non-object-specific member functions static.
|
|
There's no reason to use C strings more than absolutely necessary.
|
|
Let's just ignore the program header and always go with read+write.
Nothing else makes sense anyway.
|
|
The dynamic loader will now mark RELRO segments read-only after
performing relocations. This is pretty cool!
Note that this only applies to main executables so far,.
RELRO support for shared libraries will require some reorganizing
of the dynamic loader.
|
|
For a data segment that starts at a non-zero offset into a 4KB page and
crosses a 4KB page boundary, we were failing to pad the VM allocation,
which would cause the memcpy() to fail.
Make sure we round the segment bases down, and segment ends up, and the
issue goes away.
|
|
load_from_image() becomes map() and link(). This allows us to map
an object before mapping its dependencies.
This solves an issue where fixed-position executables (like GCC)
would clash with the ASLR placement of their own shared libraries.
|
|
Refactor DynamicLoader construction with a try_create() helper so that
we can call mmap() before making a loader. This way the loader doesn't
need to have an "mmap failed" state.
This patch also takes care of determining the ELF file size in
try_create() instead of expecting callers to provide it.
|
|
This avoids reparsing the same dynamic library file multiple times.
|
|
Instead of storing a "found" state inside the result object.
|
|
|