57 lines
2.3 KiB
Diff
57 lines
2.3 KiB
Diff
|
|
Quote from bug 1443 which explains what the patch does :
|
|
|
|
We build some random program and link it with -lust. When we run it,
|
|
it dies with a SIGSEGV before reaching main().
|
|
|
|
Libust.so depends on liburcu-bp.so from the usermode-rcu package.
|
|
Although libust.so is not prelinked, liburcu-bp.so IS prelinked; this
|
|
is critical.
|
|
|
|
Libust.so uses a TLS / __thread variable that is defined in liburcu-
|
|
bp.so. There are special ARM-specific relocation types that allow two
|
|
shared libraries to share thread-specific data. This is critical too.
|
|
|
|
One more critical issue: although liburcu-bp.so is prelinked, we can't
|
|
load it at its prelinked address, because we also link against
|
|
librt.so, and librt.so uses that address.
|
|
|
|
The dynamic linker is forced to relink liburcu-bp.so at a different
|
|
address. In the course of relinking, it processes the special ARM
|
|
relocation record mentioned above. The prelinker has already filled
|
|
in the information, which is a short offset into a table of thread-
|
|
specific data that is allocated per-thread for each library that uses
|
|
TLS. Because the normal behavior of a relocation is to add the symbol
|
|
value to an addend stored at the address being relocated, we end up
|
|
adding the short offset to itself, doubling it.
|
|
|
|
Now we have an awkward situation. The libust.so library doesn't know
|
|
about the addend, so its TLS data for this element is correct. The
|
|
liburcu-bp.so library has a different offset for the element. When we
|
|
go to initialize the element for the first time in liburcu-bp.so, we
|
|
write the address of the result at the doubled (broken) offset.
|
|
Later, when we refer to the address from libust.so, we check the value
|
|
at the correct offset, but it's NULL, so we eat hot SIGSEGV.
|
|
|
|
Upstream-Status: Pending
|
|
|
|
Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com>
|
|
---
|
|
.../libc/ports/sysdeps/arm/dl-machine.h | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
ndex 8d905e8..dcfa71e 100644
|
|
--- libc.orig/ports/sysdeps/arm/dl-machine.h
|
|
+++ libc/ports/sysdeps/arm/dl-machine.h
|
|
@@ -503,7 +503,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
|
|
|
|
case R_ARM_TLS_DTPOFF32:
|
|
if (sym != NULL)
|
|
- *reloc_addr += sym->st_value;
|
|
+ *reloc_addr = sym->st_value;
|
|
break;
|
|
|
|
case R_ARM_TLS_TPOFF32:
|
|
--
|
|
|