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]

[RFC] binutils support for x86-64 medium model shared libraries


Hi,
this patch adds neccesary binutils support for x86-64 medium PIC model
(libraries whose text+PLT+GOT size is limited to 2GB, but data section size is
unlimited).  This is implemented by adding new 64bit PC relative relocation
(PC64) and relocations allowing 64bit GOT pointer relative access to static
variables (GOTPC32 to read GOT address and GOTOFF64 to compute offsets).
The compiler is supposed to freely use 32bit IP relative addressing for
everything except for data section and use the GOT pointer relative way
within it.  The 64bit PC relative is usefull for jumptables and EH
tables.

The incarnation of this patch for earlier binutils has been in use for a while
within SUSE distro and appears to work.  It also has been tested on some
libraries really requiring the medium model.

GOT and PLT are still accessed via IP relative way as 32bit PIC is.  This brings few
issues I would like to discuss here.

1) Currently the GOT/PLT sections are placed after data section, I need
   to have thse before for medium model PIC libraries.  Please see the
   changes to linker scripts at the end of patch;  I would like to ask
   for proper sollution to this especially because I was told that this
   is in conflict with optimization Jakub implements (ie it would be
   nice to use "normal" ordering for small libraries and reversed for
   big.  IP relative access to GOT/PLT is very important for
   perfomrance...
2) In the function relocate_section is magic number 3 I have no idea
   from where is comming.  I was discussing this with Andreas Schwab
   previously and he told me that I've messed up the computation of the
   relocation (that is copied from other port that appeared to do the
   same), but his suggestion didn't work for me either and I
   unfortunately lost the email, so I can't re-check.  I will try to dig
   into this deeper but it makes me nervous and perhaps proper fix
   is obvious to everyone except me.
3) I would like to implement small data area as simple followup patch.
   This should make medium model performance mostly identical with small
   model with exception of very large static datastructures.

   This however hits another problem - in order to access
   sdata/sbss/friends in IP relative way they must appear before the
   data section.  Does it seem to be in conflict with something to
   reorder thse in linker script?

Except for these points I hope this is quite easy addition, so I would
like to commit it once these issues are resolved.  I also have companion
patch for GCC and x86-64 ABI and few extra additions for large model are
in preparation too.

thanks,
Honza

2004-08-28  Jan Hubicka  <jh@suse.cz>
	* bfd-in2.h (BFD_RELOAD_X86_64_GOTOFF64): New relocation.
	(BFD_RELOAD_X86_64_GOTPC32): New relocation.
	* elf64-x86-64.c (x86_64_elf_howto): Add entries for
	R_X86_64_PC64, R_X86_64_GOTOFF64 and R_X86_64_GOTPC32.
	* elf64-x86-64.c (x86_64_elf_reloc_map): Add entries for
	R_X86_64_PC64, R_X86_64_GOTOFF64 and R_X86_64_GOTPC32.
	(elf64_x86_64_check_relocs): Deal with new relocs.
	(elf64_x86_64_gc_sweep_hook): Deal with PC64 reloc.
	(x86_64_rlocate_section): Deal with new relocs.
	* libbfd.h (bfd_reloc_code_): Add BFD_RELOC_X86_64_GOTOFF64.
	* reloc.c (BFD_RELOC_X86_64_GOTOFF64, BFD_RELOC_X86_64_GOTPC32): New.

	* config/tc-i386.c (reloc): Add BFD_RELOC_64_PCREL.
	(tc_i386_fix_adjustable): Add GOTOFF64.
	(output_disp): Allow new types.
	(output_imm): Likewise.
	(lex_got): Add new keywords.
	(i386_displacement): Likewise.
	(md_apply_fix3): Handle 64bit PC relative relocastion.
	(md_validate_fix): Likewise.
	(tc_get_reloc): Deal with GOTPC32 and GOTOFF64.

	* x86-64.h (R_X86_64_PC64, R_X86_64_GOTOFF64, R_X86_64_GOTPC32): New relocations.

	* emulparams/elf_x86_64.sh: Add EARLY_GOT section.
	* scripttempl/elf.sc: Support EARLY_GOT section.
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.297
diff -c -3 -p -r1.297 bfd-in2.h
*** bfd/bfd-in2.h	25 Aug 2004 12:54:13 -0000	1.297
--- bfd/bfd-in2.h	28 Aug 2004 10:25:03 -0000
*************** in the instruction.  */
*** 2463,2468 ****
--- 2463,2470 ----
    BFD_RELOC_X86_64_DTPOFF32,
    BFD_RELOC_X86_64_GOTTPOFF,
    BFD_RELOC_X86_64_TPOFF32,
