From 0d65225a02967d02ec2aae02600f8578affc4ec1 Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Wed, 13 Oct 2021 09:49:34 -0300 Subject: [PATCH] elf: Fix dynamic-link.h usage on rtld.c The 4af6982e4c fix does not fully handle RTLD_BOOTSTRAP usage on rtld.c, since RTLD_BOOTSTRAP is also used on dl-machine.h on various architectures to have diferent semantics for relocation functions. This patch now includes dynamic-link.h and get-dynamic-info.h once and with RTLD_BOOTSTRAP defined. The ELF_DYNAMIC_RELOCATE calls will now call all relocation functions with expected semantic. To reorganize the include some static TLS definition is moved to its own header since it is defined on dynamic-link.h and dl-machine.h requires it (and it creates a circular dependendy that required to include dynamic-link.h twice in rtld.c). The powerpc Elf64_FuncDesc is also moved to its own header, since csu code required its definition (which would require either include elf/ folder or add a full path). Checked on x86_64, i686, aarch64, armhf, powerpc64, powerpc32, and powerpc64le. --- elf/dl-static-tls.h | 51 +++++++++++++++++++++ elf/dynamic-link.h | 33 +------------ elf/rtld.c | 19 ++++---- sysdeps/aarch64/dl-machine.h | 3 +- sysdeps/alpha/dl-machine.h | 2 +- sysdeps/arc/dl-machine.h | 5 +- sysdeps/arm/dl-machine.h | 1 + sysdeps/csky/dl-machine.h | 1 + sysdeps/generic/dl-machine.h | 1 + sysdeps/hppa/dl-machine.h | 1 + sysdeps/i386/dl-machine.h | 1 + sysdeps/ia64/dl-machine.h | 1 + sysdeps/m68k/dl-machine.h | 1 + sysdeps/microblaze/dl-machine.h | 1 + sysdeps/mips/dl-machine.h | 1 + sysdeps/nios2/dl-machine.h | 1 + sysdeps/powerpc/powerpc32/dl-machine.h | 1 + sysdeps/powerpc/powerpc64/dl-funcdesc.h | 34 ++++++++++++++ sysdeps/powerpc/powerpc64/dl-irel.h | 2 +- sysdeps/powerpc/powerpc64/dl-machine.h | 14 +----- sysdeps/riscv/dl-machine.h | 1 + sysdeps/s390/s390-32/dl-machine.h | 1 + sysdeps/s390/s390-64/dl-machine.h | 1 + sysdeps/sh/dl-machine.h | 1 + sysdeps/sparc/sparc32/dl-machine.h | 1 + sysdeps/sparc/sparc64/dl-machine.h | 1 + sysdeps/unix/sysv/linux/powerpc/libc-vdso.h | 2 +- sysdeps/x86_64/dl-machine.h | 1 + 28 files changed, 123 insertions(+), 60 deletions(-) create mode 100644 elf/dl-static-tls.h create mode 100644 sysdeps/powerpc/powerpc64/dl-funcdesc.h diff --git a/elf/dl-static-tls.h b/elf/dl-static-tls.h new file mode 100644 index 0000000000..730924fc01 --- /dev/null +++ b/elf/dl-static-tls.h @@ -0,0 +1,51 @@ +/* Inline functions for dynamic linking. + Copyright (C) 1995-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 + . */ + +#ifndef _DL_STATIC_TLS_H +#define _DL_STATIC_TLS_H + +/* This macro is used as a callback from elf_machine_rel{a,} when a + static TLS reloc is about to be performed. Since (in dl-load.c) we + permit dynamic loading of objects that might use such relocs, we + have to check whether each use is actually doable. If the object + whose TLS segment the reference resolves to was allocated space in + the static TLS block at startup, then it's ok. Otherwise, we make + an attempt to allocate it in surplus space on the fly. If that + can't be done, we fall back to the error that DF_STATIC_TLS is + intended to produce. */ +#define HAVE_STATIC_TLS(map, sym_map) \ + (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET \ + && ((sym_map)->l_tls_offset \ + != FORCED_DYNAMIC_TLS_OFFSET), 1)) + +#define CHECK_STATIC_TLS(map, sym_map) \ + do { \ + if (!HAVE_STATIC_TLS (map, sym_map)) \ + _dl_allocate_static_tls (sym_map); \ + } while (0) + +#define TRY_STATIC_TLS(map, sym_map) \ + (__builtin_expect ((sym_map)->l_tls_offset \ + != FORCED_DYNAMIC_TLS_OFFSET, 1) \ + && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \ + || _dl_try_allocate_static_tls (sym_map, true) == 0)) + +int _dl_try_allocate_static_tls (struct link_map *map, bool optional) + attribute_hidden; + +#endif diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index 21cdfc88bb..ac4cc70dea 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -16,35 +16,7 @@ License along with the GNU C Library; if not, see . */ -/* This macro is used as a callback from elf_machine_rel{a,} when a - static TLS reloc is about to be performed. Since (in dl-load.c) we - permit dynamic loading of objects that might use such relocs, we - have to check whether each use is actually doable. If the object - whose TLS segment the reference resolves to was allocated space in - the static TLS block at startup, then it's ok. Otherwise, we make - an attempt to allocate it in surplus space on the fly. If that - can't be done, we fall back to the error that DF_STATIC_TLS is - intended to produce. */ -#define HAVE_STATIC_TLS(map, sym_map) \ - (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET \ - && ((sym_map)->l_tls_offset \ - != FORCED_DYNAMIC_TLS_OFFSET), 1)) - -#define CHECK_STATIC_TLS(map, sym_map) \ - do { \ - if (!HAVE_STATIC_TLS (map, sym_map)) \ - _dl_allocate_static_tls (sym_map); \ - } while (0) - -#define TRY_STATIC_TLS(map, sym_map) \ - (__builtin_expect ((sym_map)->l_tls_offset \ - != FORCED_DYNAMIC_TLS_OFFSET, 1) \ - && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \ - || _dl_try_allocate_static_tls (sym_map, true) == 0)) - -int _dl_try_allocate_static_tls (struct link_map *map, bool optional) - attribute_hidden; - +#include #include #ifdef RESOLVE_MAP @@ -91,9 +63,6 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], # endif #endif -#include - - #ifdef RESOLVE_MAP # if defined RTLD_BOOTSTRAP || defined STATIC_PIE_BOOTSTRAP diff --git a/elf/rtld.c b/elf/rtld.c index fe5ee9ec4d..b77aaaa733 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -32,7 +32,6 @@ #include #include #include -#include "dynamic-link.h" #include #include #include @@ -53,6 +52,15 @@ #include +/* This #define produces dynamic linking inline functions for + bootstrap relocation instead of general-purpose relocation. + Since ld.so must not have any undefined symbols the result + is trivial: always the map of ld.so itself. */ +#define RTLD_BOOTSTRAP +#define RESOLVE_MAP(map, scope, sym, version, flags) map +#include "dynamic-link.h" +#include "get-dynamic-info.h" + /* Only enables rtld profiling for architectures which provides non generic hp-timing support. The generic support requires either syscall (clock_gettime), which will incur in extra overhead on loading time. @@ -507,15 +515,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info) # define bootstrap_map info.l #endif - /* This #define produces dynamic linking inline functions for - bootstrap relocation instead of general-purpose relocation. - Since ld.so must not have any undefined symbols the result - is trivial: always the map of ld.so itself. */ -#define RTLD_BOOTSTRAP -#define RESOLVE_MAP(map, scope, sym, version, flags) map -#include "get-dynamic-info.h" -#include "dynamic-link.h" - static ElfW(Addr) __attribute_used__ _dl_start (void *arg) { diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h index e30e81c902..e7b91d6530 100644 --- a/sysdeps/aarch64/dl-machine.h +++ b/sysdeps/aarch64/dl-machine.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -370,7 +371,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], } } -inline void +static inline void __attribute__ ((always_inline)) elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h index 491541326f..b9afa4546f 100644 --- a/sysdeps/alpha/dl-machine.h +++ b/sysdeps/alpha/dl-machine.h @@ -25,7 +25,7 @@ #define ELF_MACHINE_NAME "alpha" #include - +#include /* Mask identifying addresses reserved for the user program, where the dynamic linker should not map anything. */ diff --git a/sysdeps/arc/dl-machine.h b/sysdeps/arc/dl-machine.h index 4b64ffec25..20496ce1d1 100644 --- a/sysdeps/arc/dl-machine.h +++ b/sysdeps/arc/dl-machine.h @@ -30,6 +30,7 @@ #include #include #include +#include /* Dynamic Linking ABI for ARCv2 ISA. @@ -318,7 +319,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[], } } -inline void +static inline void __attribute__ ((always_inline)) elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, void *const reloc_addr_arg) @@ -327,7 +328,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, *reloc_addr += l_addr; } -inline void +static inline void __attribute__ ((always_inline)) elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[], ElfW(Addr) l_addr, const ElfW(Rela) *reloc, diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h index dfa05eee44..20c0653e82 100644 --- a/sysdeps/arm/dl-machine.h +++ b/sysdeps/arm/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef CLEAR_CACHE # error CLEAR_CACHE definition required to handle TEXTREL diff --git a/sysdeps/csky/dl-machine.h b/sysdeps/csky/dl-machine.h index ec22f87577..47e8e592d2 100644 --- a/sysdeps/csky/dl-machine.h +++ b/sysdeps/csky/dl-machine.h @@ -24,6 +24,7 @@ #include #include #include +#include /* Return nonzero if ELF header is compatible with the running host. */ static inline int diff --git a/sysdeps/generic/dl-machine.h b/sysdeps/generic/dl-machine.h index 4a4ab4fc70..6fc61a2591 100644 --- a/sysdeps/generic/dl-machine.h +++ b/sysdeps/generic/dl-machine.h @@ -20,6 +20,7 @@ #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h index e6a4575fce..3a7e20a4a7 100644 --- a/sysdeps/hppa/dl-machine.h +++ b/sysdeps/hppa/dl-machine.h @@ -29,6 +29,7 @@ #include #include #include +#include /* These two definitions must match the definition of the stub in bfd/elf32-hppa.c (see plt_stub[]). diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 78bed03eee..94056142e4 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int __attribute__ ((unused)) diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h index 2217d0b556..a53101a02f 100644 --- a/sysdeps/ia64/dl-machine.h +++ b/sysdeps/ia64/dl-machine.h @@ -27,6 +27,7 @@ #include #include #include +#include /* Translate a processor specific dynamic tag to the index in l_info array. */ diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h index 5e34c4784e..8e20139c42 100644 --- a/sysdeps/m68k/dl-machine.h +++ b/sysdeps/m68k/dl-machine.h @@ -24,6 +24,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int diff --git a/sysdeps/microblaze/dl-machine.h b/sysdeps/microblaze/dl-machine.h index 3fd4988e60..188d3340ee 100644 --- a/sysdeps/microblaze/dl-machine.h +++ b/sysdeps/microblaze/dl-machine.h @@ -23,6 +23,7 @@ #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h index f8d1298b60..15e8de551b 100644 --- a/sysdeps/mips/dl-machine.h +++ b/sysdeps/mips/dl-machine.h @@ -32,6 +32,7 @@ #include #include #include +#include /* The offset of gp from GOT might be system-dependent. It's set by ld. The same value is also */ diff --git a/sysdeps/nios2/dl-machine.h b/sysdeps/nios2/dl-machine.h index 4de602b13d..efc0bcece9 100644 --- a/sysdeps/nios2/dl-machine.h +++ b/sysdeps/nios2/dl-machine.h @@ -24,6 +24,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h index cda012dc1b..01b18ca536 100644 --- a/sysdeps/powerpc/powerpc32/dl-machine.h +++ b/sysdeps/powerpc/powerpc32/dl-machine.h @@ -25,6 +25,7 @@ #include #include #include +#include /* Translate a processor specific dynamic tag to the index in l_info array. */ diff --git a/sysdeps/powerpc/powerpc64/dl-funcdesc.h b/sysdeps/powerpc/powerpc64/dl-funcdesc.h new file mode 100644 index 0000000000..b2d1f76ce0 --- /dev/null +++ b/sysdeps/powerpc/powerpc64/dl-funcdesc.h @@ -0,0 +1,34 @@ +/* PowerPC ELFv1 function descriptor definition. + Copyright (C) 2009-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 + . */ + +#ifndef _DL_FUNCDESC_H +#define _DL_FUNCDESC_H + +#if _CALL_ELF != 2 +/* A PowerPC64 function descriptor. The .plt (procedure linkage + table) and .opd (official procedure descriptor) sections are + arrays of these. */ +typedef struct +{ + Elf64_Addr fd_func; + Elf64_Addr fd_toc; + Elf64_Addr fd_aux; +} Elf64_FuncDesc; +#endif + +#endif diff --git a/sysdeps/powerpc/powerpc64/dl-irel.h b/sysdeps/powerpc/powerpc64/dl-irel.h index 0e11b7ff64..aa9a2dca71 100644 --- a/sysdeps/powerpc/powerpc64/dl-irel.h +++ b/sysdeps/powerpc/powerpc64/dl-irel.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #define ELF_MACHINE_IRELA 1 diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h index 3f92fbb369..635cb45dcc 100644 --- a/sysdeps/powerpc/powerpc64/dl-machine.h +++ b/sysdeps/powerpc/powerpc64/dl-machine.h @@ -28,23 +28,13 @@ #include #include #include +#include +#include /* Translate a processor specific dynamic tag to the index in l_info array. */ #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM) -#if _CALL_ELF != 2 -/* A PowerPC64 function descriptor. The .plt (procedure linkage - table) and .opd (official procedure descriptor) sections are - arrays of these. */ -typedef struct -{ - Elf64_Addr fd_func; - Elf64_Addr fd_toc; - Elf64_Addr fd_aux; -} Elf64_FuncDesc; -#endif - #define ELF_MULT_MACHINES_SUPPORTED /* Return nonzero iff ELF header is compatible with the running host. */ diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h index e7289d7ddc..b8fdfde8c0 100644 --- a/sysdeps/riscv/dl-machine.h +++ b/sysdeps/riscv/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef _RTLD_PROLOGUE # define _RTLD_PROLOGUE(entry) \ diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h index cd16cc7e00..3c8054ae84 100644 --- a/sysdeps/s390/s390-32/dl-machine.h +++ b/sysdeps/s390/s390-32/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include /* This is an older, now obsolete value. */ #define EM_S390_OLD 0xA390 diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h index 0330a8d7de..9d9d0ea0d6 100644 --- a/sysdeps/s390/s390-64/dl-machine.h +++ b/sysdeps/s390/s390-64/dl-machine.h @@ -27,6 +27,7 @@ #include #include #include +#include #define ELF_MACHINE_IRELATIVE R_390_IRELATIVE diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h index 0c22dfd848..96fd894d40 100644 --- a/sysdeps/sh/dl-machine.h +++ b/sysdeps/sh/dl-machine.h @@ -24,6 +24,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int __attribute__ ((unused)) diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h index 6361cfae9e..a59c110460 100644 --- a/sysdeps/sparc/sparc32/dl-machine.h +++ b/sysdeps/sparc/sparc32/dl-machine.h @@ -28,6 +28,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h index 3fd18c6e5e..2289691689 100644 --- a/sysdeps/sparc/sparc64/dl-machine.h +++ b/sysdeps/sparc/sparc64/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include #define ELF64_R_TYPE_ID(info) ((info) & 0xff) #define ELF64_R_TYPE_DATA(info) ((info) >> 8) diff --git a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h index db388a022d..72b75d3beb 100644 --- a/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h +++ b/sysdeps/unix/sysv/linux/powerpc/libc-vdso.h @@ -24,7 +24,7 @@ #include #if (defined(__PPC64__) || defined(__powerpc64__)) && _CALL_ELF != 2 -# include +# include /* The correct solution is for _dl_vdso_vsym to return the address of the OPD for the kernel VDSO function. That address would then be stored in the __vdso_* variables and returned as the result of the IFUNC resolver function. diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 20afb0b4bc..33df0dd5fc 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -26,6 +26,7 @@ #include #include #include +#include /* Return nonzero iff ELF header is compatible with the running host. */ static inline int __attribute__ ((unused)) -- 2.30.2