This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]