Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CAFS5DSHyrCutszvpdWduF9SEcRnPSe36we_XMx_txDLYoZa+Hw@mail.gmail.com>
Date: Tue, 10 Feb 2026 16:18:39 -0300
From: Luciano Lo Giudice <lmlogiudice@...il.com>
To: Florian Weimer <fweimer@...hat.com>
Cc: musl@...ts.openwall.com
Subject: Re: [RFC] Implement the _dl_find_object interface

Hello Florian,

> The dlfo_eh_count field is never used with PT_GNU_EH_FRAME, only with
> PT_ARM_EXIDX.

Thanks, fixed.

Hello Rich,
> Is there a legitimate reason the fields differ by arch? That's rather
> an antipattern for adding new interfaces like this..

I don't know what glib's reasoning is, to be honest. I did it this way for
compatibility, but I guess
every field could be added regardless, with no consequences.

Here's the updated patch:

diff --git a/arch/arm/bits/dlfcn.h b/arch/arm/bits/dlfcn.h
new file mode 100644
index 00000000..d9a13e2c
--- /dev/null
+++ b/arch/arm/bits/dlfcn.h
@@ -0,0 +1,3 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 1
+#define DLFO_STRUCT_HAS_EH_COUNT 1
+#define DLFO_EH_SEGMENT_TYPE PT_ARM_EXIDX
diff --git a/arch/generic/bits/dlfcn.h b/arch/generic/bits/dlfcn.h
new file mode 100644
index 00000000..ec70f4e6
--- /dev/null
+++ b/arch/generic/bits/dlfcn.h
@@ -0,0 +1,3 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 1
+#define DLFO_STRUCT_HAS_EH_COUNT 0
+#define DLFO_EH_SEGMENT_TYPE PT_GNU_EH_FRAME
diff --git a/arch/x86_64/bits/dlfcn.h b/arch/x86_64/bits/dlfcn.h
new file mode 100644
index 00000000..e38879dd
--- /dev/null
+++ b/arch/x86_64/bits/dlfcn.h
@@ -0,0 +1,3 @@
+#define DLFO_STRUCT_HAS_EH_DBASE 0
+#define DLFO_STRUCT_HAS_EH_COUNT 0
+#define DLFO_EH_SEGMENT_TYPE PT_GNU_EH_FRAME
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..31b2e247 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 == DLFO_EH_SEGMENT_TYPE) {
+       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..77a520a9
--- /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 == DLFO_EH_SEGMENT_TYPE)
+      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.