This avoids a diagnostic on arm32/arm64 when running ldd on a shared
library with a PT_TLS segment:
executable's TLS segment is underaligned: alignment is 8, needs to be at least 64 for ARM64 Bionic
Bug: http://b/328822319
Test: ldd /system/lib64/libc.so
Change-Id: Idb061b980333ba3b5b3f44b52becf041d76ea0b7
LinkerBlockAllocator::alloc() always does a memset() anyway, and soinfo
contains non-POD types, so this seems both unnecessary and questionable.
Bug: http://b/298741930
Test: treehugger
Change-Id: I2b5a3858c8506c6086dfd59cbe729afb5b9ffa1c
No-one seems to understand that a crash in a random .so from call_array()
in the linker isn't a linker bug. They _seem_ to understand (or at least
claim to) when we explain that this is just the linker calling their ELF
constructors --- despite the fact that the caller of call_array() is
call_constructors().
One experiment we can try though is to inline call_array() to elide that
frame from the crash dumps. I do also wonder whether renaming
call_constructors() to call_elf_constructors() would help/hinder/make no
difference. For now I'm leaning toward "hinder" because I suspect most
people don't understand "ELF constructor" and C++ folks at least will
probably be influenced in a not wholly incorrect direction when they
hear "constructor" (whereas "ELF constructor" might mislead them back in
the direction of "strange linker magic, not my fault" again)...
(The reformatting is clang-format's decision, not mine.)
Test: treehugger
Change-Id: I65ab95ceb2e988fd053c48c66f51afba17ccfa61
Once upon a time (and, indeed, to this very day if you're on LP32) the
soinfo struct used a fixed-length buffer for the soname. This caused
some issues, mainly with app developers who accidentally included a full
Windows "C:\My Computer\...\libfoo.so" style path. To avoid all this we
switched to just pointing into the ELF file itself, where the DT_SONAME
is already stored as a NUL-terminated string. And all was well for many
years.
Now though, we've seen a bunch of slow startup traces from dogfood where
`dlopen("libnativebridge.so")` in a cold start takes 125-200ms on a recent
device, despite no IO contention. Even though libnativebridge.so is only
20KiB.
Measurement showed that every library whose soname we check required
pulling in a whole page just for the (usually) very short string. Worse,
there's readahead. In one trace we saw 18 pages of libhwui.so pulled
in just for `"libhwui.so\0"`. In fact, there were 3306 pages (~13MiB)
added to the page cache during `dlopen("libnativebridge.so")`. 13MiB for
a 20KiB shared library!
This is the obvious change to use a std::string to copy the sonames
instead. This will dirty slightly more memory, but massively improve
locality.
Testing with the same pathological setup took `dlopen("libnativebridge.so")`
down from 192ms to 819us.
Bug: http://b/177102905
Test: tested with a pathologically modified kernel
Change-Id: I33837f4706adc25f93c6fa6013e8ba970911dfb9
Add inaccessible gaps between shared libraries to make it harder for the
attackers to defeat ASLR by random probing.
To avoid excessive page table bloat, only do this when a library is
about to cross a huge page boundary, effectively allowing several
smaller libraries to be lumped together.
Bug: 158113540
Test: look at /proc/$$/maps
Change-Id: I39c0100b81f72447e8b3c6faafa561111492bf8c
This reverts commit a8cf3fef2a.
Reason for revert: memory regression due to the fragmentation of the page tables
Bug: 159810641
Bug: 158113540
Change-Id: I6212c623ff440c7f6889f0a1e82cf7a96200a411
Improve ASLR by increasing the randomly sized gaps between shared
library mappings, and keep them mapped PROT_NONE.
Bug: 158113540
Test: look at /proc/$$/maps
Change-Id: Ie72c84047fb624fe2ac8b7744b2a2d0d255ea974
Symbol lookup is O(L) where L is the number of libraries to search (e.g.
in the global and local lookup groups). Factor out the per-DSO work into
soinfo_do_lookup_impl, and optimize for the situation where all the DSOs
are using DT_GNU_HASH (rather than SysV hashes).
To load a set of libraries, the loader first constructs an auxiliary list
of libraries (SymbolLookupList, containing SymbolLookupLib objects). The
SymbolLookupList is reused for each DSO in a load group. (-Bsymbolic is
accommodated by modifying the SymbolLookupLib at the front of the list.)
To search for a symbol, soinfo_do_lookup_impl has a small loop that first
scans a vector of GNU bloom filters looking for a possible match.
There was a slight improvement from templatizing soinfo_do_lookup_impl
and skipping the does-this-DSO-lack-GNU-hash check.
Rewrite the relocation processing loop to be faster. There are specialized
functions that handle the expected relocation types in normal relocation
sections and in PLT relocation sections.
This CL can reduce the initial link time of large programs by around
40-50% (e.g. audioserver, cameraserver, etc). On the linker relocation
benchmark (64-bit walleye), it reduces the time from 131.6ms to 71.9ms.
Bug: http://b/143577578 (incidentally fixed by this CL)
Test: bionic-unit-tests
Change-Id: If40a42fb6ff566570f7280b71d58f7fa290b9343
Validate the list of defined versions explicitly, during library
prelinking, rather than implicitly as part of constructing the
VersionTracker in soinfo::link_image.
Doing the validation upfront allows removing the symbol lookup failure
code paths, which only happen on a library with invalid version
information.
Helps on the walleye 64-bit linker relocation benchmark (146.2ms ->
131.6ms)
Bug: none
Test: bionic unit tests
Change-Id: Id17508aba3af2863909f0526897c4277419322b7
Historically we've made a few mistakes where they haven't matched the
right number. And most non-Googlers are much more familiar with the
numbers, so it seems to make sense to rely more on them. Especially in
header files, which we actually expect real people to have to read from
time to time.
Test: treehugger
Change-Id: I0d4a97454ee108de1d32f21df285315c5488d886
The string is still "lib" or "lib64" with native bridge. It doesn't need
to be configured in the Android.bp file anymore, so move it to a header
file. This change will ensure that ${LIB} expands to the same thing in
both ld.config.txt and DT_RUN_PATH.
Bug: http://b/145197367
Test: manual
Change-Id: Iab87f3156f2984dd3a20e4ccda423892c8b58763
Merged-In: Iab87f3156f2984dd3a20e4ccda423892c8b58763
The run-time of dl_iterate_phdr can be noticeable for exception-handling.
e.g. I tested extest on the GitHub issue by:
- disabling the dlpi_subs/dlpi_adds-based caching in libgcc
- adding a weaker "load base hint" caching in libgcc that doesn't need
the dlpi_subs/dlpi_adds fields, but still has to iterate over every
module to validate a cache hit
extest throws 10000 exceptions, and I saw a regression from ~1550ms
runtime on Q to about ~1950ms on master. This CL reduces the regression to
about ~1700ms.
Bug: https://github.com/android/ndk/issues/1062
Test: bionic unit tests
Change-Id: I099e97e1a20f5b2aa6737789e49d965170eb85a8
Ordinary executables have a PT_INTERP path of /system/bin/linker[64], but:
- executables using bootstrap Bionic use /system/bin/bootstrap/linker[64]
- ASAN executables use /system/bin/linker_asan[64]
gdb appears to use the PT_INTERP path for debugging the dynamic linker
before the linker has initialized the r_debug module list. If the linker's
l_name differs from PT_INTERP, then gdb assumes that the linker has been
unloaded and searches for a new solib using the linker's l_name path.
gdb may print a warning like:
warning: Temporarily disabling breakpoints for unloaded shared library "$OUT/symbols/system/bin/linker64"
If I'm currently debugging the linker when this happens, gdb apparently
doesn't load debug symbols for the linker. This can be worked around with
gdb's "sharedlibrary" command, but it's better to avoid it.
Previously, when PT_INTERP was the bootstrap linker, but l_name was
"/system/bin/linker[64]", gdb would find the default non-bootstrap linker
binary and (presumably) get confused about symbol addresses.
(Also, remove the "static std::string exe_path" variable because the
soinfo::realpath_ field is a std::string that already lasts until exit. We
already use it for link_map_head.l_name in notify_gdb_of_load.)
Bug: http://b/134183407
Test: manual
Change-Id: I9a95425a3a5e9fd01e9dd272273c6ed3667dbb9a
Given that we have both linker and linker64, I didn't really want to have
to have ldd and ldd64, so this change just adds the --list option to the
linkers and a shell script wrapper "ldd" that calls the appropriate
linker behind the scenes.
Test: adb shell linker --list `which app_process32`
Test: adb shell linker64 --list `which date`
Test: adb shell ldd `which app_process32`
Test: adb shell ldd `which date`
Change-Id: I33494bda1cc3cafee54e091f97c0f2ae52d1f74b
In addition to ORIGIN, LIB is now expanded to either lib or lib64
depending on the ABI in the DT_RUNPATH.
Test: To be added (can't be added to AOSP directly since there are
internal tests that have to be updated as well)
Change-Id: I34a8316f1765a27c731bc270ee25c0ce287d7eed
Change three things regarding the work around to the fact that init is
special:
1) Only first stage init is special, so we change the check to include
accessing /proc/self/exe, which if is available, means that we're
not first stage init and do not need any work arounds.
2) Fix the fact that /init may be a symlink and may need readlink()
3) Suppress errors from realpath_fd() since these are expected to fail
due to /proc not being mounted.
Bug: 80395578
Test: sailfish boots without the audit generated from calling stat()
on /init and without the errors from realpath_fd()
Change-Id: I266f1486b142cb9a41ec791eba74122bdf38cf12
init is now built as a dynamic executable, so the dynamic linker has to
be able to run in the init process. However, since init is launched so
early, even /dev/* and /proc/* file systems are not mounted and thus
some APIs that rely on the paths do not work. The dynamic linker now
goes alternative path when it is running in the init process.
For example, /proc/self/exe is not read for the init since we always now
the path of the init (/init). Also, arc4random* APIs are not used since
the APIs rely on /dev/urandom. Linker now does not randomize library
loading order and addresses when running in the init process.
Bug: 80454183
Test: `adb reboot recovery; adb devices` shows the device ID
Change-Id: I29b6d70e4df5f7f690876126d5fe81258c1d3115
The tls_nodelete state should apply to load_group not
isolated soinfo. This actually also means that multiple
soinfos may have tls_counter on their dso_handles.
This change replaces TLS_NODELETE flag with secondary counter.
Note that access to the secondary counter (located inside soinfo)
is pretty expensive because it requires soinfo lookup by dso_handle
whereas dso_handle counter is much faster. This is why it is updated
only when dso_handle counter starts or hits 0.
Bug: http://b/80278285
Test: bionic-unit-tests --gtest_filter=dl*
Change-Id: I535583f6714e45fa2a7eaf7bb3126da20ee7cba9
Explicitly say "warning" for warnings, explicitly say what action
we're going to take (such as "(ignoring)"), always provide a link to
our documentation when there is one, explicitly say what API level the
behavior changes at, and explicitly say why we're allowing the misbehavior
for now.
Bug: http://b/71852862
Test: ran tests, looked at logcat
Change-Id: I1795a5af45deb904332b866d7d666690dae4340b
Introduce new flag to mark soinfo as TLS_NODELETE when
there are thread_local dtors associated with dso_handle
belonging to it.
Test: bionic-unit-tests --gtest_filter=dl*
Test: bionic-unit-tests-glibc --gtest_filter=dl*
Bug: https://github.com/android-ndk/ndk/issues/360
Change-Id: I724ef89fc899788f95c47e6372c38b3313f18fed
This change addresses multiple problems introduced by
02586a2a34
1. In the case of unsuccessful dlopen the failure guard is triggered
for two namespaces which leads to double unload.
2. In the case where load_tasks includes libraries from 3 and more
namespaces it results in incorrect linking of libraries shared between
second and third/forth and so on namespaces.
The root cause of these problems was recursive call to find_libraries.
It does not do what it is expected to do. It does not form new load_tasks
list and immediately jumps to linking local_group. Not only this skips
reference counting it also will include unlinked but accessible library
from third (and fourth and fifth) namespaces in invalid local group. The
best case scenario here is that for 3 or more namesapces this will
fail to link. The worse case scenario it will link the library
incorrectly with will lead to very hard to catch bugs.
This change removes recursive call and replaces it with explicit list of
local_groups which should be linked. It also revisits the way we do
reference counting - with this change the reference counts are updated after
after libraries are successfully loaded.
Also update soinfo_free to abort in case when linker tries to free same
soinfo for the second time - this makes linker behavior less undefined.
Test: bionic-unit-tests
Bug: http://b/69787209
Change-Id: Iea25ced181a98c6503cce6e2b832c91d697342d5
This library is used by a number of different libraries in the system.
Make it easy for platform libraries to use this library and create
an actual exported include file.
Change the names of the functions to reflect the new name of the library.
Run clang_format on the async_safe_log.cpp file since the formatting is
all over the place.
Bug: 31919199
Test: Compiled for angler/bullhead, and booted.
Test: Ran bionic unit tests.
Test: Ran the malloc debug tests.
Change-Id: I8071bf690c17b0ea3bc8dc5749cdd5b6ad58478a
This commit updates interface of libdl.c.
1. android_init_namespaces is replaces with android_init_anonymous_namespace
2. added 2 arguments to android_create_namespace to specify linked namespace
and the list of shared libraries sonames.
3. symbol lookup does not get past boundary libraries (added check and test for it).
Bug: http://b/26833548
Bug: http://b/21879602
Test: bionic-unit-tests --gtest_filter=dl*:Dl*
Change-Id: I32921da487a02e5bd0d2fc528904d1228394bfb9
Move soinfo and globals out of linker.cpp to
separate files.
Breaking up huge linker.cpp into smaller peaces
in order to make it easier to extract part of the
code that belongs to libdl.so and remove parts of
the code that do not belong to linker
(refactoring part 2 of many)
Change-Id: I868417f4b8d2b84d0e8265e354bc7977161497e2