aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2023-06-24 10:59:56 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2023-06-25 18:27:25 +0000
commit42ceab3ea1a997db93b65404be0ee4b17b5382d7 (patch)
treeaf8b9b51711c9fc57b62ee1aa609d8dc0acdff7f
parenta42d8fe001b912a5e4efdd4020d9bfadc07f6c7f (diff)
downloadsrc-42ceab3ea1a997db93b65404be0ee4b17b5382d7.tar.gz
src-42ceab3ea1a997db93b65404be0ee4b17b5382d7.zip
libc.a: implement _rtld_addr_phdr()
to make __cxa_thread_call_dtors() operational for statically linked binaries. Noted by: andrew Reviewed by: emaste, dim Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D40748
-rw-r--r--lib/libc/gen/dlfcn.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index 4478b41cfe98..61984e2fe86c 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <dlfcn.h>
#include <link.h>
#include <stddef.h>
+#include <string.h>
#include "namespace.h"
#include <pthread.h>
#include "un-namespace.h"
@@ -248,13 +249,48 @@ _rtld_atfork_post(int *locks __unused)
{
}
+#ifndef IN_LIBDL
+struct _rtld_addr_phdr_cb_data {
+ const void *addr;
+ struct dl_phdr_info *dli;
+};
+
+static int
+_rtld_addr_phdr_cb(struct dl_phdr_info *dli, size_t sz, void *arg)
+{
+ struct _rtld_addr_phdr_cb_data *rd;
+ const Elf_Phdr *ph;
+ unsigned i;
+
+ rd = arg;
+ for (i = 0; i < dli->dlpi_phnum; i++) {
+ ph = &dli->dlpi_phdr[i];
+ if (ph->p_type == PT_LOAD &&
+ dli->dlpi_addr + ph->p_vaddr <= (uintptr_t)rd->addr &&
+ (uintptr_t)rd->addr < dli->dlpi_addr + ph->p_vaddr +
+ ph->p_memsz) {
+ memcpy(rd->dli, dli, sz);
+ return (1);
+ }
+ }
+ return (0);
+}
+#endif
+
#pragma weak _rtld_addr_phdr
int
_rtld_addr_phdr(const void *addr __unused,
struct dl_phdr_info *phdr_info_a __unused)
{
+#ifndef IN_LIBDL
+ struct _rtld_addr_phdr_cb_data rd;
+ rd.addr = addr;
+ rd.dli = phdr_info_a;
+ return (dl_iterate_phdr(_rtld_addr_phdr_cb, &rd));
+#else
return (0);
+#endif
}
#pragma weak _rtld_get_stack_prot