This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Fix MIPS ELF64 problem with .gpword/.8byte combinations
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: binutils at sources dot redhat dot com
- Date: Thu, 07 Oct 2004 20:02:09 +0100
- Subject: Fix MIPS ELF64 problem with .gpword/.8byte combinations
This patch fixes a problem with the way composite relocations are
handled by tc-mips.c:tc_gen_reloc():
/* We are not done if this is a composite relocation to set up gp. */
assert (! fixP->fx_pcrel);
if (fixP->fx_addsy == NULL
&& !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
|| (fixP->fx_r_type == BFD_RELOC_64
&& (previous_fx_r_type == BFD_RELOC_GPREL32
|| previous_fx_r_type == BFD_RELOC_GPREL16))
|| (previous_fx_r_type == BFD_RELOC_MIPS_SUB
&& (fixP->fx_r_type == BFD_RELOC_HI16_S
|| fixP->fx_r_type == BFD_RELOC_LO16))))
fixP->fx_done = 1;
previous_fx_r_type = fixP->fx_r_type;
The author clearly intended to check for the composite fixup sequences
generated by:
%hi(%neg(%gp_rel(...)))
%lo(%neg(%gp_rel(...)))
.gpdword
but the code fails to check whether the two fixups are for the same field.
As it stands, if we have:
.gpword foo
and:
.8byte bar - foo
with no other fixups inbetween, the .8byte's fixup will be wrongly
interpreted as being part of a ".gpdword foo" directive. That means
we'll always generate a reloc for the .8byte, even if "bar - foo" is
an assembly-time constant.
Now this _ought_ to be harmless, but there's also a bug in the way
elf64-mips.c outputs relocations against absolute symbols. The end
result is either a message of the form:
a.out: symbol `*ABS*' required but not present
or a relocation against a non-existent symbol. I'm about to post a
patch to fix that, but we still don't want a relocation in the first
place, so...
...this patch fixes it by using the fx_tcbit to mark composite
relocations. Tested on mips64-elf and mips64-linux-gnu.
OK to install?
Richard
gas/
* config/tc-mips.c (append_insn): Set fx_tcbit for composite relocs.
(md_apply_fix3): Don't treat composite relocs as done.
gas/testsuite/
* gas/mips/elf-rel21.[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.271
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.271 tc-mips.c
*** gas/config/tc-mips.c 4 Oct 2004 23:25:28 -0000 1.271
--- gas/config/tc-mips.c 7 Oct 2004 18:35:35 -0000
*************** #define emit_nop() \
*** 2231,2236 ****
--- 2231,2240 ----
fixp[i] = fix_new_exp (frag_now, fixp[0]->fx_where,
fixp[0]->fx_size, address_expr,
FALSE, reloc_type[i]);
+
+ /* Use fx_tcbit to mark compound relocs. */
+ fixp[0]->fx_tcbit = 1;
+ fixp[i]->fx_tcbit = 1;
}
}
}
*************** md_apply_fix3 (fixS *fixP, valueT *valP,
*** 10897,10903 ****
{
bfd_byte *buf;
long insn;
- static int previous_fx_r_type = 0;
reloc_howto_type *howto;
/* We ignore generic BFD relocations we don't know about. */
--- 10901,10906 ----
*************** md_apply_fix3 (fixS *fixP, valueT *valP,
*** 10915,10932 ****
buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
- /* We are not done if this is a composite relocation to set up gp. */
assert (! fixP->fx_pcrel);
! if (fixP->fx_addsy == NULL
! && !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
! || (fixP->fx_r_type == BFD_RELOC_64
! && (previous_fx_r_type == BFD_RELOC_GPREL32
! || previous_fx_r_type == BFD_RELOC_GPREL16))
! || (previous_fx_r_type == BFD_RELOC_MIPS_SUB
! && (fixP->fx_r_type == BFD_RELOC_HI16_S
! || fixP->fx_r_type == BFD_RELOC_LO16))))
fixP->fx_done = 1;
- previous_fx_r_type = fixP->fx_r_type;
switch (fixP->fx_r_type)
{
--- 10918,10937 ----
buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
assert (! fixP->fx_pcrel);
!
! /* Don't treat parts of a composite relocation as done. There are two
! reasons for this:
!
! (1) The second and third parts will be against 0 (RSS_UNDEF) but
! should nevertheless be emitted if the first part is.
!
! (2) In normal usage, composite relocations are never assembly-time
! constants. The easiest way of dealing with the pathological
! exceptions is to generate a relocation against STN_UNDEF and
! leave everything up to the linker. */
! if (fixP->fx_addsy == NULL && fixP->fx_tcbit == 0)
fixP->fx_done = 1;
switch (fixP->fx_r_type)
{
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.93
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.93 mips.exp
*** gas/testsuite/gas/mips/mips.exp 18 Aug 2004 15:58:12 -0000 1.93
--- gas/testsuite/gas/mips/mips.exp 7 Oct 2004 18:35:36 -0000
*************** if { [istarget mips*-*-*] } then {
*** 662,667 ****
--- 662,670 ----
}
run_dump_test "elf-rel19"
run_dump_test "elf-rel20"
+ if $has_newabi {
+ run_dump_test "elf-rel21"
+ }
if { !$no_mips16 } {
run_dump_test "${tmips}mips${el}16-e"
*** /dev/null Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel21.d Thu Oct 7 19:06:49 2004
***************
*** 0 ****
--- 1,9 ----
+ #as: -march=mips3 -mabi=64
+ #readelf: --relocs
+ #name: MIPS ELF reloc 21
+
+ Relocation section '\.rela\.data' .*:
+ .*
+ .* R_MIPS_GPREL32 * 0+00 * \.data \+ c
+ * Type2: R_MIPS_NONE *
+ * Type3: R_MIPS_NONE *
*** /dev/null Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel21.s Thu Oct 7 19:04:04 2004
***************
*** 0 ****
--- 1,7 ----
+ .abicalls
+ .data
+ .gpword foo
+ .8byte bar - foo
+ foo:
+ .word 0
+ bar: