This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] dlfnc: Add RTLD_DL_HANDLE (dlopen handle) support to dladdr1
- From: Adhemerval Zanella <adhemerval dot zanella at linaro dot org>
- To: libc-alpha at sourceware dot org
- Date: Mon, 16 Dec 2019 16:35:20 -0300
- Subject: Re: [PATCH] dlfnc: Add RTLD_DL_HANDLE (dlopen handle) support to dladdr1
- References: <87zhiclnrv.fsf@oldenburg2.str.redhat.com>
On 07/10/2019 09:53, Florian Weimer wrote:
> 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.
I am trying to understand why exactly you need another dladdr1 flag
that is essentially handled as RTLD_DL_HANDLE. Do you see requiring
handling it different for some specific / future usage?
>
> 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.
> +
Ok.
> 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 \
Ok.
> @@ -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
Ok.
> 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);
> }
> }
Ok.
> 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
> };
>
>
Ok.
> 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>
>
Ok.
> 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>
>
Ok.
> 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");
Ok.
> +
> + /* The handle should be usable with dlsym. */
> + TEST_VERIFY (xdlsym (handle, "dlsym") == xdlsym (NULL, "dlsym"));
> +
Ok.
> + /* 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);
Ok.
> +
> + /* 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);
Ok.
> +
> + /* 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);
Ok.
> +
> + xdlclose (moddummy2_handle);
> + xdlclose (moddummy1_handle);
> + xdlclose (libc_handle);
> +
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
>
Ok.