From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7814) id 99958393A413; Wed, 12 Jan 2022 00:24:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 99958393A413 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Fangrui Song To: glibc-cvs@sourceware.org Subject: [glibc/google/grte/v5-2.27/master] elf: Support DT_RELR relative relocation format X-Act-Checkin: glibc X-Git-Author: Fangrui Song X-Git-Refname: refs/heads/google/grte/v5-2.27/master X-Git-Oldrev: c0a436544259c7aef8871c29731a48dc715039db X-Git-Newrev: 4feaf8a3a84df72b1e61a84a551272cad75bc16d Message-Id: <20220112002416.99958393A413@sourceware.org> Date: Wed, 12 Jan 2022 00:24:16 +0000 (GMT) X-BeenThere: glibc-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Glibc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 12 Jan 2022 00:24:16 -0000 https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=4feaf8a3a84df72b1e61a84a551272cad75bc16d commit 4feaf8a3a84df72b1e61a84a551272cad75bc16d Author: Fangrui Song Date: Tue Jan 11 16:20:39 2022 -0800 elf: Support DT_RELR relative relocation format Upstream patch: https://sourceware.org/pipermail/libc-alpha/2021-October/132029.html Bikeshedding: https://sourceware.org/pipermail/libc-alpha/2021-November/133009.html This commit removes configure.ac and test changes to avoid conflict when the upstream finally gets the feature. $(have-relr) is kept for local testing. To work around b/208156916, DT_NUM is not bumped. DT_RELR and DT_RELRSZ take the l_info slots at DT_VERSYM+1 and DT_VERSYM+2. Diff: --- elf/Makefile | 7 +++++++ elf/dynamic-link.h | 30 ++++++++++++++++++++++++++++++ elf/elf.h | 15 +++++++++++++-- elf/get-dynamic-info.h | 8 +++++++- elf/tst-relr-no-pie.c | 1 + elf/tst-relr.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 103 insertions(+), 3 deletions(-) diff --git a/elf/Makefile b/elf/Makefile index 1b9acb5242..6d023d75a0 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -209,6 +209,13 @@ tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog endif endif endif +ifeq ($(have-relr),yes) +tests += tst-relr tst-relr-no-pie +tests-pie += tst-relr +tests-no-pie += tst-relr-no-pie +LDFLAGS-tst-relr += -Wl,--pack-dyn-relocs=relr +LDFLAGS-tst-relr-no-pie += -Wl,--pack-dyn-relocs=relr -no-pie +endif ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-leaks1-mem.out \ $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \ diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index f576d787e3..5b146d854f 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -253,6 +253,35 @@ elf_machine_lazy_rel (struct link_map *map, # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc, boot_map) /* Nothing to do. */ # endif +/* Google-local: b/208156916. To not bump DT_NUM, use DT_VERSYM+1 for DT_RELR + and DT_VERSYM+2 for DT_RELRSZ. */ +# define ELF_DYNAMIC_DO_RELR(map) \ + do { \ + ElfW(Addr) l_addr = (map)->l_addr, *where = 0; \ + const ElfW(Relr) *r, *end; \ + if (!(map)->l_info[VERSYMIDX (DT_VERSYM + 1)]) \ + break; \ + r = (const ElfW(Relr) *)D_PTR((map), l_info[VERSYMIDX (DT_VERSYM + 1)]); \ + end = (const ElfW(Relr) *)((const char *)r + \ + (map)->l_info[VERSYMIDX (DT_VERSYM + 2)]->d_un.d_val); \ + for (; r < end; r++) \ + { \ + ElfW(Relr) entry = *r; \ + if ((entry & 1) == 0) \ + { \ + where = (ElfW(Addr) *)(l_addr + entry); \ + *where++ += l_addr; \ + } \ + else \ + { \ + for (long i = 0; (entry >>= 1) != 0; i++) \ + if ((entry & 1) != 0) \ + where[i] += l_addr; \ + where += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \ + } \ + } \ + } while (0); + /* This can't just be an inline function because GCC is too dumb to inline functions containing inlines themselves. */ # define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc, boot_map) \ @@ -261,6 +290,7 @@ elf_machine_lazy_rel (struct link_map *map, (consider_profile)); \ ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc, boot_map); \ ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc, boot_map); \ + ELF_DYNAMIC_DO_RELR ((map)); \ } while (0) #else /* NESTING */ # if ! ELF_MACHINE_NO_REL diff --git a/elf/elf.h b/elf/elf.h index 954f3266f7..35ff17cae2 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -444,8 +444,9 @@ typedef struct #define SHT_FINI_ARRAY 15 /* Array of destructors */ #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ #define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ +#define SHT_RELR 19 /* RELR relative relocations */ +#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. */ @@ -663,6 +664,11 @@ typedef struct Elf64_Sxword r_addend; /* Addend */ } Elf64_Rela; +/* RELR relocation table entry */ + +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + /* How to extract and insert information held in the r_info field. */ #define ELF32_R_SYM(val) ((val) >> 8) @@ -861,6 +867,11 @@ typedef struct #define DT_ENCODING 32 /* Start of encoded range */ #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_RELRSZ 35 /* Total size of RELR relative relocations */ +#define DT_RELR 36 /* Address of RELR relative relocations */ +#define DT_RELRENT 37 /* Size of one RELR relative relocaction */ +/* Google-local: b/208156916. Don't bump DT_NUM. */ #define DT_NUM 34 /* Number used */ #define DT_LOOS 0x6000000d /* Start of OS-specific */ #define DT_HIOS 0x6ffff000 /* End of OS-specific */ diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index f9c5b84d6a..3710d41841 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -49,7 +49,12 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) while (dyn->d_tag != DT_NULL) { - if ((d_tag_utype) dyn->d_tag < DT_NUM) + /* Google-local: b/208156916. See ELF_DYNAMIC_DO_RELR. */ + if (dyn->d_tag == DT_RELR) + info[VERSYMIDX (DT_VERSYM + 1)] = dyn; + else if (dyn->d_tag == DT_RELRSZ) + info[VERSYMIDX (DT_VERSYM + 2)] = dyn; + else if ((d_tag_utype) dyn->d_tag < DT_NUM) info[dyn->d_tag] = dyn; else if (dyn->d_tag >= DT_LOPROC && dyn->d_tag < DT_LOPROC + DT_THISPROCNUM) @@ -112,6 +117,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) # endif ADJUST_DYN_INFO (DT_JMPREL); ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); + ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM + 1)); /* DT_RELR */ ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM); # undef ADJUST_DYN_INFO diff --git a/elf/tst-relr-no-pie.c b/elf/tst-relr-no-pie.c new file mode 100644 index 0000000000..7df0cdbfd6 --- /dev/null +++ b/elf/tst-relr-no-pie.c @@ -0,0 +1 @@ +#include "tst-relr.c" diff --git a/elf/tst-relr.c b/elf/tst-relr.c new file mode 100644 index 0000000000..22eb8c75a0 --- /dev/null +++ b/elf/tst-relr.c @@ -0,0 +1,45 @@ +#include +#include +#include + +static int o, x; + +#define ELEMS O O O O O O O O X X X X X X X O O X O O X X X E X E E O X O E +#define E 0, + +#define O &o, +#define X &x, +void *arr[] = { ELEMS }; +#undef O +#undef X + +#define O 1, +#define X 2, +static char val[] = { ELEMS }; + +static int +do_test (void) +{ + ElfW(Dyn) *d = _DYNAMIC; + if (d) + { + bool has_relr = false; + for (; d->d_tag != DT_NULL; d++) + if (d->d_tag == DT_RELR) + has_relr = true; + if (!has_relr) + { + fprintf (stderr, "no DT_RELR\n"); + return 0; + } + } + + for (int i = 0; i < sizeof (arr) / sizeof (arr[0]); i++) + if (!((arr[i] == 0 && val[i] == 0) || + (arr[i] == &o && val[i] == 1) || + (arr[i] == &x && val[i] == 2))) + return 1; + return 0; +} + +#include