summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorMihailo Stojanovic <mihailo.stojanovic@rt-rk.com>2019-08-29 20:11:42 +0000
committerJoseph Myers <joseph@codesourcery.com>2019-08-29 20:11:42 +0000
commit23c1c256ae7b0f010d0fcaff60682b620887b164 (patch)
tree9d9da83514ca5c0435382b891ea801f6ce37b9a8 /sysdeps
parent605f38177dba31fe0d0183abb67e25a28fd37d15 (diff)
downloadglibc-23c1c256ae7b0f010d0fcaff60682b620887b164.tar.gz
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 'sysdeps')
-rw-r--r--sysdeps/generic/ldsodefs.h17
-rw-r--r--sysdeps/mips/ldsodefs.h15
-rw-r--r--sysdeps/mips/linkmap.h1
-rw-r--r--sysdeps/unix/sysv/linux/mips/ldsodefs.h2
-rw-r--r--sysdeps/unix/sysv/linux/mips/libc-abis2
5 files changed, 36 insertions, 1 deletions
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index b1fc5c31f9..1e193b05b0 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -47,6 +47,23 @@ __BEGIN_DECLS
#define ADDRIDX(tag) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM \
+ DT_EXTRANUM + DT_VALNUM + DT_ADDRTAGIDX (tag))
+/* Type of GNU hash which the machine uses. */
+#ifndef ELF_MACHINE_GNU_HASH_ADDRIDX
+# define ELF_MACHINE_GNU_HASH_ADDRIDX ADDRIDX (DT_GNU_HASH)
+#endif
+
+/* Calculate the index of a symbol in GNU hash. */
+#ifndef ELF_MACHINE_HASH_SYMIDX
+# define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \
+ ((hasharr) - (map)->l_gnu_chain_zero)
+#endif
+
+/* Setup MIPS xhash. Defined only for MIPS. */
+#ifndef ELF_MACHINE_XHASH_SETUP
+# define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \
+ ((void) (hash32), (void) (symbias), (void) (map))
+#endif
+
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
#define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type)
diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h
index f0acb020f5..95cd38e486 100644
--- a/sysdeps/mips/ldsodefs.h
+++ b/sysdeps/mips/ldsodefs.h
@@ -26,6 +26,21 @@ struct La_mips_32_retval;
struct La_mips_64_regs;
struct La_mips_64_retval;
+#define ELF_MACHINE_GNU_HASH_ADDRIDX (DT_MIPS_XHASH - DT_LOPROC + DT_NUM)
+
+/* Calculate the index of a symbol in MIPS xhash. */
+#define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \
+ ((map)->l_mach.mips_xlat_zero[(hasharr) - (map)->l_gnu_chain_zero])
+
+/* Setup MIPS xhash. */
+#define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \
+ do \
+ { \
+ (hash32) += (map)->l_info[DT_MIPS (SYMTABNO)]->d_un.d_val - (symbias); \
+ (map)->l_mach.mips_xlat_zero = (hash32) - (symbias); \
+ } \
+ while (0)
+
#define ARCH_PLTENTER_MEMBERS \
Elf32_Addr (*mips_o32_gnu_pltenter) (Elf32_Sym *, unsigned int, \
uintptr_t *, uintptr_t *, \
diff --git a/sysdeps/mips/linkmap.h b/sysdeps/mips/linkmap.h
index 1fb9678a6d..1e640c3ba9 100644
--- a/sysdeps/mips/linkmap.h
+++ b/sysdeps/mips/linkmap.h
@@ -3,4 +3,5 @@ struct link_map_machine
ElfW(Addr) plt; /* Address of .plt */
ElfW(Word) fpabi; /* FP ABI of the object */
unsigned int odd_spreg; /* Does the object require odd_spreg support? */
+ const Elf32_Word *mips_xlat_zero; /* .MIPS.xhash */
};
diff --git a/sysdeps/unix/sysv/linux/mips/ldsodefs.h b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
index 28257f83ae..ce7b2f9885 100644
--- a/sysdeps/unix/sysv/linux/mips/ldsodefs.h
+++ b/sysdeps/unix/sysv/linux/mips/ldsodefs.h
@@ -34,7 +34,7 @@ extern void _dl_static_init (struct link_map *map);
#undef VALID_ELF_ABIVERSION
#define VALID_ELF_ABIVERSION(osabi,ver) \
(ver == 0 \
- || (osabi == ELFOSABI_SYSV && ver < 5) \
+ || (osabi == ELFOSABI_SYSV && ver < 6) \
|| (osabi == ELFOSABI_GNU && ver < LIBC_ABI_MAX))
#endif /* ldsodefs.h */
diff --git a/sysdeps/unix/sysv/linux/mips/libc-abis b/sysdeps/unix/sysv/linux/mips/libc-abis
index eaea558720..c0b67dae3e 100644
--- a/sysdeps/unix/sysv/linux/mips/libc-abis
+++ b/sysdeps/unix/sysv/linux/mips/libc-abis
@@ -16,3 +16,5 @@ UNIQUE
MIPS_O32_FP64 mips*-*-linux*
# Absolute (SHN_ABS) symbols working correctly.
ABSOLUTE
+# GNU-style hash table with translation table.
+MIPS_XHASH