From patchwork Thu May 18 08:28:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: stsp X-Patchwork-Id: 69584 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 337393882050 for ; Thu, 18 May 2023 08:34:58 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from forward103b.mail.yandex.net (forward103b.mail.yandex.net [IPv6:2a02:6b8:c02:900:1:45:d181:d103]) by sourceware.org (Postfix) with ESMTPS id EBF943856976 for ; Thu, 18 May 2023 08:29:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org EBF943856976 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=yandex.ru Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=yandex.ru Received: from mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net (mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net [IPv6:2a02:6b8:c0c:1186:0:640:38cb:0]) by forward103b.mail.yandex.net (Yandex) with ESMTP id 88A7E60033 for ; Thu, 18 May 2023 11:29:49 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id XTYe39MDZ0U0-aalOJ8Er; Thu, 18 May 2023 11:29:49 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1684398589; bh=A3HbRwdB0rg4zGImcm+WBWHHqE/bw5mFc4mU3tIEVEw=; h=Message-Id:Date:In-Reply-To:Cc:Subject:References:To:From; b=VB5AnxAbw66qZS651CbCyE6BO4xC161WbHQfZuv0qg915rzdd/iO/dzbpAKjgK2Mm OzNZgu+LDAOyPeEpA8ja90VnWs0omkhxkyoP72/Sv2PaMmWSX3QaklFK3jIqo6oV+o 3AL2l0TdKxqQLTvi6EjyuPJS++tufOQy5FcXJrDc= Authentication-Results: mail-nwsmtp-smtp-production-main-91.iva.yp-c.yandex.net; dkim=pass header.i=@yandex.ru From: Stas Sergeev To: libc-alpha@sourceware.org Cc: Stas Sergeev Subject: [PATCH 14/14] implement RTLD_DI_DEPLIST dlinfo() request Date: Thu, 18 May 2023 13:28:54 +0500 Message-Id: <20230518082854.3903342-15-stsp2@yandex.ru> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230518082854.3903342-1-stsp2@yandex.ru> References: <20230518082854.3903342-1-stsp2@yandex.ru> MIME-Version: 1.0 X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" `RTLD_DI_DEPLIST' is a new dlinfo() request that fills in this structure: typedef struct { void **deps; /* Array of handles for the deps. */ unsigned int ndeps; /* Number of entries in the list. */ } Dl_deplist; It is needed if the user wants to move also the dependencies of the loaded solib. In this case he needs to traverse the `deps' array, make RTLD_DI_MAPINFO dlinfo() request per each handle from an array, find the object he needs by inspecting the filled-in Dl_mapinfo structure, make sure this object is not relocated yet, and move it, calling dlset_object_base() at the end. The test-suite was run on x86_64/64 and showed no regressions. Signed-off-by: Stas Sergeev --- dlfcn/Makefile | 3 +++ dlfcn/ctorlib1.c | 9 ++++++--- dlfcn/dlfcn.h | 13 ++++++++++++- dlfcn/dlinfo.c | 14 ++++++++++++++ dlfcn/tst-noreloc.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/dlfcn/Makefile b/dlfcn/Makefile index da486a9b01..0d6b16c820 100644 --- a/dlfcn/Makefile +++ b/dlfcn/Makefile @@ -104,6 +104,9 @@ $(objpfx)glrefmain.out: $(objpfx)glrefmain \ $(objpfx)failtest.out: $(objpfx)failtestmod.so $(objpfx)tst-dladdr.out: $(objpfx)glreflib1.so + +$(objpfx)ctorlib1.so: $(objpfx)glreflib1.so +LDFLAGS-ctorlib1 = $(objpfx)glreflib1.so $(objpfx)tst-noreloc.out: $(objpfx)ctorlib1.so LDFLAGS-tst-noreloc = $(LDFLAGS-rdynamic) diff --git a/dlfcn/ctorlib1.c b/dlfcn/ctorlib1.c index cf7a9096ea..7d410f6c71 100644 --- a/dlfcn/ctorlib1.c +++ b/dlfcn/ctorlib1.c @@ -21,10 +21,12 @@ #include extern int ref1 (void); + +extern int cref1 (void); int -ref1 (void) +cref1 (void) { - return 42; + return 34; } void __attribute__((constructor)) @@ -32,5 +34,6 @@ ctor (void) { int *ct = (int *) dlsym (RTLD_DEFAULT, "ctor_called"); assert (ct); - (*ct)++; + if (ref1 () == 42) + (*ct)++; } diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index eee6343833..5b36330aa9 100644 --- a/dlfcn/dlfcn.h +++ b/dlfcn/dlfcn.h @@ -179,7 +179,12 @@ enum -1 on failure. */ RTLD_DI_MAPINFO = 12, - RTLD_DI_MAX = 12 + /* Treat ARG as Dl_deplist *, and store the dependency link-maps + at that location. The dlinfo call returns 0 on success or + -1 on failure. */ + RTLD_DI_DEPLIST = 13, + + RTLD_DI_MAX = 13 }; @@ -220,6 +225,12 @@ typedef struct int relocated; /* Indicates whether an object was relocated. */ } Dl_mapinfo; +typedef struct +{ + void **deps; /* Array of handles for the deps. */ + unsigned int ndeps; /* Number of entries in the list. */ +} Dl_deplist; + struct dl_find_object { __extension__ unsigned long long int dlfo_flags; diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c index 8d7db7dbb8..4eb96bc476 100644 --- a/dlfcn/dlinfo.c +++ b/dlfcn/dlinfo.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -103,6 +104,19 @@ dlinfo_doit (void *argsblock) __rtld_lock_unlock_recursive (GL(dl_load_lock)); break; } + + case RTLD_DI_DEPLIST: + { + int i = 0; + Dl_deplist *list = (Dl_deplist *) args->arg; + assert (l == l->l_initfini[0]); + list->deps = (void **) &l->l_initfini[1]; /* Skip our own handle. */ + while (list->deps[i]) + i++; + list->ndeps = i; + args->result = 0; + break; + } } } diff --git a/dlfcn/tst-noreloc.c b/dlfcn/tst-noreloc.c index 96c05a4b06..846d2b9321 100644 --- a/dlfcn/tst-noreloc.c +++ b/dlfcn/tst-noreloc.c @@ -29,14 +29,17 @@ int ctor_called; -static void move_object (void *handle) +static void move_object (void *handle, int is_dep) { int ret; Dl_mapinfo mapinfo; void *new_addr; ret = dlinfo (handle, RTLD_DI_MAPINFO, &mapinfo); - TEST_COMPARE (ret, 0); + if (!is_dep) + TEST_COMPARE (ret, 0); + if (is_dep && (ret == -1 || mapinfo.relocated)) + return; TEST_COMPARE (mapinfo.relocated, 0); if (mapinfo.map_align != getpagesize ()) error (EXIT_FAILURE, 0, "unsupported map alignment"); @@ -59,7 +62,10 @@ do_test (void) void *handle; int (*sym) (void); Dl_info info; + Dl_info info2; + Dl_deplist deplist; int ret; + int i; handle = dlopen ("ctorlib1.so", RTLD_NOW | RTLD_NORELOCATE); if (handle == NULL) @@ -97,7 +103,11 @@ do_test (void) if (handle == NULL) error (EXIT_FAILURE, 0, "cannot load: ctorlib1.so"); - move_object (handle); + move_object (handle, 0); + ret = dlinfo (handle, RTLD_DI_DEPLIST, &deplist); + TEST_COMPARE (ret, 0); + for (i = 0; i < deplist.ndeps; i++) + move_object (deplist.deps[i], 1); TEST_COMPARE (ctor_called, 0); sym = dlsym (handle, "ref1"); @@ -113,6 +123,20 @@ do_test (void) TEST_VERIFY ((uintptr_t) info.dli_fbase < 0x100000000); #endif + sym = dlsym (handle, "cref1"); + if (sym == NULL) + error (EXIT_FAILURE, 0, "dlsym failed"); + TEST_COMPARE (ctor_called, 1); + + memset (&info2, 0, sizeof (info2)); + ret = dladdr (sym, &info2); + if (ret == 0) + error (EXIT_FAILURE, 0, "dladdr failed"); +#if MAP_32BIT != 0 + TEST_VERIFY ((uintptr_t) info2.dli_fbase < 0x100000000); +#endif + TEST_VERIFY (info2.dli_fbase != info.dli_fbase); + printf ("ret = %d\n", ret); printf ("info.dli_fname = %p (\"%s\")\n", info.dli_fname, info.dli_fname); printf ("info.dli_fbase = %p\n", info.dli_fbase);