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]

Re: Fix MIPS ELF64 problem with .gpword/.8byte combinations


Argh!  After committing the patch, I realised that I hadn't changed
the code for .cpsetup and .gpdword, both of which generate composite
relocations.  (And, of course, the testsuite didn't pick up the
mistake... ;/  Not that that's any excuse.)

The patch below fixes this.  It extends macro_build so that it can
take both single and composite relocations.  This allows the .cpsetup
code to handle the lui and addiu using single calls to macro_build.

The change to macro_build in turn needs a fix to append_insn, which
clobbers address_expr when building the second and third fixups of a
composite relocation.  We can avoid using an expression completely
by calling fix_new() instead of fix_new_exp().

The .gpdword fix is trivial: we just need to set fx_tcbit directly.

Tested as before on mips64-elf and mips64-linux-gnu.  OK to install?
Really sorry for the breakage...

Richard


gas/
	* config/tc-mips.c (append_insn): Use fix_new rather than fix_new_exp
	to build the second and third fixups for a composite relocation.
	(macro_read_relocs): New function.
	(macro_build): Use it.
	(s_cpsetup): Pass all three composite relocation codes to macro_build.
	Simplify fragging code accordingly.
	(s_gpdword): Use fix_new rather than fix_new_exp for the second part
	of the composite relocation.  Set fx_tcbit in both fixups.

gas/testsuite/
	* gas/mips/elf-rel{23,24}.[sd]: New tests.
	* gas/mips/mips.exp: New test.

Index: gas/config/tc-mips.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-mips.c,v
retrieving revision 1.272
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.272 tc-mips.c
*** gas/config/tc-mips.c	7 Oct 2004 19:12:52 -0000	1.272
--- gas/config/tc-mips.c	7 Oct 2004 22:15:00 -0000
*************** #define emit_nop()					\
*** 2224,2236 ****
  	  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]);
  
  		/* Use fx_tcbit to mark compound relocs.  */
  		fixp[0]->fx_tcbit = 1;
--- 2224,2232 ----
  	  for (i = 1; i < 3; i++)
  	    if (reloc_type[i] != BFD_RELOC_UNUSED)
  	      {
! 		fixp[i] = fix_new (frag_now, fixp[0]->fx_where,
! 				   fixp[0]->fx_size, NULL, 0,
! 				   FALSE, reloc_type[i]);
  
  		/* Use fx_tcbit to mark compound relocs.  */
  		fixp[0]->fx_tcbit = 1;
*************** macro_end (void)
*** 2975,2980 ****
--- 2971,2994 ----
      }
  }
  
+ /* Read a macro's relocation codes from *ARGS and store them in *R.
+    The first argument in *ARGS will be either the code for a single
+    relocation or -1 followed by the three codes that make up a
+    composite relocation.  */
+ 
+ static void
+ macro_read_relocs (va_list *args, bfd_reloc_code_real_type *r)
+ {
+   int i, next;
+ 
+   next = va_arg (*args, int);
+   if (next >= 0)
+     r[0] = (bfd_reloc_code_real_type) next;
+   else
+     for (i = 0; i < 3; i++)
+       r[i] = (bfd_reloc_code_real_type) va_arg (*args, int);
+ }
+ 
  /* Build an instruction created by a macro expansion.  This is passed
     a pointer to the count of instructions created so far, an
     expression, the name of the instruction to build, an operand format
*************** macro_build (expressionS *ep, const char
*** 3138,3144 ****
  	case 'i':
  	case 'j':
  	case 'o':
! 	  *r = (bfd_reloc_code_real_type) va_arg (args, int);
  	  assert (*r == BFD_RELOC_GPREL16
  		  || *r == BFD_RELOC_MIPS_LITERAL
  		  || *r == BFD_RELOC_MIPS_HIGHER
--- 3152,3158 ----
  	case 'i':
  	case 'j':
  	case 'o':
! 	  macro_read_relocs (&args, r);
  	  assert (*r == BFD_RELOC_GPREL16
  		  || *r == BFD_RELOC_MIPS_LITERAL
  		  || *r == BFD_RELOC_MIPS_HIGHER
*************** macro_build (expressionS *ep, const char
*** 3154,3160 ****
  	  continue;
  
  	case 'u':
! 	  *r = (bfd_reloc_code_real_type) va_arg (args, int);
  	  assert (ep != NULL
  		  && (ep->X_op == O_constant
  		      || (ep->X_op == O_symbol
--- 3168,3174 ----
  	  continue;
  
  	case 'u':
! 	  macro_read_relocs (&args, r);
  	  assert (ep != NULL
  		  && (ep->X_op == O_constant
  		      || (ep->X_op == O_symbol
*************** s_cpsetup (int ignore ATTRIBUTE_UNUSED)
*** 11837,11843 ****
    expressionS ex_off;
    expressionS ex_sym;
    int reg1;
-   char *f;
  
    /* If we are not generating SVR4 PIC code, .cpsetup is ignored.
       We also need NewABI support.  */
--- 11851,11856 ----
*************** s_cpsetup (int ignore ATTRIBUTE_UNUSED)
*** 11893,11915 ****
      macro_build (NULL, "daddu", "d,v,t", mips_cpreturn_register,
  		 mips_gp_register, 0);
  