+   BFD_RELOC_X86_64_GOTOFF64,
+   BFD_RELOC_X86_64_GOTPC32,
  
  /* ns32k relocations  */
    BFD_RELOC_NS32K_IMM_8,
Index: bfd/elf64-x86-64.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-x86-64.c,v
retrieving revision 1.83
diff -c -3 -p -r1.83 elf64-x86-64.c
*** bfd/elf64-x86-64.c	13 Aug 2004 03:15:59 -0000	1.83
--- bfd/elf64-x86-64.c	28 Aug 2004 10:25:03 -0000
*************** static reloc_howto_type x86_64_elf_howto
*** 102,107 ****
--- 102,116 ----
    HOWTO(R_X86_64_TPOFF32, 0, 2, 32, FALSE, 0, complain_overflow_signed,
  	bfd_elf_generic_reloc, "R_X86_64_TPOFF32", FALSE, 0xffffffff,
  	0xffffffff, FALSE),
+   HOWTO(R_X86_64_PC64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
+ 	bfd_elf_generic_reloc, "R_X86_64_PC64", FALSE, MINUS_ONE, MINUS_ONE,
+ 	TRUE),
+   HOWTO(R_X86_64_GOTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+ 	bfd_elf_generic_reloc, "R_X86_64_GOTOFF64",
+ 	FALSE, MINUS_ONE, MINUS_ONE, FALSE),
+   HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
+ 	bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
+ 	FALSE, 0xffffffff, 0xffffffff, TRUE),
  
  /* GNU extension to record C++ vtable hierarchy.  */
    HOWTO (R_X86_64_GNU_VTINHERIT, 0, 4, 0, FALSE, 0, complain_overflow_dont,
*************** static const struct elf_reloc_map x86_64
*** 146,151 ****
--- 155,163 ----
    { BFD_RELOC_X86_64_DTPOFF32,	R_X86_64_DTPOFF32, },
    { BFD_RELOC_X86_64_GOTTPOFF,	R_X86_64_GOTTPOFF, },
    { BFD_RELOC_X86_64_TPOFF32,	R_X86_64_TPOFF32, },
+   { BFD_RELOC_64_PCREL,		R_X86_64_PC64, },
+   { BFD_RELOC_X86_64_GOTOFF64,	R_X86_64_GOTOFF64, },
+   { BFD_RELOC_X86_64_GOTPC32,	R_X86_64_GOTPC32, },
    { BFD_RELOC_VTABLE_INHERIT,	R_X86_64_GNU_VTINHERIT, },
    { BFD_RELOC_VTABLE_ENTRY,	R_X86_64_GNU_VTENTRY, },
  };
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 746,752 ****
  	  }
  	  /* Fall through */
  
! 	  //case R_X86_64_GOTPCREL:
  	create_got:
  	  if (htab->sgot == NULL)
  	    {
--- 758,765 ----
  	  }
  	  /* Fall through */
  
