From patchwork Mon Aug 2 20:42:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 44554 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 D9F0C38930F0 for ; Mon, 2 Aug 2021 20:43:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D9F0C38930F0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1627936984; bh=MoeqiPFabumOagf0IIs46SNmt8QpcOm1CEVcScKgK5Q=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=JH/4/jznLLYY0Sp7pJ8lUUADA0/7FMRD6BCEg2GkfKn0LKopgtwOwLedq+HomeBXr 2EPBxQIvFa7GCD012MnEFbsPsdkSlQ3OtW7EvOl0Ant1JDpv10xG4P5BZ641x0YLxf zUmNUF7wPDfVDQBIOk7mxR5e3DUBAMOfCc6nVZUQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) by sourceware.org (Postfix) with ESMTPS id 6F7783853800 for ; Mon, 2 Aug 2021 20:42:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6F7783853800 Received: by mail-pj1-x102c.google.com with SMTP id s22-20020a17090a1c16b0290177caeba067so796795pjs.0 for ; Mon, 02 Aug 2021 13:42:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=MoeqiPFabumOagf0IIs46SNmt8QpcOm1CEVcScKgK5Q=; b=nADmG5ra/xLwvWjUKSoxjWTQSY4Ig5SgwrIDW60Z9skZiwN/mw2V8d3Eu4L+2Zl3Nx RG03e/gglHFXJSgVIow/fs7RZvCZ0X7UKjLchlLtbIF1N+1tXAmbsoLANvWXBpZqXL4+ dB2mbJMazYwdViR9leiwu+SWNNn5iizUSj6VyMVu/qHvpEQBIH1u0Q1tad13L7oDfAsk DZSzZ92OEs+nsJT+mfgWDcG2Q4x0sv63pmp3KTHCqFk+pC2gwIYfCZxEgVAb3WTrowkx Aa5NLMohYZRv1s9xN6NvgFG+PeGAHcw5/dlMg6WX9RdQaKU9neQxrBCnIitl1eeazWUI Fomg== X-Gm-Message-State: AOAM533Dla2d1SmcZ85XpR8K19abuoV3F56Qy1IGkwIat4EcSzNvDJDV 2YFpnV7nHrW/3yXsrte67uYktUDddCw= X-Google-Smtp-Source: ABdhPJxNjzQaJ5eWNcL4E1mZ4a27pQlGMaaxpOd59epLgx8O4hsLMfL9FVu07+2hjMJ4WayI0YFLOw== X-Received: by 2002:a63:c158:: with SMTP id p24mr434553pgi.336.1627936961264; Mon, 02 Aug 2021 13:42:41 -0700 (PDT) Received: from gnu-cfl-2.localdomain ([172.58.38.240]) by smtp.gmail.com with ESMTPSA id k20sm296953pji.3.2021.08.02.13.42.40 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Aug 2021 13:42:40 -0700 (PDT) Received: from gnu-cfl-2.. (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 9D560C02C7 for ; Mon, 2 Aug 2021 13:42:39 -0700 (PDT) To: libc-alpha@sourceware.org Subject: [PATCH v2 2/2] ld.so: Hide _r_debug to support DT_DEBUG [BZ #28130] Date: Mon, 2 Aug 2021 13:42:39 -0700 Message-Id: <20210802204239.205959-1-hjl.tools@gmail.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 X-Spam-Status: No, score=-3033.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: , X-Patchwork-Original-From: "H.J. Lu via Libc-alpha" From: "H.J. Lu" Reply-To: "H.J. Lu" Errors-To: libc-alpha-bounces+patchwork=sourceware.org@sourceware.org Sender: "Libc-alpha" has extern struct r_debug _r_debug; which is exported from ld.so. rtld.c has /* Initialize _r_debug. */ struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr, LM_ID_BASE); ... if (main_map->l_info[DT_DEBUG] != NULL) /* There is a DT_DEBUG entry in the dynamic section. Fill it in with the run-time address of the r_debug structure */ main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r; With COPY relocation, the address of _r_debug at run-time may be in the executable if it references _r_debug. Since debugger uses DT_DEBUG, it will reference the staled original definition of _r_debug in ld.so. 1. Make _r_debug a compatible symbol in ld.so and don't export it. The existing dynamic executables with _r_debug reference will get a copy of _r_debug which won't be updated by ld.so. But DT_DEBUG will work with debuggers. 2. Make a hidden alias of _r_debug, _r_debug_internal, and use it in ld.so. 3. Add a support function, get_r_debug, to return the value in DT_DEBUG, which is the address of _r_debug. FIXME: MIPS needs to check a different dynamic tag to get the address of _r_debug. 4. Provide struct r_debug *get_r_debug (void); #define _r_debug (*get_r_debug ()) in to support glibc tests. This fixes BZ #28130. --- elf/Makefile | 2 ++ elf/circleload1.c | 1 + elf/dl-debug.c | 28 ++++++++++++++--- elf/link.h | 3 -- elf/loadtest.c | 1 + elf/neededtest.c | 1 + elf/neededtest2.c | 1 + elf/neededtest3.c | 1 + elf/neededtest4.c | 1 + elf/unload.c | 1 + elf/unload2.c | 1 + support/Makefile | 1 + support/get_r_debug.c | 54 ++++++++++++++++++++++++++++++++ support/support.h | 6 ++++ sysdeps/generic/dl-get_r_debug.h | 28 +++++++++++++++++ 15 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 support/get_r_debug.c create mode 100644 sysdeps/generic/dl-get_r_debug.h diff --git a/elf/Makefile b/elf/Makefile index d05f410592..a4d3db922b 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -609,6 +609,8 @@ $(objpfx)ld.so: $(objpfx)librtld.os $(ld-map) $(call after-link,$@.new) $(READELF) -s $@.new \ | $(AWK) '($$7 ~ /^UND(|EF)$$/ && $$1 != "0:" && $$4 != "REGISTER") { print; p=1 } END { exit p != 0 }' + $(READELF) -rW $@.new \ + | $(AWK) '($$5 ~/_r_debug/) { print; p=1 } END { exit p != 0 }' mv -f $@.new $@ ifeq (yes,$(build-shared)) diff --git a/elf/circleload1.c b/elf/circleload1.c index 990ff84a84..e1ff8e272b 100644 --- a/elf/circleload1.c +++ b/elf/circleload1.c @@ -4,6 +4,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/dl-debug.c b/elf/dl-debug.c index 2cd5f09753..a70ba7abb7 100644 --- a/elf/dl-debug.c +++ b/elf/dl-debug.c @@ -17,7 +17,7 @@ . */ #include - +#include /* These are the members in the public `struct link_map' type. Sanity check that the internal type and the public type match. */ @@ -36,9 +36,27 @@ extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr) to examine and it looks for this particular symbol name. */ struct r_debug _r_debug; +extern struct r_debug _r_debug_internal attribute_hidden; +strong_alias (_r_debug, _r_debug_internal) + +/* Define ABI_rtld_GLIBC_2_35 from ABI_rtld_GLIBC_2_34 if there are no + symbols in GLIBC_2.35 when this macro was first used. */ +#ifndef ABI_rtld_GLIBC_2_35 +# define ABI_rtld_GLIBC_2_35 ABI_rtld_GLIBC_2_34 +#endif + +/* The latest ABI of _r_debug is GLIBC_2.33 in RV32 of RISC-V. */ +#if ABI_rtld_GLIBC_2_35 != ABI_rtld_GLIBC_2_34 +# error ABI_rtld_GLIBC_2_35 != ABI_rtld_GLIBC_2_34 +#endif + +#if SHLIB_COMPAT (rtld, GLIBC_2_0, GLIBC_2_35) +strong_alias (_r_debug, _r_debug_compat) +compat_symbol (rtld, _r_debug_compat, _r_debug, GLIBC_2_0); +#endif -/* Initialize _r_debug if it has not already been done. The argument is - the run-time load address of the dynamic linker, to be put in +/* Initialize _r_debug if it has not already been done. The argument + is the run-time load address of the dynamic linker, to be put in _r_debug.r_ldbase. Returns the address of _r_debug. */ struct r_debug * @@ -47,7 +65,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) struct r_debug *r; if (ns == LM_ID_BASE) - r = &_r_debug; + r = &_r_debug_internal; else r = &GL(dl_ns)[ns]._ns_debug; @@ -55,7 +73,7 @@ _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns) { /* Tell the debugger where to find the map of loaded objects. */ r->r_version = 1 /* R_DEBUG_VERSION XXX */; - r->r_ldbase = ldbase ?: _r_debug.r_ldbase; + r->r_ldbase = ldbase ?: _r_debug_internal.r_ldbase; r->r_map = (void *) GL(dl_ns)[ns]._ns_loaded; r->r_brk = (ElfW(Addr)) &_dl_debug_state; } diff --git a/elf/link.h b/elf/link.h index ff3a85c847..3431142d10 100644 --- a/elf/link.h +++ b/elf/link.h @@ -63,9 +63,6 @@ struct r_debug ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ }; -/* This is the instance of that structure used by the dynamic linker. */ -extern struct r_debug _r_debug; - /* This symbol refers to the "dynamic structure" in the `.dynamic' section of whatever module refers to `_DYNAMIC'. So, to find its own `struct r_debug', a program could do: diff --git a/elf/loadtest.c b/elf/loadtest.c index b5eab5e93c..9c507e8802 100644 --- a/elf/loadtest.c +++ b/elf/loadtest.c @@ -6,6 +6,7 @@ #include #include #include +#include /* How many load/unload operations do we do. */ diff --git a/elf/neededtest.c b/elf/neededtest.c index 3cea499314..252e193dca 100644 --- a/elf/neededtest.c +++ b/elf/neededtest.c @@ -4,6 +4,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/neededtest2.c b/elf/neededtest2.c index 17c75f2ba3..129c2ac486 100644 --- a/elf/neededtest2.c +++ b/elf/neededtest2.c @@ -4,6 +4,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/neededtest3.c b/elf/neededtest3.c index 41970cf2c7..5f6940fcbe 100644 --- a/elf/neededtest3.c +++ b/elf/neededtest3.c @@ -4,6 +4,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/neededtest4.c b/elf/neededtest4.c index 0ae0b7ff47..50a88e8835 100644 --- a/elf/neededtest4.c +++ b/elf/neededtest4.c @@ -4,6 +4,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/unload.c b/elf/unload.c index 4566f226f8..35c8a03f79 100644 --- a/elf/unload.c +++ b/elf/unload.c @@ -8,6 +8,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/elf/unload2.c b/elf/unload2.c index eef2bfd426..9e8b26ec55 100644 --- a/elf/unload2.c +++ b/elf/unload2.c @@ -5,6 +5,7 @@ #include #include #include +#include #define MAPS ((struct link_map *) _r_debug.r_map) diff --git a/support/Makefile b/support/Makefile index a462781718..5b6d5bb23a 100644 --- a/support/Makefile +++ b/support/Makefile @@ -32,6 +32,7 @@ libsupport-routines = \ check_hostent \ check_netent \ delayed_exit \ + get_r_debug \ ignore_stderr \ next_to_fault \ oom_error \ diff --git a/support/get_r_debug.c b/support/get_r_debug.c new file mode 100644 index 0000000000..2bc30022fe --- /dev/null +++ b/support/get_r_debug.c @@ -0,0 +1,54 @@ +/* Return a pointer to _r_debug, the internal debug structure in the + dynamic linker. + Copyright (C) 2021 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 + +/* Get a pointer to _r_debug. */ + +static int +callback (struct dl_phdr_info *info, size_t size, void *data) +{ + const ElfW(Phdr) *phdr = info->dlpi_phdr; + ElfW(Dyn) *d; + int n; + struct r_debug **debugp = (struct r_debug **) data; + + for (n = info->dlpi_phnum; --n >= 0; phdr++) + if (phdr->p_type == PT_DYNAMIC) + { + d = (void *) (info->dlpi_addr + phdr->p_vaddr); + struct r_debug *debug = dl_get_r_debug (d); + if (debug != NULL) + { + *debugp = debug; + return 1; + } + } + + return 0; +} + +struct r_debug * +get_r_debug (void) +{ + struct r_debug *debug = NULL; + dl_iterate_phdr (callback, &debug); + return debug; +} diff --git a/support/support.h b/support/support.h index 834dba9097..6d00e4c46e 100644 --- a/support/support.h +++ b/support/support.h @@ -33,6 +33,8 @@ #include /* For locale_t. */ #include +/* For struct r_debug. */ +#include __BEGIN_DECLS @@ -193,6 +195,10 @@ struct support_stack support_stack_alloc (size_t size); /* Deallocate the STACK. */ void support_stack_free (struct support_stack *stack); +/* Get a pointer to _r_debug. */ +struct r_debug *get_r_debug (void); +#define _r_debug (*get_r_debug ()) + __END_DECLS #endif /* SUPPORT_H */ diff --git a/sysdeps/generic/dl-get_r_debug.h b/sysdeps/generic/dl-get_r_debug.h new file mode 100644 index 0000000000..2595ec2ba9 --- /dev/null +++ b/sysdeps/generic/dl-get_r_debug.h @@ -0,0 +1,28 @@ +/* Get a pointer to _r_debug from PT_DYNAMIC. + Copyright (C) 2021 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 + . */ + +/* Return the value in DT_DEBUG. */ + +struct r_debug * +dl_get_r_debug (ElfW(Dyn) *d) +{ + for (; d->d_tag != DT_NULL; ++d) + if (d->d_tag == DT_DEBUG) + return (struct r_debug *) d->d_un.d_val; + return NULL; +}