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.
This commit is contained in:
Maciej W. Rozycki
2016-07-19 13:59:28 +01:00
parent 065251a0d7
commit 9d862524f6
90 changed files with 5968 additions and 113 deletions

View File

@@ -14800,6 +14800,19 @@ mips_force_relocation (fixS *fixp)
|| fixp->fx_r_type == BFD_RELOC_MICROMIPS_16_PCREL_S1)
return 1;
/* We want to keep R_MIPS_PC26_S2, R_MIPS_PC21_S2, BFD_RELOC_16_PCREL_S2
BFD_RELOC_MIPS_21_PCREL_S2 and BFD_RELOC_MIPS_26_PCREL_S2 relocations
against MIPS16 and microMIPS symbols so that we do cross-mode branch
diagnostics. */
if ((fixp->fx_r_type == R_MIPS_PC26_S2
|| fixp->fx_r_type == R_MIPS_PC21_S2
|| fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
|| fixp->fx_r_type == BFD_RELOC_MIPS_21_PCREL_S2
|| fixp->fx_r_type == BFD_RELOC_MIPS_26_PCREL_S2)
&& fixp->fx_addsy
&& ELF_ST_IS_COMPRESSED (S_GET_OTHER (fixp->fx_addsy)))
return 1;
/* We want all PC-relative relocations to be kept for R6 relaxation. */
if (ISA_IS_R6 (file_mips_opts.isa)
&& (fixp->fx_r_type == BFD_RELOC_16_PCREL_S2
@@ -14854,6 +14867,186 @@ write_reloc_insn (char *buf, bfd_reloc_code_real_type reloc,
write_insn (buf, insn);
}
/* Return TRUE if the instruction pointed to by FIXP is an invalid jump
to a symbol in another ISA mode, which cannot be converted to JALX. */
static bfd_boolean
fix_bad_cross_mode_jump_p (fixS *fixP)
{
unsigned long opcode;
int other;
char *buf;
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
other = S_GET_OTHER (fixP->fx_addsy);
buf = fixP->fx_frag->fr_literal + fixP->fx_where;
opcode = read_reloc_insn (buf, fixP->fx_r_type) >> 26;
switch (fixP->fx_r_type)
{
case BFD_RELOC_MIPS_JMP:
return opcode != 0x1d && opcode != 0x03 && ELF_ST_IS_COMPRESSED (other);
case BFD_RELOC_MICROMIPS_JMP:
return opcode != 0x3c && opcode != 0x3d && !ELF_ST_IS_MICROMIPS (other);
default:
return FALSE;
}
}
/* Return TRUE if the instruction pointed to by FIXP is an invalid JALX
jump to a symbol in the same ISA mode. */
static bfd_boolean
fix_bad_same_mode_jalx_p (fixS *fixP)
{
unsigned long opcode;
int other;
char *buf;
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
other = S_GET_OTHER (fixP->fx_addsy);
buf = fixP->fx_frag->fr_literal + fixP->fx_where;
opcode = read_reloc_insn (buf, fixP->fx_r_type) >> 26;
switch (fixP->fx_r_type)
{
case BFD_RELOC_MIPS_JMP:
return opcode == 0x1d && !ELF_ST_IS_COMPRESSED (other);
case BFD_RELOC_MIPS16_JMP:
return opcode == 0x07 && ELF_ST_IS_COMPRESSED (other);
case BFD_RELOC_MICROMIPS_JMP:
return opcode == 0x3c && ELF_ST_IS_COMPRESSED (other);
default:
return FALSE;
}
}
/* Return TRUE if the instruction pointed to by FIXP is an invalid jump
to a symbol whose value plus addend is not aligned according to the
ultimate (after linker relaxation) jump instruction's immediate field
requirement, either to (1 << SHIFT), or, for jumps from microMIPS to
regular MIPS code, to (1 << 2). */
static bfd_boolean
fix_bad_misaligned_jump_p (fixS *fixP, int shift)
{
bfd_boolean micro_to_mips_p;
valueT val;
int other;
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
other = S_GET_OTHER (fixP->fx_addsy);
val = S_GET_VALUE (fixP->fx_addsy) | ELF_ST_IS_COMPRESSED (other);
val += fixP->fx_offset;
micro_to_mips_p = (fixP->fx_r_type == BFD_RELOC_MICROMIPS_JMP
&& !ELF_ST_IS_MICROMIPS (other));
return ((val & ((1 << (micro_to_mips_p ? 2 : shift)) - 1))
!= ELF_ST_IS_COMPRESSED (other));
}
/* Return TRUE if the instruction pointed to by FIXP is an invalid branch
to a symbol whose annotation indicates another ISA mode. For absolute
symbols check the ISA bit instead. */
static bfd_boolean
fix_bad_cross_mode_branch_p (fixS *fixP)
{
bfd_boolean absolute_p;
unsigned long opcode;
asection *symsec;
valueT val;
int other;
char *buf;
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
symsec = S_GET_SEGMENT (fixP->fx_addsy);
absolute_p = bfd_is_abs_section (symsec);
val = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
other = S_GET_OTHER (fixP->fx_addsy);
buf = fixP->fx_frag->fr_literal + fixP->fx_where;
opcode = read_reloc_insn (buf, fixP->fx_r_type) >> 16;
switch (fixP->fx_r_type)
{
case BFD_RELOC_16_PCREL_S2:
case BFD_RELOC_MIPS_21_PCREL_S2:
case BFD_RELOC_MIPS_26_PCREL_S2:
return absolute_p ? val & 1 : ELF_ST_IS_COMPRESSED (other);
case BFD_RELOC_MIPS16_16_PCREL_S1:
return absolute_p ? !(val & 1) : !ELF_ST_IS_MIPS16 (other);
case BFD_RELOC_MICROMIPS_7_PCREL_S1:
case BFD_RELOC_MICROMIPS_10_PCREL_S1:
case BFD_RELOC_MICROMIPS_16_PCREL_S1:
return absolute_p ? !(val & 1) : !ELF_ST_IS_MICROMIPS (other);
default:
abort ();
}
}
/* Return TRUE if the symbol plus addend associated with a regular MIPS
branch instruction pointed to by FIXP is not aligned according to the
branch instruction's immediate field requirement. We need the addend
to preserve the ISA bit and also the sum must not have bit 2 set. We
must explicitly OR in the ISA bit from symbol annotation as the bit
won't be set in the symbol's value then. */
static bfd_boolean
fix_bad_misaligned_branch_p (fixS *fixP)
{
bfd_boolean absolute_p;
asection *symsec;
valueT isa_bit;
valueT val;
valueT off;
int other;
if (!fixP->fx_addsy || S_FORCE_RELOC (fixP->fx_addsy, TRUE))
return FALSE;
symsec = S_GET_SEGMENT (fixP->fx_addsy);
absolute_p = bfd_is_abs_section (symsec);
val = S_GET_VALUE (fixP->fx_addsy);
other = S_GET_OTHER (fixP->fx_addsy);
off = fixP->fx_offset;
isa_bit = absolute_p ? (val + off) & 1 : ELF_ST_IS_COMPRESSED (other);
val |= ELF_ST_IS_COMPRESSED (other);
val += off;
return (val & 0x3) != isa_bit;
}
/* Make the necessary checks on a regular MIPS branch pointed to by FIXP
and its calculated value VAL. */
static void
fix_validate_branch (fixS *fixP, valueT val)
{
if (fixP->fx_done && (val & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (0x%lx)"),
(long) (val + md_pcrel_from (fixP)));
else if (fix_bad_cross_mode_branch_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to a symbol in another ISA mode"));
else if (fix_bad_misaligned_branch_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (0x%lx)"),
(long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot encode misaligned addend "
"in the relocatable field (0x%lx)"),
(long) fixP->fx_offset);
}
/* Apply a fixup to the object file. */
void
@@ -14962,6 +15155,40 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_MIPS_JMP:
case BFD_RELOC_MIPS16_JMP:
case BFD_RELOC_MICROMIPS_JMP:
{
int shift;
gas_assert (!fixP->fx_done);
/* Shift is 2, unusually, for microMIPS JALX. */
if (fixP->fx_r_type == BFD_RELOC_MICROMIPS_JMP
&& (read_compressed_insn (buf, 4) >> 26) != 0x3c)
shift = 1;
else
shift = 2;
if (fix_bad_cross_mode_jump_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("jump to a symbol in another ISA mode"));
else if (fix_bad_same_mode_jalx_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("JALX to a symbol in the same ISA mode"));
else if (fix_bad_misaligned_jump_p (fixP, shift))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("jump to misaligned address (0x%lx)"),
(long) (S_GET_VALUE (fixP->fx_addsy)
+ fixP->fx_offset));
else if (HAVE_IN_PLACE_ADDENDS
&& (fixP->fx_offset & ((1 << shift) - 1)) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot encode misaligned addend "
"in the relocatable field (0x%lx)"),
(long) fixP->fx_offset);
}
/* Fall through. */
case BFD_RELOC_MIPS_SHIFT5:
case BFD_RELOC_MIPS_SHIFT6:
case BFD_RELOC_MIPS_GOT_DISP:
@@ -14997,8 +15224,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_MIPS16_HI16:
case BFD_RELOC_MIPS16_HI16_S:
case BFD_RELOC_MIPS16_LO16:
case BFD_RELOC_MIPS16_JMP:
case BFD_RELOC_MICROMIPS_JMP:
case BFD_RELOC_MICROMIPS_GOT_DISP:
case BFD_RELOC_MICROMIPS_GOT_PAGE:
case BFD_RELOC_MICROMIPS_GOT_OFST:
@@ -15072,9 +15297,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_MIPS_21_PCREL_S2:
if ((*valP & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (%lx)"), (long) *valP);
fix_validate_branch (fixP, *valP);
if (!fixP->fx_done)
break;
@@ -15090,9 +15313,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_MIPS_26_PCREL_S2:
if ((*valP & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (%lx)"), (long) *valP);
fix_validate_branch (fixP, *valP);
if (!fixP->fx_done)
break;
@@ -15150,9 +15371,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_16_PCREL_S2:
if ((*valP & 0x3) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (%lx)"), (long) *valP);
fix_validate_branch (fixP, *valP);
/* We need to save the bits in the instruction since fixup_segment()
might be deleting the relocation entry (i.e., a branch within
@@ -15205,6 +15424,21 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
case BFD_RELOC_MICROMIPS_10_PCREL_S1:
case BFD_RELOC_MICROMIPS_16_PCREL_S1:
gas_assert (!fixP->fx_done);
if (fix_bad_cross_mode_branch_p (fixP))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to a symbol in another ISA mode"));
else if (fixP->fx_addsy
&& !S_FORCE_RELOC (fixP->fx_addsy, TRUE)
&& !bfd_is_abs_section (S_GET_SEGMENT (fixP->fx_addsy))
&& (fixP->fx_offset & 0x1) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch to misaligned address (0x%lx)"),
(long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x1) != 0)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("cannot encode misaligned addend "
"in the relocatable field (0x%lx)"),
(long) fixP->fx_offset);
break;
case BFD_RELOC_VTABLE_INHERIT:
@@ -17814,6 +18048,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
offsetT val;
char *buf;
unsigned int user_length, length;
bfd_boolean need_reloc;
unsigned long insn;
bfd_boolean ext;
segT symsec;
@@ -17823,6 +18058,13 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
ext = RELAX_MIPS16_EXTENDED (fragp->fr_subtype);
val = resolve_symbol_value (fragp->fr_symbol) + fragp->fr_offset;
symsec = S_GET_SEGMENT (fragp->fr_symbol);
need_reloc = (S_FORCE_RELOC (fragp->fr_symbol, TRUE)
|| (operand->root.type == OP_PCREL
? asec != symsec
: !bfd_is_abs_section (symsec)));
if (operand->root.type == OP_PCREL)
{
const struct mips_pcrel_operand *pcrel_op;
@@ -17835,6 +18077,16 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
complicated; see mips16_extended_frag. */
if (pcrel_op->include_isa_bit)
{
if (!need_reloc)
{
if (!ELF_ST_IS_MIPS16 (S_GET_OTHER (fragp->fr_symbol)))
as_bad_where (fragp->fr_file, fragp->fr_line,
_("branch to a symbol in another ISA mode"));
else if ((fragp->fr_offset & 0x1) != 0)
as_bad_where (fragp->fr_file, fragp->fr_line,
_("branch to misaligned address (0x%lx)"),
(long) val);
}
addr += 2;
if (ext)
addr += 2;
@@ -17875,11 +18127,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
else
user_length = 0;
symsec = S_GET_SEGMENT (fragp->fr_symbol);
if (S_FORCE_RELOC (fragp->fr_symbol, TRUE)
|| (operand->root.type == OP_PCREL
? asec != symsec
: !bfd_is_abs_section (symsec)))
if (need_reloc)
{
bfd_reloc_code_real_type reloc = BFD_RELOC_NONE;
expressionS exp;