! 	case R_X86_64_GOTOFF64:
! 	case R_X86_64_GOTPC32:
  	create_got:
  	  if (htab->sgot == NULL)
  	    {
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 799,804 ****
--- 812,818 ----
  	case R_X86_64_PC8:
  	case R_X86_64_PC16:
  	case R_X86_64_PC32:
+ 	case R_X86_64_PC64:
  	case R_X86_64_64:
  	  if (h != NULL && !info->shared)
  	    {
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 842,848 ****
  	       && (sec->flags & SEC_ALLOC) != 0
  	       && (((r_type != R_X86_64_PC8)
  		    && (r_type != R_X86_64_PC16)
! 		    && (r_type != R_X86_64_PC32))
  		   || (h != NULL
  		       && (! info->symbolic
  			   || h->root.type == bfd_link_hash_defweak
--- 856,863 ----
  	       && (sec->flags & SEC_ALLOC) != 0
  	       && (((r_type != R_X86_64_PC8)
  		    && (r_type != R_X86_64_PC16)
! 		    && (r_type != R_X86_64_PC32)
! 		    && (r_type != R_X86_64_PC64))
  		   || (h != NULL
  		       && (! info->symbolic
  			   || h->root.type == bfd_link_hash_defweak
*************** elf64_x86_64_check_relocs (bfd *abfd, st
*** 946,952 ****
  	      p->count += 1;
  	      if (r_type == R_X86_64_PC8
  		  || r_type == R_X86_64_PC16
! 		  || r_type == R_X86_64_PC32)
  		p->pc_count += 1;
  	    }
  	  break;
--- 961,968 ----
  	      p->count += 1;
  	      if (r_type == R_X86_64_PC8
  		  || r_type == R_X86_64_PC16
! 		  || r_type == R_X86_64_PC32
! 		  || r_type == R_X86_64_PC64)
  		p->pc_count += 1;
  	    }
  	  break;
*************** elf64_x86_64_gc_sweep_hook (bfd *abfd, s
*** 1088,1093 ****
--- 1104,1110 ----
  	case R_X86_64_PC8:
  	case R_X86_64_PC16:
  	case R_X86_64_PC32:
+ 	case R_X86_64_PC64:
  	  if (info->shared)
  	    break;
  	  /* Fall thru */
*************** elf64_x86_64_relocate_section (bfd *outp
*** 1946,1951 ****
--- 1963,1969 ----
  	case R_X86_64_PC8:
  	case R_X86_64_PC16:
  	case R_X86_64_PC32:
+ 	case R_X86_64_PC64:
  	  if (info->shared
  	      && !SYMBOL_REFERENCES_LOCAL (info, h)
  	      && (input_section->flags & SEC_ALLOC) != 0
*************** elf64_x86_64_relocate_section (bfd *outp
*** 1981,1987 ****
  		   || h->root.type != bfd_link_hash_undefweak)
  	       && ((r_type != R_X86_64_PC8
  		    && r_type != R_X86_64_PC16
! 		    && r_type != R_X86_64_PC32)
  		   || !SYMBOL_CALLS_LOCAL (info, h)))
  	      || (ELIMINATE_COPY_RELOCS
  		  && !info->shared
--- 1999,2006 ----
  		   || h->root.type != bfd_link_hash_undefweak)
  	       && ((r_type != R_X86_64_PC8
  		    && r_type != R_X86_64_PC16
! 		    && r_type != R_X86_64_PC32
! 		    && r_type != R_X86_64_PC64)
  		   || !SYMBOL_CALLS_LOCAL (info, h)))
  	      || (ELIMINATE_COPY_RELOCS
  		  && !info->shared
*************** elf64_x86_64_relocate_section (bfd *outp
*** 2027,2032 ****
--- 2046,2052 ----
  		       && (r_type == R_X86_64_PC8
  			   || r_type == R_X86_64_PC16
  			   || r_type == R_X86_64_PC32
+ 			   || r_type == R_X86_64_PC64
  			   || !info->shared
  			   || !info->symbolic
  			   || (h->elf_link_hash_flags
*************** elf64_x86_64_relocate_section (bfd *outp
*** 2395,2400 ****
--- 2415,2439 ----
  	  relocation = tpoff (info, relocation);
  	  break;
  
+ 	case R_X86_64_GOTOFF64:
+ 	  /* Relocation is relative to the start of the global offset
+ 	     table.  */
+ 
+ 	  /* Note that sgot->output_offset is not involved in this
+ 	     calculation.  We always want the start of .got.  If we
+ 	     defined _GLOBAL_OFFSET_TABLE in a different way, as is
+ 	     permitted by the ABI, we might have to change this
+ 	     calculation.  */
+ 	  relocation -= htab->sgot->output_section->vma;
+ 	  break;
+ 
+ 	case R_X86_64_GOTPC32:
+ 	  /* Use global offset table as symbol value.
+ 	     ??? This constant makes it to come out right... */
+ 	  relocation = htab->sgot->output_section->vma - 3;
+ 	  unresolved_reloc = FALSE;
+ 	  break;
+ 
  	default:
  	  break;
  	}
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.122
diff -c -3 -p -r1.122 libbfd.h
*** bfd/libbfd.h	25 Aug 2004 12:54:14 -0000	1.122
--- bfd/libbfd.h	28 Aug 2004 10:25:03 -0000
*************** static const char *const bfd_reloc_code_
*** 989,994 ****
--- 989,995 ----
    "BFD_RELOC_X86_64_DTPOFF32",
    "BFD_RELOC_X86_64_GOTTPOFF",
    "BFD_RELOC_X86_64_TPOFF32",
+   "BFD_RELOC_X86_64_GOTOFF64",
    "BFD_RELOC_NS32K_IMM_8",
    "BFD_RELOC_NS32K_IMM_16",
    "BFD_RELOC_NS32K_IMM_32",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.111
diff -c -3 -p -r1.111 reloc.c
*** bfd/reloc.c	25 Aug 2004 12:54:14 -0000	1.111
--- bfd/reloc.c	28 Aug 2004 10:25:03 -0000
*************** ENUMX
*** 2278,2283 ****
--- 2278,2287 ----
    BFD_RELOC_X86_64_GOTTPOFF
  ENUMX
    BFD_RELOC_X86_64_TPOFF32
+ ENUMX
+   BFD_RELOC_X86_64_GOTOFF64
+ ENUMX
+   BFD_RELOC_X86_64_GOTPC32
  ENUMDOC
    x86-64/elf relocations
  
Index: gas/config/tc-i386.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-i386.c,v
retrieving revision 1.156
diff -c -3 -p -r1.156 tc-i386.c
*** gas/config/tc-i386.c	21 Jul 2004 18:18:02 -0000	1.156
--- gas/config/tc-i386.c	28 Aug 2004 10:25:06 -0000
*************** reloc (size, pcrel, sign, other)
*** 1194,1199 ****
--- 1194,1200 ----
  	case 1: return BFD_RELOC_8_PCREL;
  	case 2: return BFD_RELOC_16_PCREL;
  	case 4: return BFD_RELOC_32_PCREL;
+ 	case 8: return BFD_RELOC_64_PCREL;
  	}
        as_bad (_("can not do %d byte pc-relative relocation"), size);
      }
*************** tc_i386_fix_adjustable (fixP)
*** 1258,1263 ****
--- 1259,1265 ----
        || fixP->fx_r_type == BFD_RELOC_386_TLS_GOTIE
        || fixP->fx_r_type == BFD_RELOC_386_TLS_LE_32
        || fixP->fx_r_type == BFD_RELOC_386_TLS_LE
+       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
        || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
        || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
        || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
*************** output_disp (insn_start_frag, insn_start
*** 3336,3349 ****
  
  	      p = frag_more (size);
  	      reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
! 	      if (reloc_type == BFD_RELOC_32
! 		  && GOT_symbol
! 		  && GOT_symbol == i.op[n].disps->X_add_symbol
! 		  && (i.op[n].disps->X_op == O_symbol
! 		      || (i.op[n].disps->X_op == O_add
! 			  && ((symbol_get_value_expression
! 			       (i.op[n].disps->X_op_symbol)->X_op)
! 			      == O_subtract))))
  		{
  		  offsetT add;
  
--- 3338,3354 ----
  
  	      p = frag_more (size);
  	      reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
! 	      if ((reloc_type == BFD_RELOC_32
! 		   && GOT_symbol
! 		   && GOT_symbol == i.op[n].disps->X_add_symbol
! 		   && (i.op[n].disps->X_op == O_symbol
! 		       || (i.op[n].disps->X_op == O_add
! 			   && ((symbol_get_value_expression
! 				(i.op[n].disps->X_op_symbol)->X_op)
! 			       == O_subtract))))
! 		  || (reloc_type == BFD_RELOC_32_PCREL
! 		      && GOT_symbol
! 		      && GOT_symbol == i.op[n].disps->X_add_symbol))
  		{
  		  offsetT add;
  
*************** output_disp (insn_start_frag, insn_start
*** 3360,3369 ****
  		      add += p - frag_now->fr_literal;
  		    }
  
- 		  /* We don't support dynamic linking on x86-64 yet.  */
  		  if (flag_code == CODE_64BIT)
! 		    abort ();
! 		  reloc_type = BFD_RELOC_386_GOTPC;
  		  i.op[n].disps->X_add_number += add;
  		}
  	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
--- 3365,3374 ----
  		      add += p - frag_now->fr_literal;
  		    }
  
  		  if (flag_code == CODE_64BIT)
! 		    reloc_type = BFD_RELOC_X86_64_GOTPC32;
! 		  else
! 		    reloc_type = BFD_RELOC_386_GOTPC;
  		  i.op[n].disps->X_add_number += add;
  		}
  	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
*************** output_imm (insn_start_frag, insn_start_
*** 3471,3484 ****
  	       * since the expression is not pcrel, I felt it would be
  	       * confusing to do it this way.  */
  
! 	      if (reloc_type == BFD_RELOC_32
! 		  && GOT_symbol
! 		  && GOT_symbol == i.op[n].imms->X_add_symbol
! 		  && (i.op[n].imms->X_op == O_symbol
! 		      || (i.op[n].imms->X_op == O_add
! 			  && ((symbol_get_value_expression
! 			       (i.op[n].imms->X_op_symbol)->X_op)
! 			      == O_subtract))))
  		{
  		  offsetT add;
  
--- 3476,3492 ----
  	       * since the expression is not pcrel, I felt it would be
  	       * confusing to do it this way.  */
  
! 	      if ((reloc_type == BFD_RELOC_32
! 		   && GOT_symbol
! 		   && GOT_symbol == i.op[n].imms->X_add_symbol
! 		   && (i.op[n].imms->X_op == O_symbol
! 		       || (i.op[n].imms->X_op == O_add
! 			   && ((symbol_get_value_expression
! 				(i.op[n].imms->X_op_symbol)->X_op)
! 			       == O_subtract))))
! 		  || (reloc_type == BFD_RELOC_32_PCREL
! 		      && GOT_symbol
! 		      && GOT_symbol == i.op[n].disps->X_add_symbol))
  		{
  		  offsetT add;
  
*************** output_imm (insn_start_frag, insn_start_
*** 3495,3504 ****
  		      add += p - frag_now->fr_literal;
  		    }
  
- 		  /* We don't support dynamic linking on x86-64 yet.  */
  		  if (flag_code == CODE_64BIT)
! 		    abort ();
! 		  reloc_type = BFD_RELOC_386_GOTPC;
  		  i.op[n].imms->X_add_number += add;
  		}
  	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
--- 3503,3512 ----
  		      add += p - frag_now->fr_literal;
  		    }
  
  		  if (flag_code == CODE_64BIT)
! 		    reloc_type = BFD_RELOC_X86_64_GOTPC32;
! 		  else
! 		    reloc_type = BFD_RELOC_386_GOTPC;
  		  i.op[n].imms->X_add_number += add;
  		}
  	      fix_new_exp (frag_now, p - frag_now->fr_literal, size,
*************** lex_got (reloc, adjust)
*** 3531,3537 ****
      const enum bfd_reloc_code_real rel[NUM_FLAG_CODE];
    } gotrel[] = {
      { "PLT",      { BFD_RELOC_386_PLT32,      0, BFD_RELOC_X86_64_PLT32    } },
!     { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     0, 0                         } },
      { "GOTPCREL", { 0,                        0, BFD_RELOC_X86_64_GOTPCREL } },
      { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, BFD_RELOC_X86_64_TLSGD    } },
      { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,    0, 0                         } },
--- 3539,3545 ----
      const enum bfd_reloc_code_real rel[NUM_FLAG_CODE];
    } gotrel[] = {
      { "PLT",      { BFD_RELOC_386_PLT32,      0, BFD_RELOC_X86_64_PLT32    } },
!     { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     0,  BFD_RELOC_X86_64_GOTOFF64} },
      { "GOTPCREL", { 0,                        0, BFD_RELOC_X86_64_GOTPCREL } },
      { "TLSGD",    { BFD_RELOC_386_TLS_GD,     0, BFD_RELOC_X86_64_TLSGD    } },
      { "TLSLDM",   { BFD_RELOC_386_TLS_LDM,    0, 0                         } },
*************** lex_got (reloc, adjust)
*** 3542,3548 ****
      { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 } },
      { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0, 0                         } },
      { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0, 0                         } },
!     { "GOT",      { BFD_RELOC_386_GOT32,      0, BFD_RELOC_X86_64_GOT32    } }
    };
    char *cp;
    unsigned int j;
--- 3550,3557 ----
      { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, 0, BFD_RELOC_X86_64_DTPOFF32 } },
      { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0, 0                         } },
      { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0, 0                         } },
