This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] dlfnc: Add RTLD_DL_HANDLE (dlopen handle) support to dladdr1
- From: Florian Weimer <fweimer at redhat dot com>
- To: libc-alpha at sourceware dot org
- Date: Mon, 07 Oct 2019 14:53:56 +0200
- Subject: [PATCH] dlfnc: Add RTLD_DL_HANDLE (dlopen handle) support to dladdr1
Previously, only struct link_map * results were supported. While
the two pointers are the same in the currrent implementation, this
is not gurantueed by the interface in other places.
-----
Note: Not posting a ChangeLog entry, on the assumption that we will
switch to automatic generation.
diff --git a/NEWS b/NEWS
index d7286841c9..2ea7378d10 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,9 @@ Major new features:
18661-1:2014 and TS 18661-3:2015 as amended by the resolution of
Clarification Request 13 to TS 18661-3.
+* The dladdr1 function accepts a new flag, RTLD_DL_HANDLE, to obtain a
+ handle (as used with dlsym and other functions) based on an address.
+
Deprecated and removed features, and other changes affecting compatibility:
* The totalorder and totalordermag functions, and the corresponding
diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 749bb79b91..2169a77f83 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -36,7 +36,7 @@ endif
ifeq (yes,$(build-shared))
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
- bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen
+ bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen tst-dladdr1-handle
endif
modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
defaultmod2 errmsg1mod modatexit modcxaatexit \
@@ -151,3 +151,6 @@ $(objpfx)bug-dl-leaf-lib-cb.so: $(objpfx)bug-dl-leaf-lib.so
$(objpfx)tst-rec-dlopen: $(libdl)
$(objpfx)tst-rec-dlopen.out: $(objpfx)moddummy1.so $(objpfx)moddummy2.so
+
+$(objpfx)tst-dladdr1-handle: $(libdl)
+$(objpfx)tst-dladdr1-handle.out: $(objpfx)moddummy1.so $(objpfx)moddummy2.so
diff --git a/dlfcn/dladdr1.c b/dlfcn/dladdr1.c
index 63e78ff525..536116543e 100644
--- a/dlfcn/dladdr1.c
+++ b/dlfcn/dladdr1.c
@@ -45,6 +45,7 @@ __dladdr1 (const void *address, Dl_info *info, void **extra, int flags)
case RTLD_DL_SYMENT:
return _dl_addr (address, info, NULL, (const ElfW(Sym) **) extra);
case RTLD_DL_LINKMAP:
+ case RTLD_DL_HANDLE:
return _dl_addr (address, info, (struct link_map **) extra, NULL);
}
}
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h
index ebd3c457e3..b657f2762f 100644
--- a/dlfcn/dlfcn.h
+++ b/dlfcn/dlfcn.h
@@ -111,7 +111,12 @@ enum
RTLD_DL_SYMENT = 1,
/* The object containing the address (struct link_map *). */
- RTLD_DL_LINKMAP = 2
+ RTLD_DL_LINKMAP = 2,
+
+ /* The object containing the address, as identified by its handle
+ (void *). The handle is compatible with functions such as
+ dlsym. */
+ RTLD_DL_HANDLE = 3
};
diff --git a/dlfcn/moddummy1.c b/dlfcn/moddummy1.c
index 6e549fa7d2..6496d2eaeb 100644
--- a/dlfcn/moddummy1.c
+++ b/dlfcn/moddummy1.c
@@ -1,4 +1,4 @@
-/* Provide a dummy DSO for tst-rec-dlopen to use. */
+/* Provide a dummy DSO for tst-rec-dlopen, tst-dladdr1-handle to use. */
#include <stdio.h>
#include <stdlib.h>
diff --git a/dlfcn/moddummy2.c b/dlfcn/moddummy2.c
index cb4edc8da7..4e63e9a1fc 100644
--- a/dlfcn/moddummy2.c
+++ b/dlfcn/moddummy2.c
@@ -1,4 +1,4 @@
-/* Provide a dummy DSO for tst-rec-dlopen to use. */
+/* Provide a dummy DSO for tst-rec-dlopen, tst-dladdr1-handle to use. */
#include <stdio.h>
#include <stdlib.h>
diff --git a/dlfcn/tst-dladdr1-handle.c b/dlfcn/tst-dladdr1-handle.c
new file mode 100644
index 0000000000..25f36a2edf
--- /dev/null
+++ b/dlfcn/tst-dladdr1-handle.c
@@ -0,0 +1,75 @@
+/* Test for dladdr1 with RTLD_DL_HANDLE.
+ Copyright (C) 2019 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <gnu/lib-names.h>
+#include <link.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <stddef.h>
+
+static void
+local_function (void)
+{
+}
+
+static int
+do_test (void)
+{
+ Dl_info info;
+ void *handle;
+
+ if (dladdr1 (&local_function, &info, &handle, RTLD_DL_HANDLE) == 0)
+ FAIL_EXIT1 ("dladdr1 for local_function failed");
+
+ /* The handle should be usable with dlsym. */
+ TEST_VERIFY (xdlsym (handle, "dlsym") == xdlsym (NULL, "dlsym"));
+
+ /* Check that libc is correctly identified. Use an obscure libc
+ function as reference, to avoid PLT stubs and similar constructs
+ moving the active definition to another object. */
+ void *libc_handle = xdlopen (LIBC_SO, RTLD_NOW);
+ void *ptr = xdlsym (libc_handle, "grantpt");
+ if (dladdr1 (ptr, &info, &handle, RTLD_DL_HANDLE) == 0)
+ FAIL_EXIT1 ("dladdr1 for grantpt failed");
+ TEST_VERIFY (handle == libc_handle);
+
+ /* Check that the handle of a new-loaded shared object is
+ returned from dladdr1. */
+ void *moddummy1_handle = xdlopen ("moddummy1.so", RTLD_NOW);
+ ptr = xdlsym (moddummy1_handle, "dummy1");
+ if (dladdr1 (ptr, &info, &handle, RTLD_DL_HANDLE) == 0)
+ FAIL_EXIT1 ("dladdr1 for dummy1 failed");
+ TEST_VERIFY (handle == moddummy1_handle);
+
+ /* Check that the handle of a shared object loaded into a new
+ namespace is returned from dladdr1. */
+ void *moddummy2_handle = xdlmopen (LM_ID_NEWLM, "moddummy2.so", RTLD_NOW);
+ ptr = xdlsym (moddummy2_handle, "dummy2");
+ if (dladdr1 (ptr, &info, &handle, RTLD_DL_HANDLE) == 0)
+ FAIL_EXIT1 ("dladdr1 for dummy2 failed");
+ TEST_VERIFY (handle == moddummy2_handle);
+
+ xdlclose (moddummy2_handle);
+ xdlclose (moddummy1_handle);
+ xdlclose (libc_handle);
+
+ return 0;
+}
+
+#include <support/test-driver.c>