This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
MIPS patch to correct the size of %neg() fixups
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Cc: echristo at redhat dot com, drow at mvista dot com
- Date: 10 Jun 2003 20:56:26 +0100
- Subject: MIPS patch to correct the size of %neg() fixups
This code:
foo:
lui $2,%hi(%neg(%gp_rel(foo)))
sub $sp,$sp,28
causes an internal error:
/tmp/abort.s:2: Error: internal error: fixup not contained within frag
gas is creating a separate fixup for the each relocation operator
in the first instruction. The size of the fixup is determined
by the corresponding relocation's howto.
Problem is, R_MIPS_SUB is a 64-bit relocation, so it gets a 64-bit
fixup. The "sub" macro then forces the start of a new frag, so the
R_MIPS_SUB fixup goes beyond the end of the old frag.
As I understand it, the relocation field should be determined
by the outermost operator (%hi() in this case) and all three
fixups should use that size.
Also, the handling of the second and third operators in a compound
relocation had this code cut&paste from the first:
/* These relocations can have an addend that won't fit in
4 octets for 64bit assembly. */
if (HAVE_64BIT_GPRS
&& ! howto->partial_inplace
&& (reloc_type[1] == BFD_RELOC_16
...
I think this is unnecessary because both fixups have an addend of zero.
Patch tested on mips-sgi-irix6.5 and mips64-elf. No regressions.
OK to install?
Daniel: if possible, I'd really like this to go into 2.14.
It's needed to bootstrap gcc 3.4 on irix.
Richard
gas/
* config/tc-mips.c (append_insn): In a compound relocation, take the
field width from the final (outermost) operator.
gas/testsuite/
* gas/mips/elf-rel15.[sd]: New test.
* gas/mips/mips.exp: Run it.
Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.212
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.212 tc-mips.c
*** gas/config/tc-mips.c 4 Jun 2003 06:38:38 -0000 1.212
--- gas/config/tc-mips.c 10 Jun 2003 19:39:31 -0000
*************** #define emit_nop() \
*** 2154,2166 ****
}
else
{
- reloc_howto_type *howto;
-
need_reloc:
/* Don't generate a reloc if we are writing into a variant frag. */
if (place == NULL)
{
! howto = bfd_reloc_type_lookup (stdoutput, reloc_type[0]);
fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
bfd_get_reloc_size(howto),
address_expr,
--- 2154,2173 ----
}
else
{
need_reloc:
/* Don't generate a reloc if we are writing into a variant frag. */
if (place == NULL)
{
! reloc_howto_type *howto;
! int i;
!
! /* In a compound relocation, it is the final (outermost)
! operator that determines the relocated field. */
! for (i = 1; i < 3; i++)
! if (reloc_type[i] == BFD_RELOC_UNUSED)
! break;
!
! howto = bfd_reloc_type_lookup (stdoutput, reloc_type[i - 1]);
fixp[0] = fix_new_exp (frag_now, f - frag_now->fr_literal,
bfd_get_reloc_size(howto),
address_expr,
*************** #define emit_nop() \
*** 2207,2283 ****
hi_fixup->seg = now_seg;
}
! if (reloc_type[1] != BFD_RELOC_UNUSED)
! {
! /* FIXME: This symbol can be one of
! RSS_UNDEF, RSS_GP, RSS_GP0, RSS_LOC. */
! address_expr->X_op = O_absent;
! address_expr->X_add_symbol = 0;
! address_expr->X_add_number = 0;
!
! howto = bfd_reloc_type_lookup (stdoutput, reloc_type[1]);
! fixp[1] = fix_new_exp (frag_now, f - frag_now->fr_literal,
! bfd_get_reloc_size(howto),
! address_expr, FALSE, reloc_type[1]);
!
! /* These relocations can have an addend that won't fit in
! 4 octets for 64bit assembly. */
! if (HAVE_64BIT_GPRS
! && ! howto->partial_inplace
! && (reloc_type[1] == BFD_RELOC_16
! || reloc_type[1] == BFD_RELOC_32
! || reloc_type[1] == BFD_RELOC_MIPS_JMP
! || reloc_type[1] == BFD_RELOC_HI16_S
! || reloc_type[1] == BFD_RELOC_LO16
! || reloc_type[1] == BFD_RELOC_GPREL16
! || reloc_type[1] == BFD_RELOC_MIPS_LITERAL
! || reloc_type[1] == BFD_RELOC_GPREL32
! || reloc_type[1] == BFD_RELOC_64
! || reloc_type[1] == BFD_RELOC_CTOR
! || reloc_type[1] == BFD_RELOC_MIPS_SUB
! || reloc_type[1] == BFD_RELOC_MIPS_HIGHEST
! || reloc_type[1] == BFD_RELOC_MIPS_HIGHER
! || reloc_type[1] == BFD_RELOC_MIPS_SCN_DISP
! || reloc_type[1] == BFD_RELOC_MIPS_REL16
! || reloc_type[1] == BFD_RELOC_MIPS_RELGOT))
! fixp[1]->fx_no_overflow = 1;
!
! if (reloc_type[2] != BFD_RELOC_UNUSED)
! {
! address_expr->X_op = O_absent;
! address_expr->X_add_symbol = 0;
! address_expr->X_add_number = 0;
!
! howto = bfd_reloc_type_lookup (stdoutput, reloc_type[2]);
! fixp[2] = fix_new_exp (frag_now,
! f - frag_now->fr_literal,
! bfd_get_reloc_size(howto),
! address_expr, FALSE,
! reloc_type[2]);
! /* These relocations can have an addend that won't fit in
! 4 octets for 64bit assembly. */
! if (HAVE_64BIT_GPRS
! && ! howto->partial_inplace
! && (reloc_type[2] == BFD_RELOC_16
! || reloc_type[2] == BFD_RELOC_32
! || reloc_type[2] == BFD_RELOC_MIPS_JMP
! || reloc_type[2] == BFD_RELOC_HI16_S
! || reloc_type[2] == BFD_RELOC_LO16
! || reloc_type[2] == BFD_RELOC_GPREL16
! || reloc_type[2] == BFD_RELOC_MIPS_LITERAL
! || reloc_type[2] == BFD_RELOC_GPREL32
! || reloc_type[2] == BFD_RELOC_64
! || reloc_type[2] == BFD_RELOC_CTOR
! || reloc_type[2] == BFD_RELOC_MIPS_SUB
! || reloc_type[2] == BFD_RELOC_MIPS_HIGHEST
! || reloc_type[2] == BFD_RELOC_MIPS_HIGHER
! || reloc_type[2] == BFD_RELOC_MIPS_SCN_DISP
! || reloc_type[2] == BFD_RELOC_MIPS_REL16
! || reloc_type[2] == BFD_RELOC_MIPS_RELGOT))
! fixp[2]->fx_no_overflow = 1;
! }
! }
}
}
}
--- 2214,2230 ----
hi_fixup->seg = now_seg;
}
! for (i = 1; i < 3; i++)
! if (reloc_type[i] != BFD_RELOC_UNUSED)
! {
! address_expr->X_op = O_absent;
! address_expr->X_add_symbol = 0;
! address_expr->X_add_number = 0;
! fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where,
! fixp[0]->fx_size, address_expr,
! FALSE, reloc_type[i]);
! }
}
}
}
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.72
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.72 mips.exp
*** gas/testsuite/gas/mips/mips.exp 22 May 2003 12:13:43 -0000 1.72
--- gas/testsuite/gas/mips/mips.exp 10 Jun 2003 19:39:32 -0000
*************** if { [istarget mips*-*-*] } then {
*** 645,650 ****
--- 645,652 ----
run_dump_test "elf-rel14"
if $has_newabi {
+ run_dump_test "elf-rel15"
+
run_dump_test "elf-rel-got-n32"
run_dump_test "elf-rel-xgot-n32"
run_dump_test "elf-rel-got-n64"
*** /dev/null Thu Apr 11 15:25:15 2002
--- gas/testsuite/gas/mips/elf-rel15.d Tue Jun 10 20:08:39 2003
***************
*** 0 ****
--- 1,14 ----
+ #objdump: -dr
+ #as: -mabi=n32 -mips3
+
+ .*: file format .*
+
+ Disassembly of section \.text:
+
+ 00000000 <foo>:
+ 0: 3c020000 lui v0,0x0
+ 0: R_MIPS_GPREL16 \.text
+ 0: R_MIPS_SUB \*ABS\*
+ 0: R_MIPS_HI16 \*ABS\*
+ 4: 23bdffe4 addi sp,sp,-28
+ ...
*** /dev/null Thu Apr 11 15:25:15 2002
--- gas/testsuite/gas/mips/elf-rel15.s Tue Jun 10 20:08:03 2003
***************
*** 0 ****
--- 1,4 ----
+ foo:
+ lui $2,%hi(%neg(%gp_rel(foo)))
+ sub $sp,$sp,28
+ .space 16