!     { "GOT",      { BFD_RELOC_386_GOT32,      0, BFD_RELOC_X86_64_GOT32    } },
! //{ "GOTOFF64", { 0,                        0, BFD_RELOC_X86_64_GOTOFF64 } }
    };
    char *cp;
    unsigned int j;
*************** i386_displacement (disp_start, disp_end)
*** 3934,3939 ****
--- 3943,3949 ----
       the symbol table.  We will ultimately change the relocation
       to be relative to the beginning of the section.  */
    if (i.reloc[this_operand] == BFD_RELOC_386_GOTOFF
+       || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64
        || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
      {
        if (exp->X_op != O_symbol)
*************** i386_displacement (disp_start, disp_end)
*** 3941,3947 ****
  	  as_bad (_("bad expression used with @%s"),
  		  (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
  		   ? "GOTPCREL"
! 		   : "GOTOFF"));
  	  return 0;
  	}
  
--- 3951,3959 ----
  	  as_bad (_("bad expression used with @%s"),
  		  (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
  		   ? "GOTPCREL"
! 		   : (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64
! 		   ? "GOTOFF64"
! 		   : "GOTOFF")));
  	  return 0;
  	}
  
*************** md_estimate_size_before_relax (fragP, se
*** 4400,4407 ****
  	reloc_type = fragP->fr_var;
        else if (size == 2)
  	reloc_type = BFD_RELOC_16_PCREL;
!       else
  	reloc_type = BFD_RELOC_32_PCREL;
  
        old_fr_fix = fragP->fr_fix;
        opcode = (unsigned char *) fragP->fr_opcode;
--- 4412,4421 ----
  	reloc_type = fragP->fr_var;
        else if (size == 2)
  	reloc_type = BFD_RELOC_16_PCREL;
!       else if (size == 4)
  	reloc_type = BFD_RELOC_32_PCREL;
+       else
+ 	reloc_type = BFD_RELOC_64_PCREL;
  
        old_fr_fix = fragP->fr_fix;
        opcode = (unsigned char *) fragP->fr_opcode;
*************** md_apply_fix3 (fixP, valP, seg)
*** 4642,4647 ****
--- 4656,4664 ----
  	default:
  	  break;
  
+ 	case BFD_RELOC_64:
+ 	  fixP->fx_r_type = BFD_RELOC_64_PCREL;
+ 	  break;
  	case BFD_RELOC_32:
  	  fixP->fx_r_type = BFD_RELOC_32_PCREL;
  	  break;
*************** md_apply_fix3 (fixP, valP, seg)
*** 4655,4661 ****
      }
  
    if (fixP->fx_addsy != NULL
!       && (fixP->fx_r_type == BFD_RELOC_32_PCREL
  	  || fixP->fx_r_type == BFD_RELOC_16_PCREL
  	  || fixP->fx_r_type == BFD_RELOC_8_PCREL)
        && !use_rela_relocations)
