summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2021-01-04 15:57:46 -0500
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-01-17 05:50:31 -0500
commit3d3fd7d89dd6c28d4aedf76fdcdbd514414f4fe1 (patch)
treefd16e0eefc565337d7619ad3791977ee64469fe4
parentd56fdad76c5fe025ad628aad727c8a1c7e745513 (diff)
downloadhaskell-3d3fd7d89dd6c28d4aedf76fdcdbd514414f4fe1.tar.gz
rts/linker: Don't assume existence of dlinfo
The native-code codepath uses dlinfo to identify memory regions owned by a loaded dynamic object, facilitating safe unload. Unfortunately, this interface is not always available. Add an autoconf check for it and introduce a safe fallback behavior. Fixes #19159.
-rw-r--r--configure.ac2
-rw-r--r--rts/Linker.c1
-rw-r--r--rts/LinkerInternals.h3
-rw-r--r--rts/linker/Elf.c28
4 files changed, 22 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac
index c9cf01e713..d3fbb48b86 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1126,6 +1126,8 @@ AS_IF([test "$UseSystemLibFFI" = "YES"], [
dnl ** check whether we need -ldl to get dlopen()
AC_CHECK_LIB([dl], [dlopen])
AC_CHECK_LIB([dl], [dlopen], [AC_SUBST([CabalHaveLibdl], [True])], [AC_SUBST([CabalHaveLibdl], [False])])
+dnl ** check whether we have dlinfo
+AC_CHECK_FUNCS([dlinfo])
dnl --------------------------------------------------
dnl * Miscellaneous feature tests
diff --git a/rts/Linker.c b/rts/Linker.c
index 5502965355..2ca9014379 100644
--- a/rts/Linker.c
+++ b/rts/Linker.c
@@ -1459,7 +1459,6 @@ mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
oc->rx_m32 = m32_allocator_new(true);
#endif
- oc->l_addr = NULL;
oc->nc_ranges = NULL;
oc->dlopen_handle = NULL;
diff --git a/rts/LinkerInternals.h b/rts/LinkerInternals.h
index 695f65dbdb..44fe337802 100644
--- a/rts/LinkerInternals.h
+++ b/rts/LinkerInternals.h
@@ -322,9 +322,6 @@ struct _ObjectCode {
/* handle returned from dlopen */
void *dlopen_handle;
- /* base virtual address of the loaded code */
- void *l_addr;
-
/* virtual memory ranges of loaded code */
NativeCodeRange *nc_ranges;
};
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index cc8d2c3309..9aaaedc0b2 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -1985,9 +1985,15 @@ int ocRunInit_ELF( ObjectCode *oc )
* Shared object loading
*/
+#if defined(HAVE_DLINFO)
+struct piterate_cb_info {
+ ObjectCode *nc;
+ void *l_addr; /* base virtual address of the loaded code */
+};
+
static int loadNativeObjCb_(struct dl_phdr_info *info,
size_t _size GNUC3_ATTRIBUTE(__unused__), void *data) {
- ObjectCode* nc = (ObjectCode*) data;
+ struct piterate_cb_info *s = (struct piterate_cb_info *) data;
// This logic mimicks _dl_addr_inside_object from glibc
// For reference:
@@ -2006,22 +2012,23 @@ static int loadNativeObjCb_(struct dl_phdr_info *info,
// return 0;
// }
- if ((void*) info->dlpi_addr == nc->l_addr) {
+ if ((void*) info->dlpi_addr == s->l_addr) {
int n = info->dlpi_phnum;
while (--n >= 0) {
if (info->dlpi_phdr[n].p_type == PT_LOAD) {
NativeCodeRange* ncr =
stgMallocBytes(sizeof(NativeCodeRange), "loadNativeObjCb_");
- ncr->start = (void*) ((char*) nc->l_addr + info->dlpi_phdr[n].p_vaddr);
+ ncr->start = (void*) ((char*) s->l_addr + info->dlpi_phdr[n].p_vaddr);
ncr->end = (void*) ((char*) ncr->start + info->dlpi_phdr[n].p_memsz);
- ncr->next = nc->nc_ranges;
- nc->nc_ranges = ncr;
+ ncr->next = s->nc->nc_ranges;
+ s->nc->nc_ranges = ncr;
}
}
}
return 0;
}
+#endif /* defined(HAVE_DLINFO) */
static void copyErrmsg(char** errmsg_dest, char* errmsg) {
if (errmsg == NULL) errmsg = "loadNativeObj_ELF: unknown error";
@@ -2064,6 +2071,7 @@ void * loadNativeObj_ELF (pathchar *path, char **errmsg)
foreignExportsLoadingObject(nc);
hdl = dlopen(path, RTLD_NOW|RTLD_LOCAL);
+ nc->dlopen_handle = hdl;
foreignExportsFinishedLoadingObject();
if (hdl == NULL) {
/* dlopen failed; save the message in errmsg */
@@ -2071,6 +2079,7 @@ void * loadNativeObj_ELF (pathchar *path, char **errmsg)
goto dlopen_fail;
}
+#if defined(HAVE_DLINFO)
struct link_map *map;
if (dlinfo(hdl, RTLD_DI_LINKMAP, &map) == -1) {
/* dlinfo failed; save the message in errmsg */
@@ -2078,15 +2087,18 @@ void * loadNativeObj_ELF (pathchar *path, char **errmsg)
goto dlinfo_fail;
}
- nc->l_addr = (void*) map->l_addr;
- nc->dlopen_handle = hdl;
hdl = NULL; // pass handle ownership to nc
- dl_iterate_phdr(loadNativeObjCb_, nc);
+ struct piterate_cb_info piterate_info = {
+ .nc = nc,
+ .l_addr = (void *) map->l_addr
+ };
+ dl_iterate_phdr(loadNativeObjCb_, &piterate_info);
if (!nc->nc_ranges) {
copyErrmsg(errmsg, "dl_iterate_phdr failed to find obj");
goto dl_iterate_phdr_fail;
}
+#endif /* defined (HAVE_DLINFO) */
insertOCSectionIndices(nc);