Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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.