--- 4672,4679 ----
      }
  
    if (fixP->fx_addsy != NULL
!       && (fixP->fx_r_type == BFD_RELOC_64_PCREL
! 	  || fixP->fx_r_type == BFD_RELOC_32_PCREL
  	  || fixP->fx_r_type == BFD_RELOC_16_PCREL
  	  || fixP->fx_r_type == BFD_RELOC_8_PCREL)
        && !use_rela_relocations)
*************** i386_validate_fix (fixp)
*** 5159,5165 ****
  {
    if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol)
      {
-       /* GOTOFF relocation are nonsense in 64bit mode.  */
        if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
  	{
  	  if (flag_code != CODE_64BIT)
--- 5177,5182 ----
*************** i386_validate_fix (fixp)
*** 5169,5176 ****
        else
  	{
  	  if (flag_code == CODE_64BIT)
! 	    abort ();
! 	  fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
  	}
        fixp->fx_subsy = 0;
      }
--- 5186,5194 ----
        else
  	{
  	  if (flag_code == CODE_64BIT)
! 	    fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
! 	  else
! 	    fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
  	}
        fixp->fx_subsy = 0;
      }
*************** tc_gen_reloc (section, fixp)
*** 5189,5194 ****
--- 5207,5213 ----
      case BFD_RELOC_X86_64_PLT32:
      case BFD_RELOC_X86_64_GOT32:
      case BFD_RELOC_X86_64_GOTPCREL:
