bfd/
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index 5433771c13fc0f8f7a2646e1be73c300b28a092c..b6c973f6dbc8bff6acabd1fc49b8cc4c6f9bd0c9 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, },
@@ -335,7 +350,7 @@ static const bfd_byte elf64_x86_64_plt0_entry[PLT_ENTRY_SIZE] =
 {
   0xff, 0x35, 8, 0, 0, 0,      /* pushq GOT+8(%rip)  */
   0xff, 0x25, 16, 0, 0, 0,     /* jmpq *GOT+16(%rip) */
-  0x90, 0x90, 0x90, 0x90       /* pad out to 16 bytes with nops.  */
+  0x0f, 0x1f, 0x40, 0x00       /* nopl 0(%rax)       */
 };
 
 /* Subsequent entries in a procedure linkage table look like this.  */
@@ -510,7 +525,8 @@ elf64_x86_64_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+                                     sizeof (struct elf64_x86_64_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -660,11 +676,14 @@ elf64_x86_64_copy_indirect_symbol (struct bfd_link_info *info,
 static bfd_boolean
 elf64_x86_64_mkobject (bfd *abfd)
 {
-  bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
-  abfd->tdata.any = bfd_zalloc (abfd, amt);
   if (abfd->tdata.any == NULL)
-    return FALSE;
-  return TRUE;
+    {
+      bfd_size_type amt = sizeof (struct elf64_x86_64_obj_tdata);
+      abfd->tdata.any = bfd_zalloc (abfd, amt);
+      if (abfd->tdata.any == NULL)
+       return FALSE;
+    }
+  return bfd_elf_mkobject (abfd);
 }
 
 static bfd_boolean
@@ -776,6 +795,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.  */
@@ -794,6 +816,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;
              }
@@ -857,6 +887,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)
            {
@@ -884,6 +915,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:
@@ -956,7 +997,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                    && (r_type != R_X86_64_PC32)
                    && (r_type != R_X86_64_PC64))
                   || (h != NULL
-                      && (! info->symbolic
+                      && (! SYMBOLIC_BIND (info, h)
                           || h->root.type == bfd_link_hash_defweak
                           || !h->def_regular))))
              || (ELIMINATE_COPY_RELOCS
@@ -984,7 +1025,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
                  if (name == NULL)
                    return FALSE;
 
-                 if (strncmp (name, ".rela", 5) != 0
+                 if (! CONST_STRNEQ (name, ".rela")
                      || strcmp (bfd_get_section_name (abfd, sec),
                                 name + 5) != 0)
                    {
@@ -1093,38 +1134,20 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
 
 static asection *
 elf64_x86_64_gc_mark_hook (asection *sec,
-                          struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          struct bfd_link_info *info,
                           Elf_Internal_Rela *rel,
                           struct elf_link_hash_entry *h,
                           Elf_Internal_Sym *sym)
 {
   if (h != NULL)
-    {
-      switch (ELF64_R_TYPE (rel->r_info))
-       {
-       case R_X86_64_GNU_VTINHERIT:
-       case R_X86_64_GNU_VTENTRY:
-         break;
-
-       default:
-         switch (h->root.type)
-           {
-           case bfd_link_hash_defined:
-           case bfd_link_hash_defweak:
-             return h->root.u.def.section;
-
-           case bfd_link_hash_common:
-             return h->root.u.c.p->section;
-
-           default:
-             break;
-           }
-       }
-    }
-  else
-    return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-
-  return NULL;
+    switch (ELF64_R_TYPE (rel->r_info))
+      {
+      case R_X86_64_GNU_VTINHERIT:
+      case R_X86_64_GNU_VTENTRY:
+       return NULL;
+      }
+
+  return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
 }
 
 /* Update the got entry reference counts for the section being removed.         */
@@ -1188,8 +1211,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;
            }
@@ -1214,6 +1242,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)
@@ -1565,9 +1594,21 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+      if (eh->dyn_relocs != NULL
          && h->root.type == bfd_link_hash_undefweak)
-       eh->dyn_relocs = NULL;
+       {
+         if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+           eh->dyn_relocs = NULL;
+
+         /* Make sure undefined weak symbols are output as a dynamic
+            symbol in PIEs.  */
+         else if (h->dynindx == -1
+                  && !h->forced_local)
+           {
+             if (! bfd_elf_link_record_dynamic_symbol (info, h))
+               return FALSE;
+           }
+       }
     }
   else if (ELIMINATE_COPY_RELOCS)
     {
@@ -1824,7 +1865,7 @@ elf64_x86_64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
+      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
        {
          if (s->size != 0 && s != htab->srelplt)
            relocs = TRUE;
@@ -2083,11 +2124,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 ();
 
@@ -2096,6 +2149,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)
@@ -2120,7 +2186,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;
                    }
                }
