[PATCH] x86-64: support newer relocation types

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] x86-64: support newer relocation types

Jan Beulich
This adds support for the new x86-64 relocation types added in ABI draft
0.95 (or in a slightly earlier version). In addition, it fixes the overflow
complaint types for two x86-64 and one i386 relocation types.

Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.

Jan

bfd/
2005-06-08  Jan Beulich  <[hidden email]>

        * bfd-in2.h (elf_x86_64_reloc_type): Add BFD_RELOC_X86_64_GOTOFF64
        and BFD_RELOC_X86_64_GOTPC32.
        * libbfd.h (bfd_reloc_code_real_names): Likewise.
        * elf64-x86-64.c (x86_64_elf_howto_table): Adjust overflow complaint
        handler for R_X86_64_PC16 and R_X86_64_8. Add entries for
        R_X86_64_PC64, R_X86_64_GOTOFF64, and R_X86_64_GOTPC32.
        (x86_64_reloc_map): Add entries for R_X86_64_PC64, R_X86_64_GOTOFF64,
        and R_X86_64_GOTPC32.
        (elf64_x86_64_info_to_howto): Adjust bounding relocation type.
        (elf64_x86_64_check_relocs): Also handle R_X86_64_PC64,
        R_X86_64_GOTOFF64, and R_X86_64_GOTPC32.
        (elf64_x86_64_relocate_section): Likewise.
        (elf64_x86_64_gc_sweep_hook): Also handle R_X86_64_PC64.
        * elf32-i386.c (elf_howto_table): Adjust overflow complaint handler
        for R_386_PC16.

gas/
2005-06-08  Jan Beulich  <[hidden email]>

        * config/tc-i386.c (reloc): Also handle BFD_RELOC_64_PCREL.
        (tc_i386_fix_adjustable): Include BFD_RELOC_X86_64_GOTOFF64.
        (output_disp): Use BFD_RELOC_X86_64_GOTPC32 instead of aborting.
        (output_imm): Likewise.
        (tc_gen_reloc): Likewise. Also handle BFD_RELOC_X86_64_GOTOFF64
        and BFD_RELOC_X86_64_GOTPC32. Also convert 8-byte pc-relative
        relocations.
        (lex_got): Use BFD_RELOC_X86_64_GOTOFF64 for 64-bit @gotoff.
        (i386_validate_fix): Likewise.
        (x86_cons): Also handle quad values in 64-bit mode.
        (i386_displacement): Also handle BFD_RELOC_X86_64_GOTOFF64.
        (md_apply_fix): Also handle convert BFD_RELOC_64 to pc-relative
        variant. Also check for BFD_RELOC_64_PCREL.

gas/testsuite/
2005-06-08  Jan Beulich  <[hidden email]>

        * gas/i386/x86-64-pcrel.s: Add insn requiring 64-bit pc-relative
        relocation. Add insns for all widths of non-pc-relative relocations.
        * gas/i386/x86-64-pcrel.d: Adjust.

include/elf/
2005-06-08  Jan Beulich  <[hidden email]>

        * x86-64.h (elf_x86_64_reloc_type): Adjust comment for
        R_X86_64_GOTPCREL. Add R_X86_64_PC64, R_X86_64_GOTOFF64, and
        R_X86_64_GOTPC32.

--- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/bfd-in2.h 2005-06-08 14:50:36.000000000 +0200
+++ 2005-06-08/bfd/bfd-in2.h 2005-06-08 15:41:20.906779680 +0200
@@ -2617,6 +2617,8 @@ in the instruction.  */
   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,
--- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf32-i386.c 2005-06-08 14:50:38.000000000 +0200
+++ 2005-06-08/bfd/elf32-i386.c 2005-06-08 15:41:20.913778616 +0200
@@ -95,7 +95,7 @@ static reloc_howto_type elf_howto_table[
   HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
  bfd_elf_generic_reloc, "R_386_16",
  TRUE, 0xffff, 0xffff, FALSE),
-  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
+  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_signed,
  bfd_elf_generic_reloc, "R_386_PC16",
  TRUE, 0xffff, 0xffff, TRUE),
   HOWTO(R_386_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
--- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf64-x86-64.c 2005-05-18 08:09:48.000000000 +0200
+++ 2005-06-08/bfd/elf64-x86-64.c 2005-06-08 15:41:20.944773904 +0200
@@ -73,9 +73,9 @@ static reloc_howto_type x86_64_elf_howto
  FALSE),
   HOWTO(R_X86_64_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
  bfd_elf_generic_reloc, "R_X86_64_16", FALSE, 0xffff, 0xffff, FALSE),
-  HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_bitfield,
+  HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_signed,
  bfd_elf_generic_reloc, "R_X86_64_PC16", FALSE, 0xffff, 0xffff, TRUE),
-  HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_signed,
+  HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
  bfd_elf_generic_reloc, "R_X86_64_8", FALSE, 0xff, 0xff, FALSE),
   HOWTO(R_X86_64_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed,
  bfd_elf_generic_reloc, "R_X86_64_PC8", FALSE, 0xff, 0xff, TRUE),
@@ -103,6 +103,15 @@ static reloc_howto_type x86_64_elf_howto
   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_bitfield,
+ 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_bitfield,
+ 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,
@@ -147,6 +156,9 @@ static const struct elf_reloc_map x86_64
   { 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, },
 };
@@ -179,13 +191,13 @@ elf64_x86_64_info_to_howto (bfd *abfd AT
   r_type = ELF64_R_TYPE (dst->r_info);
   if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT)
     {
-      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_TPOFF32);
+      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_GOTPC32);
       i = r_type;
     }
   else
     {
       BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);
-      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_TPOFF32 - 1);
+      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_GOTPC32 - 1);
     }
   cache_ptr->howto = &x86_64_elf_howto_table[i];
   BFD_ASSERT (r_type == cache_ptr->howto->type);
@@ -749,7 +761,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
   }
   /* Fall through */
 
-  //case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTOFF64:
+ case R_X86_64_GOTPC32:
  create_got:
   if (htab->sgot == NULL)
     {
@@ -802,6 +815,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
  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)
     {
@@ -816,7 +830,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
       /* We may need a .plt entry if the function this reloc
  refers to is in a shared lib.  */
       h->plt.refcount += 1;
-      if (r_type != R_X86_64_PC32)
+      if (r_type != R_X86_64_PC32 && r_type != R_X86_64_PC64)
  h->pointer_equality_needed = 1;
     }
 
@@ -845,7 +859,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
        && (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_PC32)
+    && (r_type != R_X86_64_PC64))
    || (h != NULL
        && (! info->symbolic
    || h->root.type == bfd_link_hash_defweak
@@ -948,7 +963,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
       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_PC32
+  || r_type == R_X86_64_PC64)
  p->pc_count += 1;
     }
   break;
@@ -1093,6 +1109,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, s
  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 */
@@ -1941,6 +1958,42 @@ elf64_x86_64_relocate_section (bfd *outp
 
   break;
 
+ case R_X86_64_GOTOFF64:
+  /* Relocation is relative to the start of the global offset
+     table.  */
+
+  /* Check to make sure it isn't a protected function symbol
+     for shared library since it may not be local when used
+     as function address.  */
+  if (info->shared
+      && h
+      && h->def_regular
+      && h->type == STT_FUNC
+      && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
+    {
+      (*_bfd_error_handler)
+ (_("%B: relocation R_X86_64_GOTOFF64 against protected function `%s' can not be used when making a shared object"),
+ input_bfd, h->root.root.string);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Note that sgot is not involved in this
+     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
+  break;
+
+ case R_X86_64_GOTPC32:
+  /* 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_PLT32:
   /* Relocation is to the entry for this symbol in the
      procedure linkage table.  */
@@ -1999,6 +2052,7 @@ elf64_x86_64_relocate_section (bfd *outp
  case R_X86_64_8:
  case R_X86_64_16:
  case R_X86_64_32:
+ case R_X86_64_PC64:
  case R_X86_64_64:
   /* FIXME: The ABI says the linker should make sure the value is
      the same when it's zeroextended to 64 bit. */
@@ -2016,7 +2070,8 @@ elf64_x86_64_relocate_section (bfd *outp
    || 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_PC32
+    && r_type != R_X86_64_PC64)
    || !SYMBOL_CALLS_LOCAL (info, h)))
       || (ELIMINATE_COPY_RELOCS
   && !info->shared
@@ -2060,6 +2115,7 @@ elf64_x86_64_relocate_section (bfd *outp
        && (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->def_regular))
--- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/libbfd.h 2005-06-08 14:50:42.000000000 +0200
+++ 2005-06-08/bfd/libbfd.h 2005-06-08 15:41:20.948773296 +0200
@@ -1049,6 +1049,8 @@ static const char *const bfd_reloc_code_
   "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",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
--- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/config/tc-i386.c 2005-06-08 14:50:49.000000000 +0200
+++ 2005-06-08/gas/config/tc-i386.c 2005-06-08 15:41:20.962771168 +0200
@@ -1222,6 +1222,7 @@ reloc (size, pcrel, sign, other)
  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);
     }
@@ -1294,6 +1295,7 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -3526,10 +3528,10 @@ output_disp (insn_start_frag, insn_start
       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;
+  if (flag_code != CODE_64BIT)
+    reloc_type = BFD_RELOC_386_GOTPC;
+  else
+    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,
@@ -3662,10 +3664,10 @@ output_imm (insn_start_frag, insn_start_
       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;
+  if (flag_code != CODE_64BIT)
+    reloc_type = BFD_RELOC_386_GOTPC;
+  else
+    reloc_type = BFD_RELOC_X86_64_GOTPC32;
   i.op[n].imms->X_add_number += add;
  }
       fix_new_exp (frag_now, p - frag_now->fr_literal, size,
@@ -3698,7 +3700,7 @@ lex_got (reloc, adjust)
     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                         } },
+    { "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                         } },
@@ -3792,7 +3794,7 @@ x86_cons (exp, size)
      expressionS *exp;
      int size;
 {
-  if (size == 4)
+  if (size == 4 || (flag_code == CODE_64BIT && size == 8))
     {
       /* Handle @GOTOFF and the like in an expression.  */
       char *save;
@@ -4104,7 +4106,8 @@ i386_displacement (disp_start, disp_end)
      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_GOTPCREL)
+      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
+      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
     {
       if (exp->X_op != O_symbol)
  {
@@ -4122,6 +4125,8 @@ i386_displacement (disp_start, disp_end)
       exp->X_op_symbol = GOT_symbol;
       if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
  i.reloc[this_operand] = BFD_RELOC_32_PCREL;
+      else if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
+ i.reloc[this_operand] = BFD_RELOC_64;
       else
  i.reloc[this_operand] = BFD_RELOC_32;
     }
@@ -4812,6 +4817,9 @@ md_apply_fix (fixP, valP, seg)
  default:
   break;
 
+ case BFD_RELOC_64:
+  fixP->fx_r_type = BFD_RELOC_64_PCREL;
+  break;
  case BFD_RELOC_32:
  case BFD_RELOC_X86_64_32S:
   fixP->fx_r_type = BFD_RELOC_32_PCREL;
@@ -4827,6 +4835,7 @@ md_apply_fix (fixP, valP, seg)
 
   if (fixP->fx_addsy != NULL
       && (fixP->fx_r_type == BFD_RELOC_32_PCREL
+  || fixP->fx_r_type == BFD_RELOC_64_PCREL
   || fixP->fx_r_type == BFD_RELOC_16_PCREL
   || fixP->fx_r_type == BFD_RELOC_8_PCREL)
       && !use_rela_relocations)
@@ -5339,7 +5348,6 @@ i386_validate_fix (fixp)
 {
   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)
@@ -5348,9 +5356,10 @@ i386_validate_fix (fixp)
  }
       else
  {
-  if (flag_code == CODE_64BIT)
-    abort ();
-  fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+  if (flag_code != CODE_64BIT)
+    fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+  else
+    fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
  }
       fixp->fx_subsy = 0;
     }
@@ -5386,6 +5395,8 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_DTPOFF32:
     case BFD_RELOC_X86_64_GOTTPOFF:
     case BFD_RELOC_X86_64_TPOFF32:
+    case BFD_RELOC_X86_64_GOTOFF64:
+    case BFD_RELOC_X86_64_GOTPC32:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5415,6 +5426,9 @@ tc_gen_reloc (section, fixp)
     case 1: code = BFD_RELOC_8_PCREL;  break;
     case 2: code = BFD_RELOC_16_PCREL; break;
     case 4: code = BFD_RELOC_32_PCREL; break;
+#ifdef BFD64
+    case 8: code = BFD_RELOC_64_PCREL; break;
+#endif
     }
  }
       else
@@ -5442,10 +5456,10 @@ tc_gen_reloc (section, fixp)
       && 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;
+      if (flag_code != CODE_64BIT)
+ code = BFD_RELOC_386_GOTPC;
+      else
+ code = BFD_RELOC_X86_64_GOTPC32;
     }
 
   rel = (arelent *) xmalloc (sizeof (arelent));
--- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-04-11 08:11:28.000000000 +0200
+++ 2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-06-08 15:41:20.964770864 +0200
@@ -8,7 +8,12 @@ Disassembly of section .text:
 0+000 <_start>:
 [ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_PC8[ ]+xtrn\+(0x)?1
 [ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC16[ ]+xtrn\+(0x)?2
-[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
-[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
-[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
+[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
+[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC64[ ]+xtrn\+(0x)?2
+[ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_8[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_16[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_32[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_64[ ]+xtrn
 #pass
--- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-04-11 08:11:28.000000000 +0200
+++ 2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-06-08 15:41:20.966770560 +0200
@@ -4,6 +4,12 @@ _start:
  movw $(xtrn - .), %ax
  movl $(xtrn - .), %eax
  movq $(xtrn - .), %rax
+ movabsq $(xtrn - .), %rax
+
+ movb $xtrn, %al
+ movw $xtrn, %ax
+ movl $xtrn, %eax
  movq $xtrn, %rax
+ movabsq $xtrn, %rax
 
  .p2align 4,0
--- /home/jbeulich/src/binutils/mainline/2005-06-08/include/elf/x86-64.h 2005-05-13 12:17:11.000000000 +0200
+++ 2005-06-08/include/elf/x86-64.h 2005-06-08 15:41:20.967770408 +0200
@@ -34,7 +34,7 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_JUMP_SLOT,7)      /* Create PLT entry */
      RELOC_NUMBER (R_X86_64_RELATIVE, 8)      /* Adjust by program base */
      RELOC_NUMBER (R_X86_64_GOTPCREL, 9)      /* 32 bit signed pc relative
-                                                 offset to GOT */
+                                                 offset to GOT entry */
      RELOC_NUMBER (R_X86_64_32,       10)     /* Direct 32 bit zero extended */
      RELOC_NUMBER (R_X86_64_32S,      11)     /* Direct 32 bit sign extended */
      RELOC_NUMBER (R_X86_64_16,       12)     /* Direct 16 bit zero extended */
@@ -49,6 +49,10 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_DTPOFF32, 21)     /* Offset in TLS block */
      RELOC_NUMBER (R_X86_64_GOTTPOFF, 22)     /* PC relative offset to IE GOT entry */
      RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
+     RELOC_NUMBER (R_X86_64_PC64,     24)     /* PC relative 64 bit */
+     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 */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)


binutils-mainline-x86_64-abi095-relocs.patch (20K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka-2
> This adds support for the new x86-64 relocation types added in ABI draft
> 0.95 (or in a slightly earlier version). In addition, it fixes the overflow
> complaint types for two x86-64 and one i386 relocation types.
>
> Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.

Hi,
as mentioned off-list, we (Jan and me) developed two implementations of
the binutils changes independently.  I was holding the patch as I wanted
to do the changes in sync with GCC that was frozen at that point (I will
update the GCC patch this week too as it is now good time to submit it).
I am sorry that this lead to diplicated effort.

My one also contains the changes to linker script needed to get medium
model working, but since Jan's implementation is more up-to-date I think
the best scheme is to go with his patch and I will break out remaining
pieces out of my patch once new relocations are in place.  Also I think
I can approve this patch as x86-64 maintainer, but I don't feel
competent to comment on linker script stuff.

I have however few problems with the patch...

> --- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf32-i386.c 2005-06-08 14:50:38.000000000 +0200
> +++ 2005-06-08/bfd/elf32-i386.c 2005-06-08 15:41:20.913778616 +0200
> @@ -95,7 +95,7 @@ static reloc_howto_type elf_howto_table[
>    HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
>   bfd_elf_generic_reloc, "R_386_16",
>   TRUE, 0xffff, 0xffff, FALSE),
> -  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
> +  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_signed,

I would preffer to handle this via separate patch (even tought the
change looks correct to me, see bellow)

>   bfd_elf_generic_reloc, "R_386_PC16",
>   TRUE, 0xffff, 0xffff, TRUE),
>    HOWTO(R_386_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
> --- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf64-x86-64.c 2005-05-18 08:09:48.000000000 +0200
> +++ 2005-06-08/bfd/elf64-x86-64.c 2005-06-08 15:41:20.944773904 +0200
> @@ -73,9 +73,9 @@ static reloc_howto_type x86_64_elf_howto
>   FALSE),
>    HOWTO(R_X86_64_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
>   bfd_elf_generic_reloc, "R_X86_64_16", FALSE, 0xffff, 0xffff, FALSE),
> -  HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_bitfield,
> +  HOWTO(R_X86_64_PC16,0, 1, 16, TRUE, 0, complain_overflow_signed,
>   bfd_elf_generic_reloc, "R_X86_64_PC16", FALSE, 0xffff, 0xffff, TRUE),
> -  HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_signed,
> +  HOWTO(R_X86_64_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,
>   bfd_elf_generic_reloc, "R_X86_64_8", FALSE, 0xff, 0xff, FALSE),
>    HOWTO(R_X86_64_PC8, 0, 0, 8, TRUE, 0, complain_overflow_signed,
>   bfd_elf_generic_reloc, "R_X86_64_PC8", FALSE, 0xff, 0xff, TRUE),
> @@ -103,6 +103,15 @@ static reloc_howto_type x86_64_elf_howto
>    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_bitfield,
> + 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_bitfield,
> + 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),


Well, mine version reads here:
+   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),

I think Jan's patch is correct in this respect (as unlike for smaller
relocation times, the address "wrap around"), but please double check.

> +  /* Note that sgot is not involved in this
> +     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
> + + htab->sgotplt->output_offset;
> +  break;
> +
> + case R_X86_64_GOTPC32:
> +  /* Use global offset table as symbol value.  */
> +  relocation = htab->sgotplt->output_section->vma
> +       + htab->sgotplt->output_offset;
> +  unresolved_reloc = FALSE;
> +  break;


There is another difference relative to my implementation:

+  /* 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.  */
+  relocation = htab->sgot->output_section->vma;
+  unresolved_reloc = FALSE;
+  break;
+

Mine implementation went out from kind of trial and error process to get
the numbers in relocations right, so your's might be correct, but it
clearly shows that I am not competent to review this portion of patch so
I would preffer someone more BFD aware to comment here.

> +
>   case R_X86_64_PLT32:
>    /* Relocation is to the entry for this symbol in the
>       procedure linkage table.  */
> @@ -1999,6 +2052,7 @@ elf64_x86_64_relocate_section (bfd *outp
>   case R_X86_64_8:
>   case R_X86_64_16:
>   case R_X86_64_32:
> + case R_X86_64_PC64:
>   case R_X86_64_64:
>    /* FIXME: The ABI says the linker should make sure the value is
>       the same when it's zeroextended to 64 bit. */
> @@ -2016,7 +2070,8 @@ elf64_x86_64_relocate_section (bfd *outp
>     || 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_PC32
> +    && r_type != R_X86_64_PC64)
>     || !SYMBOL_CALLS_LOCAL (info, h)))
>        || (ELIMINATE_COPY_RELOCS
>    && !info->shared
> @@ -2060,6 +2115,7 @@ elf64_x86_64_relocate_section (bfd *outp
>         && (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->def_regular))
> --- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/libbfd.h 2005-06-08 14:50:42.000000000 +0200
> +++ 2005-06-08/bfd/libbfd.h 2005-06-08 15:41:20.948773296 +0200
> @@ -1049,6 +1049,8 @@ static const char *const bfd_reloc_code_
>    "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",
>    "BFD_RELOC_NS32K_IMM_8",
>    "BFD_RELOC_NS32K_IMM_16",
>    "BFD_RELOC_NS32K_IMM_32",
> --- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/config/tc-i386.c 2005-06-08 14:50:49.000000000 +0200
> +++ 2005-06-08/gas/config/tc-i386.c 2005-06-08 15:41:20.962771168 +0200
> @@ -1222,6 +1222,7 @@ reloc (size, pcrel, sign, other)
>   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);
>      }
> @@ -1294,6 +1295,7 @@ tc_i386_fix_adjustable (fixP)
>        || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
>        || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
>        || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
> +      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
>        || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
>        || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
>      return 0;

I think you need to add matching of GOT relative arithmetics:
*************** output_disp (insn_start_frag, insn_start
*** 3336,3353 ****
 
       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;
 
!  if (insn_start_frag == frag_now)
     add = (p - frag_now->fr_literal) - insn_start_off;
   else
     {
--- 3338,3360 ----
 
       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;
 
!  if (flag_code == CODE_64BIT)
!    add = 0;
!  else if (insn_start_frag == frag_now)
     add = (p - frag_now->fr_literal) - insn_start_off;
   else
     {

> @@ -3526,10 +3528,10 @@ output_disp (insn_start_frag, insn_start
>        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;
> +  if (flag_code != CODE_64BIT)
> +    reloc_type = BFD_RELOC_386_GOTPC;
> +  else
> +    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,

And here too:
*************** 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;
 
--- 3478,3494 ----
        * 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;
 

> @@ -3662,10 +3664,10 @@ output_imm (insn_start_frag, insn_start_
>        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;
> +  if (flag_code != CODE_64BIT)
> +    reloc_type = BFD_RELOC_386_GOTPC;
> +  else
> +    reloc_type = BFD_RELOC_X86_64_GOTPC32;
>    i.op[n].imms->X_add_number += add;
>   }
>        fix_new_exp (frag_now, p - frag_now->fr_literal, size,
> @@ -3698,7 +3700,7 @@ lex_got (reloc, adjust)
>      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                         } },
> +    { "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                         } },
> @@ -3792,7 +3794,7 @@ x86_cons (exp, size)

And here the GOT relocation:
*************** 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;
--- 3552,3558 ----
      { "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;

>       expressionS *exp;
>       int size;
>  {
> -  if (size == 4)
> +  if (size == 4 || (flag_code == CODE_64BIT && size == 8))
>      {
>        /* Handle @GOTOFF and the like in an expression.  */
>        char *save;
> @@ -4104,7 +4106,8 @@ i386_displacement (disp_start, disp_end)
>       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_GOTPCREL)
> +      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
> +      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
>      {
>        if (exp->X_op != O_symbol)
>   {
> @@ -4122,6 +4125,8 @@ i386_displacement (disp_start, disp_end)
>        exp->X_op_symbol = GOT_symbol;
>        if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
>   i.reloc[this_operand] = BFD_RELOC_32_PCREL;
> +      else if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
> + i.reloc[this_operand] = BFD_RELOC_64;
>        else
>   i.reloc[this_operand] = BFD_RELOC_32;
>      }
> @@ -4812,6 +4817,9 @@ md_apply_fix (fixP, valP, seg)
>   default:
>    break;
>  
> + case BFD_RELOC_64:
> +  fixP->fx_r_type = BFD_RELOC_64_PCREL;
> +  break;
>   case BFD_RELOC_32:
>   case BFD_RELOC_X86_64_32S:
>    fixP->fx_r_type = BFD_RELOC_32_PCREL;
> @@ -4827,6 +4835,7 @@ md_apply_fix (fixP, valP, seg)
>  
>    if (fixP->fx_addsy != NULL
>        && (fixP->fx_r_type == BFD_RELOC_32_PCREL
> +  || fixP->fx_r_type == BFD_RELOC_64_PCREL
>    || fixP->fx_r_type == BFD_RELOC_16_PCREL
>    || fixP->fx_r_type == BFD_RELOC_8_PCREL)
>        && !use_rela_relocations)
> @@ -5339,7 +5348,6 @@ i386_validate_fix (fixp)
>  {
>    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)
> @@ -5348,9 +5356,10 @@ i386_validate_fix (fixp)
>   }
>        else
>   {
> -  if (flag_code == CODE_64BIT)
> -    abort ();
> -  fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
> +  if (flag_code != CODE_64BIT)
> +    fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
> +  else
> +    fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
>   }
>        fixp->fx_subsy = 0;
>      }
> @@ -5386,6 +5395,8 @@ tc_gen_reloc (section, fixp)
>      case BFD_RELOC_X86_64_DTPOFF32:
>      case BFD_RELOC_X86_64_GOTTPOFF:
>      case BFD_RELOC_X86_64_TPOFF32:
> +    case BFD_RELOC_X86_64_GOTOFF64:
> +    case BFD_RELOC_X86_64_GOTPC32:
>      case BFD_RELOC_RVA:
>      case BFD_RELOC_VTABLE_ENTRY:
>      case BFD_RELOC_VTABLE_INHERIT:
> @@ -5415,6 +5426,9 @@ tc_gen_reloc (section, fixp)
>      case 1: code = BFD_RELOC_8_PCREL;  break;
>      case 2: code = BFD_RELOC_16_PCREL; break;
>      case 4: code = BFD_RELOC_32_PCREL; break;
> +#ifdef BFD64
> +    case 8: code = BFD_RELOC_64_PCREL; break;
> +#endif
>      }
>   }
>        else
> @@ -5442,10 +5456,10 @@ tc_gen_reloc (section, fixp)
>        && 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;
> +      if (flag_code != CODE_64BIT)
> + code = BFD_RELOC_386_GOTPC;
> +      else
> + code = BFD_RELOC_X86_64_GOTPC32;
>      }
>  
>    rel = (arelent *) xmalloc (sizeof (arelent));
And GOT arithmetic here...
*************** 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));
--- 5275,5288 ----
        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));

> --- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-04-11 08:11:28.000000000 +0200
> +++ 2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-06-08 15:41:20.964770864 +0200
> @@ -8,7 +8,12 @@ Disassembly of section .text:
>  0+000 <_start>:
>  [ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_PC8[ ]+xtrn\+(0x)?1
>  [ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC16[ ]+xtrn\+(0x)?2
> -[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
> -[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
> -[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
> +[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
> +[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
> +[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC64[ ]+xtrn\+(0x)?2
> +[ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_8[ ]+xtrn
> +[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_16[ ]+xtrn
> +[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_32[ ]+xtrn
> +[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
> +[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_64[ ]+xtrn
>  #pass
> --- /home/jbeulich/src/binutils/mainline/2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-04-11 08:11:28.000000000 +0200
> +++ 2005-06-08/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-06-08 15:41:20.966770560 +0200
> @@ -4,6 +4,12 @@ _start:
>   movw $(xtrn - .), %ax
>   movl $(xtrn - .), %eax
>   movq $(xtrn - .), %rax
> + movabsq $(xtrn - .), %rax
> +
> + movb $xtrn, %al
> + movw $xtrn, %ax
> + movl $xtrn, %eax
>   movq $xtrn, %rax
> + movabsq $xtrn, %rax
>  
>   .p2align 4,0
> --- /home/jbeulich/src/binutils/mainline/2005-06-08/include/elf/x86-64.h 2005-05-13 12:17:11.000000000 +0200
> +++ 2005-06-08/include/elf/x86-64.h 2005-06-08 15:41:20.967770408 +0200
> @@ -34,7 +34,7 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
>       RELOC_NUMBER (R_X86_64_JUMP_SLOT,7)      /* Create PLT entry */
>       RELOC_NUMBER (R_X86_64_RELATIVE, 8)      /* Adjust by program base */
>       RELOC_NUMBER (R_X86_64_GOTPCREL, 9)      /* 32 bit signed pc relative
> -                                                 offset to GOT */
> +                                                 offset to GOT entry */
>       RELOC_NUMBER (R_X86_64_32,       10)     /* Direct 32 bit zero extended */
>       RELOC_NUMBER (R_X86_64_32S,      11)     /* Direct 32 bit sign extended */
>       RELOC_NUMBER (R_X86_64_16,       12)     /* Direct 16 bit zero extended */
> @@ -49,6 +49,10 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
>       RELOC_NUMBER (R_X86_64_DTPOFF32, 21)     /* Offset in TLS block */
>       RELOC_NUMBER (R_X86_64_GOTTPOFF, 22)     /* PC relative offset to IE GOT entry */
>       RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
> +     RELOC_NUMBER (R_X86_64_PC64,     24)     /* PC relative 64 bit */
> +     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 */
>       RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
>       RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
>  END_RELOC_NUMBERS (R_X86_64_max)
>

Otherwise our patches are almost equivalent (so I believe they are
correct ;).  I would preffer the tc-i386.c changes  (even if the
arithmetic syntax can be added incrementally) to go in and someone BFD
aware to comment on the relocatino handling issues, but otherwise the
patch would be OK.

Thanks,
Honza
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

H.J. Lu-27
On Sun, Jun 12, 2005 at 02:28:25PM +0200, Jan Hubicka wrote:

>
> > +  /* Note that sgot is not involved in this
> > +     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
> > + + htab->sgotplt->output_offset;
> > +  break;
> > +
> > + case R_X86_64_GOTPC32:
> > +  /* Use global offset table as symbol value.  */
> > +  relocation = htab->sgotplt->output_section->vma
> > +       + htab->sgotplt->output_offset;
> > +  unresolved_reloc = FALSE;
> > +  break;
>
>
> There is another difference relative to my implementation:
>
> +  /* 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.  */
> +  relocation = htab->sgot->output_section->vma;
> +  unresolved_reloc = FALSE;
> +  break;
> +
>
Jan's version is the same as i386. I believe those relocations are
the same between i386 and x86_64.



H.J.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
> On Sun, Jun 12, 2005 at 02:28:25PM +0200, Jan Hubicka wrote:
> >
> > > +  /* Note that sgot is not involved in this
> > > +     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
> > > + + htab->sgotplt->output_offset;
> > > +  break;
> > > +
> > > + case R_X86_64_GOTPC32:
> > > +  /* Use global offset table as symbol value.  */
> > > +  relocation = htab->sgotplt->output_section->vma
> > > +       + htab->sgotplt->output_offset;
> > > +  unresolved_reloc = FALSE;
> > > +  break;
> >
> >
> > There is another difference relative to my implementation:
> >
> > +  /* 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.  */
> > +  relocation = htab->sgot->output_section->vma;
> > +  unresolved_reloc = FALSE;
> > +  break;
> > +
> >
> Jan's version is the same as i386. I believe those relocations are
> the same between i386 and x86_64.

Yeah, I just copied it around and it seemed to fit, but I am not quite
sure whether REL/RELA difference does not play important role here...

Honza
>
>
>
> H.J.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>> --- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf32-i386.c 2005-06-08 14:50:38.000000000 +0200
>> +++ 2005-06-08/bfd/elf32-i386.c 2005-06-08 15:41:20.913778616 +0200
>> @@ -95,7 +95,7 @@ static reloc_howto_type elf_howto_table[
>>    HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
>>   bfd_elf_generic_reloc, "R_386_16",
>>   TRUE, 0xffff, 0xffff, FALSE),
>> -  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
>> +  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_signed,
>
>I would preffer to handle this via separate patch (even tought the
>change looks correct to me, see bellow)

This I can certainly do, though it seemed wasted effort to break this out given the identical adjustments made to the respective 64-bit code.

>> +  HOWTO(R_X86_64_PC64, 0, 4, 64, TRUE, 0, complain_overflow_bitfield,
>> + bfd_elf_generic_reloc, "R_X86_64_PC64", FALSE, MINUS_ONE, MINUS_ONE,
>> + TRUE),
>
>Well, mine version reads here:
>+   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),
>
>I think Jan's patch is correct in this respect (as unlike for smaller
>relocation times, the address "wrap around"), but please double check.

I'm not sure what to double check here.

>> +  /* Note that sgot is not involved in this
>> +     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
>> + + htab->sgotplt->output_offset;
>> +  break;
>> +
>> + case R_X86_64_GOTPC32:
>> +  /* Use global offset table as symbol value.  */
>> +  relocation = htab->sgotplt->output_section->vma
>> +       + htab->sgotplt->output_offset;
>> +  unresolved_reloc = FALSE;
>> +  break;
>
>There is another difference relative to my implementation:
>
>+  /* 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.  */
>+  relocation = htab->sgot->output_section->vma;
>+  unresolved_reloc = FALSE;
>+  break;
>+

I'm fairly sure the code in the patch is correct: What you want here is the address of the GOT, not the address of the section the GOT is contained in. Of course, in practice GOT will probably never live in a section shared with something else, but who knows...

>I think you need to add matching of GOT relative arithmetics:
>*************** output_disp (insn_start_frag, insn_start
>*** 3336,3353 ****
>  
>        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;
>  
>!  if (insn_start_frag == frag_now)
>      add = (p - frag_now->fr_literal) - insn_start_off;
>    else
>      {
>--- 3338,3360 ----
>  
>        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;
>  
>!  if (flag_code == CODE_64BIT)
>!    add = 0;
>!  else if (insn_start_frag == frag_now)
>      add = (p - frag_now->fr_literal) - insn_start_off;
>    else
>      {

If so, this would seem to be an unrelated change, as the GOTPC32 reloc in my patch is handled exactly like the i386 one (which of course is very broken, but obviously cannot be fixed). Or maybe I don't see how you would see BFD_RELOC_32_PCREL to end up here.

>And here the GOT relocation:
>*************** 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;
>--- 3552,3558 ----
>      { "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;

Hmm, this confuses me. All the difference consists in an (ill) comma as far as I can see.

>> @@ -5442,10 +5456,10 @@ tc_gen_reloc (section, fixp)
>>        && 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;
>> +      if (flag_code != CODE_64BIT)
>> + code = BFD_RELOC_386_GOTPC;
>> +      else
>> + code = BFD_RELOC_X86_64_GOTPC32;
>>      }
>>  
>>    rel = (arelent *) xmalloc (sizeof (arelent));
>And GOT arithmetic here...
>*************** 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));
>--- 5275,5288 ----
>        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));

Yours is the same change as mine (except for the BFD_RELOC_32_PCREL, as above), isn't it?

>Otherwise our patches are almost equivalent (so I believe they are
>correct ;).  I would preffer the tc-i386.c changes  (even if the
>arithmetic syntax can be added incrementally) to go in and someone BFD
>aware to comment on the relocatino handling issues, but otherwise the
>patch would be OK.

Now, how do we go further with this? Who's going to finally approve it?

Jan
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
In reply to this post by Jan Beulich
> >> --- /home/jbeulich/src/binutils/mainline/2005-06-08/bfd/elf32-i386.c 2005-06-08 14:50:38.000000000 +0200
> >> +++ 2005-06-08/bfd/elf32-i386.c 2005-06-08 15:41:20.913778616 +0200
> >> @@ -95,7 +95,7 @@ static reloc_howto_type elf_howto_table[
> >>    HOWTO(R_386_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,
> >>   bfd_elf_generic_reloc, "R_386_16",
> >>   TRUE, 0xffff, 0xffff, FALSE),
> >> -  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_bitfield,
> >> +  HOWTO(R_386_PC16, 0, 1, 16, TRUE, 0, complain_overflow_signed,
> >
> >I would preffer to handle this via separate patch (even tought the
> >change looks correct to me, see bellow)
>
> This I can certainly do, though it seemed wasted effort to break this out given the identical adjustments made to the respective 64-bit code.
>
> >> +  HOWTO(R_X86_64_PC64, 0, 4, 64, TRUE, 0, complain_overflow_bitfield,
> >> + bfd_elf_generic_reloc, "R_X86_64_PC64", FALSE, MINUS_ONE, MINUS_ONE,
> >> + TRUE),
> >
> >Well, mine version reads here:
> >+   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),
> >
> >I think Jan's patch is correct in this respect (as unlike for smaller
> >relocation times, the address "wrap around"), but please double check.
>
> I'm not sure what to double check here.

I am pretty convinced that bitfield is correct here now.

>
> >> +  /* Note that sgot is not involved in this
> >> +     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
> >> + + htab->sgotplt->output_offset;
> >> +  break;
> >> +
> >> + case R_X86_64_GOTPC32:
> >> +  /* Use global offset table as symbol value.  */
> >> +  relocation = htab->sgotplt->output_section->vma
> >> +       + htab->sgotplt->output_offset;
> >> +  unresolved_reloc = FALSE;
> >> +  break;
> >
> >There is another difference relative to my implementation:
> >
> >+  /* 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.  */
> >+  relocation = htab->sgot->output_section->vma;
> >+  unresolved_reloc = FALSE;
> >+  break;
> >+
>
> I'm fairly sure the code in the patch is correct: What you want here
> is the address of the GOT, not the address of the section the GOT is
> contained in. Of course, in practice GOT will probably never live in a
> section shared with something else, but who knows...

I guess that explains why both versions are working and why some other
backends are using my version of code too.
>
> If so, this would seem to be an unrelated change, as the GOTPC32 reloc in my patch is handled exactly like the i386 one (which of course is very broken, but obviously cannot be fixed). Or maybe I don't see how you would see BFD_RELOC_32_PCREL to end up here.

i386 GOT relocation is different from GOTPC32 in a way that one is IP
relative and other not.
I386 way of encoding GOT relocation is:
        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L2], %ebx
While for x86-64 we want something like:
        leaq    _GLOBAL_OFFSET_TABLE_(%rip), %rbx
So the expression to match needs tobe slightly different.

>
> >And here the GOT relocation:
> >*************** 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;
> >--- 3552,3558 ----
> >      { "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;
>
> Hmm, this confuses me. All the difference consists in an (ill) comma as far as I can see.

I used to have there GOTOFF64 keyword but then replaced it by GOTOFF,
but forgot the comma in, sorry.

>
> >> @@ -5442,10 +5456,10 @@ tc_gen_reloc (section, fixp)
> >>        && 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;
> >> +      if (flag_code != CODE_64BIT)
> >> + code = BFD_RELOC_386_GOTPC;
> >> +      else
> >> + code = BFD_RELOC_X86_64_GOTPC32;
> >>      }
> >>  
> >>    rel = (arelent *) xmalloc (sizeof (arelent));
> >And GOT arithmetic here...
> >*************** 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));
> >--- 5275,5288 ----
> >        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));
>
> Yours is the same change as mine (except for the BFD_RELOC_32_PCREL, as above), isn't it?

Yes, but I think we need BFD_RELOC_32_PCREL for the PCrelative encoding
above.
>
> Now, how do we go further with this? Who's going to finally approve it?

While in theory I can approve x86-64 patches, in BFD area I don't think
I am competent to, so I would preffer if some other maintainer looked
into it or at least didn't complained for some time.

Honza
>
> Jan
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>> If so, this would seem to be an unrelated change, as the GOTPC32 reloc in my
>>patch is handled exactly like the i386 one (which of course is very broken, but
>>obviously cannot be fixed). Or maybe I don't see how you would see
>>BFD_RELOC_32_PCREL to end up here.
>
>i386 GOT relocation is different from GOTPC32 in a way that one is IP
>relative and other not.
>I386 way of encoding GOT relocation is:
>        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L2], %ebx
>While for x86-64 we want something like:
> leaq    _GLOBAL_OFFSET_TABLE_(%rip), %rbx
>So the expression to match needs tobe slightly different.

While the explanation is only partly right (we're talking about i386's GOTPC vs. x86-64's GOTPC32 here, which have identical semantics), it also occured to me that the RIP-relative addressing makes a difference here. So I guess I'll have to add such code to the disp parser. However, the similar code in the immediate parser doesn't need to be changed (because in an immediate there cannot be any RIP-relative). Hopefully I'll have a revised patch later today...

Jan

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
In reply to this post by Jan Beulich
> >> If so, this would seem to be an unrelated change, as the GOTPC32 reloc in my
> >>patch is handled exactly like the i386 one (which of course is very broken, but
> >>obviously cannot be fixed). Or maybe I don't see how you would see
> >>BFD_RELOC_32_PCREL to end up here.
> >
> >i386 GOT relocation is different from GOTPC32 in a way that one is IP
> >relative and other not.
> >I386 way of encoding GOT relocation is:
> >        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L2], %ebx
> >While for x86-64 we want something like:
> > leaq    _GLOBAL_OFFSET_TABLE_(%rip), %rbx
> >So the expression to match needs tobe slightly different.
>
> While the explanation is only partly right (we're talking about i386's
> GOTPC vs. x86-64's GOTPC32 here, which have identical semantics), it

Oops, sorry.  I forgot that the i386 equivalent also ends up in PC
relative relocation despite the lack of harware support, but anyway I
would like to have the RIP relative syntax instead of having to invent
new labels to encode GOTPC32

> also occured to me that the RIP-relative addressing makes a difference
> here. So I guess I'll have to add such code to the disp parser.
> However, the similar code in the immediate parser doesn't need to be
> changed (because in an immediate there cannot be any RIP-relative).

Even tought I think at least early versions of gas accepted (%rip)
suffix to make immediates IP relative, this probably don't make much
sense here.  We probably would want to use something like
_GLOBAL_OFFSET_TABLE_-. as do for IP relative relocations in unwind
tables, if we ever will use this feature at all...  I think that is
covered by the i386-alike pattern matching, right?

> Hopefully I'll have a revised patch later today...

Thanks!  I've updated the medium model patches for current GCC so I will
give it some testing afterwards.

Honza
>
> Jan
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
> > >> If so, this would seem to be an unrelated change, as the GOTPC32 reloc in my
> > >>patch is handled exactly like the i386 one (which of course is very broken, but
> > >>obviously cannot be fixed). Or maybe I don't see how you would see
> > >>BFD_RELOC_32_PCREL to end up here.
> > >
> > >i386 GOT relocation is different from GOTPC32 in a way that one is IP
> > >relative and other not.
> > >I386 way of encoding GOT relocation is:
> > >        addl    $_GLOBAL_OFFSET_TABLE_+[.-.L2], %ebx
> > >While for x86-64 we want something like:
> > > leaq    _GLOBAL_OFFSET_TABLE_(%rip), %rbx
> > >So the expression to match needs tobe slightly different.
> >
> > While the explanation is only partly right (we're talking about i386's
> > GOTPC vs. x86-64's GOTPC32 here, which have identical semantics), it
>
> Oops, sorry.  I forgot that the i386 equivalent also ends up in PC
> relative relocation despite the lack of harware support, but anyway I
> would like to have the RIP relative syntax instead of having to invent
> new labels to encode GOTPC32

Not quite right either - extra label is not needed here, but
leaq    _GLOBAL_OFFSET_TABLE_-., %rbx would be absolute addressing and
leaq    _GLOBAL_OFFSET_TABLE_-.(%rip), %rbx would be IP relative
addressing to the same address as line above, so there would be no way
to encode IP relative addressing to _GLOBAL_OFFSET_TABLE_ via this kind
of arithmetics...

Honza
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>> Hopefully I'll have a revised patch later today...
>
>Thanks!  I've updated the medium model patches for current GCC so I will
>give it some testing afterwards.

Updating the patch to support for the new x86-64 relocation types added in
ABI draft 0.95 (or a slightly earlier version).

Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.

Jan

bfd/
2005-06-16  Jan Beulich  <[hidden email]>

        * bfd-in2.h (elf_x86_64_reloc_type): Add BFD_RELOC_X86_64_GOTOFF64
        and BFD_RELOC_X86_64_GOTPC32.
        * libbfd.h (bfd_reloc_code_real_names): Likewise.
        * elf64-x86-64.c (x86_64_elf_howto_table): Add entries for
        R_X86_64_PC64, R_X86_64_GOTOFF64, and R_X86_64_GOTPC32.
        (x86_64_reloc_map): Add entries for R_X86_64_PC64, R_X86_64_GOTOFF64,
        and R_X86_64_GOTPC32.
        (elf64_x86_64_info_to_howto): Adjust bounding relocation type.
        (elf64_x86_64_check_relocs): Also handle R_X86_64_PC64,
        R_X86_64_GOTOFF64, and R_X86_64_GOTPC32.
        (elf64_x86_64_relocate_section): Likewise.
        (elf64_x86_64_gc_sweep_hook): Also handle R_X86_64_PC64.

gas/
2005-06-16  Jan Beulich  <[hidden email]>

        * config/tc-i386.c (reloc): Also handle BFD_RELOC_64_PCREL.
        (tc_i386_fix_adjustable): Include BFD_RELOC_X86_64_GOTOFF64,
        BFD_RELOC_X86_64_DTPOFF64, and BFD_RELOC_X86_64_TPOFF64.
        (output_disp): Do GOTPC conversion also for BFD_RELOC_X86_64_32S
        and BFD_RELOC_32_PCREL. Use BFD_RELOC_X86_64_GOTPC32 instead of
        aborting.
        (output_imm): Do GOTPC conversion also for BFD_RELOC_X86_64_32S.
        Use BFD_RELOC_X86_64_GOTPC32 instead of aborting.
        (tc_gen_reloc): Do GOTPC conversion also for BFD_RELOC_32_PCREL.
        Use BFD_RELOC_X86_64_GOTPC32 instead of aborting. Also handle
        BFD_RELOC_X86_64_GOTOFF64, BFD_RELOC_X86_64_GOTPC32,
        BFD_RELOC_X86_64_DTPOFF64, and BFD_RELOC_X86_64_TPOFF64. Also
        convert 8-byte pc-relative relocations.
        (lex_got): Use BFD_RELOC_X86_64_GOTOFF64 for 64-bit @gotoff.
        (i386_validate_fix): Likewise.
        (x86_cons): Also handle quad values in 64-bit mode.
        (i386_displacement): Also handle BFD_RELOC_X86_64_GOTOFF64.
        (md_apply_fix): Include BFD_RELOC_X86_64_DTPOFF64 and
        BFD_RELOC_X86_64_TPOFF64 in the TLS check. Also convert BFD_RELOC_64
        to pc-relative variant. Also check for BFD_RELOC_64_PCREL.

gas/testsuite/
2005-06-16  Jan Beulich  <[hidden email]>

        * gas/i386/x86-64-pcrel.s: Add insn requiring 64-bit pc-relative
        relocation. Add insns for all widths of non-pc-relative relocations.
        * gas/i386/x86-64-pcrel.d: Adjust.

include/elf/
2005-06-16  Jan Beulich  <[hidden email]>

        * x86-64.h (elf_x86_64_reloc_type): Adjust comment for
        R_X86_64_GOTPCREL. Add R_X86_64_PC64, R_X86_64_GOTOFF64, and
        R_X86_64_GOTPC32.

--- /home/jbeulich/src/binutils/mainline/2005-06-16/bfd/bfd-in2.h 2005-06-08 14:50:36.000000000 +0200
+++ 2005-06-16/bfd/bfd-in2.h 2005-06-08 15:41:21.000000000 +0200
@@ -2617,6 +2617,8 @@ in the instruction.  */
   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,
--- /home/jbeulich/src/binutils/mainline/2005-06-16/bfd/elf64-x86-64.c 2005-05-18 08:09:48.000000000 +0200
+++ 2005-06-16/bfd/elf64-x86-64.c 2005-06-08 15:41:21.000000000 +0200
@@ -103,6 +103,15 @@ static reloc_howto_type x86_64_elf_howto
   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_bitfield,
+ 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_bitfield,
+ 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,
@@ -147,6 +156,9 @@ static const struct elf_reloc_map x86_64
   { 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, },
 };
@@ -179,13 +191,13 @@ elf64_x86_64_info_to_howto (bfd *abfd AT
   r_type = ELF64_R_TYPE (dst->r_info);
   if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT)
     {
-      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_TPOFF32);
+      BFD_ASSERT (r_type <= (unsigned int) R_X86_64_GOTPC32);
       i = r_type;
     }
   else
     {
       BFD_ASSERT (r_type < (unsigned int) R_X86_64_max);
-      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_TPOFF32 - 1);
+      i = r_type - ((unsigned int) R_X86_64_GNU_VTINHERIT - R_X86_64_GOTPC32 - 1);
     }
   cache_ptr->howto = &x86_64_elf_howto_table[i];
   BFD_ASSERT (r_type == cache_ptr->howto->type);
@@ -749,7 +761,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
   }
   /* Fall through */
 
-  //case R_X86_64_GOTPCREL:
+ case R_X86_64_GOTOFF64:
+ case R_X86_64_GOTPC32:
  create_got:
   if (htab->sgot == NULL)
     {
@@ -802,6 +815,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
  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)
     {
@@ -816,7 +830,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
       /* We may need a .plt entry if the function this reloc
  refers to is in a shared lib.  */
       h->plt.refcount += 1;
-      if (r_type != R_X86_64_PC32)
+      if (r_type != R_X86_64_PC32 && r_type != R_X86_64_PC64)
  h->pointer_equality_needed = 1;
     }
 
@@ -845,7 +859,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
        && (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_PC32)
+    && (r_type != R_X86_64_PC64))
    || (h != NULL
        && (! info->symbolic
    || h->root.type == bfd_link_hash_defweak
@@ -948,7 +963,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
       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_PC32
+  || r_type == R_X86_64_PC64)
  p->pc_count += 1;
     }
   break;
@@ -1093,6 +1109,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, s
  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 */
@@ -1941,6 +1958,42 @@ elf64_x86_64_relocate_section (bfd *outp
 
   break;
 
+ case R_X86_64_GOTOFF64:
+  /* Relocation is relative to the start of the global offset
+     table.  */
+
+  /* Check to make sure it isn't a protected function symbol
+     for shared library since it may not be local when used
+     as function address.  */
+  if (info->shared
+      && h
+      && h->def_regular
+      && h->type == STT_FUNC
+      && ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
+    {
+      (*_bfd_error_handler)
+ (_("%B: relocation R_X86_64_GOTOFF64 against protected function `%s' can not be used when making a shared object"),
+ input_bfd, h->root.root.string);
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
+  /* Note that sgot is not involved in this
+     calculation.  We always want the start of .got.plt.  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->sgotplt->output_section->vma
+ + htab->sgotplt->output_offset;
+  break;
+
+ case R_X86_64_GOTPC32:
+  /* 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_PLT32:
   /* Relocation is to the entry for this symbol in the
      procedure linkage table.  */
@@ -1999,6 +2052,7 @@ elf64_x86_64_relocate_section (bfd *outp
  case R_X86_64_8:
  case R_X86_64_16:
  case R_X86_64_32:
+ case R_X86_64_PC64:
  case R_X86_64_64:
   /* FIXME: The ABI says the linker should make sure the value is
      the same when it's zeroextended to 64 bit. */
@@ -2016,7 +2070,8 @@ elf64_x86_64_relocate_section (bfd *outp
    || 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_PC32
+    && r_type != R_X86_64_PC64)
    || !SYMBOL_CALLS_LOCAL (info, h)))
       || (ELIMINATE_COPY_RELOCS
   && !info->shared
@@ -2060,6 +2115,7 @@ elf64_x86_64_relocate_section (bfd *outp
        && (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->def_regular))
--- /home/jbeulich/src/binutils/mainline/2005-06-16/bfd/libbfd.h 2005-06-08 14:50:42.000000000 +0200
+++ 2005-06-16/bfd/libbfd.h 2005-06-08 15:41:21.000000000 +0200
@@ -1049,6 +1049,8 @@ static const char *const bfd_reloc_code_
   "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",
   "BFD_RELOC_NS32K_IMM_8",
   "BFD_RELOC_NS32K_IMM_16",
   "BFD_RELOC_NS32K_IMM_32",
--- /home/jbeulich/src/binutils/mainline/2005-06-16/gas/config/tc-i386.c 2005-06-08 14:50:49.000000000 +0200
+++ 2005-06-16/gas/config/tc-i386.c 2005-06-16 15:43:25.923892176 +0200
@@ -1222,6 +1222,7 @@ reloc (size, pcrel, sign, other)
  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);
     }
@@ -1292,8 +1293,11 @@ tc_i386_fix_adjustable (fixP)
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
       || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
       || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
+      || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF64
       || fixP->fx_r_type == BFD_RELOC_X86_64_GOTTPOFF
       || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF32
+      || fixP->fx_r_type == BFD_RELOC_X86_64_TPOFF64
+      || fixP->fx_r_type == BFD_RELOC_X86_64_GOTOFF64
       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 0;
@@ -3502,14 +3506,16 @@ output_disp (insn_start_frag, insn_start
 
       p = frag_more (size);
       reloc_type = reloc (size, pcrel, sign, i.reloc[n]);
-      if (reloc_type == BFD_RELOC_32
-  && GOT_symbol
+      if (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
+ || reloc_type == BFD_RELOC_X86_64_32S)
+       && (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))
  {
   offsetT add;
 
@@ -3526,10 +3532,10 @@ output_disp (insn_start_frag, insn_start
       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;
+  if (flag_code != CODE_64BIT)
+    reloc_type = BFD_RELOC_386_GOTPC;
+  else
+    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,
@@ -3638,7 +3644,8 @@ output_imm (insn_start_frag, insn_start_
        * since the expression is not pcrel, I felt it would be
        * confusing to do it this way.  */
 
-      if (reloc_type == BFD_RELOC_32
+      if ((reloc_type == BFD_RELOC_32
+   || reloc_type == BFD_RELOC_X86_64_32S)
   && GOT_symbol
   && GOT_symbol == i.op[n].imms->X_add_symbol
   && (i.op[n].imms->X_op == O_symbol
@@ -3662,10 +3669,10 @@ output_imm (insn_start_frag, insn_start_
       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;
+  if (flag_code != CODE_64BIT)
+    reloc_type = BFD_RELOC_386_GOTPC;
+  else
+    reloc_type = BFD_RELOC_X86_64_GOTPC32;
   i.op[n].imms->X_add_number += add;
  }
       fix_new_exp (frag_now, p - frag_now->fr_literal, size,
@@ -3698,7 +3705,7 @@ lex_got (reloc, adjust)
     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                         } },
+    { "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                         } },
@@ -3792,7 +3799,7 @@ x86_cons (exp, size)
      expressionS *exp;
      int size;
 {
-  if (size == 4)
+  if (size == 4 || (flag_code == CODE_64BIT && size == 8))
     {
       /* Handle @GOTOFF and the like in an expression.  */
       char *save;
@@ -4104,7 +4111,8 @@ i386_displacement (disp_start, disp_end)
      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_GOTPCREL)
+      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL
+      || i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
     {
       if (exp->X_op != O_symbol)
  {
@@ -4122,6 +4130,8 @@ i386_displacement (disp_start, disp_end)
       exp->X_op_symbol = GOT_symbol;
       if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTPCREL)
  i.reloc[this_operand] = BFD_RELOC_32_PCREL;
+      else if (i.reloc[this_operand] == BFD_RELOC_X86_64_GOTOFF64)
+ i.reloc[this_operand] = BFD_RELOC_64;
       else
  i.reloc[this_operand] = BFD_RELOC_32;
     }
@@ -4812,6 +4822,9 @@ md_apply_fix (fixP, valP, seg)
  default:
   break;
 
+ case BFD_RELOC_64:
+  fixP->fx_r_type = BFD_RELOC_64_PCREL;
+  break;
  case BFD_RELOC_32:
  case BFD_RELOC_X86_64_32S:
   fixP->fx_r_type = BFD_RELOC_32_PCREL;
@@ -4827,6 +4840,7 @@ md_apply_fix (fixP, valP, seg)
 
   if (fixP->fx_addsy != NULL
       && (fixP->fx_r_type == BFD_RELOC_32_PCREL
+  || fixP->fx_r_type == BFD_RELOC_64_PCREL
   || fixP->fx_r_type == BFD_RELOC_16_PCREL
   || fixP->fx_r_type == BFD_RELOC_8_PCREL)
       && !use_rela_relocations)
@@ -4901,7 +4915,9 @@ md_apply_fix (fixP, valP, seg)
       case BFD_RELOC_386_TLS_LDO_32:
       case BFD_RELOC_386_TLS_LE_32:
       case BFD_RELOC_X86_64_DTPOFF32:
+      case BFD_RELOC_X86_64_DTPOFF64:
       case BFD_RELOC_X86_64_TPOFF32:
+      case BFD_RELOC_X86_64_TPOFF64:
  S_SET_THREAD_LOCAL (fixP->fx_addsy);
  break;
 
@@ -5339,7 +5355,6 @@ i386_validate_fix (fixp)
 {
   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)
@@ -5348,9 +5363,10 @@ i386_validate_fix (fixp)
  }
       else
  {
-  if (flag_code == CODE_64BIT)
-    abort ();
-  fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+  if (flag_code != CODE_64BIT)
+    fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
+  else
+    fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
  }
       fixp->fx_subsy = 0;
     }
@@ -5384,8 +5400,12 @@ tc_gen_reloc (section, fixp)
     case BFD_RELOC_X86_64_TLSGD:
     case BFD_RELOC_X86_64_TLSLD:
     case BFD_RELOC_X86_64_DTPOFF32:
+    case BFD_RELOC_X86_64_DTPOFF64:
     case BFD_RELOC_X86_64_GOTTPOFF:
     case BFD_RELOC_X86_64_TPOFF32:
+    case BFD_RELOC_X86_64_TPOFF64:
+    case BFD_RELOC_X86_64_GOTOFF64:
+    case BFD_RELOC_X86_64_GOTPC32:
     case BFD_RELOC_RVA:
     case BFD_RELOC_VTABLE_ENTRY:
     case BFD_RELOC_VTABLE_INHERIT:
@@ -5415,6 +5435,9 @@ tc_gen_reloc (section, fixp)
     case 1: code = BFD_RELOC_8_PCREL;  break;
     case 2: code = BFD_RELOC_16_PCREL; break;
     case 4: code = BFD_RELOC_32_PCREL; break;
+#ifdef BFD64
+    case 8: code = BFD_RELOC_64_PCREL; break;
+#endif
     }
  }
       else
@@ -5438,14 +5461,14 @@ tc_gen_reloc (section, fixp)
       break;
     }
 
-  if (code == BFD_RELOC_32
+  if ((code == BFD_RELOC_32 || code == BFD_RELOC_32_PCREL)
       && 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;
+      if (flag_code != CODE_64BIT)
+ code = BFD_RELOC_386_GOTPC;
+      else
+ code = BFD_RELOC_X86_64_GOTPC32;
     }
 
   rel = (arelent *) xmalloc (sizeof (arelent));
--- /home/jbeulich/src/binutils/mainline/2005-06-16/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-04-11 08:11:28.000000000 +0200
+++ 2005-06-16/gas/testsuite/gas/i386/x86-64-pcrel.d 2005-06-08 15:41:21.000000000 +0200
@@ -8,7 +8,12 @@ Disassembly of section .text:
 0+000 <_start>:
 [ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_PC8[ ]+xtrn\+(0x)?1
 [ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC16[ ]+xtrn\+(0x)?2
-[ ]*[0-9a-f]+:[ ]+b8 00 00 00 00[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
-[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
-[ ]*[0-9a-f]+:[ ]+48 c7 c0 00 00 00 00[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?1
+[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC32[ ]+xtrn\+(0x)?3
+[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_PC64[ ]+xtrn\+(0x)?2
+[ ]*[0-9a-f]+:[ ]+b0 00[ ]+movb?[ ]+\$(0x)?0,%al[ ]*[0-9a-f]+:[ ]+R_X86_64_8[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+66 b8 00 00[ ]+movw?[ ]+\$(0x)?0,%ax[ ]*[0-9a-f]+:[ ]+R_X86_64_16[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+b8( 00){4}[ ]+movl?[ ]+\$(0x)?0,%eax[ ]*[0-9a-f]+:[ ]+R_X86_64_32[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+48 c7 c0( 00){4}[ ]+movq?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_32S[ ]+xtrn
+[ ]*[0-9a-f]+:[ ]+48 b8( 00){8}[ ]+mov(abs)?q?[ ]+\$(0x)?0,%rax[ ]*[0-9a-f]+:[ ]+R_X86_64_64[ ]+xtrn
 #pass
--- /home/jbeulich/src/binutils/mainline/2005-06-16/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-04-11 08:11:28.000000000 +0200
+++ 2005-06-16/gas/testsuite/gas/i386/x86-64-pcrel.s 2005-06-08 15:41:21.000000000 +0200
@@ -4,6 +4,12 @@ _start:
  movw $(xtrn - .), %ax
  movl $(xtrn - .), %eax
  movq $(xtrn - .), %rax
+ movabsq $(xtrn - .), %rax
+
+ movb $xtrn, %al
+ movw $xtrn, %ax
+ movl $xtrn, %eax
  movq $xtrn, %rax
+ movabsq $xtrn, %rax
 
  .p2align 4,0
--- /home/jbeulich/src/binutils/mainline/2005-06-16/include/elf/x86-64.h 2005-05-13 12:17:11.000000000 +0200
+++ 2005-06-16/include/elf/x86-64.h 2005-06-08 15:41:21.000000000 +0200
@@ -34,7 +34,7 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_JUMP_SLOT,7)      /* Create PLT entry */
      RELOC_NUMBER (R_X86_64_RELATIVE, 8)      /* Adjust by program base */
      RELOC_NUMBER (R_X86_64_GOTPCREL, 9)      /* 32 bit signed pc relative
-                                                 offset to GOT */
+                                                 offset to GOT entry */
      RELOC_NUMBER (R_X86_64_32,       10)     /* Direct 32 bit zero extended */
      RELOC_NUMBER (R_X86_64_32S,      11)     /* Direct 32 bit sign extended */
      RELOC_NUMBER (R_X86_64_16,       12)     /* Direct 16 bit zero extended */
@@ -49,6 +49,10 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_ty
      RELOC_NUMBER (R_X86_64_DTPOFF32, 21)     /* Offset in TLS block */
      RELOC_NUMBER (R_X86_64_GOTTPOFF, 22)     /* PC relative offset to IE GOT entry */
      RELOC_NUMBER (R_X86_64_TPOFF32,  23)     /* Offset in initial TLS block */
+     RELOC_NUMBER (R_X86_64_PC64,     24)     /* PC relative 64 bit */
+     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 */
      RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250)       /* GNU C++ hack  */
      RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251)         /* GNU C++ hack  */
 END_RELOC_NUMBERS (R_X86_64_max)


binutils-mainline-x86_64-abi095-relocs.patch (21K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Richard Henderson-2
The patch looks ok to me.


r~
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
> The patch looks ok to me.

I've also bootstrapped GCC with medium model PIC in hacked to default to
medium with it too and everything seems to work fine now, tanks!

Honza
>
>
> r~
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>>> Jan Hubicka <[hidden email]> 17.06.05 00:33:53 >>>
>> The patch looks ok to me.
>
>I've also bootstrapped GCC with medium model PIC in hacked to default to
>medium with it too and everything seems to work fine now, tanks!

So do I take these combined statements as approval for checkin?

Thanks, Jan

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Hubicka
In reply to this post by Jan Beulich
> >>> Jan Hubicka <[hidden email]> 17.06.05 00:33:53 >>>
> >> The patch looks ok to me.
> >
> >I've also bootstrapped GCC with medium model PIC in hacked to default to
> >medium with it too and everything seems to work fine now, tanks!
>
> So do I take these combined statements as approval for checkin?

Sure ;)
Honza
>
> Thanks, Jan
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

H.J. Lu-27
In reply to this post by Jan Beulich
On Wed, Jun 08, 2005 at 08:17:55AM -0600, Jan Beulich wrote:

> This adds support for the new x86-64 relocation types added in ABI draft
> 0.95 (or in a slightly earlier version). In addition, it fixes the overflow
> complaint types for two x86-64 and one i386 relocation types.
>
> Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.
>
> Jan
>
> bfd/
> 2005-06-08  Jan Beulich  <[hidden email]>
>
> * bfd-in2.h (elf_x86_64_reloc_type): Add BFD_RELOC_X86_64_GOTOFF64
> and BFD_RELOC_X86_64_GOTPC32.

bfd-in2.h is a generated file. Please put new relocations in reloc.c.

Thanks.


H.J.
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>>> "H. J. Lu" <[hidden email]> 18.06.05 00:35:26 >>>
>On Wed, Jun 08, 2005 at 08:17:55AM -0600, Jan Beulich wrote:
>> This adds support for the new x86-64 relocation types added in ABI draft
>> 0.95 (or in a slightly earlier version). In addition, it fixes the overflow
>> complaint types for two x86-64 and one i386 relocation types.
>>
>> Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.
>>
>> Jan
>>
>> bfd/
>> 2005-06-08  Jan Beulich  <[hidden email]>
>>
>> * bfd-in2.h (elf_x86_64_reloc_type): Add BFD_RELOC_X86_64_GOTOFF64
>> and BFD_RELOC_X86_64_GOTPC32.
>
>bfd-in2.h is a generated file. Please put new relocations in reloc.c.

Sorry, I failed to recognize that (though it should have been obvious). Applying the below as obvious.

Jan

bfd/
2005-06-08  Jan Beulich  <[hidden email]>

        * reloc.c (bfd_reloc_code_real): Add BFD_RELOC_X86_64_GOTOFF64 and
        BFD_RELOC_X86_64_GOTPC32.

--- /home/jbeulich/src/binutils/mainline/2005-06-16/bfd/reloc.c 2005-06-16 10:41:52.000000000 +0200
+++ 2005-06-16/bfd/reloc.c 2005-06-20 09:11:46.044507296 +0200
@@ -2362,6 +2362,10 @@ ENUMX
   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
 


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] x86-64: support newer relocation types

Jan Beulich
In reply to this post by Jan Beulich
>>> "H. J. Lu" <[hidden email]> 18.06.05 00:35:26 >>>
>On Wed, Jun 08, 2005 at 08:17:55AM -0600, Jan Beulich wrote:
>> This adds support for the new x86-64 relocation types added in ABI draft
>> 0.95 (or in a slightly earlier version). In addition, it fixes the overflow
>> complaint types for two x86-64 and one i386 relocation types.
>>
>> Built and tested on i686-pc-linux-gnu and x86_64-unknown-linux-gnu.
>>
>> Jan
>>
>> bfd/
>> 2005-06-08  Jan Beulich  <[hidden email]>
>>
>> * bfd-in2.h (elf_x86_64_reloc_type): Add BFD_RELOC_X86_64_GOTOFF64
>> and BFD_RELOC_X86_64_GOTPC32.
>
>bfd-in2.h is a generated file. Please put new relocations in reloc.c.

Oh, I see you already fixed that. (libbfd.h formally would have needed regeneration, too).

Thanks!
Jan