Upstream commit: fffc2df8a3e2c8cda2991063d23086360268b777 - i386: Provide GLIBC_ABI_GNU_TLS symbol version [BZ #33221] - i386: Update ___tls_get_addr to preserve vector registers - Extend struct r_debug to support multiple namespaces (RHEL-101985) - Fix a potential crash in the dynamic loader when processing specific symbol versions (RHEL-109683) - Signal la_objopen for ld.so with dlmopen (RHEL-109693) - Switch to main malloc after final ld.so self-relocation (RHEL-109703) - Prevent ld.so from asserting and crashing during audited library loads (RHEL-109702) - x86-64: Provide GLIBC_ABI_DT_X86_64_PLT symbol version (RHEL-109621) - x86-64, i386: Provide GLIBC_ABI_GNU2_TLS symbol version (RHEL-109625) - Ensure fallback initialization of ctype TLS data pointers to fix segfaults in programs using dlmopen or auditors (RHEL-72018) - Handle load segment gaps in _dl_find_object (RHEL-104854) - AArch64: Improve codegen in SVE log1p - AArch64: Optimize inverse trig functions - AArch64: Avoid memset ifunc in cpu-features.c [BZ #33112] Resolves: RHEL-109536 Resolves: RHEL-72018 Resolves: RHEL-101985 Resolves: RHEL-104854 Resolves: RHEL-109621 Resolves: RHEL-109625 Resolves: RHEL-109683 Resolves: RHEL-109693 Resolves: RHEL-109702 Resolves: RHEL-109703
194 lines
5.0 KiB
Diff
194 lines
5.0 KiB
Diff
commit fbade65338cff0a3a1699a8627a8180e9a01a627
|
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
Date: Thu Feb 22 10:42:55 2024 -0300
|
|
|
|
arm: Use _dl_find_object on __gnu_Unwind_Find_exidx (BZ 31405)
|
|
|
|
Instead of __dl_iterate_phdr. On ARM dlfo_eh_frame/dlfo_eh_count
|
|
maps to PT_ARM_EXIDX vaddr start / length.
|
|
|
|
On a Neoverse N1 machine with 160 cores, the following program:
|
|
|
|
$ cat test.c
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <assert.h>
|
|
|
|
enum {
|
|
niter = 1024,
|
|
ntimes = 128,
|
|
};
|
|
|
|
static void *
|
|
tf (void *arg)
|
|
{
|
|
int a = (int) arg;
|
|
|
|
for (int i = 0; i < niter; i++)
|
|
{
|
|
void *p[ntimes];
|
|
for (int j = 0; j < ntimes; j++)
|
|
p[j] = malloc (a * 128);
|
|
for (int j = 0; j < ntimes; j++)
|
|
free (p[j]);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
enum { nthreads = 16 };
|
|
pthread_t t[nthreads];
|
|
|
|
for (int i = 0; i < nthreads; i ++)
|
|
assert (pthread_create (&t[i], NULL, tf, (void *) i) == 0);
|
|
|
|
for (int i = 0; i < nthreads; i++)
|
|
{
|
|
void *r;
|
|
assert (pthread_join (t[i], &r) == 0);
|
|
assert (r == NULL);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
$ arm-linux-gnueabihf-gcc -fsanitize=address test.c -o test
|
|
|
|
Improves from ~15s to 0.5s.
|
|
|
|
Checked on arm-linux-gnueabihf.
|
|
|
|
(cherry picked from commit f4c142bb9fe6b02c0af8cfca8a920091e2dba44b)
|
|
|
|
diff --git a/elf/Makefile b/elf/Makefile
|
|
index 92da608da1ebc175..f5646c434f19a667 100644
|
|
--- a/elf/Makefile
|
|
+++ b/elf/Makefile
|
|
@@ -34,6 +34,7 @@ routines = \
|
|
dl-addr \
|
|
dl-addr-obj \
|
|
dl-early_allocate \
|
|
+ dl-find_object \
|
|
dl-iteratephdr \
|
|
dl-libc \
|
|
dl-origin \
|
|
@@ -60,7 +61,6 @@ dl-routines = \
|
|
dl-deps \
|
|
dl-exception \
|
|
dl-execstack \
|
|
- dl-find_object \
|
|
dl-fini \
|
|
dl-init \
|
|
dl-load \
|
|
diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c
|
|
index 940fa5c2236af666..449302eda35ce96f 100644
|
|
--- a/elf/dl-find_object.c
|
|
+++ b/elf/dl-find_object.c
|
|
@@ -356,7 +356,7 @@ _dlfo_lookup (uintptr_t pc, struct dl_find_object_internal *first1, size_t size)
|
|
}
|
|
|
|
int
|
|
-_dl_find_object (void *pc1, struct dl_find_object *result)
|
|
+__dl_find_object (void *pc1, struct dl_find_object *result)
|
|
{
|
|
uintptr_t pc = (uintptr_t) pc1;
|
|
|
|
@@ -463,7 +463,8 @@ _dl_find_object (void *pc1, struct dl_find_object *result)
|
|
return -1;
|
|
} /* Transaction retry loop. */
|
|
}
|
|
-rtld_hidden_def (_dl_find_object)
|
|
+hidden_def (__dl_find_object)
|
|
+weak_alias (__dl_find_object, _dl_find_object)
|
|
|
|
/* _dlfo_process_initial is called twice. First to compute the array
|
|
sizes from the initial loaded mappings. Second to fill in the
|
|
diff --git a/include/dlfcn.h b/include/dlfcn.h
|
|
index a44420fa37439a85..f49ee1b0c9958d38 100644
|
|
--- a/include/dlfcn.h
|
|
+++ b/include/dlfcn.h
|
|
@@ -4,7 +4,8 @@
|
|
#include <link.h> /* For ElfW. */
|
|
#include <stdbool.h>
|
|
|
|
-rtld_hidden_proto (_dl_find_object)
|
|
+extern __typeof (_dl_find_object) __dl_find_object;
|
|
+hidden_proto (__dl_find_object)
|
|
|
|
/* Internally used flag. */
|
|
#define __RTLD_DLOPEN 0x80000000
|
|
diff --git a/sysdeps/arm/find_exidx.c b/sysdeps/arm/find_exidx.c
|
|
index d647865e5a098cd5..a924d59b9f75d7b2 100644
|
|
--- a/sysdeps/arm/find_exidx.c
|
|
+++ b/sysdeps/arm/find_exidx.c
|
|
@@ -16,64 +16,15 @@
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <link.h>
|
|
-#include <unwind.h>
|
|
-
|
|
-struct unw_eh_callback_data
|
|
-{
|
|
- _Unwind_Ptr pc;
|
|
- _Unwind_Ptr exidx_start;
|
|
- int exidx_len;
|
|
-};
|
|
-
|
|
-
|
|
-/* Callback to determines if the PC lies within an object, and remember the
|
|
- location of the exception index table if it does. */
|
|
-
|
|
-static int
|
|
-find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
|
|
-{
|
|
- struct unw_eh_callback_data * data;
|
|
- const ElfW(Phdr) *phdr;
|
|
- int i;
|
|
- int match;
|
|
- _Unwind_Ptr load_base;
|
|
-
|
|
- data = (struct unw_eh_callback_data *) ptr;
|
|
- load_base = info->dlpi_addr;
|
|
- phdr = info->dlpi_phdr;
|
|
-
|
|
- match = 0;
|
|
- for (i = info->dlpi_phnum; i > 0; i--, phdr++)
|
|
- {
|
|
- if (phdr->p_type == PT_LOAD)
|
|
- {
|
|
- _Unwind_Ptr vaddr = phdr->p_vaddr + load_base;
|
|
- if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
|
|
- match = 1;
|
|
- }
|
|
- else if (phdr->p_type == PT_ARM_EXIDX)
|
|
- {
|
|
- data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base);
|
|
- data->exidx_len = phdr->p_memsz;
|
|
- }
|
|
- }
|
|
-
|
|
- return match;
|
|
-}
|
|
-
|
|
|
|
/* Find the exception index table containing PC. */
|
|
|
|
_Unwind_Ptr
|
|
__gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount)
|
|
{
|
|
- struct unw_eh_callback_data data;
|
|
-
|
|
- data.pc = pc;
|
|
- data.exidx_start = 0;
|
|
- if (__dl_iterate_phdr (find_exidx_callback, &data) <= 0)
|
|
+ struct dl_find_object data;
|
|
+ if (__dl_find_object ((void *) pc, &data) < 0)
|
|
return 0;
|
|
-
|
|
- *pcount = data.exidx_len / 8;
|
|
- return data.exidx_start;
|
|
+ *pcount = data.dlfo_eh_count;
|
|
+ return (_Unwind_Ptr) data.dlfo_eh_frame;
|
|
}
|