diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4ce81a664d..fa83823d88 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2016-05-28 Maciej W. Rozycki + + * elfxx-mips.c (mips_elf_calculate_relocation): + : Drop the region bits of the + reloc location from calculation, treat the addend as signed with + local non-section symbols and enable overflow detection. + 2016-05-28 Alan Modra * aoutx.h: Adjust linker callback calls throughout file, diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 5143fcb434..d519090dc1 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -5247,6 +5247,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* TRUE if the symbol referred to by this relocation is a local symbol. */ bfd_boolean local_p, was_local_p; + /* TRUE if the symbol referred to by this relocation is a section + symbol. */ + bfd_boolean section_p = FALSE; /* TRUE if the symbol referred to by this relocation is "_gp_disp". */ bfd_boolean gp_disp_p = FALSE; /* TRUE if the symbol referred to by this relocation is @@ -5302,12 +5305,12 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, sym = local_syms + r_symndx; sec = local_sections[r_symndx]; + section_p = ELF_ST_TYPE (sym->st_info) == STT_SECTION; + symbol = sec->output_section->vma + sec->output_offset; - if (ELF_ST_TYPE (sym->st_info) != STT_SECTION - || (sec->flags & SEC_MERGE)) + if (!section_p || (sec->flags & SEC_MERGE)) symbol += sym->st_value; - if ((sec->flags & SEC_MERGE) - && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + if ((sec->flags & SEC_MERGE) && section_p) { addend = _bfd_elf_rel_local_sym (abfd, sym, &sec, addend); addend -= symbol; @@ -5773,9 +5776,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, /* Shift is 2, unusually, for microMIPS JALX. */ shift = (!*cross_mode_jump_p && r_type == R_MICROMIPS_26_S1) ? 1 : 2; - if (was_local_p) - value = addend | ((p + 4) & (0xfc000000 << shift)); - else if (howto->partial_inplace) + if (howto->partial_inplace && !section_p) value = _bfd_mips_elf_sign_extend (addend, 26 + shift); else value = addend; @@ -5787,7 +5788,7 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, return bfd_reloc_outofrange; value >>= shift; - if (!was_local_p && h->root.root.type != bfd_link_hash_undefweak) + if (was_local_p || h->root.root.type != bfd_link_hash_undefweak) overflowed_p = (value >> 26) != ((p + 4) >> (26 + shift)); value &= howto->dst_mask; } diff --git a/ld/ChangeLog b/ld/ChangeLog index fde9553fc7..13fb7459a7 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2016-05-28 Maciej W. Rozycki + + * testsuite/ld-mips-elf/jal-global-overflow-0.d: New test. + * testsuite/ld-mips-elf/jal-global-overflow-1.d: New test. + * testsuite/ld-mips-elf/jal-local-overflow-0.d: New test. + * testsuite/ld-mips-elf/jal-local-overflow-1.d: New test. + * testsuite/ld-mips-elf/jal-global-overflow.s: New test source. + * testsuite/ld-mips-elf/jal-local-overflow.s: New test source. + * testsuite/ld-mips-elf/mips-elf.exp: Run the new tests. + 2016-05-28 Alan Modra * ldmain.c (multiple_definition, multiple_common, add_to_set, diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d b/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d new file mode 100644 index 0000000000..f02bfeae9f --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-global-overflow-0.d @@ -0,0 +1,20 @@ +#name: MIPS JAL to global symbol overflow 0 +#source: jal-global-overflow.s +#as: -EB -32 +#ld: -EB -Ttext 0x20000000 -e 0x20000000 +#objdump: -dr --prefix-addresses --show-raw-insn + +.*: +file format .*mips.* + +Disassembly of section \.text: + \.\.\. +[0-9a-f]+ <[^>]*> 0c001000 jal 20004000 +[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero +[0-9a-f]+ <[^>]*> 0c000800 jal 20002000 +[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero + \.\.\. +[0-9a-f]+ <[^>]*> 0c000800 jal 20002000 +[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero +[0-9a-f]+ <[^>]*> 0c001000 jal 20004000 +[0-9a-f]+ <[^>]*> 00000027 nor zero,zero,zero + \.\.\. diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d b/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d new file mode 100644 index 0000000000..da6e750a0d --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-global-overflow-1.d @@ -0,0 +1,8 @@ +#name: MIPS JAL to global symbol overflow 1 +#source: jal-global-overflow.s +#as: -EB -32 +#ld: -EB -Ttext 0x1fffd000 -e 0x1fffd000 +#error: \A[^\n]*: In function `foo':\n +#error: \(\.text\+0x2000\): relocation truncated to fit: R_MIPS_26 against `abar'\n +#error: [^\n]*: In function `bar':\n +#error: \(\.text\+0x4000\): relocation truncated to fit: R_MIPS_26 against `afoo'\Z diff --git a/ld/testsuite/ld-mips-elf/jal-global-overflow.s b/ld/testsuite/ld-mips-elf/jal-global-overflow.s new file mode 100644 index 0000000000..a67d0bf878 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-global-overflow.s @@ -0,0 +1,37 @@ + .text + .set noreorder + .org 0x2000 + + .align 4 + .globl foo + .ent foo +foo: + jal abar - 8 + nor $0, $0 + + .globl afoo + .aent afoo +afoo: + jal afoo - 8 + nor $0, $0 + .end foo + + .org 0x4000 + + .align 4 + .globl bar + .ent bar +bar: + jal afoo - 8 + nor $0, $0 + + .globl abar + .aent abar +abar: + jal abar - 8 + nor $0, $0 + .end bar + +# Force some (non-delay-slot) zero bytes, to make 'objdump' print ... + .align 4, 0 + .space 16 diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d b/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d new file mode 100644 index 0000000000..592b2aec92 --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-local-overflow-0.d @@ -0,0 +1,6 @@ +#name: MIPS JAL to local symbol overflow 0 +#source: jal-local-overflow.s +#as: -EB -32 +#ld: -EB -Ttext 0x20000000 -e 0x20000000 +#objdump: -dr --prefix-addresses --show-raw-insn +#dump: jal-global-overflow-0.d diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d b/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d new file mode 100644 index 0000000000..869df0ed0f --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-local-overflow-1.d @@ -0,0 +1,8 @@ +#name: MIPS JAL to local symbol overflow 1 +#source: jal-local-overflow.s +#as: -EB -32 +#ld: -EB -Ttext 0x1fffd000 -e 0x1fffd000 +#error: \A[^\n]*: In function `foo':\n +#error: \(\.text\+0x2000\): relocation truncated to fit: R_MIPS_26 against `.text'\n +#error: [^\n]*: In function `bar':\n +#error: \(\.text\+0x4000\): relocation truncated to fit: R_MIPS_26 against `.text'\Z diff --git a/ld/testsuite/ld-mips-elf/jal-local-overflow.s b/ld/testsuite/ld-mips-elf/jal-local-overflow.s new file mode 100644 index 0000000000..9b22f677dc --- /dev/null +++ b/ld/testsuite/ld-mips-elf/jal-local-overflow.s @@ -0,0 +1,35 @@ + .text + .set noreorder + .org 0x2000 + + .align 4 + .globl foo + .ent foo +foo: + jal abar - 8 + nor $0, $0 + + .aent afoo +afoo: + jal afoo - 8 + nor $0, $0 + .end foo + + .org 0x4000 + + .align 4 + .globl bar + .ent bar +bar: + jal afoo - 8 + nor $0, $0 + + .aent abar +abar: + jal abar - 8 + nor $0, $0 + .end bar + +# Force some (non-delay-slot) zero bytes, to make 'objdump' print ... + .align 4, 0 + .space 16 diff --git a/ld/testsuite/ld-mips-elf/mips-elf.exp b/ld/testsuite/ld-mips-elf/mips-elf.exp index 3fa151a1c1..f8c8b09bda 100644 --- a/ld/testsuite/ld-mips-elf/mips-elf.exp +++ b/ld/testsuite/ld-mips-elf/mips-elf.exp @@ -493,6 +493,12 @@ if {$linux_gnu} { run_dump_test "jaloverflow" run_dump_test "jaloverflow-2" + +run_dump_test "jal-global-overflow-0" [list [list ld $abi_ldflags(o32)]] +run_dump_test "jal-global-overflow-1" [list [list ld $abi_ldflags(o32)]] +run_dump_test "jal-local-overflow-0" [list [list ld $abi_ldflags(o32)]] +run_dump_test "jal-local-overflow-1" [list [list ld $abi_ldflags(o32)]] + run_dump_test "undefweak-overflow" [list [list as $abi_asflags(o32)] \ [list ld $abi_ldflags(o32)]]