|
|
Message-ID: <CAFS5DSE6=Hm0HfVjjo6nqyyvBvbbXTeWUi4wZvXtFMwsq+=DUg@mail.gmail.com>
Date: Fri, 6 Feb 2026 20:28:14 -0300
From: Luciano Lo Giudice <lmlogiudice@...il.com>
To: Luciano Lo Giudice <lmlogiudice@...il.com>, musl@...ts.openwall.com
Subject: Re: [RFC] Implement the _dl_find_object interface
Here's the newest patch, with the requested changes:
diff --git a/arch/arm/bits/dlfcn.h b/arch/arm/bits/dlfcn.h
new file mode 100644
index 00000000..c3c48482
--- /dev/null
+++ b/arch/arm/bits/dlfcn.h
@@ -0,0 +1,2 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 1
+#define DLFO_STRUCT_HAS_EH_COUNT 1
diff --git a/arch/generic/bits/dlfcn.h b/arch/generic/bits/dlfcn.h
new file mode 100644
index 00000000..11d2dbec
--- /dev/null
+++ b/arch/generic/bits/dlfcn.h
@@ -0,0 +1,2 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 1
+#define DLFO_STRUCT_HAS_EH_COUNT 0
diff --git a/arch/x86_64/bits/dlfcn.h b/arch/x86_64/bits/dlfcn.h
new file mode 100644
index 00000000..a000c9d7
--- /dev/null
+++ b/arch/x86_64/bits/dlfcn.h
@@ -0,0 +1,2 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 0
+#define DLFO_STRUCT_HAS_EH_COUNT 0
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 13ab71dd..b735e90e 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -25,14 +25,46 @@ void *dlopen(const char *, int);
void *dlsym(void *__restrict, const char *__restrict);
#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#include <bits/dlfcn.h>
+#include <bits/alltypes.h>
+
typedef struct {
const char *dli_fname;
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
+
+
+#define DLFO_FLAG_SFRAME 1
+
+struct dl_find_object {
+ unsigned long long dlfo_flags;
+ void *dlfo_map_start;
+ void *dlfo_map_end;
+ struct link_map *dlfo_link_map;
+ void *dlfo_eh_frame;
+#if DLFO_STRUCT_HAS_EH_DBASE
+ void *dlfo_eh_dbase;
+# if __LONG_MAX == 0x7fffffffL
+ unsigned int __pad1;
+# endif
+#endif
+#if DLFO_STRUCT_HAS_EH_COUNT
+ int dlfo_eh_count;
+ unsigned int __pad2;
+#endif
+ void *dlfo_sframe;
+# if __LONG_MAX == 0x7fffffffL
+ unsigned int __pad3;
+# endif
+ unsigned long long __extra[7];
+};
+
int dladdr(const void *, Dl_info *);
int dlinfo(void *, int, void *);
+int _dl_find_object(void *, struct dl_find_object *);
#endif
#if _REDIR_TIME64
diff --git a/include/elf.h b/include/elf.h
index d6ae539a..ff196ffa 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -612,6 +612,7 @@ typedef struct {
#define PT_GNU_STACK 0x6474e551
#define PT_GNU_RELRO 0x6474e552
#define PT_GNU_PROPERTY 0x6474e553
+#define PT_GNU_SFRAME 0x6474e554
#define PT_LOSUNW 0x6ffffffa
#define PT_SUNWBSS 0x6ffffffa
#define PT_SUNWSTACK 0x6ffffffb
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 715948f4..74326ac3 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -2437,3 +2437,48 @@ static void error_impl(const char *fmt, ...)
static void error_noop(const char *fmt, ...)
{
}
+
+int _dl_find_object(void *addr, struct dl_find_object *obj)
+{
+ struct dso *p;
+ Phdr *phdr;
+ size_t cnt, esize;
+ unsigned int read;
+
+ pthread_rwlock_rdlock(&lock);
+ p = addr2dso((size_t)addr);
+ pthread_rwlock_unlock(&lock);
+
+ if (!p) return -1;
+
+ memset(obj, 0, sizeof(*obj));
+ obj->dlfo_map_start = p->map;
+ obj->dlfo_map_end = p->map + p->map_len;
+ obj->dlfo_link_map = (void *)p;
+#if DLFO_STRUCT_HAS_EH_DBASE
+ obj->dlfo_eh_dbase = p->got;
+#endif
+
+ phdr = p->phdr;
+ cnt = p->phnum;
+ esize = p->phentsize;
+ read = 0;
+
+ for (; cnt--; phdr = (void *)((char *)phdr + esize)) {
+ if (phdr->p_type == PT_GNU_EH_FRAME) {
+ obj->dlfo_eh_frame = laddr(p, phdr->p_vaddr);
+#if DLFO_STRUCT_HAS_EH_COUNT
+ obj->dlfo_eh_count = (int)(phdr->p_memsz / 8);
+#endif
+ read |= 1;
+ } else if (phdr->p_type == PT_GNU_SFRAME) {
+ obj->dlfo_flags |= DLFO_FLAG_SFRAME;
+ obj->dlfo_sframe = laddr(p, phdr->p_vaddr);
+ read |= 2;
+ }
+
+ if (read == 3) break;
+ }
+
+ return 0;
+}
diff --git a/src/ldso/dl_find_object.c b/src/ldso/dl_find_object.c
new file mode 100644
index 00000000..47c23f59
--- /dev/null
+++ b/src/ldso/dl_find_object.c
@@ -0,0 +1,76 @@
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <elf.h>
+#include <link.h>
+#include <string.h>
+#include "libc.h"
+
+#define AUX_CNT 38
+
+extern weak hidden const size_t _DYNAMIC[];
+
+static int
+dl_find_object_impl (void *addr, struct dl_find_object *obj)
+{
+ unsigned char *p;
+ ElfW(Phdr) *phdr, *eh_frame = 0, *sframe = 0;
+ size_t i, aux[AUX_CNT] = { 0 };
+ size_t base = 0, end = ~(size_t)0, cnt;
+ int found = 0;
+
+ for (i = 0; libc.auxv[i]; i += 2)
+ if (libc.auxv[i] < AUX_CNT)
+ aux[libc.auxv[i]] = libc.auxv[i + 1];
+
+ for (p = (void *)aux[AT_PHDR], cnt = aux[AT_PHNUM];
+ cnt; --cnt, p += aux[AT_PHENT]) {
+
+ phdr = (void *)p;
+ if (phdr->p_type == PT_PHDR) {
+ base = aux[AT_PHDR] - phdr->p_vaddr;
+ end = base + phdr->p_memsz;
+ }
+
+ if (phdr->p_type == PT_DYNAMIC && _DYNAMIC)
+ base = (size_t)_DYNAMIC - phdr->p_vaddr;
+ else if (phdr->p_type == PT_GNU_EH_FRAME)
+ eh_frame = phdr;
+ else if (phdr->p_type == PT_GNU_SFRAME)
+ sframe = phdr;
+ }
+
+ /* Test if the requested address is valid. */
+ for (p = (void *)aux[AT_PHDR], cnt = aux[AT_PHNUM];
+ cnt; --cnt, p += aux[AT_PHENT]) {
+
+ phdr = (void *)p;
+ if (phdr->p_type == PT_LOAD &&
+ (size_t)addr >= base + phdr->p_vaddr &&
+ (size_t)addr < base + phdr->p_vaddr + phdr->p_memsz) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) return -1;
+
+ memset(obj, 0, sizeof(*obj));
+ obj->dlfo_map_start = (void *)base;
+ obj->dlfo_map_end = (void *)end;
+
+ if (eh_frame) {
+ obj->dlfo_eh_frame = (void *)(base + eh_frame->p_vaddr);
+#if DLFO_STRUCT_HAS_EH_COUNT
+ obj->dlfo_eh_count = (int)(eh_frame->p_memsz / 8);
+#endif
+ }
+
+ if (sframe) {
+ obj->dlfo_sframe = (void *)(base + sframe->p_vaddr);
+ obj->dlfo_flags |= DLFO_FLAG_SFRAME;
+ }
+
+ return 0;
+}
+
+weak_alias (dl_find_object_impl, _dl_find_object);
Content of type "text/html" skipped
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.