991d05ce2f
Mesa's Intel Anvil Vulkan driver requires dl_iterate_phdr, which relibc lacked (meson cc.has_function fails). Implement it against the dynamic linker's authoritative object list: store each object's program headers on the DSO (new DSO.phdrs, populated in both from_raw and new), add Linker::iter_dsos, and add a src/header/link module exporting dl_iterate_phdr that walks the loaded objects and reports each one's base/name/phdr-table to the callback (stopping early on non-zero return, per spec). Static binaries (no linker) report zero objects. Hand-written include/link.h declares struct dl_phdr_info with a correctly-typed const Elf64_Phdr* dlpi_phdr.
46 lines
1.6 KiB
C
46 lines
1.6 KiB
C
/*
|
|
* link.h — dynamic-linker introspection (dl_iterate_phdr).
|
|
*
|
|
* Non-POSIX (glibc/BSD extension). The implementation of dl_iterate_phdr lives
|
|
* in relibc's dynamic linker (src/header/link/mod.rs); this header only
|
|
* declares the ABI. Keep `struct dl_phdr_info` in sync with the Rust
|
|
* `DlPhdrInfo` struct in that module.
|
|
*/
|
|
#ifndef _RELIBC_LINK_H
|
|
#define _RELIBC_LINK_H
|
|
|
|
#include <elf.h>
|
|
#include <stddef.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct dl_phdr_info {
|
|
Elf64_Addr dlpi_addr; /* base / load bias of the object */
|
|
const char *dlpi_name; /* object pathname (NUL-terminated) */
|
|
const Elf64_Phdr *dlpi_phdr; /* pointer to the program header array */
|
|
Elf64_Half dlpi_phnum; /* number of program headers */
|
|
/* glibc-compatible extension fields */
|
|
unsigned long long dlpi_adds; /* # objects added since process start */
|
|
unsigned long long dlpi_subs; /* # objects removed since start */
|
|
size_t dlpi_tls_modid; /* TLS module ID (0 if none) */
|
|
void *dlpi_tls_data; /* TLS block for the calling thread */
|
|
};
|
|
|
|
/*
|
|
* Call `callback` once per loaded object. `size` is sizeof(struct dl_phdr_info).
|
|
* Iteration stops as soon as a callback returns non-zero, and that value is
|
|
* returned; otherwise the return value is that of the last callback (or 0 when
|
|
* there are no objects).
|
|
*/
|
|
int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info,
|
|
size_t size, void *data),
|
|
void *data);
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
#endif /* _RELIBC_LINK_H */
|