Commit graph

18 commits

Author SHA1 Message Date
Paul Kirth
4d4377881d [riscv][bionic] Prototype TLS Descriptor support
Add basic assembly stubs for TLS Descriptor support in the dynamic
linker, and enable several code paths related to TLSDESC for RISC-V.

Note: This patch requires an updated toolchain that supports TLSDESC
for RISC-V, and the `-mtls-dialect=` compiler option specifically.

Test: adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests --gtest_filter=*tls*
Bug: 322984914
Change-Id: I74bd0fa216b44b4ca2c5a5a6aec37b3fc47b00d9
2024-06-07 14:30:22 -07:00
Ryan Prichard
2a901e6937 Call relocate_relr before the ifunc resolvers
Previously, on RISC-V, the static hwcap variable in
__bionic_call_ifunc_resolver resulted in a call to __cxa_guard_acquire,
which used a GOT access to __stack_chk_guard, but the GOT hadn't yet
been initialized. Fix this problem by applying RELR relocations
earlier.

Bug: http://b/330725041
Test: lunch aosp_cf_riscv64_phone-trunk_staging-eng; boot device
Change-Id: Ib10fdcc0d2c1b875eba6bc5e0115a6768d6f25ee
2024-04-04 03:23:04 -07:00
Peter Collingbourne
e0ebca8fa3 linker: Process RELR relocations before ANDROID_REL[A].
ANDROID_REL[A] need to be processed after RELR in case it contains
an IRELATIVE relocation with a resolver that accesses data relocated
by RELR.

Bug: 331466607
Change-Id: I50865e67fc1492d75324ef3cb9defef3f8b88421
2024-03-26 18:38:32 -07:00
Ryan Prichard
68eb690f86 Merge changes Idb061b98,I93c17ca6 into main
* changes:
  ldd: skip relocation processing, TLS modules, CFI
  Guard against linker[64] having a PT_TLS segment
2024-03-14 22:58:51 +00:00
Ryan Prichard
32bb3673c1 ldd: skip relocation processing, TLS modules, CFI
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
2024-03-14 14:01:04 -07:00
Ryan Prichard
b4937462f5 Guard against linker[64] having a PT_TLS segment
The loader doesn't currently support using TLS within itself.
Previously, if a TLS segment was accidentally linked into the loader,
then the loader's `soinfo_tls* tls_` field would be initialized with a
valid TlsSegment, but the loader soinfo wouldn't be registered with
linker_tls.cpp, so the module ID would be 0. (The first valid module ID
is 1.)

The result was architecture-dependent. On x86, everything worked until
the first TLS access, which segfaulted. On arm64, relocating TLSDESC
hit a CHECK() failure on the invalid module ID.

Make the loader more robust:
 * Abort in the loader if it detects that it has a TLS segment.
 * For R_GENERIC_TLS_DTPMOD, verify that a module ID is valid before
   writing it.

Bug: none
Test: manually add a thread_local variable to the loader
Test: bionic-unit-tests
Change-Id: I93c17ca65df4af2d46288957a0e483b0e2b13862
2024-03-14 13:25:16 -07:00
Kalesh Singh
4084b555b2 Reapply "RELAND: bionic: loader: Extend LOAD segment VMAs"
This reverts commit 7a04fedc78.

Test: Dexcom G7 app
Bug: 328797737
Change-Id: I575d626b1313d1c66bf25f29c43a9a101024a4f8
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
2024-03-13 13:37:30 -07:00
Kalesh Singh
7a04fedc78 Revert "RELAND: bionic: loader: Extend LOAD segment VMAs"
Revert submission 2966884

Reason for revert: b/328266487

Reverted changes: /q/submissionid:2966884

Bug: 328266487
Change-Id: I45a2c5888eefab36c069f992de00ec8c87105288
2024-03-07 13:32:34 -08:00
Kalesh Singh
944164c5e2 RELAND: bionic: loader: Extend LOAD segment VMAs
When the page_size < p_align of the ELF load segment, the loader
will end up creating extra PROT_NONE gap VMA mappings between the
LOAD segments. This problem is exacerbated by Android's zygote
model, where the number of loaded .so's can lead to ~30MB increase
in vm_area_struct unreclaimable slab memory.

Extend the LOAD segment VMA's to cover the range between the
segment's end and the start of the next segment, being careful
to avoid touching regions of the extended mapping where the offset
would overrun the size of the file. This avoids the loader
creating an additional gap VMA for each LOAD segment.

Consider a system with 4KB page size and the ELF files with 64K
alignment. e.g:

$ readelf -Wl /system/lib64/bootstrap/libc.so | grep 'Type\|LOAD'

Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0441a8 0x0441a8 R   0x10000
LOAD           0x0441b0 0x00000000000541b0 0x00000000000541b0 0x091860 0x091860 R E 0x10000
LOAD           0x0d5a10 0x00000000000f5a10 0x00000000000f5a10 0x003d40 0x003d40 RW  0x10000
LOAD           0x0d9760 0x0000000000109760 0x0000000000109760 0x0005c0 0x459844 RW  0x10000

Before this patch:

$ cat /proc/1/maps | grep -A1 libc.so

7fa1d4a90000-7fa1d4ad5000 r--p 00000000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4ad5000-7fa1d4ae4000 ---p 00000000 00:00 0
7fa1d4ae4000-7fa1d4b76000 r-xp 00044000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b76000-7fa1d4b85000 ---p 00000000 00:00 0
7fa1d4b85000-7fa1d4b8a000 r--p 000d5000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b8a000-7fa1d4b99000 ---p 00000000 00:00 0
7fa1d4b99000-7fa1d4b9a000 rw-p 000d9000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b9a000-7fa1d4feb000 rw-p 00000000 00:00 0                          [anon:.bss]

3 additional PROT_NONE (---p) VMAs for gap mappings.

After this patch:

$ cat /proc/1/maps | grep -A1 libc.so

7f468f069000-7f468f0bd000 r--p 00000000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f0bd000-7f468f15e000 r-xp 00044000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f15e000-7f468f163000 r--p 000d5000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f163000-7f468f172000 rw-p 000da000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f172000-7f468f173000 rw-p 000d9000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f173000-7f468f5c4000 rw-p 00000000 00:00 0                          [anon:.bss]

No additional gap VMAs. However notice there is an extra RW VMA at
offset 0x000da000. This is caused by the RO protection of the
GNU_RELRO segment, which causes the extended RW VMA to split.
The GNU_RELRO protection extension is handled in the subsequent
patch in this series.

Bug: 316403210
Bug: 300367402
Bug: 307803052
Bug: 312550202
Test: atest -c linker-unit-tests
Test: atest -c bionic-unit-tests
Change-Id: I7150ed22af0723cc0b2d326c046e4e4a8b56ad09
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
2024-02-27 06:13:11 +00:00
Zheng Pan
92a7e1c55c Revert "bionic: loader: Extend LOAD segment VMAs"
Revert submission 2803156-loader_crt_pad_segment

Reason for revert: b/324952273

Reverted changes: /q/submissionid:2803156-loader_crt_pad_segment

Change-Id: I8af115c426c0113914abbf8fbd3e74c0d89408d1
2024-02-14 00:04:10 +00:00
Kalesh Singh
4b4fb6f439 bionic: loader: Extend LOAD segment VMAs
When the page_size < p_align of the ELF load segment, the loader
will end up creating extra PROT_NONE gap VMA mappings between the
LOAD segments. This problem is exacerbated by Android's zygote
model, where the number of loaded .so's can lead to ~30MB increase
in vm_area_struct unreclaimable slab memory.

Extend the LOAD segment VMA's to cover the range between the
segment's end and the start of the next segment, being careful
to avoid touching regions of the extended mapping where the offset
would overrun the size of the file. This avoids the loader
creating an additional gap VMA for each LOAD segment.

Consider a system with 4KB page size and the ELF files with 64K
alignment. e.g:

$ readelf -Wl /system/lib64/bootstrap/libc.so | grep 'Type\|LOAD'

Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x0441a8 0x0441a8 R   0x10000
LOAD           0x0441b0 0x00000000000541b0 0x00000000000541b0 0x091860 0x091860 R E 0x10000
LOAD           0x0d5a10 0x00000000000f5a10 0x00000000000f5a10 0x003d40 0x003d40 RW  0x10000
LOAD           0x0d9760 0x0000000000109760 0x0000000000109760 0x0005c0 0x459844 RW  0x10000

Before this patch:

$ cat /proc/1/maps | grep -A1 libc.so

7fa1d4a90000-7fa1d4ad5000 r--p 00000000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4ad5000-7fa1d4ae4000 ---p 00000000 00:00 0
7fa1d4ae4000-7fa1d4b76000 r-xp 00044000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b76000-7fa1d4b85000 ---p 00000000 00:00 0
7fa1d4b85000-7fa1d4b8a000 r--p 000d5000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b8a000-7fa1d4b99000 ---p 00000000 00:00 0
7fa1d4b99000-7fa1d4b9a000 rw-p 000d9000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7fa1d4b9a000-7fa1d4feb000 rw-p 00000000 00:00 0                          [anon:.bss]

3 additional PROT_NONE (---p) VMAs for gap mappings.

After this patch:

$ cat /proc/1/maps | grep -A1 libc.so

7f468f069000-7f468f0bd000 r--p 00000000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f0bd000-7f468f15e000 r-xp 00044000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f15e000-7f468f163000 r--p 000d5000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f163000-7f468f172000 rw-p 000da000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f172000-7f468f173000 rw-p 000d9000 fe:09 20635520                   /system/lib64/bootstrap/libc.so
7f468f173000-7f468f5c4000 rw-p 00000000 00:00 0                          [anon:.bss]

