327 lines
11 KiB
Diff
327 lines
11 KiB
Diff
From 6676e967dba405ca31d57b63e096becd13d4a200 Mon Sep 17 00:00:00 2001
|
|
From: Rahul Chaudhry <rahulchaudhry@chromium.org>
|
|
Date: Thu, 15 Mar 2018 14:30:17 -0700
|
|
Subject: [PATCH 4/8] sys-libs/glibc: add support for SHT_RELR sections.
|
|
|
|
This patch adds experimental support for SHT_RELR sections, proposed
|
|
here: https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
|
|
|
|
SHT_RELR sections are supported for arm, aarch64, and x86_64 targets.
|
|
To enable them, pass '--experimental-use-relr' flag to gold.
|
|
|
|
Definitions for the new ELF section type and dynamic array tags, as well
|
|
as the encoding used in the new section are all under discussion and are
|
|
subject to change. We plan to send the patch upstream after the gABI has
|
|
been updated to include the new definitions.
|
|
|
|
[Adrian: forward-ported to glibc 2.32]
|
|
---
|
|
elf/do-rel.h | 41 ++++++++++++++++++++++++++++++++++--
|
|
elf/dynamic-link.h | 15 +++++++++++++
|
|
elf/elf.h | 15 +++++++++++--
|
|
elf/get-dynamic-info.h | 7 ++++++
|
|
sysdeps/aarch64/dl-machine.h | 10 +++++++++
|
|
sysdeps/arm/dl-machine.h | 10 +++++++++
|
|
sysdeps/i386/dl-machine.h | 10 +++++++++
|
|
sysdeps/x86_64/dl-machine.h | 10 +++++++++
|
|
8 files changed, 114 insertions(+), 4 deletions(-)
|
|
|
|
--- a/elf/do-rel.h
|
|
+++ b/elf/do-rel.h
|
|
@@ -28,6 +28,12 @@
|
|
# define elf_machine_rel_relative elf_machine_rela_relative
|
|
#endif
|
|
|
|
+#ifdef DO_RELR
|
|
+# define elf_dynamic_do_Rel elf_dynamic_do_Relr
|
|
+# define Rel Relr
|
|
+# define elf_machine_rel_relative elf_machine_relr_relative
|
|
+#endif
|
|
+
|
|
#ifndef DO_ELF_MACHINE_REL_RELATIVE
|
|
# define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
|
|
elf_machine_rel_relative (l_addr, relative, \
|
|
@@ -48,12 +54,12 @@ elf_dynamic_do_Rel (struct link_map *map
|
|
const ElfW(Rel) *r = (const void *) reladdr;
|
|
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
|
|
ElfW(Addr) l_addr = map->l_addr;
|
|
-# if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
|
|
+# if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP && !defined DO_RELR
|
|
const ElfW(Rel) *r2 = NULL;
|
|
const ElfW(Rel) *end2 = NULL;
|
|
# endif
|
|
|
|
-#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP
|
|
+#if (!defined DO_RELA || !defined ELF_MACHINE_PLT_REL) && !defined RTLD_BOOTSTRAP && !defined DO_RELR
|
|
/* We never bind lazily during ld.so bootstrap. Unfortunately gcc is
|
|
not clever enough to see through all the function calls to realize
|
|
that. */
|
|
@@ -82,8 +88,10 @@ elf_dynamic_do_Rel (struct link_map *map
|
|
else
|
|
#endif
|
|
{
|
|
+# if !defined DO_RELR
|
|
const ElfW(Sym) *const symtab =
|
|
(const void *) D_PTR (map, l_info[DT_SYMTAB]);
|
|
+# endif
|
|
const ElfW(Rel) *relative = r;
|
|
r += nrelative;
|
|
|
|
@@ -110,9 +118,36 @@ elf_dynamic_do_Rel (struct link_map *map
|
|
if (l_addr != 0 || ! map->l_info[VALIDX(DT_GNU_PRELINKED)])
|
|
# endif
|
|
#endif
|
|
+
|
|
+#ifdef DO_RELR
|
|
+ {
|
|
+ ElfW(Addr) base = 0;
|
|
+ for (; relative < end; ++relative)
|
|
+ {
|
|
+ ElfW(Relr) entry = *relative;
|
|
+ if ((entry&1) == 0)
|
|
+ {
|
|
+ elf_machine_relr_relative (l_addr, scope, (void *) (l_addr + entry));
|
|
+ base = entry + sizeof(ElfW(Addr));
|
|
+ continue;
|
|
+ }
|
|
+ ElfW(Addr) offset = base;
|
|
+ while (entry != 0)
|
|
+ {
|
|
+ entry >>= 1;
|
|
+ if ((entry&1) != 0)
|
|
+ elf_machine_relr_relative (l_addr, scope, (void *) (l_addr + offset));
|
|
+ offset += sizeof(ElfW(Addr));
|
|
+ }
|
|
+ base += (8*sizeof(ElfW(Addr)) - 1) * sizeof(ElfW(Addr));
|
|
+ }
|
|
+ }
|
|
+#else
|
|
for (; relative < r; ++relative)
|
|
DO_ELF_MACHINE_REL_RELATIVE (map, l_addr, relative);
|
|
+#endif
|
|
|
|
+#if !defined DO_RELR
|
|
#ifdef RTLD_BOOTSTRAP
|
|
/* The dynamic linker always uses versioning. */
|
|
assert (map->l_info[VERSYMIDX (DT_VERSYM)] != NULL);
|
|
@@ -211,6 +246,7 @@ elf_dynamic_do_Rel (struct link_map *map
|
|
# endif
|
|
}
|
|
#endif
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
@@ -220,3 +256,4 @@ elf_dynamic_do_Rel (struct link_map *map
|
|
#undef elf_machine_rel_relative
|
|
#undef DO_ELF_MACHINE_REL_RELATIVE
|
|
#undef DO_RELA
|
|
+#undef DO_RELR
|
|
--- a/elf/dynamic-link.h
|
|
+++ b/elf/dynamic-link.h
|
|
@@ -50,6 +50,11 @@ static inline void __attribute__((always_i
|
|
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
|
|
void *const reloc_addr);
|
|
# endif
|
|
+# if ! ELF_MACHINE_NO_RELR
|
|
+static inline void __attribute__((always_inline))
|
|
+elf_machine_relr_relative (ElfW(Addr) l_addr, struct r_scope_elem *scope[],
|
|
+ void *const reloc_addr);
|
|
+# endif
|
|
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
|
|
static inline void __attribute__((always_inline))
|
|
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
|
|
@@ -146,6 +151,15 @@ elf_machine_lazy_rel (struct link_map *m
|
|
# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
|
# endif
|
|
|
|
+# if ! ELF_MACHINE_NO_RELR
|
|
+# define DO_RELR
|
|
+# include "do-rel.h"
|
|
+# define ELF_DYNAMIC_DO_RELR(map, scope, lazy, skip_ifunc) \
|
|
+ _ELF_DYNAMIC_DO_RELOC (RELR, Relr, map, scope, lazy, skip_ifunc, 1)
|
|
+# else
|
|
+# define ELF_DYNAMIC_DO_RELR(map, scope, lazy, skip_ifunc) /* Nothing to do. */
|
|
+# endif
|
|
+
|
|
/* This can't just be an inline function because GCC is too dumb
|
|
to inline functions containing inlines themselves. */
|
|
# define ELF_DYNAMIC_RELOCATE(map, scope, lazy, consider_profile, skip_ifunc) \
|
|
@@ -154,6 +168,7 @@ elf_machine_lazy_rel (struct link_map *m
|
|
(consider_profile)); \
|
|
ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
|
|
ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
|
|
+ ELF_DYNAMIC_DO_RELR ((map), (scope), edr_lazy, skip_ifunc); \
|
|
} while (0)
|
|
|
|
#endif
|
|
--- a/elf/elf.h
|
|
+++ b/elf/elf.h
|
|
@@ -443,7 +443,8 @@ typedef struct
|
|
#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
|
|
#define SHT_GROUP 17 /* Section group */
|
|
#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */
|
|
-#define SHT_NUM 19 /* Number of defined types. */
|
|
+#define SHT_RELR 19 /* Relative relocation, only offsets */
|
|
+#define SHT_NUM 20 /* Number of defined types. */
|
|
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
|
|
#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
|
|
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
|
|
@@ -662,6 +663,12 @@ typedef struct
|
|
Elf64_Sxword r_addend; /* Addend */
|
|
} Elf64_Rela;
|
|
|
|
+/* Relocation table entry for relative (in section of type SHT_RELR). */
|
|
+
|
|
+typedef Elf32_Word Elf32_Relr; /* offset/bitmap for relative relocations */
|
|
+
|
|
+typedef Elf64_Xword Elf64_Relr; /* offset/bitmap for relative relocations */
|
|
+
|
|
/* How to extract and insert information held in the r_info field. */
|
|
|
|
#define ELF32_R_SYM(val) ((val) >> 8)
|
|
@@ -887,7 +894,10 @@ typedef struct
|
|
#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
|
|
#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
|
|
#define DT_SYMTAB_SHNDX 34 /* Address of SYMTAB_SHNDX section */
|
|
-#define DT_NUM 35 /* Number used */
|
|
+#define DT_RELRSZ 35
|
|
+#define DT_RELR 36
|
|
+#define DT_RELRENT 37
|
|
+#define DT_NUM 38 /* Number used */
|
|
#define DT_LOOS 0x6000000d /* Start of OS-specific */
|
|
#define DT_HIOS 0x6ffff000 /* End of OS-specific */
|
|
#define DT_LOPROC 0x70000000 /* Start of processor-specific */
|
|
@@ -939,6 +949,7 @@ typedef struct
|
|
GNU extension. */
|
|
#define DT_VERSYM 0x6ffffff0
|
|
|
|
+#define DT_RELRCOUNT 0x6ffffff8
|
|
#define DT_RELACOUNT 0x6ffffff9
|
|
#define DT_RELCOUNT 0x6ffffffa
|
|
|
|
--- a/elf/get-dynamic-info.h
|
|
+++ b/elf/get-dynamic-info.h
|
|
@@ -89,6 +89,9 @@ elf_get_dynamic_info (struct link_map *l
|
|
# if ! ELF_MACHINE_NO_REL
|
|
ADJUST_DYN_INFO (DT_REL);
|
|
# endif
|
|
+# if ! ELF_MACHINE_NO_RELR
|
|
+ ADJUST_DYN_INFO (DT_RELR);
|
|
+#endif
|
|
ADJUST_DYN_INFO (DT_JMPREL);
|
|
ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
|
|
ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
|
|
@@ -113,6 +116,10 @@ elf_get_dynamic_info (struct link_map *l
|
|
if (info[DT_REL] != NULL)
|
|
assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel)));
|
|
#endif
|
|
+#if ! ELF_MACHINE_NO_RELR
|
|
+ if (info[DT_RELR] != NULL)
|
|
+ assert (info[DT_RELRENT]->d_un.d_val == sizeof (ElfW(Relr)));
|
|
+# endif
|
|
if (bootstrap || static_pie_bootstrap)
|
|
{
|
|
assert (info[DT_RUNPATH] == NULL);
|
|
--- a/sysdeps/aarch64/dl-machine.h
|
|
+++ b/sysdeps/aarch64/dl-machine.h
|
|
@@ -384,6 +385,15 @@ elf_machine_rela_relative (ElfW(Addr) l_
|
|
}
|
|
|
|
static inline void
|
|
+__attribute__ ((always_inline))
|
|
+elf_machine_relr_relative (ElfW(Addr) l_addr, struct r_scope_elem *scope[],
|
|
+ void *const reloc_addr_arg)
|
|
+{
|
|
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
|
|
+ *reloc_addr += l_addr;
|
|
+}
|
|
+
|
|
+static inline void
|
|
__attribute__ ((always_inline))
|
|
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
|
|
ElfW(Addr) l_addr,
|
|
--- a/sysdeps/arm/dl-machine.h
|
|
+++ b/sysdeps/arm/dl-machine.h
|
|
@@ -637,6 +638,15 @@ elf_machine_rel_relative (Elf32_Addr l_a
|
|
*reloc_addr += l_addr;
|
|
}
|
|
|
|
+static inline void
|
|
+__attribute ((always_inline))
|
|
+elf_machine_relr_relative (ElfW(Addr) l_addr, struct r_scope_elem *scope[],
|
|
+ void *const reloc_addr_arg)
|
|
+{
|
|
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
|
|
+ *reloc_addr += l_addr;
|
|
+}
|
|
+
|
|
# ifndef RTLD_BOOTSTRAP
|
|
static inline void
|
|
__attribute__ ((always_inline))
|
|
--- a/sysdeps/i386/dl-machine.h
|
|
+++ b/sysdeps/i386/dl-machine.h
|
|
@@ -626,6 +626,15 @@ elf_machine_rel_relative (Elf32_Addr l_a
|
|
*reloc_addr += l_addr;
|
|
}
|
|
|
|
+static inline void
|
|
+__attribute ((always_inline))
|
|
+elf_machine_relr_relative (ElfW(Addr) l_addr, struct r_scope_elem *scope[],
|
|
+ void *const reloc_addr_arg)
|
|
+{
|
|
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
|
|
+ *reloc_addr += l_addr;
|
|
+}
|
|
+
|
|
# ifndef RTLD_BOOTSTRAP
|
|
static inline void
|
|
__attribute__ ((always_inline))
|
|
--- a/sysdeps/x86_64/dl-machine.h
|
|
+++ b/sysdeps/x86_64/dl-machine.h
|
|
@@ -545,6 +546,15 @@ elf_machine_rela_relative (ElfW(Addr) l_
|
|
}
|
|
|
|
static inline void
|
|
+__attribute ((always_inline))
|
|
+elf_machine_relr_relative (ElfW(Addr) l_addr, struct r_scope_elem *scope[],
|
|
+ void *const reloc_addr_arg)
|
|
+{
|
|
+ ElfW(Addr) *const reloc_addr = reloc_addr_arg;
|
|
+ *reloc_addr += l_addr;
|
|
+}
|
|
+
|
|
+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,
|
|
--- a/sysdeps/arm/dl-machine-rel.h 2022-02-03 05:27:54.000000000 +0000
|
|
+++ b/sysdeps/arm/dl-machine-rel.h 2022-04-11 10:16:03.103743770 +0000
|
|
@@ -23,6 +23,7 @@
|
|
Prelinked libraries may use Elf32_Rela though. */
|
|
#define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
|
|
#define ELF_MACHINE_NO_REL 0
|
|
+#define ELF_MACHINE_NO_RELR 0
|
|
|
|
/* ARM never uses Elf32_Rela relocations for the dynamic linker.
|
|
Prelinked libraries may use Elf32_Rela though. */
|
|
--- a/sysdeps/generic/dl-machine-rel.h 2022-02-03 05:27:54.000000000 +0000
|
|
+++ b/sysdeps/generic/dl-machine-rel.h 2022-04-11 10:28:40.996539086 +0000
|
|
@@ -23,6 +23,7 @@
|
|
#define ELF_MACHINE_NO_REL 1
|
|
/* Defined if the architecture supports Elf{32,64}_Rela relocations. */
|
|
#define ELF_MACHINE_NO_RELA 0
|
|
+#define ELF_MACHINE_NO_RELR 0
|
|
/* Used to calculate the index of link_map l_reloc_result. */
|
|
#define PLTREL ElfW(Rela)
|
|
|
|
--- a/sysdeps/i386/dl-machine-rel.h 2022-02-03 05:27:54.000000000 +0000
|
|
+++ b/sysdeps/i386/dl-machine-rel.h 2022-04-11 10:16:17.677066810 +0000
|
|
@@ -23,6 +23,7 @@
|
|
Prelinked libraries may use Elf32_Rela though. */
|
|
#define ELF_MACHINE_NO_RELA defined RTLD_BOOTSTRAP
|
|
#define ELF_MACHINE_NO_REL 0
|
|
+#define ELF_MACHINE_NO_RELR 0
|
|
|
|
/* The i386 never uses Elf32_Rela relocations for the dynamic linker.
|
|
Prelinked libraries may use Elf32_Rela though. */
|