From patchwork Mon Oct 7 12:53:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 34843 Received: (qmail 118352 invoked by alias); 7 Oct 2019 12:54:02 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 118225 invoked by uid 89); 7 Oct 2019 12:54:02 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_NUMSUBJECT, KAM_SHORT, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=amended, Request, 2015 X-HELO: mx1.redhat.com From: Florian Weimer To: libc-alpha@sourceware.org Subject: [PATCH] dlfnc: Add RTLD_DL_HANDLE (dlopen handle) support to dladdr1 Date: Mon, 07 Oct 2019 14:53:56 +0200 Message-ID: <87zhiclnrv.fsf@oldenburg2.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux) MIME-Version: 1.0 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 #include 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 #include 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 + . */ + +#include +#include +#include +#include +#include +#include + +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