This implements the dladdr() function which lets the caller look up
the symbol name, symbol address as well as library name and library
base address for an arbitrary address.
When using BIND_NOW (e.g. via -Wl,-z,now) we would fail to load ELF
images while doing relocations when we encounter a weak symbol. Instead
we should just patch the PLT entry with a null pointer.
This can be reproduced with:
$ cat test.cpp
int main()
{
std::cout << "Hello World!" << std::endl;
}
$ g++ -o test -Wl,-z,now test.cpp
$ ./test
did not find symbol while doing relocations for library test: _ITM_RU1
Avoid promotion of static strings to AK::String, instead use
AK::StringView and operator ""sv, to force string view's instead
which avoids allocation of String. This code path isn't hot enough
that it makes a huge difference, but every bit counts.
We had two functions for doing mostly the same thing. Combine both
of them into String::find() and use that everywhere.
Also add some tests to cover basic behavior.
The expression address - candidate.address can yield a value that
cannot safely be converted to an i32 which would result in
binary_search failing to find some symbols.
By constraining two implementations, the compiler will select the best
fitting one. All this will require is duplicating the implementation and
simplifying for the `void` case.
This constraining also informs both the caller and compiler by passing
the callback parameter types as part of the constraint
(e.g.: `IterationFunction<int>`).
Some `for_each` functions in LibELF only take functions which return
`void`. This is a minimal correctness check, as it removes one way for a
function to incompletely do something.
There seems to be a possible idiom where inside a lambda, a `return;` is
the same as `continue;` in a for-loop.
For whatever reason, symbolication was doing an O(n) walk of all the
symbols, despite having sorted them beforehand.
Changing this to a binary_search() makes symbolication noticeably
faster and improves Profiler startup time.
We were using ELF::Image::section(0) to indicate the "undefined"
section, when what we really wanted was just Optional<Section>.
So let's use Optional instead. :^)
With this fixed dlopen() no longer crashes when given an invalid
ELF image and instead returns an error code that can be retrieved
with dlerror().
Fixes#6995.
This enables us to use keys of type NonnullRefPtr in HashMaps and
HashTables.
This commit also includes fixes in various places that used
HashMap<T, NonnullRefPtr<U>>::get() and expected to get an
Optional<NonnullRefPtr<U>> and now get an Optional<U*>.
When loading a library at runtime with dlopen(), we now check that:
1. The library's TLS size does not overflow the size of the allocated
TLS block.
2. The Library's TLS data is all zeroed.
We check for both of these cases because we currently do not support
them correctly. When we do add support for them, we can remove these
checks.
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 fixes a regression that was introduced in f40ee1b and caused the
tls_offset of all objects other than the main program to be 0.
After this fix map_library's is_program argument is no longer used, so
it was removed.
We had some inconsistencies before:
- Sometimes "The", sometimes "the"
- Sometimes trailing ".", sometimes no trailing "."
I picked the most common one (lowecase "the", trailing ".") and applied
it to all copyright headers.
By using the exact same string everywhere we can ensure nothing gets
missed during a global search (and replace), and that these
inconsistencies are not spread any further (as copyright headers are
commonly copied to new files).
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 *
The shared library libicudata.so has a DT_SYMBOLIC entry:
Dynamic Section:
NEEDED libgcc_s.so
SONAME libicudata.so.69
SYMBOLIC 0x00000000
HASH 0x00000094
STRTAB 0x000000c8
SYMTAB 0x000000a8
STRSZ 0x0000002a
SYMENT 0x00000010
According to the ELF spec DT_SYMBOLIC has no special meaning
for the dynamic loader.
The calculation for TLS relocations was incorrect which would
result in overlapping TLS variables when more than one shared
object used TLS variables.
This bug can be reproduced with a shared library and a program
like this:
$ cat tlstest.c
#include <string.h>
__thread char tls_val[1024];
void set_val() { memset(tls_val, 0, sizeof(tls_val)); }
$ gcc -g -shared -o usr/lib/libtlstest.so tlstest.c
$ cat test.c
void set_val();
int main() { set_val(); }
$ gcc -g -o tls test.c -ltlstest
Due to the way the TLS relocations are done this program would
clobber libc's TLS variables (e.g. errno).
Mostly due to the fact that clang-format allows aligned comments via
AlignTrailingComments.
We could also use raw string literals in inline asm, which clang-format
deals with properly (and would be nicer in a lot of places).