diff options
author | Mihailo Stojanovic <mihailo.stojanovic@rt-rk.com> | 2019-08-29 20:11:42 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2019-08-29 20:11:42 +0000 |
commit | 23c1c256ae7b0f010d0fcaff60682b620887b164 (patch) | |
tree | 9d9da83514ca5c0435382b891ea801f6ce37b9a8 /elf | |
parent | 605f38177dba31fe0d0183abb67e25a28fd37d15 (diff) | |
download | glibc-23c1c256ae7b0f010d0fcaff60682b620887b164.tar.gz glibc-23c1c256ae7b0f010d0fcaff60682b620887b164.tar.xz glibc-23c1c256ae7b0f010d0fcaff60682b620887b164.zip |
MIPS support for GNU hash
This patch is a reimplementation of [1], which was submitted back in 2015. Copyright issue has been sorted [2] last year. It proposed a new section (.gnu.xhash) and related dynamic tag (GT_GNU_XHASH). The new section would be virtually identical to the existing .gnu.hash except for the translation table (xlat) which would contain correct MIPS .dynsym indexes corresponding to the hashvals in chains. This is because MIPS ABI imposes a different ordering of the dynsyms than the one expected by the .gnu.hash section. Another addition would be a leading word at the beggining of the section, which would contain the number of entries in the translation table. In this patch, the new section name and dynamic tag are changed to reflect the fact that the section should be treated as MIPS specific (.MIPS.xhash and DT_MIPS_XHASH). This patch addresses the alignment issue reported in [3] which is caused by the leading word of the .MIPS.xhash section. Leading word is now removed in the corresponding binutils patch, and the number of entries in the translation table is computed using DT_MIPS_SYMTABNO dynamic tag. Since the MIPS specific dl-lookup.c file was removed following the initial patch submission, I opted for the definition of three new macros in the generic ldsodefs.h. ELF_MACHINE_GNU_HASH_ADDRIDX defines the index of the dynamic tag in the l_info array. ELF_MACHINE_HASH_SYMIDX is used to calculate the index of a symbol in GNU hash. On MIPS, it is defined to look up the symbol index in the translation table. ELF_MACHINE_XHASH_SETUP is defined for MIPS only. It initializes the .MIPS.xhash pointer in the link_map_machine struct. The other major change is bumping the highest EI_ABIVERSION value for MIPS to suggest that the dynamic linker now supports GNU hash. The patch was tested by running the glibc testsuite for the three MIPS ABIs (o32, n32 and n64) and for x86_64-linux-gnu. [1] https://sourceware.org/ml/binutils/2015-10/msg00057.html [2] https://sourceware.org/ml/binutils/2018-03/msg00025.html [3] https://sourceware.org/ml/binutils/2016-01/msg00006.html * elf/dl-addr.c (determine_info): Calculate the symbol index using the newly defined ELF_MACHINE_HASH_SYMIDX macro. * elf/dl-lookup.c (do_lookup_x): Ditto. (_dl_setup_hash): Initialize MIPS xhash translation table. * elf/elf.h (SHT_MIPS_XHASH): New define. (DT_MIPS_XHASH): New define. * sysdeps/generic/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New define. (ELF_MACHINE_HASH_SYMIDX): Ditto. (ELF_MACHINE_XHASH_SETUP): Ditto. * sysdeps/mips/ldsodefs.h (ELF_MACHINE_GNU_HASH_ADDRIDX): New define. (ELF_MACHINE_HASH_SYMIDX): Ditto. (ELF_MACHINE_XHASH_SETUP): Ditto. * sysdeps/mips/linkmap.h (struct link_map_machine): New member. * sysdeps/unix/sysv/linux/mips/ldsodefs.h: Increment valid ABI version. * sysdeps/unix/sysv/linux/mips/libc-abis: New ABI version.
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-addr.c | 5 | ||||
-rw-r--r-- | elf/dl-lookup.c | 10 | ||||
-rw-r--r-- | elf/elf.h | 5 |
3 files changed, 13 insertions, 7 deletions
diff --git a/elf/dl-addr.c b/elf/dl-addr.c index 9d285d76a7..3f2297af55 100644 --- a/elf/dl-addr.c +++ b/elf/dl-addr.c @@ -42,7 +42,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, ElfW(Word) strtabsize = match->l_info[DT_STRSZ]->d_un.d_val; const ElfW(Sym) *matchsym = NULL; - if (match->l_info[ADDRIDX (DT_GNU_HASH)] != NULL) + if (match->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL) { /* We look at all symbol table entries referenced by the hash table. */ @@ -57,6 +57,7 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, { /* The hash table never references local symbols so we can omit that test here. */ + symndx = ELF_MACHINE_HASH_SYMIDX (match, hasharr); if ((symtab[symndx].st_shndx != SHN_UNDEF || symtab[symndx].st_value != 0) && symtab[symndx].st_shndx != SHN_ABS @@ -65,8 +66,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info, matchsym, addr) && symtab[symndx].st_name < strtabsize) matchsym = (ElfW(Sym) *) &symtab[symndx]; - - ++symndx; } while ((*hasharr++ & 1u) == 0); } diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index eb23cca4e3..f9d6c36b39 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -403,7 +403,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash, do if (((*hasharr ^ new_hash) >> 1) == 0) { - symidx = hasharr - map->l_gnu_chain_zero; + symidx = ELF_MACHINE_HASH_SYMIDX (map, hasharr); sym = check_match (undef_name, ref, version, flags, type_class, &symtab[symidx], symidx, strtab, map, &versioned_sym, @@ -909,10 +909,10 @@ _dl_setup_hash (struct link_map *map) { Elf_Symndx *hash; - if (__glibc_likely (map->l_info[ADDRIDX (DT_GNU_HASH)] != NULL)) + if (__glibc_likely (map->l_info[ELF_MACHINE_GNU_HASH_ADDRIDX] != NULL)) { Elf32_Word *hash32 - = (void *) D_PTR (map, l_info[ADDRIDX (DT_GNU_HASH)]); + = (void *) D_PTR (map, l_info[ELF_MACHINE_GNU_HASH_ADDRIDX]); map->l_nbuckets = *hash32++; Elf32_Word symbias = *hash32++; Elf32_Word bitmask_nwords = *hash32++; @@ -927,6 +927,10 @@ _dl_setup_hash (struct link_map *map) map->l_gnu_buckets = hash32; hash32 += map->l_nbuckets; map->l_gnu_chain_zero = hash32 - symbias; + + /* Initialize MIPS xhash translation table. */ + ELF_MACHINE_XHASH_SETUP (hash32, symbias, map); + return; } diff --git a/elf/elf.h b/elf/elf.h index 7c6d6094ed..5b6ea638b4 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -1715,6 +1715,7 @@ typedef struct #define SHT_MIPS_EH_REGION 0x70000027 #define SHT_MIPS_XLATE_OLD 0x70000028 #define SHT_MIPS_PDR_EXCEPTION 0x70000029 +#define SHT_MIPS_XHASH 0x7000002b /* Legal values for sh_flags field of Elf32_Shdr. */ @@ -1962,7 +1963,9 @@ typedef struct in a PIE as it stores a relative offset from the address of the tag rather than an absolute address. */ #define DT_MIPS_RLD_MAP_REL 0x70000035 -#define DT_MIPS_NUM 0x36 +/* GNU-style hash table with xlat. */ +#define DT_MIPS_XHASH 0x70000036 +#define DT_MIPS_NUM 0x37 /* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ |