Patch by matz@suse.de:
authorAndreas Jaeger <aj@suse.de>
Thu, 23 Mar 2006 08:23:09 +0000 (08:23 +0000)
committerAndreas Jaeger <aj@suse.de>
Thu, 23 Mar 2006 08:23:09 +0000 (08:23 +0000)
bfd/ChangeLog:
* reloc.c: Add BFD_RELOC_X86_64_GOT64, BFD_RELOC_X86_64_GOTPCREL64,
BFD_RELOC_X86_64_GOTPC64, BFD_RELOC_X86_64_GOTPLT64,
BFD_RELOC_X86_64_PLTOFF64.
* bfd-in2.h: Regenerated.
* libbfd.h: Regenerated.
* elf64-x86-64.c (x86_64_elf_howto_table): Correct comment.
Add howtos for above relocs.
(x86_64_reloc_map): Add mappings for new relocs.
(elf64_x86_64_check_relocs): R_X86_64_GOT64, R_X86_64_GOTPCREL64,
R_X86_64_GOTPLT64 need a got entry.  R_X86_64_GOTPLT64 also a PLT
entry.  R_X86_64_GOTPC64 needs a .got section.  R_X86_64_PLTOFF64
needs a PLT entry.
(elf64_x86_64_gc_sweep_hook): Reflect changes from
elf64_x86_64_check_relocs for the new relocs.
(elf64_x86_64_relocate_section): Handle new relocs.

gas/ChangeLog:
* config/tc-i386.c (type_names): Correct placement of 'static'.
(reloc): Map some more relocs to their 64 bit counterpart when
size is 8.
(output_insn): Work around breakage if DEBUG386 is defined.
(output_disp): A BFD_RELOC_64 with GOT_symbol as operand also
needs to be mapped to BFD_RELOC_X86_64_GOTPC64 or
BFD_RELOC_X86_64_GOTPC32.  Also x86-64 handles pcrel addressing
different from i386.
(output_imm): Ditto.
(lex_got): Recognize @PLTOFF and @GOTPLT.  Make @GOT accept also
Imm64.
(md_convert_frag): Jumps can now be larger than 2GB away, error
out in that case.
(tc_gen_reloc): New relocs are passed through.  BFD_RELOC_64
and BFD_RELOC_64_PCREL are mapped to BFD_RELOC_X86_64_GOTPC64.

gas/testsuite/ChangeLog:
* gas/i386/reloc64.s: Accept 64-bit forms.
* gas/i386/reloc64.d: Adjust.
* gas/i386/reloc64.l: Adjust.

include/ChangeLog:
* elf/x86-64.h: Add the new relocations with their official
numbers.

bfd/bfd-in2.h
bfd/elf64-x86-64.c
bfd/libbfd.h
bfd/libcoff.h
bfd/reloc.c
gas/config/tc-i386.c
gas/testsuite/gas/i386/reloc64.d
gas/testsuite/gas/i386/reloc64.l
gas/testsuite/gas/i386/reloc64.s
include/elf/x86-64.h

index 62886c9..20f4bbf 100644 (file)
@@ -2707,6 +2707,11 @@ in the instruction.  */
   BFD_RELOC_X86_64_TPOFF32,
   BFD_RELOC_X86_64_GOTOFF64,
   BFD_RELOC_X86_64_GOTPC32,
+  BFD_RELOC_X86_64_GOT64,
+  BFD_RELOC_X86_64_GOTPCREL64,
+  BFD_RELOC_X86_64_GOTPC64,
+  BFD_RELOC_X86_64_GOTPLT64,
+  BFD_RELOC_X86_64_PLTOFF64,
   BFD_RELOC_X86_64_GOTPC32_TLSDESC,
   BFD_RELOC_X86_64_TLSDESC_CALL,
   BFD_RELOC_X86_64_TLSDESC,
index 504a19b..9befd69 100644 (file)
@@ -31,8 +31,8 @@
 #define MINUS_ONE (~ (bfd_vma) 0)
 
 /* The relocation "howto" table.  Order of fields:
-   type, size, bitsize, pc_relative, complain_on_overflow,
-   special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset.  */
+   type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
+   special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset.  */
 static reloc_howto_type x86_64_elf_howto_table[] =
 {
   HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
@@ -112,11 +112,21 @@ static reloc_howto_type x86_64_elf_howto_table[] =
   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),
-  EMPTY_HOWTO (27),
-  EMPTY_HOWTO (28),
-  EMPTY_HOWTO (29),
-  EMPTY_HOWTO (30),
-  EMPTY_HOWTO (31),
+  HOWTO(R_X86_64_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_GOT64", FALSE, MINUS_ONE, MINUS_ONE,
+       FALSE),
+  HOWTO(R_X86_64_GOTPCREL64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", FALSE, MINUS_ONE,
+       MINUS_ONE, TRUE),
+  HOWTO(R_X86_64_GOTPC64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_GOTPC64",
+       FALSE, MINUS_ONE, MINUS_ONE, TRUE),
+  HOWTO(R_X86_64_GOTPLT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", FALSE, MINUS_ONE,
+       MINUS_ONE, FALSE),
+  HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
+       bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE,
+       MINUS_ONE, FALSE),
   EMPTY_HOWTO (32),
   EMPTY_HOWTO (33),
   HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
@@ -185,6 +195,11 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
   { 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_X86_64_GOT64,    R_X86_64_GOT64, },
+  { BFD_RELOC_X86_64_GOTPCREL64,R_X86_64_GOTPCREL64, },
+  { BFD_RELOC_X86_64_GOTPC64,  R_X86_64_GOTPC64, },
+  { BFD_RELOC_X86_64_GOTPLT64, R_X86_64_GOTPLT64, },
+  { BFD_RELOC_X86_64_PLTOFF64, R_X86_64_PLTOFF64, },
   { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
   { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
   { BFD_RELOC_X86_64_TLSDESC,  R_X86_64_TLSDESC, },
@@ -777,6 +792,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
        case R_X86_64_GOT32:
        case R_X86_64_GOTPCREL:
        case R_X86_64_TLSGD:
+       case R_X86_64_GOT64:
+       case R_X86_64_GOTPCREL64:
+       case R_X86_64_GOTPLT64:
        case R_X86_64_GOTPC32_TLSDESC:
        case R_X86_64_TLSDESC_CALL:
          /* This symbol requires a global offset table entry.  */
@@ -795,6 +813,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
 
            if (h != NULL)
              {
+               if (r_type == R_X86_64_GOTPLT64)
+                 {
+                   /* This relocation indicates that we also need
+                      a PLT entry, as this is a function.  We don't need
+                      a PLT entry for local symbols.  */
+                   h->needs_plt = 1;
+                   h->plt.refcount += 1;
+                 }
                h->got.refcount += 1;
                old_tls_type = elf64_x86_64_hash_entry (h)->tls_type;
              }
@@ -858,6 +884,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
 
        case R_X86_64_GOTOFF64:
        case R_X86_64_GOTPC32:
+       case R_X86_64_GOTPC64:
        create_got:
          if (htab->sgot == NULL)
            {
@@ -885,6 +912,16 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
          h->plt.refcount += 1;
          break;
 
+       case R_X86_64_PLTOFF64:
+         /* This tries to form the 'address' of a function relative
+            to GOT.  For global symbols we need a PLT entry.  */
+         if (h != NULL)
+           {
+             h->needs_plt = 1;
+             h->plt.refcount += 1;
+           }
+         goto create_got;
+
        case R_X86_64_8:
        case R_X86_64_16:
        case R_X86_64_32:
@@ -1189,8 +1226,13 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_GOTTPOFF:
        case R_X86_64_GOT32:
        case R_X86_64_GOTPCREL:
+       case R_X86_64_GOT64:
+       case R_X86_64_GOTPCREL64:
+       case R_X86_64_GOTPLT64:
          if (h != NULL)
            {
+             if (r_type == R_X86_64_GOTPLT64 && h->plt.refcount > 0)
+               h->plt.refcount -= 1;
              if (h->got.refcount > 0)
                h->got.refcount -= 1;
            }
@@ -1215,6 +1257,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
          /* Fall thru */
 
        case R_X86_64_PLT32:
+       case R_X86_64_PLTOFF64:
          if (h != NULL)
            {
              if (h->plt.refcount > 0)
@@ -2096,11 +2139,23 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
         copied into the output file to be resolved at run time.  */
       switch (r_type)
        {
+       asection *base_got;
        case R_X86_64_GOT32:
+       case R_X86_64_GOT64:
          /* Relocation is to the entry for this symbol in the global
             offset table.  */
        case R_X86_64_GOTPCREL:
-         /* Use global offset table as symbol value.  */
+       case R_X86_64_GOTPCREL64:
+         /* Use global offset table entry as symbol value.  */
+       case R_X86_64_GOTPLT64:
+         /* This is the same as GOT64 for relocation purposes, but
+            indicates the existence of a PLT entry.  The difficulty is,
+            that we must calculate the GOT slot offset from the PLT
+            offset, if this symbol got a PLT entry (it was global).
+            Additionally if it's computed from the PLT entry, then that
+            GOT offset is relative to .got.plt, not to .got.  */
+         base_got = htab->sgot;
+
          if (htab->sgot == NULL)
            abort ();
 
@@ -2109,6 +2164,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              bfd_boolean dyn;
 
              off = h->got.offset;
+             if (h->needs_plt
+                 && h->plt.offset != (bfd_vma)-1
+                 && off == (bfd_vma)-1)
+               {
+                 /* We can't use h->got.offset here to save
+                    state, or even just remember the offset, as
+                    finish_dynamic_symbol would use that as offset into
+                    .got.  */
+                 bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
+                 off = (plt_index + 3) * GOT_ENTRY_SIZE;
+                 base_got = htab->sgotplt;
+               }
+
              dyn = htab->elf.dynamic_sections_created;
 
              if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
@@ -2133,7 +2201,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  else
                    {
                      bfd_put_64 (output_bfd, relocation,
-                                 htab->sgot->contents + off);
+                                 base_got->contents + off);
+                     /* Note that this is harmless for the GOTPLT64 case,
+                        as -1 | 1 still is -1.  */
                      h->got.offset |= 1;
                    }
                }
@@ -2155,7 +2225,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              else
                {
                  bfd_put_64 (output_bfd, relocation,
-                             htab->sgot->contents + off);
+                             base_got->contents + off);
 
                  if (info->shared)
                    {
@@ -2169,8 +2239,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                      if (s == NULL)
                        abort ();
 
-                     outrel.r_offset = (htab->sgot->output_section->vma
-                                        + htab->sgot->output_offset
+                     outrel.r_offset = (base_got->output_section->vma
+                                        + base_got->output_offset
                                         + off);
                      outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
                      outrel.r_addend = relocation;
@@ -2186,9 +2256,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          if (off >= (bfd_vma) -2)
            abort ();
 
-         relocation = htab->sgot->output_section->vma
-                      + htab->sgot->output_offset + off;
-         if (r_type != R_X86_64_GOTPCREL)
+         relocation = base_got->output_section->vma
+                      + base_got->output_offset + off;
+         if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64)
            relocation -= htab->sgotplt->output_section->vma
                          - htab->sgotplt->output_offset;
 
@@ -2224,12 +2294,31 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          break;
 
        case R_X86_64_GOTPC32:
+       case R_X86_64_GOTPC64:
          /* Use global offset table as symbol value.  */
          relocation = htab->sgotplt->output_section->vma
                       + htab->sgotplt->output_offset;
          unresolved_reloc = FALSE;
          break;
 
+       case R_X86_64_PLTOFF64:
+         /* Relocation is PLT entry relative to GOT.  For local
+            symbols it's the symbol itself relative to GOT.  */
+          if (h != NULL
+             /* See PLT32 handling.  */
+             && h->plt.offset != (bfd_vma) -1
+             && htab->splt != NULL)
+           {
+             relocation = (htab->splt->output_section->vma
+                           + htab->splt->output_offset
+                           + h->plt.offset);
+             unresolved_reloc = FALSE;
+           }
+
+         relocation -= htab->sgotplt->output_section->vma
+                       + htab->sgotplt->output_offset;
+         break;
+
        case R_X86_64_PLT32:
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
index 0c18868..94dfeb7 100644 (file)
@@ -7,7 +7,7 @@
    (This include file is not for users of the library.)
 
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
 
    Written by Cygnus Support.
@@ -1065,6 +1065,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_X86_64_TPOFF32",
   "BFD_RELOC_X86_64_GOTOFF64",
   "BFD_RELOC_X86_64_GOTPC32",
+  "BFD_RELOC_X86_64_GOT64",
+  "BFD_RELOC_X86_64_GOTPCREL64",
+  "BFD_RELOC_X86_64_GOTPC64",
+  "BFD_RELOC_X86_64_GOTPLT64",
+  "BFD_RELOC_X86_64_PLTOFF64",
   "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
   "BFD_RELOC_X86_64_TLSDESC_CALL",
   "BFD_RELOC_X86_64_TLSDESC",
index b0b271c..f756f30 100644 (file)
@@ -4,7 +4,7 @@
 
 /* BFD COFF object file private structure.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005
+   2000, 2001, 2002, 2003, 2004, 2005, 2006
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
index d0c3f30..920a5f2 100644 (file)
@@ -2352,6 +2352,16 @@ ENUMX
 ENUMX
   BFD_RELOC_X86_64_GOTPC32
 ENUMX
+  BFD_RELOC_X86_64_GOT64
+ENUMX
+  BFD_RELOC_X86_64_GOTPCREL64
+ENUMX
+  BFD_RELOC_X86_64_GOTPC64
+ENUMX
+  BFD_RELOC_X86_64_GOTPLT64
+ENUMX
+  BFD_RELOC_X86_64_PLTOFF64
+ENUMX
   BFD_RELOC_X86_64_GOTPC32_TLSDESC
 ENUMX
   BFD_RELOC_X86_64_TLSDESC_CALL
index f42a9a4..fe222da 100644 (file)
@@ -1169,13 +1169,12 @@ ps (s)
           segment_name (S_GET_SEGMENT (s)));
 }
 
-struct type_name
+static struct type_name
   {
     unsigned int mask;
     char *tname;
   }
-
-static const type_names[] =
+const type_names[] =
 {
   { Reg8, "r8" },
   { Reg16, "r16" },
@@ -1238,6 +1237,18 @@ reloc (unsigned int size,
       if (size == 8)
        switch (other)
          {
+           case BFD_RELOC_X86_64_GOT32:
+             return BFD_RELOC_X86_64_GOT64;
+             break;
+           case BFD_RELOC_X86_64_PLTOFF64:
+             return BFD_RELOC_X86_64_PLTOFF64;
+             break;
+           case BFD_RELOC_X86_64_GOTPC32:
+             other = BFD_RELOC_X86_64_GOTPC64;
+             break;
+           case BFD_RELOC_X86_64_GOTPCREL:
+             other = BFD_RELOC_X86_64_GOTPCREL64;
+             break;
            case BFD_RELOC_X86_64_TPOFF32:
              other = BFD_RELOC_X86_64_TPOFF64;
              break;
@@ -3569,7 +3580,7 @@ check_prefix:
 #ifdef DEBUG386
   if (flag_debug)
     {
-      pi (line, &i);
+      pi ("" /*line*/, &i);
     }
 #endif /* DEBUG386  */
 }
@@ -3654,7 +3665,9 @@ output_disp (insn_start_frag, insn_start_off)
              if (GOT_symbol
                  && GOT_symbol == i.op[n].disps->X_add_symbol
                  && (((reloc_type == BFD_RELOC_32
-                       || reloc_type == BFD_RELOC_X86_64_32S)
+                       || reloc_type == BFD_RELOC_X86_64_32S
+                       || (reloc_type == BFD_RELOC_64
+                           && object_64bit))
                       && (i.op[n].disps->X_op == O_symbol
                           || (i.op[n].disps->X_op == O_add
                               && ((symbol_get_value_expression
@@ -3678,10 +3691,17 @@ output_disp (insn_start_frag, insn_start_off)
                    }
 
                  if (!object_64bit)
-                   reloc_type = BFD_RELOC_386_GOTPC;
+                   {
+                     reloc_type = BFD_RELOC_386_GOTPC;
+                     i.op[n].imms->X_add_number += add;
+                   }
+                 else if (reloc_type == BFD_RELOC_64)
+                   reloc_type = BFD_RELOC_X86_64_GOTPC64;
                  else
+                   /* Don't do the adjustment for x86-64, as there
+                      the pcrel addressing is relative to the _next_
+                      insn, and that is taken care of in other code.  */
                    reloc_type = BFD_RELOC_X86_64_GOTPC32;
-                 i.op[n].disps->X_add_number += add;
                }
              fix_new_exp (frag_now, p - frag_now->fr_literal, size,
                           i.op[n].disps, pcrel, reloc_type);
@@ -3790,7 +3810,8 @@ output_imm (insn_start_frag, insn_start_off)
               * confusing to do it this way.  */
 
              if ((reloc_type == BFD_RELOC_32
-                  || reloc_type == BFD_RELOC_X86_64_32S)
+                  || reloc_type == BFD_RELOC_X86_64_32S
+                  || reloc_type == BFD_RELOC_64)
                  && GOT_symbol
                  && GOT_symbol == i.op[n].imms->X_add_symbol
                  && (i.op[n].imms->X_op == O_symbol
@@ -3816,8 +3837,10 @@ output_imm (insn_start_frag, insn_start_off)
 
                  if (!object_64bit)
                    reloc_type = BFD_RELOC_386_GOTPC;
-                 else
+                 else if (size == 4)
                    reloc_type = BFD_RELOC_X86_64_GOTPC32;
+                 else if (size == 8)
+                   reloc_type = BFD_RELOC_X86_64_GOTPC64;
                  i.op[n].imms->X_add_number += add;
                }
              fix_new_exp (frag_now, p - frag_now->fr_literal, size,
@@ -3870,12 +3893,19 @@ lex_got (enum bfd_reloc_code_real *reloc,
      int *adjust,
      unsigned int *types)
 {
+  /* Some of the relocations depend on the size of what field is to
+     be relocated.  But in our callers i386_immediate and i386_displacement
+     we don't yet know the operand size (this will be set by insn
+     matching).  Hence we record the word32 relocation here,
+     and adjust the reloc according to the real size in reloc().  */
   static const struct {
     const char *str;
     const enum bfd_reloc_code_real rel[2];
     const unsigned int types64;
   } gotrel[] = {
+    { "PLTOFF",   { 0,                        BFD_RELOC_X86_64_PLTOFF64 }, Imm64 },
     { "PLT",      { BFD_RELOC_386_PLT32,      BFD_RELOC_X86_64_PLT32    }, Imm32|Imm32S|Disp32 },
+    { "GOTPLT",   { 0,                        BFD_RELOC_X86_64_GOTPLT64 }, Imm64|Disp64 },
     { "GOTOFF",   { BFD_RELOC_386_GOTOFF,     BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
     { "GOTPCREL", { 0,                        BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
     { "TLSGD",    { BFD_RELOC_386_TLS_GD,     BFD_RELOC_X86_64_TLSGD    }, Imm32|Imm32S|Disp32 },
@@ -3887,7 +3917,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
     { "DTPOFF",   { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
     { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE,  0                         }, 0 },
     { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE,     0                         }, 0 },
-    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32 },
+    { "GOT",      { BFD_RELOC_386_GOT32,      BFD_RELOC_X86_64_GOT32    }, Imm32|Imm32S|Disp32|Imm64 },
     { "TLSDESC",  { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
     { "TLSCALL",  { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
   };
@@ -4947,6 +4977,20 @@ md_convert_frag (abfd, sec, fragP)
        }
     }
 
+  /* If size if less then four we are sure that the operand fits,
+     but if it's 4, then it could be that the displacement is larger
+     then -/+ 2GB.  */
+  if (DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype) == 4
+      && object_64bit
+      && ((addressT) (displacement_from_opcode_start - extension
+                      + ((addressT) 1 << 31))
+          > (((addressT) 2 << 31) - 1)))
+    {
+      as_bad_where (fragP->fr_file, fragP->fr_line,
+                   _("jump target out of range"));
+      /* Make us emit 0.  */
+      displacement_from_opcode_start = extension;
+    }
   /* Now put displacement after opcode.  */
   md_number_to_chars ((char *) where_to_put_displacement,
                      (valueT) (displacement_from_opcode_start - extension),
@@ -5708,6 +5752,11 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_TPOFF64:
     case BFD_RELOC_X86_64_GOTOFF64:
     case BFD_RELOC_X86_64_GOTPC32:
+    case BFD_RELOC_X86_64_GOT64:
+    case BFD_RELOC_X86_64_GOTPCREL64:
+    case BFD_RELOC_X86_64_GOTPC64:
+    case BFD_RELOC_X86_64_GOTPLT64:
+    case BFD_RELOC_X86_64_PLTOFF64:
     case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
     case BFD_RELOC_X86_64_TLSDESC_CALL:
     case BFD_RELOC_RVA:
@@ -5776,6 +5825,12 @@ tc_gen_reloc (section, fixp)
       else
        code = BFD_RELOC_X86_64_GOTPC32;
     }
+  if ((code == BFD_RELOC_64 || code == BFD_RELOC_64_PCREL)
+      && GOT_symbol
+      && fixp->fx_addsy == GOT_symbol)
+    {
+      code = BFD_RELOC_X86_64_GOTPC64;
+    }
 
   rel = (arelent *) xmalloc (sizeof (arelent));
   rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
index 8503d23..11dfdb4 100644 (file)
@@ -19,6 +19,7 @@ Disassembly of section \.text:
 .*[    ]+R_X86_64_PC32[        ]+xtrn\+0xf+c
 .*[    ]+R_X86_64_PC32[        ]+xtrn\+0xf+c
 .*[    ]+R_X86_64_PC8[         ]+xtrn\+0xf+f
+.*[    ]+R_X86_64_GOT64[       ]+xtrn
 .*[    ]+R_X86_64_GOT32[       ]+xtrn
 .*[    ]+R_X86_64_GOT32[       ]+xtrn
 .*[    ]+R_X86_64_GOTOFF64[    ]+xtrn
@@ -26,7 +27,7 @@ Disassembly of section \.text:
 .*[    ]+R_X86_64_GOTPCREL[    ]+xtrn
 .*[    ]+R_X86_64_GOTPCREL[    ]+xtrn\+0xf+c
 .*[    ]+R_X86_64_GOTPC32[     ]+_GLOBAL_OFFSET_TABLE_\+0x0*2
-.*[    ]+R_X86_64_GOTPC32[     ]+_GLOBAL_OFFSET_TABLE_\+0xf+f
+.*[    ]+R_X86_64_GOTPC32[     ]+_GLOBAL_OFFSET_TABLE_\+0xf+c
 .*[    ]+R_X86_64_GOTPC32[     ]+_GLOBAL_OFFSET_TABLE_\+0x0*2
 .*[    ]+R_X86_64_PLT32[       ]+xtrn
 .*[    ]+R_X86_64_PLT32[       ]+xtrn
@@ -50,7 +51,9 @@ Disassembly of section \.data:
 #...
 .*[    ]+R_X86_64_64[  ]+xtrn
 .*[    ]+R_X86_64_PC64[        ]+xtrn
+.*[    ]+R_X86_64_GOT64[       ]+xtrn
 .*[    ]+R_X86_64_GOTOFF64[    ]+xtrn
+.*[    ]+R_X86_64_GOTPCREL64[  ]+xtrn
 .*[    ]+R_X86_64_DTPOFF64[    ]+xtrn
 .*[    ]+R_X86_64_TPOFF64[     ]+xtrn
 .*[    ]+R_X86_64_32[  ]+xtrn
index 62a762b..87a5c77 100644 (file)
@@ -1,6 +1,5 @@
 .*: Assembler messages:
 .*:29: Error: .*
-.*:33: Error: .*
 .*:35: Error: .*
 .*:36: Error: .*
 .*:37: Error: .*
@@ -50,8 +49,6 @@
 .*:123: Error: .*
 .*:125: Error: .*
 .*:126: Error: .*
-.*:131: Error: .*
-.*:133: Error: .*
 .*:136: Error: .*
 .*:137: Error: .*
 .*:138: Error: .*
index 1ae14dd..47ebfa8 100644 (file)
@@ -30,7 +30,7 @@ bad   mov     xtrn(%eip), %eax
        call    xtrn
        jrcxz   xtrn
 
-bad    movabs  $xtrn@got, %rax
+       movabs  $xtrn@got, %rax
        add     $xtrn@got, %rax
 bad    mov     $xtrn@got, %eax
 bad    mov     $xtrn@got, %ax
@@ -128,9 +128,9 @@ bad call    xtrn@tpoff
  .data
        .quad   xtrn
        .quad   xtrn - .
-bad    .quad   xtrn@got
+       .quad   xtrn@got
        .quad   xtrn@gotoff
-bad    .quad   xtrn@gotpcrel
+       .quad   xtrn@gotpcrel
 ill    .quad   _GLOBAL_OFFSET_TABLE_
 ill    .quad   _GLOBAL_OFFSET_TABLE_ - .
 bad    .quad   xtrn@plt
index 74655fb..b09a558 100644 (file)
@@ -54,7 +54,16 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
      RELOC_NUMBER (R_X86_64_GOTOFF64, 25)     /* 64 bit offset to GOT */
      RELOC_NUMBER (R_X86_64_GOTPC32,  26)     /* 32 bit signed pc relative
                                                  offset to GOT */
-     /* 27 .. 33 */
+     RELOC_NUMBER (R_X86_64_GOT64,    27)     /* 64 bit GOT entry offset */
+     RELOC_NUMBER (R_X86_64_GOTPCREL64, 28)   /* 64 bit signed pc relative
+                                                offset to GOT entry */
+     RELOC_NUMBER (R_X86_64_GOTPC64,  29)     /* 64 bit signed pc relative
+                                                offset to GOT */
+     RELOC_NUMBER (R_X86_64_GOTPLT64, 30)     /* like GOT64, but indicates
+                                                that PLT entry is needed */
+     RELOC_NUMBER (R_X86_64_PLTOFF64, 31)     /* 64 bit GOT relative offset
+                                                to PLT entry */
+     /* 32 .. 33 */
      RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34)
                                              /* 32 bit signed pc relative
                                                 offset to TLS descriptor