No additional gap VMAs. However notice there is an extra RW VMA at
offset 0x000da000. This is caused by the RO protection of the
GNU_RELRO segment, which causes the extended RW VMA to split.
The GNU_RELRO protection extension is handled in the subsequent
patch in this series.

Bug: 316403210
Bug: 300367402
Bug: 307803052
Bug: 312550202
Test: atest -c linker-unit-tests [Later patch]
Test: atest -c bionic-unit-tests
Change-Id: I3363172c02d5a4e2b2a39c44809e433a4716bc45
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
2024-02-08 13:07:04 -08:00
Evgenii Stepanov
6bbb75aa77 Revert "Linker support for MTE globals."
Revert submission 2709995

Reason for revert: linker crash in soinfo::apply_relr_reloc

Reverted changes: /q/submissionid:2709995

Bug: 314038442
Change-Id: I2c6ad7f46fb1174f009253602ad08ceb36aa7d71
2023-12-06 19:01:46 +00:00
Mitch Phillips
e8139f585a Linker support for MTE globals.
This patch adds the necessary bionic code for the linker to protect
global data using MTE.

The implementation is described in the MemtagABI addendum to the
AArch64 ELF ABI:
https://github.com/ARM-software/abi-aa/blob/main/memtagabielf64/memtagabielf64.rst

In summary, this patch includes:

1. When MTE globals is requested, the linker maps writable SHF_ALLOC
   sections as anonymous pages with PROT_MTE (copying the file contents
   into the anonymous mapping), rather than using a file-backed private
   mapping. This is required as file-based mappings are not necessarily
   backed by the kernel with tag-capable memory. For sections already
   mapped by the kernel when the linker is invoked via. PT_INTERP, we
   unmap the contents, remap a PROT_MTE+anonymous mapping in its place,
   and re-load the file contents from disk.

2. When MTE globals is requested, the linker tags areas of global memory
   (as defined in SHT_AARCH64_MEMTAG_GLOBALS_DYNAMIC) with random tags,
   but ensuring that adjacent globals are never tagged using the same
   memory tag (to provide detemrinistic overflow detection).

3. Changes to RELATIVE, ABS64, and GLOB_DAT relocations to load and
   store tags in the right places. This ensures that the address tags are
   materialized into the GOT entries as well. These changes are a
   functional no-op to existing binaries and/or non-MTE capable hardware.

Bug: N/A
Test: atest bionic-unit-tests CtsBionicTestCases --test-filter=*Memtag*

Change-Id: Id7b1a925339b14949d5a8f607dd86928624bda0e
2023-11-20 15:53:06 +01:00
Elliott Hughes
43462707a1 riscv64 TLS support.
Signed-off-by: Mao Han <han_mao@linux.alibaba.com>
Signed-off-by: Xia Lifang <lifang_xia@linux.alibaba.com>
Signed-off-by: Chen Guoyin <chenguoyin.cgy@linux.alibaba.com>
Signed-off-by: Wang Chen <wangchen20@iscas.ac.cn>
Signed-off-by: Lu Xufan <luxufan@iscas.ac.cn>
Test: treehugger
Change-Id: I14efb4a03a3dc2ec736d7e47a3f8859c886eb9d6
2022-10-10 20:30:24 +00:00
Ryan Prichard
8ea6af53e2 Always process TLS relocs using general code path
This is important for enabling the error about unsupported TLS
relocations to local symbols. The fast path tends to skip this error,
because it fails during lookup_symbol(). Add a test for this error.

I didn't see a performance regression in the linker_relocation
benchmark.

Bug: http://b/226978634
Test: m bionic-unit-tests
Change-Id: Ibef9bde2973cf8c2d420ecc9e8fe2c69a5097ce2
2022-03-25 15:51:11 -07:00
Elliott Hughes
14798930ec Remove unused mips/mips64 code from the linker.
Test: treehugger
Change-Id: I42f1e4c492ac644cf78e7c1196ba9b3518f9c8f8
2020-02-13 15:58:48 -08:00
Ryan Prichard
4f140695d9 Restore handling of R_GENERIC_NONE relocations
Previously, the linker was ignoring the symbol of the R_GENERIC_NONE
relocation, so continue ignoring it. This is a little unfortunate because
it requires adding an extra condition on the fast path for relocation
handling.

I tried benchmarking this change, and I can't tell whether it has no
effect or is a regression of up to 1%. It might be possible to refactor
this code (e.g. do the lookup anyway, but avoid reporting an error), or by
changing the linker behavior, but this simple change gets the linker
working again.

Bug: http://b/147719203
Test: verify that the broken app works again
Change-Id: I7589b65705fec522d5fbadc05136dd5489833aea
2020-01-15 15:19:17 -08:00
Ryan Prichard
339ecef22d Optimize GNU hash linking for large inputs
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
2020-01-13 13:29:25 -08:00