From 47cab0ec91e4e1699dd5729b54220453f89670b0 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 15 Jun 2025 11:38:54 +0800 Subject: [PATCH v2] elf: Add DL_ADDRESS_WITHOUT_RELOC [BZ #33088] Add DL_ADDRESS_WITHOUT_RELOC to force an address into a general purpose register to prevent loading it into a vector register directly before run-time relocation. Change _end from extern char _end[] attribute_hidden; to extern char _end attribute_hidden; so that DL_ADDRESS_WITHOUT_RELOC can be used to get its address. This is an updated fix for BZ #33088. Signed-off-by: H.J. Lu --- elf/dl-before-reloc.h | 22 ++++++++++++++++++++++ elf/rtld.c | 12 ++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 elf/dl-before-reloc.h diff --git a/elf/dl-before-reloc.h b/elf/dl-before-reloc.h new file mode 100644 index 0000000000..d2ebbcaa52 --- /dev/null +++ b/elf/dl-before-reloc.h @@ -0,0 +1,22 @@ +/* Facilities before run-time relocation. + Copyright (C) 2025 Free Software Foundation, Inc. + Copyright The GNU Toolchain Authors. + 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 + . */ + +/* Get the address VAR before run-time relocation. */ +#define DL_ADDRESS_WITHOUT_RELOC(var) \ + ({ __typeof (var) _result = var; asm ("" : "+r"(_result)); _result; }) diff --git a/elf/rtld.c b/elf/rtld.c index e6a181dc31..136858101f 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -428,7 +429,7 @@ static ElfW(Addr) _dl_start_final (void *arg, /* These are defined magically by the linker. */ extern const ElfW(Ehdr) __ehdr_start attribute_hidden; -extern char _end[] attribute_hidden; +extern char _end attribute_hidden; #ifdef RTLD_START @@ -476,11 +477,10 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) #endif _dl_setup_hash (&_dl_rtld_map); _dl_rtld_map.l_real = &_dl_rtld_map; - _dl_rtld_map.l_map_start = (ElfW(Addr)) &__ehdr_start; - /* Prevent run-time relocations against __ehdr_start and _end. */ - asm ("" : "+g" (_dl_rtld_map.l_map_start)); - _dl_rtld_map.l_map_end = (ElfW(Addr)) _end; - asm ("" : "+g" (_dl_rtld_map.l_map_end)); + _dl_rtld_map.l_map_start + = (ElfW(Addr)) DL_ADDRESS_WITHOUT_RELOC (&__ehdr_start); + _dl_rtld_map.l_map_end + = (ElfW(Addr)) DL_ADDRESS_WITHOUT_RELOC (&_end); /* Copy the TLS related data if necessary. */ #ifndef DONT_USE_BOOTSTRAP_MAP # if NO_TLS_OFFSET != 0 -- 2.49.0