diff options
author | Mihailo Stojanovic <mihailo.stojanovic@rt-rk.com> | 2019-08-09 11:06:37 +0100 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-08-09 11:06:37 +0100 |
commit | f16a9783c5f085443d806646074e9c06fdee9a88 (patch) | |
tree | 98daf0fca4cd2a572ee12f1d6b895739b235b008 /ld | |
parent | 1ba7cdcd931ddf672e4a8a6483593f9b94e55965 (diff) | |
download | gdb-f16a9783c5f085443d806646074e9c06fdee9a88.zip gdb-f16a9783c5f085443d806646074e9c06fdee9a88.tar.gz gdb-f16a9783c5f085443d806646074e9c06fdee9a88.tar.bz2 |
Add support for a MIPS specific .MIPS.xhash section.
This patch is a reimplementation of [1] which was submitted in 2015 by
Neil Schellenberger. Copyright issue was sorted out [2] last year.
It proposed a new section (.gnu.xhash) and related dynamic tag
(DT_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 on the
dynsyms than the one expected by the .gnu.hash section. Another addition
would be a leading word (ngnusyms) 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 as reported in [3], which is
caused by the leading word added to the .MIPS.xhash section. Leading word
is removed in this patch, and the number of entries in the translation
table is now calculated using DT_MIPS_SYMTABNO dynamic tag (this is
addressed by the corresponding glibc patch).
Suggestions on coding style in [4] were taken into account. Existing
GNU hash testcase was covered, and another one was added in the MIPS
part of the testsuite.
The other major change is reserving MIPS ABI version 5 for .MIPS.xhash,
marking the need of support for .MIPS.xhash in the dynamic linker (again,
addressed in the corresponding glibc patch). This is something which I
am not sure of, especially after reading [5]. I am confused on whether
this ABI version is reserved for IFUNC, or it can be used for this
purpose.
Already mentioned glibc patch is submitted at:
https://sourceware.org/ml/libc-alpha/2019-06/msg00456.html
[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
[4] https://sourceware.org/ml/binutils/2016-02/msg00097.html
[5] https://sourceware.org/ml/libc-alpha/2016-12/msg00853.html
ld * emulparams/elf32bmip.sh: Add .MIPS.xhash section.
* emulparams/elf32bmipn32-defs.sh: Add .MIPS.xhash section.
* emulparams/elf64bmip-defs.sh: Add .MIPS.xhash section.
* emultempl/mipself.em: Remove mips_after_parse function.
* testsuite/ld-elf/hash.d: Update comment.
* testsuite/ld-mips-elf/hash1.d: New test.
* testsuite/ld-mips-elf/hash1.s: Ditto.
* testsuite/ld-mips-elf/hash1a.d: Remove.
* testsuite/ld-mips-elf/hash1b.d: Ditto.
* testsuite/ld-mips-elf/hash1c.d: Ditto
* testsuite/ld-mips-elf/hash2.d: New test.
* testsuite/ld-mips-elf/mips-elf.exp: New tests.
* testsuite/ld-mips-elf/start.s: New test.
bfd * elf-bfd.h (struct elf_backend_data): New members.
* elflink.c (_bfd_elf_link_create_dynamic_sections): Create
.gnu.hash section if necessary.
(struct collect_gnu_hash_codes): New member.
(elf_gnu_hash_process_symidx): New function name.
(elf_renumber_gnu_hash_syms): Ignore local and undefined
symbols. Record xlat location for every symbol which should have
a .MIPS.xhash entry.
(bfd_elf_size_dynamic_sections): Add DT_GNU_HASH dynamic tag to
dynamic section if necessary.
(GNU_HASH_SECTION_NAME): New define.
(bfd_elf_size_dynsym_hash_dynstr): Get .MIPS.xhash section.
Update the section size info.
* elfxx-mips.c (struct mips_elf_hash_sort_data): New members.
(struct mips_elf_link_hash_entry): New member.
(mips_elf_link_hash_newfunc): Initialize .MIPS.xhash translation
table location.
(mips_elf_sort_hash_table): Initialize the pointer to the
.MIPS.xhash section.
(mips_elf_sort_hash_table_f): Populate the .MIPS.xhash
translation table entry with the symbol dynindx.
(_bfd_mips_elf_section_from_shdr): Add SHT_MIPS_XHASH.
(_bfd_mips_elf_fake_sections): Initialize .MIPS.xhash section
info.
(_bfd_mips_elf_create_dynamic_sections): Create .MIPS.xhash
section.
(_bfd_mips_elf_size_dynamic_sections): Add DT_MIPS_XHASH tag to
dynamic section.
(_bfd_mips_elf_finish_synamic_sections): Add DT_MIPS_XHASH.
(_bfd_mips_elf_final_write_processing): Set .MIPS.xhash section
sh_link info.
(_bfd_mips_elf_get_target_dtag): Get DT_MIPS_XHASH tag.
(MIPS_LIBC_ABI_XHASH): New ABI version enum value.
(_bfd_mips_post_process_headers): Mark the ABI version as
MIPS_LIBC_ABI_XHASH if there exists a .MIPS.xhash section,
but not a .hash section.
(_bfd_mips_elf_record_xhash_symbol): New function. Record a
position in the translation table, associated with the hash
entry.
* elfxx-mips.h (literal_reloc_p): Define
elf_backend_record_xhash_symbol backend hook.
* elfxx-target.h: Initialize elf_backend_record_xhash_symbol
backend hook.
include * elf/mips.h (SHT_GNU_XHASH): New define.
(DT_GNU_XHASH): New define.
binutils * readelf.c (get_mips_dynamic_type): Return MIPS_XHASH dynamic type.
(get_mips_section_type_name): Return MI{S_XHASH name string.
(dynamic_section_mips_val): Initialize the .MIPS.xhash dynamic
info.
(process_symbol_table): Initialize the .MIPS.xhash section
pointer. Adjust the readelf output to support the new section.
(process_object): Set the .MIPS.xhash dynamic info to zero.
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 16 | ||||
-rw-r--r-- | ld/emulparams/elf32bmip.sh | 1 | ||||
-rw-r--r-- | ld/emulparams/elf32bmipn32-defs.sh | 1 | ||||
-rw-r--r-- | ld/emulparams/elf64bmip-defs.sh | 1 | ||||
-rw-r--r-- | ld/emultempl/mipself.em | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-elf/hash.d | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash1.d | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash1.s | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash1a.d | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash1b.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash1c.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/hash2.d | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/mips-elf.exp | 5 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/start.s | 12 |
14 files changed, 69 insertions, 34 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 3010abb..6ff1a47 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,19 @@ +2019-08-09 Mihailo Stojanovic <mihailo.stojanovic@rt-rk.com> + + * emulparams/elf32bmip.sh: Add .MIPS.xhash section. + * emulparams/elf32bmipn32-defs.sh: Add .MIPS.xhash section. + * emulparams/elf64bmip-defs.sh: Add .MIPS.xhash section. + * emultempl/mipself.em: Remove mips_after_parse function. + * testsuite/ld-elf/hash.d: Update comment. + * testsuite/ld-mips-elf/hash1.d: New test. + * testsuite/ld-mips-elf/hash1.s: Ditto. + * testsuite/ld-mips-elf/hash1a.d: Remove. + * testsuite/ld-mips-elf/hash1b.d: Ditto. + * testsuite/ld-mips-elf/hash1c.d: Ditto + * testsuite/ld-mips-elf/hash2.d: New test. + * testsuite/ld-mips-elf/mips-elf.exp: New tests. + * testsuite/ld-mips-elf/start.s: New test. + 2019-08-08 Nick Clifton <nickc@redhat.com> PR 24887 diff --git a/ld/emulparams/elf32bmip.sh b/ld/emulparams/elf32bmip.sh index abbcb5b..1e0200a 100644 --- a/ld/emulparams/elf32bmip.sh +++ b/ld/emulparams/elf32bmip.sh @@ -19,6 +19,7 @@ fi INITIAL_READONLY_SECTIONS="${INITIAL_READONLY_SECTIONS} .MIPS.abiflags ${RELOCATING-0} : { *(.MIPS.abiflags) } .reginfo ${RELOCATING-0} : { *(.reginfo) } + .MIPS.xhash ${RELOCATING-0} : { *(.MIPS.xhash) } " OTHER_TEXT_SECTIONS='*(.mips16.fn.*) *(.mips16.call.*)' # Unlike most targets, the MIPS backend puts all dynamic relocations diff --git a/ld/emulparams/elf32bmipn32-defs.sh b/ld/emulparams/elf32bmipn32-defs.sh index bd01790..80dce8f 100644 --- a/ld/emulparams/elf32bmipn32-defs.sh +++ b/ld/emulparams/elf32bmipn32-defs.sh @@ -87,6 +87,7 @@ if test -z "${CREATE_SHLIB}"; then fi INITIAL_READONLY_SECTIONS="${INITIAL_READONLY_SECTIONS} .MIPS.abiflags ${RELOCATING-0} : { *(.MIPS.abiflags) } + .MIPS.xhash ${RELOCATING-0} : { *(.MIPS.xhash) } .reginfo ${RELOCATING-0} : { *(.reginfo) }" # Discard any .MIPS.content* or .MIPS.events* sections. The linker # doesn't know how to adjust them. diff --git a/ld/emulparams/elf64bmip-defs.sh b/ld/emulparams/elf64bmip-defs.sh index 61d6c00..4165f51 100644 --- a/ld/emulparams/elf64bmip-defs.sh +++ b/ld/emulparams/elf64bmip-defs.sh @@ -2,5 +2,6 @@ source_sh ${srcdir}/emulparams/elf32bmipn32-defs.sh COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" INITIAL_READONLY_SECTIONS=" .MIPS.abiflags ${RELOCATING-0} : { *(.MIPS.abiflags) } + .MIPS.xhash ${RELOCATING-0} : { *(.MIPS.xhash) } .MIPS.options : { *(.MIPS.options) } " diff --git a/ld/emultempl/mipself.em b/ld/emultempl/mipself.em index ec908d7..fe46e0d 100644 --- a/ld/emultempl/mipself.em +++ b/ld/emultempl/mipself.em @@ -46,21 +46,6 @@ static bfd_boolean insn32; static bfd_boolean ignore_branch_isa; static bfd_boolean compact_branches; -static void -mips_after_parse (void) -{ - /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different - ways. .gnu.hash needs symbols to be grouped by hash code whereas the - MIPS ABI requires a mapping between the GOT and the symbol table. */ - if (link_info.emit_gnu_hash) - { - einfo (_("%X%P: .gnu.hash is incompatible with the MIPS ABI\n")); - link_info.emit_hash = TRUE; - link_info.emit_gnu_hash = FALSE; - } - gld${EMULATION_NAME}_after_parse (); -} - struct hook_stub_info { lang_statement_list_type add; @@ -337,6 +322,5 @@ PARSE_AND_LIST_ARGS_CASES=' break; ' -LDEMUL_AFTER_PARSE=mips_after_parse LDEMUL_BEFORE_ALLOCATION=mips_before_allocation LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements diff --git a/ld/testsuite/ld-elf/hash.d b/ld/testsuite/ld-elf/hash.d index fb07912..efe675e 100644 --- a/ld/testsuite/ld-elf/hash.d +++ b/ld/testsuite/ld-elf/hash.d @@ -3,7 +3,7 @@ #ld: -shared --hash-style=gnu #target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi #xfail: mips*-*-* -# GNU hash is not supported for MIPS targets due to psABI restrictions +# MIPS uses a different style of GNU hash due to psABI restrictions # on dynsym table ordering. #... diff --git a/ld/testsuite/ld-mips-elf/hash1.d b/ld/testsuite/ld-mips-elf/hash1.d new file mode 100644 index 0000000..3b9725d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/hash1.d @@ -0,0 +1,11 @@ +#source: hash1.s +#readelf: -d -I +#ld: -nostdlib -shared --hash-style=gnu +#target: [check_shared_lib_support] +#xfail: mips*-*-irix* + +#... + +0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+ +#... + +1 +1 +\( 50.0%\) +100.0% +#... diff --git a/ld/testsuite/ld-mips-elf/hash1.s b/ld/testsuite/ld-mips-elf/hash1.s index 4e7fe2f..587cef1 100644 --- a/ld/testsuite/ld-mips-elf/hash1.s +++ b/ld/testsuite/ld-mips-elf/hash1.s @@ -1 +1,7 @@ - nop +.globl foo + +.text + +foo: + jr $ra + nop diff --git a/ld/testsuite/ld-mips-elf/hash1a.d b/ld/testsuite/ld-mips-elf/hash1a.d deleted file mode 100644 index c189c93..0000000 --- a/ld/testsuite/ld-mips-elf/hash1a.d +++ /dev/null @@ -1,5 +0,0 @@ -#source: hash1.s -#ld: -shared --hash-style=sysv -#objdump: -dr -#target: [check_shared_lib_support] -#pass diff --git a/ld/testsuite/ld-mips-elf/hash1b.d b/ld/testsuite/ld-mips-elf/hash1b.d deleted file mode 100644 index 5cafede..0000000 --- a/ld/testsuite/ld-mips-elf/hash1b.d +++ /dev/null @@ -1,4 +0,0 @@ -#source: hash1.s -#ld: -shared --hash-style=both -#target: [check_shared_lib_support] -#error: .gnu.hash is incompatible with the MIPS ABI diff --git a/ld/testsuite/ld-mips-elf/hash1c.d b/ld/testsuite/ld-mips-elf/hash1c.d deleted file mode 100644 index 379620a..0000000 --- a/ld/testsuite/ld-mips-elf/hash1c.d +++ /dev/null @@ -1,4 +0,0 @@ -#source: hash1.s -#ld: -shared --hash-style=gnu -#target: [check_shared_lib_support] -#error: .gnu.hash is incompatible with the MIPS ABI diff --git a/ld/testsuite/ld-mips-elf/hash2.d b/ld/testsuite/ld-mips-elf/hash2.d new file mode 100644 index 0000000..79fda3c --- /dev/null +++ b/ld/testsuite/ld-mips-elf/hash2.d @@ -0,0 +1,17 @@ +#source: start.s +#readelf: -d -s -D +#ld: -shared --hash-style=gnu +#target: [check_shared_lib_support] +#xfail: mips*-*-irix* + +#... + +0x[0-9a-z]+ +\(MIPS_XHASH\) +0x[0-9a-z]+ +#... + +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] _start +#... + +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] main +#... + +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] start +#... + +[0-9]+ +[0-9]+: +[0-9a-f]+ +[0-9]+ +NOTYPE +GLOBAL +DEFAULT +[1-9] __start +#... diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index 1fee8ef..3c7ce6a 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -854,9 +854,8 @@ if { $linux_gnu } { run_dump_test_n32 "emit-relocs-1" {{as -EB} {ld -EB}} -run_dump_test "hash1a" -run_dump_test "hash1b" -run_dump_test "hash1c" +run_dump_test "hash1" +run_dump_test "hash2" if { $linux_gnu && $has_abi(o32) } { # The number of symbols that are always included in the symbol table diff --git a/ld/testsuite/ld-mips-elf/start.s b/ld/testsuite/ld-mips-elf/start.s new file mode 100644 index 0000000..ee26ab3 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/start.s @@ -0,0 +1,12 @@ + .text + .globl start +start: + .globl _start +_start: + .globl __start +__start: + .globl main +main: + .globl _main +_main: + .dc.a 0 |