!   /* Ensure there's room for the next two instructions, so that `f'
!      doesn't end up with an address in the wrong frag.  */
!   frag_grow (8);
!   f = frag_more (0);
!   macro_build (&ex_sym, "lui", "t,u", mips_gp_register, BFD_RELOC_GPREL16);
!   fix_new (frag_now, f - frag_now->fr_literal,
! 	   8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
!   fix_new (frag_now, f - frag_now->fr_literal,
! 	   4, NULL, 0, 0, BFD_RELOC_HI16_S);
  
-   f = frag_more (0);
    macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register,
! 	       mips_gp_register, BFD_RELOC_GPREL16);
!   fix_new (frag_now, f - frag_now->fr_literal,
! 	   8, NULL, 0, 0, BFD_RELOC_MIPS_SUB);
!   fix_new (frag_now, f - frag_now->fr_literal,
! 	   4, NULL, 0, 0, BFD_RELOC_LO16);
  
    macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
  	       mips_gp_register, reg1);
--- 11906,11917 ----
      macro_build (NULL, "daddu", "d,v,t", mips_cpreturn_register,
  		 mips_gp_register, 0);
  
!   macro_build (&ex_sym, "lui", "t,u", mips_gp_register,
! 	       -1, BFD_RELOC_GPREL16, BFD_RELOC_MIPS_SUB, BFD_RELOC_HI16_S);
  
    macro_build (&ex_sym, "addiu", "t,r,j", mips_gp_register,
! 	       mips_gp_register, -1, BFD_RELOC_GPREL16,
! 	       BFD_RELOC_MIPS_SUB, BFD_RELOC_LO16);
  
    macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t", mips_gp_register,
  	       mips_gp_register, reg1);
*************** s_gpdword (int ignore ATTRIBUTE_UNUSED)
*** 12093,12106 ****
    p = frag_more (8);
    md_number_to_chars (p, 0, 8);
    fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
! 	       BFD_RELOC_GPREL32);
  
    /* GPREL32 composed with 64 gives a 64-bit GP offset.  */
!   ex.X_op = O_absent;
!   ex.X_add_symbol = 0;
!   ex.X_add_number = 0;
!   fix_new_exp (frag_now, p - frag_now->fr_literal, 8, &ex, FALSE,
! 	       BFD_RELOC_64);
  
    demand_empty_rest_of_line ();
  }
--- 12095,12105 ----
    p = frag_more (8);
    md_number_to_chars (p, 0, 8);
    fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE,
! 	       BFD_RELOC_GPREL32)->fx_tcbit = 1;
  
    /* GPREL32 composed with 64 gives a 64-bit GP offset.  */
!   fix_new (frag_now, p - frag_now->fr_literal, 8, NULL, 0,
! 	   FALSE, BFD_RELOC_64)->fx_tcbit = 1;
  
    demand_empty_rest_of_line ();
  }
Index: gas/testsuite/gas/mips/mips.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/mips/mips.exp,v
retrieving revision 1.95
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.95 mips.exp
*** gas/testsuite/gas/mips/mips.exp	7 Oct 2004 19:15:29 -0000	1.95
--- gas/testsuite/gas/mips/mips.exp	7 Oct 2004 22:15:01 -0000
*************** if { [istarget mips*-*-*] } then {
*** 665,670 ****
--- 665,672 ----
  	if $has_newabi {
  	    run_dump_test "elf-rel21"
  	    run_dump_test "elf-rel22"
+ 	    run_dump_test "elf-rel23"
+ 	    run_dump_test "elf-rel24"
  	}
  
  	if { !$no_mips16 } {
*** /dev/null	Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel23.d	Thu Oct  7 22:56:10 2004
***************
*** 0 ****
--- 1,19 ----
+ #as: -march=mips3 -mabi=64
+ #objdump: -dr -Mgpr-names=numeric
+ #name: MIPS ELF reloc 23
+ 
+ .*: * file format elf64-tradbigmips
+ 
+ Disassembly of section \.text:
+ 
+ 0+00 <.*>:
+ .*:	0380282d 	move	\$5,\$28
+ .*:	3c1c0000 	lui	\$28,0x0
+ 			.*: R_MIPS_GPREL16	foo
+ 			.*: R_MIPS_SUB	\*ABS\*
+ 			.*: R_MIPS_HI16	\*ABS\*
+ .*:	279c0000 	addiu	\$28,\$28,0
+ 			.*: R_MIPS_GPREL16	foo
+ 			.*: R_MIPS_SUB	\*ABS\*
+ 			.*: R_MIPS_LO16	\*ABS\*
+ .*:	0384e02d 	daddu	\$28,\$28,\$4
*** /dev/null	Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel23.s	Thu Oct  7 22:31:39 2004
***************
*** 0 ****
--- 1,6 ----
+ 	.abicalls
+ 	.globl	foo
+ 	.ent	foo
+ foo:
+ 	.cpsetup $4,$5,foo
+ 	.end	foo
*** /dev/null	Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel24.d	Thu Oct  7 22:47:30 2004
***************
*** 0 ****
--- 1,12 ----
+ #as: -march=mips3 -mabi=64
+ #readelf: --relocs
+ #name: MIPS ELF reloc 24
+ 
+ Relocation section '\.rela\.text' .*:
+ .*
+ .* R_MIPS_GPREL32 * 0+00 foo \+ 0
+  * Type2: R_MIPS_64 *
+  * Type3: R_MIPS_NONE *
+ .* R_MIPS_GPREL32 * 0+00 \.text \+ 10
+  * Type2: R_MIPS_64 *
+  * Type3: R_MIPS_NONE *
*** /dev/null	Fri Apr 23 00:21:55 2004
--- gas/testsuite/gas/mips/elf-rel24.s	Thu Oct  7 22:46:28 2004
***************
*** 0 ****
--- 1,4 ----
+ 	.abicalls
+ 	.gpdword	foo
+ 	.gpdword	bar
+ bar:


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