diff options
author | Maciej W. Rozycki <macro@mips.com> | 2018-06-20 00:37:51 +0100 |
---|---|---|
committer | Maciej W. Rozycki <macro@mips.com> | 2018-06-20 00:37:51 +0100 |
commit | 789ff5b6c26ce7e4ebfcfa5a9a695407c17fa4ea (patch) | |
tree | ce7958d48139f89d91d1137fdeebe4df2c040c27 /bfd | |
parent | 6a382bceadc7228d20746079570a15f115e55d0c (diff) | |
download | gdb-789ff5b6c26ce7e4ebfcfa5a9a695407c17fa4ea.zip gdb-789ff5b6c26ce7e4ebfcfa5a9a695407c17fa4ea.tar.gz gdb-789ff5b6c26ce7e4ebfcfa5a9a695407c17fa4ea.tar.bz2 |
PR ld/22966: Fix n64 MIPS `.got.plt' range checks
The addressable signed 32-bit range for n64 MIPS `.got.plt' references
is from 0xffffffff7fff8000 to 0x7fff7fff, due to how the composition of
an LUI and an LD instruction works for address calculation in the 64-bit
addressing mode, such as when CP0.Status.UX=1.
We currently have a range check in `mips_finish_exec_plt', however it is
not correct as it verifies that the `.got.plt' start address referred is
between 0xffffffff80000000 and 0x7fffffff. It is also implemented as an
assertion rather than a proper error message despite that the situation
can be triggered by user input. Additionally there is no check made for
individual `.got.plt' entries referred even though they can be out of
range while the `.got.plt' start address is not.
Fix all these problems and use the correct range for the check, limiting
it to n64 output files, and then issue a proper error message both in
`mips_finish_exec_plt' and in `_bfd_mips_elf_finish_dynamic_symbol',
suggesting the use of the `-Ttext-segment=...' option that will often
work and with the default linker scripts in particular. Add suitable
tests covering boundary cases.
bfd/
PR ld/22966
* elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Verify the
`.got.plt' entry referred is in range.
(mips_finish_exec_plt): Correct the range check for `.got.plt'
start. Replace the assertion used for that with a proper error
message.
ld/
PR ld/22966
* testsuite/ld-mips-elf/n64-plt-1.dd: New test.
* testsuite/ld-mips-elf/n64-plt-1.gd: New test.
* testsuite/ld-mips-elf/n64-plt-2.ed: New test.
* testsuite/ld-mips-elf/n64-plt-3.ed: New test.
* testsuite/ld-mips-elf/n64-plt-4.dd: New test.
* testsuite/ld-mips-elf/n64-plt-4.gd: New test.
* testsuite/ld-mips-elf/n64-plt-1.ld: New test linker script.
* testsuite/ld-mips-elf/n64-plt-2.ld: New test linker script.
* testsuite/ld-mips-elf/n64-plt-3.ld: New test linker script.
* testsuite/ld-mips-elf/n64-plt-4.ld: New test linker script.
* testsuite/ld-mips-elf/n64-plt.s: New test source.
* testsuite/ld-mips-elf/n64-plt-lib.s: New test source.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 31 |
2 files changed, 38 insertions, 2 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b812fdc..d12dc99 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,14 @@ 2018-06-19 Maciej W. Rozycki <macro@mips.com> + PR ld/22966 + * elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Verify the + `.got.plt' entry referred is in range. + (mips_finish_exec_plt): Correct the range check for `.got.plt' + start. Replace the assertion used for that with a proper error + message. + +2018-06-19 Maciej W. Rozycki <macro@mips.com> + * elfxx-mips.c (_bfd_mips_elf_finish_dynamic_symbol): Fix formatting. diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index d25f4ff..844750eb 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -10602,6 +10602,22 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, got_address_high = ((got_address + 0x8000) >> 16) & 0xffff; got_address_low = got_address & 0xffff; + /* The PLT sequence is not safe for N64 if .got.plt entry's address + cannot be loaded in two instructions. */ + if (ABI_64_P (output_bfd) + && ((got_address + 0x80008000) & ~(bfd_vma) 0xffffffff) != 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: `%pA' entry VMA of %#" PRIx64 " outside the 32-bit range " + "supported; consider using `-Ttext-segment=...'"), + output_bfd, + htab->root.sgotplt->output_section, + (int64_t) got_address); + bfd_set_error (bfd_error_no_error); + return FALSE; + } + /* Initially point the .got.plt entry at the PLT header. */ loc = (htab->root.sgotplt->contents + got_index * MIPS_ELF_GOT_SIZE (dynobj)); @@ -11246,8 +11262,19 @@ mips_finish_exec_plt (bfd *output_bfd, struct bfd_link_info *info) /* The PLT sequence is not safe for N64 if .got.plt's address can not be loaded in two instructions. */ - BFD_ASSERT ((gotplt_value & ~(bfd_vma) 0x7fffffff) == 0 - || ~(gotplt_value | 0x7fffffff) == 0); + if (ABI_64_P (output_bfd) + && ((gotplt_value + 0x80008000) & ~(bfd_vma) 0xffffffff) != 0) + { + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB: `%pA' start VMA of %#" PRIx64 " outside the 32-bit range " + "supported; consider using `-Ttext-segment=...'"), + output_bfd, + htab->root.sgotplt->output_section, + (int64_t) gotplt_value); + bfd_set_error (bfd_error_no_error); + return FALSE; + } /* Install the PLT header. */ loc = htab->root.splt->contents; |