+     case BFD_RELOC_X86_64_GOTPC32:
      case BFD_RELOC_386_PLT32:
      case BFD_RELOC_386_GOT32:
      case BFD_RELOC_386_GOTOFF:
*************** tc_gen_reloc (section, fixp)
*** 5201,5206 ****
--- 5220,5226 ----
      case BFD_RELOC_386_TLS_GOTIE:
      case BFD_RELOC_386_TLS_LE_32:
      case BFD_RELOC_386_TLS_LE:
+     case BFD_RELOC_X86_64_GOTOFF64:
      case BFD_RELOC_X86_64_32S:
      case BFD_RELOC_X86_64_TLSGD:
      case BFD_RELOC_X86_64_TLSLD:
*************** tc_gen_reloc (section, fixp)
*** 5229,5234 ****
--- 5249,5255 ----
  	    case 1: code = BFD_RELOC_8_PCREL;  break;
  	    case 2: code = BFD_RELOC_16_PCREL; break;
  	    case 4: code = BFD_RELOC_32_PCREL; break;
+ 	    case 8: code = BFD_RELOC_64_PCREL; break;
  	    }
  	}
        else
*************** tc_gen_reloc (section, fixp)
*** 5252,5265 ****
        break;
      }
  
!   if (code == BFD_RELOC_32
        && GOT_symbol
        && fixp->fx_addsy == GOT_symbol)
      {
-       /* We don't support GOTPC on 64bit targets.  */
        if (flag_code == CODE_64BIT)
! 	abort ();
!       code = BFD_RELOC_386_GOTPC;
      }
  
    rel = (arelent *) xmalloc (sizeof (arelent));
