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 | |
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.
-rw-r--r-- | bfd/ChangeLog | 9 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 31 | ||||
-rw-r--r-- | ld/ChangeLog | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/mips-elf.exp | 44 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-1.dd | 26 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-1.gd | 18 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-1.ld | 22 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-2.ed | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-2.ld | 23 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-3.ed | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-3.ld | 23 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-4.dd | 26 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-4.gd | 18 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-4.ld | 23 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt-lib.s | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-mips-elf/n64-plt.s | 9 |
16 files changed, 300 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; diff --git a/ld/ChangeLog b/ld/ChangeLog index 495eeef..235fa51 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,22 @@ 2018-06-19 Maciej W. Rozycki <macro@mips.com> + 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. + +2018-06-19 Maciej W. Rozycki <macro@mips.com> + * testsuite/ld-elf/shared.exp: XFAIL DT_TEXTREL map file warning test for `mips*-*-*'. diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index 29e2274..1631d85 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -1167,6 +1167,50 @@ if { $linux_gnu } { } } +# Verify graceful handling of n64 PLT 32-bit range overflows. Given +# that the alignment of `.got.plt' is 8 the highest usable positive +# address is 0x7fff7ff8 and the lowest usable negative address is +# 0xffffffff7fff8000. +if { $linux_gnu } { + run_ld_link_tests [list \ + [list "Shared library for MIPS n64 PLT 32-bit range tests" \ + "-shared $abi_ldflags(n64)" "" \ + "$abi_asflags(n64)" \ + { n64-plt-lib.s } \ + {} \ + "n64-plt-lib.so"] \ + [list "MIPS n64 PLT 32-bit range test 1" \ + "$abi_ldflags(n64) -T n64-plt-1.ld -e foo" \ + "tmpdir/n64-plt-lib.so" \ + "$abi_asflags(n64)" \ + { n64-plt.s } \ + { { objdump -d n64-plt-1.dd } \ + { readelf -A n64-plt-1.gd } } \ + "n64-plt-1"] \ + [list "MIPS n64 PLT 32-bit range test 2" \ + "$abi_ldflags(n64) -T n64-plt-2.ld -e foo" \ + "tmpdir/n64-plt-lib.so" \ + "$abi_asflags(n64)" \ + { n64-plt.s } \ + { { ld n64-plt-2.ed } } \ + "n64-plt-2"] \ + [list "MIPS n64 PLT 32-bit range test 3" \ + "$abi_ldflags(n64) -T n64-plt-3.ld -e foo" \ + "tmpdir/n64-plt-lib.so" \ + "$abi_asflags(n64)" \ + { n64-plt.s } \ + { { ld n64-plt-3.ed } } \ + "n64-plt-3"] \ + [list "MIPS n64 PLT 32-bit range test 4" \ + "$abi_ldflags(n64) -T n64-plt-4.ld -e foo" \ + "tmpdir/n64-plt-lib.so" \ + "$abi_asflags(n64)" \ + { n64-plt.s } \ + { { objdump -d n64-plt-4.dd } \ + { readelf -A n64-plt-4.gd } } \ + "n64-plt-4"]] +} + # PR ld/19908 export class tests. if { $linux_gnu } { run_ld_link_tests [list \ diff --git a/ld/testsuite/ld-mips-elf/n64-plt-1.dd b/ld/testsuite/ld-mips-elf/n64-plt-1.dd new file mode 100644 index 0000000..4c24a9a --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-1.dd @@ -0,0 +1,26 @@ +.*: +file format .*mips.* + +Disassembly of section \.plt: + +0000000010000280 <_PROCEDURE_LINKAGE_TABLE_>: + 10000280: 3c0e7fff lui t2,0x7fff + 10000284: ddd97fe8 ld t9,32744\(t2\) + 10000288: 25ce7fe8 addiu t2,t2,32744 + 1000028c: 030ec023 subu t8,t8,t2 + 10000290: 03e07825 move t3,ra + 10000294: 0018c0c2 srl t8,t8,0x3 + 10000298: 0320f809 jalr t9 + 1000029c: 2718fffe addiu t8,t8,-2 + +00000000100002a0 <bar@plt>: + 100002a0: 3c0f7fff lui t3,0x7fff + 100002a4: ddf97ff8 ld t9,32760\(t3\) + 100002a8: 03200008 jr t9 + 100002ac: 25f87ff8 addiu t8,t3,32760 + +Disassembly of section \.text: + +00000000100002b0 <foo>: + 100002b0: 080000a8 j 100002a0 <bar@plt> + 100002b4: 00000000 nop + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/n64-plt-1.gd b/ld/testsuite/ld-mips-elf/n64-plt-1.gd new file mode 100644 index 0000000..5804e66 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-1.gd @@ -0,0 +1,18 @@ +Primary GOT: + Canonical gp value: 000000007ffffff0 + + Reserved entries: + Address Access Initial Purpose + 000000007fff8000 -32752\(gp\) 0000000000000000 Lazy resolver + 000000007fff8008 -32744\(gp\) 8000000000000000 Module pointer \(GNU extension\) + +PLT GOT: + + Reserved entries: + Address Initial Purpose + 000000007fff7fe8 0000000000000000 PLT lazy resolver + 000000007fff7ff0 0000000000000000 Module pointer + + Entries: + Address Initial Sym\.Val\. Type Ndx Name + 000000007fff7ff8 0000000010000280 0000000000000000 FUNC UND bar diff --git a/ld/testsuite/ld-mips-elf/n64-plt-1.ld b/ld/testsuite/ld-mips-elf/n64-plt-1.ld new file mode 100644 index 0000000..1ef3106 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-1.ld @@ -0,0 +1,22 @@ +MEMORY +{ + text (rx) : ORIGIN = 0x10000000, LENGTH = 0x10000 + data (w) : ORIGIN = 0x7fff7fe8, LENGTH = 0x10000 +} +SECTIONS +{ + .dynamic : { *(.dynamic) } >text + .hash : { *(.hash) } >text + .dynsym : { *(.dynsym) } >text + .dynstr : { *(.dynstr) } >text + .rel.plt : { *(.rel.plt) } >text + .plt : { *(.plt) } >text + .text : { *(.text) } >text + .interp : { *(.interp) } >text + .got.plt : { *(.got.plt) } >data + .got : { *(.got) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +} diff --git a/ld/testsuite/ld-mips-elf/n64-plt-2.ed b/ld/testsuite/ld-mips-elf/n64-plt-2.ed new file mode 100644 index 0000000..4a42ec1 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-2.ed @@ -0,0 +1 @@ +[^\n]*: `\.got\.plt' entry VMA of 0x7fff8000 outside the 32-bit range supported; consider using `-Ttext-segment=\.\.\.' diff --git a/ld/testsuite/ld-mips-elf/n64-plt-2.ld b/ld/testsuite/ld-mips-elf/n64-plt-2.ld new file mode 100644 index 0000000..4d2ab48 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-2.ld @@ -0,0 +1,23 @@ +MEMORY +{ + text (rx) : ORIGIN = 0x10000000, LENGTH = 0x10000 + data (w) : ORIGIN = 0x7fff7ff0, LENGTH = 0x10000 +} +SECTIONS +{ + .dynamic : { *(.dynamic) } >text + .hash : { *(.hash) } >text + .dynsym : { *(.dynsym) } >text + .dynstr : { *(.dynstr) } >text + .rel.plt : { *(.rel.plt) } >text + .plt : { *(.plt) } >text + .text : { *(.text) } >text + .interp : { *(.interp) } >text + .got.plt : { *(.got.plt) } >data + .rld.map : { *(.rld.map) } >data + .got : { *(.got) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +} diff --git a/ld/testsuite/ld-mips-elf/n64-plt-3.ed b/ld/testsuite/ld-mips-elf/n64-plt-3.ed new file mode 100644 index 0000000..29a346b --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-3.ed @@ -0,0 +1 @@ +[^\n]*: `\.got\.plt' start VMA of 0xffffffff7fff7ff0 outside the 32-bit range supported; consider using `-Ttext-segment=\.\.\.' diff --git a/ld/testsuite/ld-mips-elf/n64-plt-3.ld b/ld/testsuite/ld-mips-elf/n64-plt-3.ld new file mode 100644 index 0000000..be88c49 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-3.ld @@ -0,0 +1,23 @@ +MEMORY +{ + text (rx) : ORIGIN = 0xffffffff10000000, LENGTH = 0x10000 + data (w) : ORIGIN = 0xffffffff7fff7ff0, LENGTH = 0x10000 +} +SECTIONS +{ + .dynamic : { *(.dynamic) } >text + .hash : { *(.hash) } >text + .dynsym : { *(.dynsym) } >text + .dynstr : { *(.dynstr) } >text + .rel.plt : { *(.rel.plt) } >text + .plt : { *(.plt) } >text + .text : { *(.text) } >text + .interp : { *(.interp) } >text + .got.plt : { *(.got.plt) } >data + .rld.map : { *(.rld.map) } >data + .got : { *(.got) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +} diff --git a/ld/testsuite/ld-mips-elf/n64-plt-4.dd b/ld/testsuite/ld-mips-elf/n64-plt-4.dd new file mode 100644 index 0000000..01c5025 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-4.dd @@ -0,0 +1,26 @@ +.*: +file format .*mips.* + +Disassembly of section \.plt: + +ffffffff10000280 <_PROCEDURE_LINKAGE_TABLE_>: +ffffffff10000280: 3c0e8000 lui t2,0x8000 +ffffffff10000284: ddd98000 ld t9,-32768\(t2\) +ffffffff10000288: 25ce8000 addiu t2,t2,-32768 +ffffffff1000028c: 030ec023 subu t8,t8,t2 +ffffffff10000290: 03e07825 move t3,ra +ffffffff10000294: 0018c0c2 srl t8,t8,0x3 +ffffffff10000298: 0320f809 jalr t9 +ffffffff1000029c: 2718fffe addiu t8,t8,-2 + +ffffffff100002a0 <bar@plt>: +ffffffff100002a0: 3c0f8000 lui t3,0x8000 +ffffffff100002a4: ddf98010 ld t9,-32752\(t3\) +ffffffff100002a8: 03200008 jr t9 +ffffffff100002ac: 25f88010 addiu t8,t3,-32752 + +Disassembly of section \.text: + +ffffffff100002b0 <foo>: +ffffffff100002b0: 080000a8 j ffffffff100002a0 <bar@plt> +ffffffff100002b4: 00000000 nop + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/n64-plt-4.gd b/ld/testsuite/ld-mips-elf/n64-plt-4.gd new file mode 100644 index 0000000..f9d1ac9 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-4.gd @@ -0,0 +1,18 @@ +Primary GOT: + Canonical gp value: ffffffff80000010 + + Reserved entries: + Address Access Initial Purpose + ffffffff7fff8020 -32752\(gp\) 0000000000000000 Lazy resolver + ffffffff7fff8028 -32744\(gp\) 8000000000000000 Module pointer \(GNU extension\) + +PLT GOT: + + Reserved entries: + Address Initial Purpose + ffffffff7fff8000 0000000000000000 PLT lazy resolver + ffffffff7fff8008 0000000000000000 Module pointer + + Entries: + Address Initial Sym\.Val\. Type Ndx Name + ffffffff7fff8010 ffffffff10000280 0000000000000000 FUNC UND bar diff --git a/ld/testsuite/ld-mips-elf/n64-plt-4.ld b/ld/testsuite/ld-mips-elf/n64-plt-4.ld new file mode 100644 index 0000000..e1f602d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-4.ld @@ -0,0 +1,23 @@ +MEMORY +{ + text (rx) : ORIGIN = 0xffffffff10000000, LENGTH = 0x10000 + data (w) : ORIGIN = 0xffffffff7fff8000, LENGTH = 0x10000 +} +SECTIONS +{ + .dynamic : { *(.dynamic) } >text + .hash : { *(.hash) } >text + .dynsym : { *(.dynsym) } >text + .dynstr : { *(.dynstr) } >text + .rel.plt : { *(.rel.plt) } >text + .plt : { *(.plt) } >text + .text : { *(.text) } >text + .interp : { *(.interp) } >text + .got.plt : { *(.got.plt) } >data + .rld.map : { *(.rld.map) } >data + .got : { *(.got) } >data + .symtab : { *(.symtab) } + .strtab : { *(.strtab) } + .shstrtab : { *(.shstrtab) } + /DISCARD/ : { *(*) } +} diff --git a/ld/testsuite/ld-mips-elf/n64-plt-lib.s b/ld/testsuite/ld-mips-elf/n64-plt-lib.s new file mode 100644 index 0000000..40409af --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt-lib.s @@ -0,0 +1,11 @@ + .abicalls + .text + + .globl bar + .ent bar +bar: + .frame $sp, 0, $31 + .mask 0x00000000, 0 + .fmask 0x00000000, 0 + jr $31 + .end bar diff --git a/ld/testsuite/ld-mips-elf/n64-plt.s b/ld/testsuite/ld-mips-elf/n64-plt.s new file mode 100644 index 0000000..9732044 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/n64-plt.s @@ -0,0 +1,9 @@ + .abicalls + .option pic0 + .text + + .globl foo + .ent foo +foo: + j bar + .end foo |