MIPS: Verify the ISA mode and alignment of branch and jump targets
authorMaciej W. Rozycki <macro@imgtec.com>
Tue, 19 Jul 2016 12:59:28 +0000 (13:59 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Tue, 19 Jul 2016 13:46:30 +0000 (14:46 +0100)
commit9d862524f6ae9703fe8e264dd4785756d358570a
treebd5585c84b4fedc97b3068865b82eeb10d781e29
parent065251a0d7a5b0b079ed1f86247573a07d7d98c8
MIPS: Verify the ISA mode and alignment of branch and jump targets

Verify that the ISA mode of branch targets is the same as the referring
relocation, so that an attempt to produce a branch between instructions
encoded in different ISA modes each causes an error rather than silently
producing non-functional code.  Make sure that no symbol or addend bits
are silently truncated: terminate with an error if the relocation value
calculated cannot be encoded in the relocatable field of a branch; for
REL targets also applying to any intermediate addend.

Also make jump target's alignment verification consistent with that for
branches.

This change will require an update to some obscure handcoded assembly
sources which make branches to labels placed at data objects, however
for microMIPS code only.  These labels will have to be updated with the
`.insn' directive for containing code to assemble and link successfully.
Such code is broken as any such labels have always been required by the
microMIPS architecture specification[1][2] to be annotated this way for
correct interpretation, and with our old code missing `.insn' directives
caused labels to present different semantics depending on whether they
were referred with branch (ISA bit ignored) or other relocations (ISA
bit respected).

Enforcing these checks however will ensure errors in building software,
like mixed regular MIPS and microMIPS code links with branches between,
will be diagnosed at the build time rather than causing odd run-time
errors such as intermittent crashes.  It will also let cross-mode BAL
instructions be converted to JALX instructions, with a separate change.

References:

[1] "MIPS Architecture for Programmers, Volume II-B: The microMIPS32
    Instruction Set", MIPS Technologies, Inc., Document Number: MD00582,
    Revision 5.04, January 15, 2014, Section 7.1 "Assembly-Level
    Compatibility", p. 533

[2] "MIPS Architecture for Programmers, Volume II-B: The microMIPS64
    Instruction Set", MIPS Technologies, Inc., Document Number: MD00594,
    Revision 5.04, January 15, 2014, Section 8.1 "Assembly-Level
    Compatibility", p. 623

bfd/
* elfxx-mips.c (b_reloc_p): Add R_MICROMIPS_PC16_S1,
R_MICROMIPS_PC10_S1 and R_MICROMIPS_PC7_S1.
(branch_reloc_p): New function.
(mips_elf_calculate_relocation): Handle ISA mode determination
for relocations against section symbols, against absolute
symbols and absolute relocations.  Also set `*cross_mode_jump_p'
for branches.
<R_MIPS16_26, R_MIPS_26, R_MICROMIPS_26_S1>: Suppress alignment
checks for weak undefined symbols.  Also check target alignment
within the same ISA mode.
<R_MIPS_PC16, R_MIPS_GNU_REL16_S2>: Handle cross-mode branches
in the alignment check.
<R_MICROMIPS_PC7_S1>: Add an alignment check.
<R_MICROMIPS_PC10_S1>: Likewise.
<R_MICROMIPS_PC16_S1>: Likewise.
(mips_elf_perform_relocation): Report a failure for unsupported
same-mode JALX instructions and cross-mode branches.
(_bfd_mips_elf_relocate_section) <bfd_reloc_outofrange>: Add
error messages for jumps to misaligned addresses.

gas/
* config/tc-mips.c (mips_force_relocation): Also retain branch
relocations against MIPS16 and microMIPS symbols.
(fix_bad_cross_mode_jump_p): New function.
(fix_bad_same_mode_jalx_p): Likewise.
(fix_bad_misaligned_jump_p): Likewise.
(fix_bad_cross_mode_branch_p): Likewise.
(fix_bad_misaligned_branch_p): Likewise.
(fix_validate_branch): Likewise.
(md_apply_fix) <BFD_RELOC_MIPS_JMP, BFD_RELOC_MIPS16_JMP>
<BFD_RELOC_MICROMIPS_JMP>: Separate from BFD_RELOC_MIPS_SHIFT5,
etc.  Verify the ISA mode and alignment of the jump target.
<BFD_RELOC_MIPS_21_PCREL_S2>: Replace the inline alignment check
with a call to `fix_validate_branch'.
<BFD_RELOC_MIPS_26_PCREL_S2>: Likewise.
<BFD_RELOC_16_PCREL_S2>: Likewise.
<BFD_RELOC_MICROMIPS_7_PCREL_S1, BFD_RELOC_MICROMIPS_10_PCREL_S1>
<BFD_RELOC_MICROMIPS_16_PCREL_S1>: Retain the original addend.
Verify the ISA mode and alignment of the branch target.
(md_convert_frag): Verify the ISA mode and alignment of resolved
MIPS16 branch targets.
* testsuite/gas/mips/branch-misc-1.s: Annotate non-instruction
branch targets with `.insn'.
* testsuite/gas/mips/branch-misc-5.s: Likewise.
* testsuite/gas/mips/micromips@branch-misc-5-64.d: Update
accordingly.
* testsuite/gas/mips/micromips@branch-misc-5pic-64.d: Likewise.
* testsuite/gas/mips/micromips-branch-relax.s: Annotate
non-instruction branch target with `.insn'.
* testsuite/gas/mips/micromips.s: Replace microMIPS JALX targets
with external symbols.
* testsuite/gas/mips/micromips-insn32.d: Update accordingly.
* testsuite/gas/mips/micromips-noinsn32.d: Likewise.
* testsuite/gas/mips/micromips-trap.d: Likewise.
* testsuite/gas/mips/micromips.d: Likewise.
* testsuite/gas/mips/mips16.s: Annotate non-instruction branch
targets with `.insn'.
* testsuite/gas/mips/mips16.d: Update accordingly.
* testsuite/gas/mips/mips16-64.d: Likewise.
* testsuite/gas/mips/mips16-dwarf2.s: Annotate non-instruction
branch target with `.insn'.
* testsuite/gas/mips/relax-swap3.s: Likewise.
* testsuite/gas/mips/branch-local-2.l: New list test.
* testsuite/gas/mips/branch-local-3.l: New list test.
* testsuite/gas/mips/branch-local-n32-2.l: New list test.
* testsuite/gas/mips/branch-local-n32-3.l: New list test.
* testsuite/gas/mips/branch-local-n64-2.l: New list test.
* testsuite/gas/mips/branch-local-n64-3.l: New list test.
* testsuite/gas/mips/unaligned-jump-1.l: New list test.
* testsuite/gas/mips/unaligned-jump-2.l: New list test.
* testsuite/gas/mips/unaligned-jump-3.d: New test.
* testsuite/gas/mips/unaligned-jump-mips16-1.l: New list test.
* testsuite/gas/mips/unaligned-jump-mips16-2.l: New list test.
* testsuite/gas/mips/unaligned-jump-mips16-3.d: New test.
* testsuite/gas/mips/unaligned-jump-micromips-1.l: New list
test.
* testsuite/gas/mips/unaligned-jump-micromips-2.l: New list
test.
* testsuite/gas/mips/unaligned-jump-micromips-3.d: New test.
* testsuite/gas/mips/unaligned-branch-1.l: New list test.
* testsuite/gas/mips/unaligned-branch-2.l: New list test.
* testsuite/gas/mips/unaligned-branch-3.d: New test.
* testsuite/gas/mips/unaligned-branch-r6-1.l: New list test.
* testsuite/gas/mips/unaligned-branch-r6-2.l: New list test.
* testsuite/gas/mips/unaligned-branch-r6-3.l: New list test.
* testsuite/gas/mips/unaligned-branch-r6-4.l: New list test.
* testsuite/gas/mips/unaligned-branch-r6-5.d: New test.
* testsuite/gas/mips/unaligned-branch-r6-6.d: New test.
* testsuite/gas/mips/unaligned-branch-mips16-1.l: New list test.
* testsuite/gas/mips/unaligned-branch-mips16-2.l: New list test.
* testsuite/gas/mips/unaligned-branch-mips16-3.d: New test.
* testsuite/gas/mips/unaligned-branch-micromips-1.l: New list
test.
* testsuite/gas/mips/unaligned-branch-micromips-2.l: New list
test.
* testsuite/gas/mips/unaligned-branch-micromips-3.d: New test.
* testsuite/gas/mips/branch-local-2.s: New test source.
* testsuite/gas/mips/branch-local-3.s: New test source.
* testsuite/gas/mips/branch-local-n32-2.s: New test source.
* testsuite/gas/mips/branch-local-n32-3.s: New test source.
* testsuite/gas/mips/branch-local-n64-2.s: New test source.
* testsuite/gas/mips/branch-local-n64-3.s: New test source.
* testsuite/gas/mips/unaligned-jump-1.s: New test source.
* testsuite/gas/mips/unaligned-jump-2.s: New test source.
* testsuite/gas/mips/unaligned-jump-mips16-1.s: New test source.
* testsuite/gas/mips/unaligned-jump-mips16-2.s: New test source.
* testsuite/gas/mips/unaligned-jump-micromips-1.s: New test
source.
* testsuite/gas/mips/unaligned-jump-micromips-2.s: New test
source.
* testsuite/gas/mips/unaligned-branch-1.s: New test source.
* testsuite/gas/mips/unaligned-branch-2.s: New test source.
* testsuite/gas/mips/unaligned-branch-r6-1.s: New test source.
* testsuite/gas/mips/unaligned-branch-r6-2.s: New test source.
* testsuite/gas/mips/unaligned-branch-r6-3.s: New test source.
* testsuite/gas/mips/unaligned-branch-r6-4.s: New test source.
* testsuite/gas/mips/unaligned-branch-mips16-1.s: New test
source.
* testsuite/gas/mips/unaligned-branch-mips16-2.s: New test
source.
* testsuite/gas/mips/unaligned-branch-micromips-1.s: New test
source.
* testsuite/gas/mips/unaligned-branch-micromips-2.s: New test
source.
* testsuite/gas/mips/mips.exp: Run the new tests.

ld/
* testsuite/ld-mips-elf/unaligned-jalx-1.d: Update error message
expected.
* testsuite/ld-mips-elf/unaligned-jalx-addend-1.d: Likewise.
* testsuite/ld-mips-elf/unaligned-jalx-addend-mips16-1.d:
Likewise.
* testsuite/ld-mips-elf/unaligned-jalx-addend-micromips-1.d:
Likewise.
* testsuite/ld-mips-elf/unaligned-jalx-mips16-1.d: Likewise.
* testsuite/ld-mips-elf/unaligned-jalx-micromips-1.d: Likewise.
* testsuite/ld-mips-elf/undefweak-overflow.s: Add jumps,
microMIPS BAL and MIPS16 instructions.
* testsuite/ld-mips-elf/undefweak-overflow.d: Update
accordingly.
* testsuite/ld-mips-elf/unaligned-branch-2.d: New test.
* testsuite/ld-mips-elf/unaligned-branch-r6-1.d: New test.
* testsuite/ld-mips-elf/unaligned-branch-r6-2.d: New test.
* testsuite/ld-mips-elf/unaligned-branch-mips16.d: New test.
* testsuite/ld-mips-elf/unaligned-branch-micromips.d: New test.
* testsuite/ld-mips-elf/unaligned-jump-mips16.d: New test.
* testsuite/ld-mips-elf/unaligned-jump-micromips.d: New test.
* testsuite/ld-mips-elf/unaligned-jump.d: New test.
* testsuite/ld-mips-elf/mips-elf.exp: Run the new tests.
90 files changed:
bfd/ChangeLog
bfd/elfxx-mips.c
gas/ChangeLog
gas/config/tc-mips.c
gas/testsuite/gas/mips/branch-local-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-3.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-3.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n32-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n32-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n32-3.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n32-3.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n64-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n64-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n64-3.l [new file with mode: 0644]
gas/testsuite/gas/mips/branch-local-n64-3.s [new file with mode: 0644]
gas/testsuite/gas/mips/branch-misc-1.s
gas/testsuite/gas/mips/branch-misc-5.s
gas/testsuite/gas/mips/micromips-branch-relax.s
gas/testsuite/gas/mips/micromips-insn32.d
gas/testsuite/gas/mips/micromips-noinsn32.d
gas/testsuite/gas/mips/micromips-trap.d
gas/testsuite/gas/mips/micromips.d
gas/testsuite/gas/mips/micromips.s
gas/testsuite/gas/mips/micromips@branch-misc-5-64.d
gas/testsuite/gas/mips/micromips@branch-misc-5pic-64.d
gas/testsuite/gas/mips/mips.exp
gas/testsuite/gas/mips/mips16-64.d
gas/testsuite/gas/mips/mips16-dwarf2.s
gas/testsuite/gas/mips/mips16.d
gas/testsuite/gas/mips/mips16.s
gas/testsuite/gas/mips/relax-swap3.s
gas/testsuite/gas/mips/unaligned-branch-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-micromips-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-micromips-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-micromips-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-micromips-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-micromips-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-mips16-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-mips16-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-mips16-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-mips16-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-mips16-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-3.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-3.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-4.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-4.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-5.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-branch-r6-6.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-micromips-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-micromips-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-micromips-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-micromips-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-micromips-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-mips16-1.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-mips16-1.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-mips16-2.l [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-mips16-2.s [new file with mode: 0644]
gas/testsuite/gas/mips/unaligned-jump-mips16-3.d [new file with mode: 0644]
ld/ChangeLog
ld/testsuite/ld-mips-elf/mips-elf.exp
ld/testsuite/ld-mips-elf/unaligned-branch-2.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-branch-micromips.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-branch-mips16.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-branch-r6-1.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-branch-r6-2.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-jalx-1.d
ld/testsuite/ld-mips-elf/unaligned-jalx-addend-1.d
ld/testsuite/ld-mips-elf/unaligned-jalx-addend-micromips-1.d
ld/testsuite/ld-mips-elf/unaligned-jalx-addend-mips16-1.d
ld/testsuite/ld-mips-elf/unaligned-jalx-micromips-1.d
ld/testsuite/ld-mips-elf/unaligned-jalx-mips16-1.d
ld/testsuite/ld-mips-elf/unaligned-jump-micromips.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-jump-mips16.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/unaligned-jump.d [new file with mode: 0644]
ld/testsuite/ld-mips-elf/undefweak-overflow.d
ld/testsuite/ld-mips-elf/undefweak-overflow.s