--- 5273,5286 ----
        break;
      }
  
!   if ((code == BFD_RELOC_32 || code == BFD_RELOC_32_PCREL)
        && GOT_symbol
        && fixp->fx_addsy == GOT_symbol)
      {
        if (flag_code == CODE_64BIT)
!         code = BFD_RELOC_X86_64_GOTPC32;
!       else
!         code = BFD_RELOC_386_GOTPC;
      }
  
    rel = (arelent *) xmalloc (sizeof (arelent));
Index: include/elf/x86-64.h
===================================================================
RCS file: /cvs/src/src/include/elf/x86-64.h,v
retrieving revision 1.3
diff -c -3 -p -r1.3 x86-64.h
*** include/elf/x86-64.h	27 Sep 2002 19:29:16 -0000	1.3
--- include/elf/x86-64.h	28 Aug 2004 10:25:07 -0000
*************** START_RELOC_NUMBERS (elf_x86_64_reloc_ty
*** 51,56 ****
--- 51,59 ----
       RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
       RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
       RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
+      RELOC_NUMBER (R_X86_64_PC64,     24)      /* PC relative 64 bit signed */
+      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)      /* 64bit offset to GOT */
+      RELOC_NUMBER (R_X86_64_GOTPC32,  26)      /* 32 bit PC relative offset to GOT */
  END_RELOC_NUMBERS (R_X86_64_max)
  
  #endif
