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
This commit is contained in:
Konstantin Belousov 2023-06-24 13:59:56 +03:00
parent a42d8fe001
commit 42ceab3ea1

View file

@ -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