@@ -2142,7 +2210,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)
                    {
@@ -2156,8 +2224,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;
@@ -2173,9 +2241,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;
 
@@ -2211,12 +2279,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.  */
@@ -2283,8 +2370,13 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
          /* r_symndx will be zero only for relocs against symbols
             from removed linkonce sections, or sections discarded by
             a linker script.  */
-         if (r_symndx == 0
-             || (input_section->flags & SEC_ALLOC) == 0)
+         if (r_symndx == 0)
+           {
+             _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+             break;
+           }
+
+         if ((input_section->flags & SEC_ALLOC) == 0)
            break;
 
          if ((info->shared
@@ -2340,7 +2432,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                           || r_type == R_X86_64_PC32
                           || r_type == R_X86_64_PC64
                           || !info->shared
-                          || !info->symbolic
+                          || !SYMBOLIC_BIND (info, h)
                           || !h->def_regular))
                {
                  outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
@@ -2370,9 +2462,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                        {
                          asection *osec;
 
+                         /* We are turning this relocation into one
+                            against a section symbol.  It would be
+                            proper to subtract the symbol's value,
+                            osec->vma, from the emitted reloc addend,
+                            but ld.so expects buggy relocs.  */
                          osec = sec->output_section;
                          sindx = elf_section_data (osec)->dynindx;
-                         BFD_ASSERT (sindx > 0);
+                         if (sindx == 0)
+                           {
+                             asection *oi = htab->elf.text_index_section;
+                             sindx = elf_section_data (oi)->dynindx;
+                           }
+                         BFD_ASSERT (sindx != 0);
                        }
 
                      outrel.r_info = ELF64_R_INFO (sindx, r_type);
@@ -2512,8 +2614,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
                  val = bfd_get_8 (input_bfd, contents + roff + 1);
                  BFD_ASSERT (val == 0x10);
 
-                 /* Now modify the instruction as appropriate.  */
-                 bfd_put_8 (output_bfd, 0x90, contents + roff);
+                 /* Now modify the instruction as appropriate.  Use
+                    xchg %ax,%ax instead of 2 nops.  */
+                 bfd_put_8 (output_bfd, 0x66, contents + roff);
                  bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
                  continue;
                }
@@ -2805,8 +2908,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
              val = bfd_get_8 (input_bfd, contents + roff + 1);
              BFD_ASSERT (val == 0x10);
 
-             /* Now modify the instruction as appropriate.  */
-             bfd_put_8 (output_bfd, 0x90, contents + roff);
+             /* Now modify the instruction as appropriate.  Use
+                xchg %ax,%ax instead of 2 nops.  */
+             bfd_put_8 (output_bfd, 0x66, contents + roff);
              bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
 
              continue;
@@ -2928,12 +3032,6 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
          if (r == bfd_reloc_overflow)
            {
-             if (h != NULL
-                 && h->root.type == bfd_link_hash_undefweak
-                 && howto->pc_relative)
-               /* Ignore reloc overflow on branches to undefweak syms.  */
-               continue;
-
              if (! ((*info->callbacks->reloc_overflow)
                     (info, (h ? &h->root : NULL), name, howto->name,
                      (bfd_vma) 0, input_bfd, input_section,
@@ -3119,7 +3217,7 @@ elf64_x86_64_finish_dynamic_symbol (bfd *output_bfd,
 
   /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute.  */
   if (strcmp (h->root.root.string, "_DYNAMIC") == 0
-      || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+      || h == htab->elf.hgot)
     sym->st_shndx = SHN_ABS;
 
   return TRUE;
@@ -3492,7 +3590,8 @@ elf64_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
 }
 
 static int
-elf64_x86_64_additional_program_headers (bfd *abfd)
+elf64_x86_64_additional_program_headers (bfd *abfd,
+                                        struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
   int count = 0; 
@@ -3512,23 +3611,38 @@ elf64_x86_64_additional_program_headers (bfd *abfd)
   return count;
 }
 
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section.  */
+
+static bfd_boolean
+elf64_x86_64_hash_symbol (struct elf_link_hash_entry *h)
+{
+  if (h->plt.offset != (bfd_vma) -1
+      && !h->def_regular
+      && !h->pointer_equality_needed)
+    return FALSE;
+
+  return _bfd_elf_hash_symbol (h);
+}
+
 static const struct bfd_elf_special_section 
   elf64_x86_64_special_sections[]=
 {
-  { ".gnu.linkonce.lb",        16, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
-  { ".gnu.linkonce.lr",        16, -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
-  { ".gnu.linkonce.lt",        16, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR + SHF_X86_64_LARGE},
-  { ".lbss",   5, -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
-  { ".ldata",  6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
-  { ".lrodata",        8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
-  { NULL,      0,  0, 0,            0 }
+  { STRING_COMMA_LEN (".gnu.linkonce.lb"), -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { STRING_COMMA_LEN (".gnu.linkonce.lr"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
+  { STRING_COMMA_LEN (".gnu.linkonce.lt"), -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR + SHF_X86_64_LARGE},
+  { STRING_COMMA_LEN (".lbss"),                   -2, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { STRING_COMMA_LEN (".ldata"),          -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_X86_64_LARGE},
+  { STRING_COMMA_LEN (".lrodata"),        -2, SHT_PROGBITS, SHF_ALLOC + SHF_X86_64_LARGE},
+  { NULL,                      0,          0, 0,            0 }
 };
 
 #define TARGET_LITTLE_SYM                  bfd_elf64_x86_64_vec
 #define TARGET_LITTLE_NAME                 "elf64-x86-64"
 #define ELF_ARCH                           bfd_arch_i386
 #define ELF_MACHINE_CODE                   EM_X86_64
-#define ELF_MAXPAGESIZE                            0x100000
+#define ELF_MAXPAGESIZE                            0x200000
+#define ELF_MINPAGESIZE                            0x1000
+#define ELF_COMMONPAGESIZE                 0x1000
 
 #define elf_backend_can_gc_sections        1
 #define elf_backend_can_refcount           1
@@ -3558,6 +3672,7 @@ static const struct bfd_elf_special_section
 #define elf_backend_relocate_section       elf64_x86_64_relocate_section
 #define elf_backend_size_dynamic_sections   elf64_x86_64_size_dynamic_sections
 #define elf_backend_always_size_sections    elf64_x86_64_always_size_sections
+#define elf_backend_init_index_section     _bfd_elf_init_1_index_section
 #define elf_backend_plt_sym_val                    elf64_x86_64_plt_sym_val
 #define elf_backend_object_p               elf64_x86_64_elf_object_p
 #define bfd_elf64_mkobject                 elf64_x86_64_mkobject
@@ -3583,5 +3698,38 @@ static const struct bfd_elf_special_section
   elf64_x86_64_special_sections
 #define elf_backend_additional_program_headers \
   elf64_x86_64_additional_program_headers
+#define elf_backend_hash_symbol \
+  elf64_x86_64_hash_symbol
+
+#include "elf64-target.h"
+
+/* FreeBSD support.  */
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM                  bfd_elf64_x86_64_freebsd_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME                 "elf64-x86-64-freebsd"
+
+/* The kernel recognizes executables as valid only if they carry a
+   "FreeBSD" label in the ELF header.  So we put this label on all
+   executables and (for simplicity) also all other object files.  */
+
+static void
+elf64_x86_64_fbsd_post_process_headers (bfd * abfd,
+                                       struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+{
+  Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
+
+  i_ehdrp = elf_elfheader (abfd);
+
+  /* Put an ABI label supported by FreeBSD >= 4.1.  */
+  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
+}
+
+#undef  elf_backend_post_process_headers
+#define elf_backend_post_process_headers  elf64_x86_64_fbsd_post_process_headers
+
+#undef  elf64_bed
+#define elf64_bed elf64_x86_64_fbsd_bed
 
 #include "elf64-target.h"
This page took 0.045301 seconds and 4 git commands to generate.