Index: ld/emulparams/elf_x86_64.sh
===================================================================
RCS file: /cvs/src/src/ld/emulparams/elf_x86_64.sh,v
retrieving revision 1.12
diff -c -3 -p -r1.12 elf_x86_64.sh
*** ld/emulparams/elf_x86_64.sh	11 May 2004 17:08:33 -0000	1.12
--- ld/emulparams/elf_x86_64.sh	28 Aug 2004 10:25:07 -0000
*************** NOP=0x90909090
*** 11,18 ****
  TEMPLATE_NAME=elf32
  GENERATE_SHLIB_SCRIPT=yes
  GENERATE_PIE_SCRIPT=yes
  NO_SMALL_DATA=yes
  SEPARATE_GOTPLT=24
  
  if [ "x${host}" = "x${target}" ]; then
    case " $EMULATION_LIBPATH " in
--- 11,19 ----
  TEMPLATE_NAME=elf32
  GENERATE_SHLIB_SCRIPT=yes
  GENERATE_PIE_SCRIPT=yes
  SEPARATE_GOTPLT=24
  NO_SMALL_DATA=yes
+ EARLY_GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
  
  if [ "x${host}" = "x${target}" ]; then
    case " $EMULATION_LIBPATH " in
Index: ld/scripttempl/elf.sc
===================================================================
RCS file: /cvs/src/src/ld/scripttempl/elf.sc,v
retrieving revision 1.46
diff -c -3 -p -r1.46 elf.sc
*** ld/scripttempl/elf.sc	5 Jul 2004 20:00:13 -0000	1.46
--- ld/scripttempl/elf.sc	28 Aug 2004 10:25:07 -0000
*************** if test -n "${COMMONPAGESIZE}"; then
*** 97,103 ****
  fi
  INTERP=".interp       ${RELOCATING-0} : { *(.interp) }"
  PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
! if test -z "$GOT"; then
    if test -z "$SEPARATE_GOTPLT"; then
      GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
    else
--- 97,103 ----
  fi
  INTERP=".interp       ${RELOCATING-0} : { *(.interp) }"
  PLT=".plt          ${RELOCATING-0} : { *(.plt) }"
! if test -z "$GOT" && test -z "$EARLY_GOT" ; then
    if test -z "$SEPARATE_GOTPLT"; then
      GOT=".got          ${RELOCATING-0} : { *(.got.plt) *(.got) }"
    else
*************** cat <<EOF
*** 303,308 ****
--- 303,309 ----
      KEEP (*(.fini))
      ${RELOCATING+${FINI_END}}
    } =${NOP-0}
+   ${EARLY_GOT}
    ${RELOCATING+PROVIDE (__etext = .);}
    ${RELOCATING+PROVIDE (_etext = .);}
    ${RELOCATING+PROVIDE (etext = .);}


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