[PATCH] ntdll: get struct link_map fully working on all FreeBSD versions
Damjan Jovanovic
damjan.jov at gmail.com
Sun Nov 15 01:52:13 CST 2020
autoheader and autoconf need to be run.
Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
configure.ac | 3 +++
dlls/ntdll/unix/loader.c | 25 +++++++++++++++++++++++--
2 files changed, 26 insertions(+), 2 deletions(-)
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index 666219f5f36..455dc07b0e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2219,6 +2219,9 @@ CFLAGS="$ac_save_CFLAGS"
dnl Check for -ldl
AC_SEARCH_LIBS(dlopen, dl)
WINE_CHECK_LIB_FUNCS(dladdr dlinfo,[$DL_LIBS])
+AC_CHECK_MEMBERS([struct link_map.l_base],,,
+[#include <elf.h>
+#include <link.h>])
dnl Check for -lpoll for Mac OS X/Darwin
if test "$ac_cv_func_poll" = no
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index c2b6ea603e3..43ddc6f166b 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -1412,9 +1412,30 @@ found:
caddr_t relocbase = (caddr_t)map->l_addr;
#ifdef __FreeBSD__
- /* On older FreeBSD versions, l_addr was the absolute load address, now it's the relocation offset. */
+ /* l_addr changed meaning from absolute load address (which is now l_base)
+ * to relocation offset, but also got moved within the struct, breaking
+ * the ABI via struct layout change:
+ *
+ * OLD header: NEW header:
+ * typedef struct link_map { typedef struct link_map {
+ * caddr_t l_addr; caddr_t l_base;
+ * ... ...
+ * ... caddr_t l_addr;
+ * }; };
+ *
+ * OLD ld-elf.so: NEW ld-elf.so:
+ * ... exports _rtld_version_laddr_offset
+ *
+ * Since the header change and rtld change aren't coupled, we have to
+ * worry about the interaction between link.h version at compile time,
+ * and ld-elf.so version at runtime...
+ */
+#ifdef HAVE_STRUCT_LINK_MAP_L_BASE
if (!dlsym(RTLD_DEFAULT, "_rtld_version_laddr_offset"))
- if (!get_relocbase(map->l_addr, &relocbase)) return;
+ if (!get_relocbase(map->l_base, &relocbase)) return;
+#else
+ if (!get_relocbase(map->l_addr, &relocbase)) return;
+#endif
#endif
switch (dyn->d_tag)
{
More information about the wine-devel
mailing list