This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: MIPS patch to correct the size of %neg() fixups
Richard Sandiford wrote:
[snip]
> It sounds like you're saying that:
>
> R_MIPS_GPREL16
> R_MIPS_SUB
> R_MIPS_HI16
>
> should be treated as having a 64-bit relocation field, but that's
> exactly what I'm trying to avoid. ;)
>
> The ABI says:
>
> The implication [...] is that a relocation type consists of two
> components. The first component is the operation to be
> performed [...]. The second component is a specification of
> field to be relocated, which is relevant only for the first
> operation in the sequence (where it may specify an addend for
> the Elf64_Rel relocation) and the last operation in a sequence
> (where it specifies the field rewritten by the relocation).
Ah, thanks, I had missed this.
Another thing: At least the FIXME about RSS_* values should be retained,
so I prefer a patch like the one below.
Thiemo
diff -urpNX /bigdisk/src/gcc-exclude source-orig/gas/config/tc-mips.c source/gas/config/tc-mips.c
--- source-orig/gas/config/tc-mips.c Tue Jun 10 17:05:26 2003
+++ source/gas/config/tc-mips.c Wed Jun 11 12:49:42 2003
@@ -2154,15 +2173,22 @@ append_insn (place, ip, address_expr, re
}
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]);
+ 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),
+ bfd_get_reloc_size (howto),
address_expr,
reloc_type[0] == BFD_RELOC_16_PCREL_S2,
reloc_type[0]);
@@ -2216,31 +2242,9 @@ append_insn (place, ip, address_expr, re
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;
+ fixp[1] = fix_new_exp (frag_now, fixp[0]->fx_where,
+ fixp[0]->fx_size, address_expr,
+ FALSE, reloc_type[1]);
if (reloc_type[2] != BFD_RELOC_UNUSED)
{
@@ -2249,33 +2253,9 @@ append_insn (place, ip, address_expr, re
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;
+ fixp[2] = fix_new_exp (frag_now, fixp[0]->fx_where,
+ fixp[0]->fx_size, address_expr,
+ FALSE, reloc_type[2]);
}
}
}