daily update
[deliverable/binutils-gdb.git] / bfd / elf32-ppc.c
index ec407fdb40227635bcd1a06676cdfa2c12c2fa67..6e80a1e29c289fad723f880ffbece3403d4d8079 100644 (file)
@@ -1,6 +1,6 @@
 /* PowerPC-specific support for 32-bit ELF
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005 Free Software Foundation, Inc.
+   2004, 2005, 2006 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -1708,11 +1708,14 @@ struct ppc_elf_obj_tdata
 static bfd_boolean
 ppc_elf_mkobject (bfd *abfd)
 {
-  bfd_size_type amt = sizeof (struct ppc_elf_obj_tdata);
-  abfd->tdata.any = bfd_zalloc (abfd, amt);
   if (abfd->tdata.any == NULL)
-    return FALSE;
-  return TRUE;
+    {
+      bfd_size_type amt = sizeof (struct ppc_elf_obj_tdata);
+      abfd->tdata.any = bfd_zalloc (abfd, amt);
+      if (abfd->tdata.any == NULL)
+       return FALSE;
+    }
+  return bfd_elf_mkobject (abfd);
 }
 
 /* Fix bad default arch selected for a 32 bit input bfd when the
@@ -1869,7 +1872,8 @@ ppc_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED,
    need to bump up the number of section headers.  */
 
 static int
-ppc_elf_additional_program_headers (bfd *abfd)
+ppc_elf_additional_program_headers (bfd *abfd,
+                                   struct bfd_link_info *info ATTRIBUTE_UNUSED)
 {
   asection *s;
   int ret = 0;
@@ -2313,6 +2317,13 @@ struct ppc_elf_link_hash_entry
 
 #define ppc_elf_hash_entry(ent) ((struct ppc_elf_link_hash_entry *) (ent))
 
+enum ppc_elf_plt_type {
+  PLT_UNSET,
+  PLT_OLD,
+  PLT_NEW,
+  PLT_VXWORKS
+};
+
 /* PPC ELF linker hash table.  */
 
 struct ppc_elf_link_hash_table
@@ -2349,9 +2360,11 @@ struct ppc_elf_link_hash_table
   /* Non-zero if allocating the header left a gap.  */
   unsigned int got_gap;
 
-  /* Whether to use new plt/got layout or not.  */
-  unsigned int new_plt:1;
-  unsigned int old_plt:1;
+  /* The type of PLT we have chosen to use.  */
+  enum ppc_elf_plt_type plt_type;
+
+  /* Whether we can use the new PLT layout.  */
+  unsigned int can_use_new_plt:1;
 
   /* Set if we should emit symbols for stubs.  */
   unsigned int emit_stub_syms:1;
@@ -2421,8 +2434,9 @@ ppc_elf_link_hash_table_create (bfd *abfd)
   if (ret == NULL)
     return NULL;
 
-  if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd,
-                                      ppc_elf_link_hash_newfunc))
+  if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
+                                     ppc_elf_link_hash_newfunc,
+                                     sizeof (struct ppc_elf_link_hash_entry)))
     {
       free (ret);
       return NULL;
@@ -2539,19 +2553,9 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
        return FALSE;
     }
 
-  /* Create the section for VxWorks static plt relocations.  */
-  if (htab->is_vxworks && !info->shared)
-    {
-      s = bfd_make_section (abfd, ".rela.plt.unloaded");
-      flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY
-              | SEC_LINKER_CREATED);
-      if (s == NULL
-         || ! bfd_set_section_flags (abfd, s, flags)
-         || ! bfd_set_section_alignment (abfd, s,
-                 get_elf_backend_data (abfd)->s->log_file_align))
-       return FALSE;
-      htab->srelplt2 = s;
-    }
+  if (htab->is_vxworks
+      && !elf_vxworks_create_dynamic_sections (abfd, info, &htab->srelplt2))
+    return FALSE;
 
   htab->relplt = bfd_get_section_by_name (abfd, ".rela.plt");
   htab->plt = s = bfd_get_section_by_name (abfd, ".plt");
@@ -2559,6 +2563,9 @@ ppc_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
     abort ();
 
   flags = SEC_ALLOC | SEC_CODE | SEC_LINKER_CREATED;
+  if (htab->plt_type == PLT_VXWORKS)
+    /* The VxWorks PLT is a loaded section with contents.  */
+    flags |= SEC_HAS_CONTENTS | SEC_LOAD | SEC_READONLY;
   return bfd_set_section_flags (abfd, s, flags);
 }
 
@@ -2677,9 +2684,12 @@ static bfd_boolean
 is_ppc_elf_target (const struct bfd_target *targ)
 {
   extern const bfd_target bfd_elf32_powerpc_vec;
+  extern const bfd_target bfd_elf32_powerpc_vxworks_vec;
   extern const bfd_target bfd_elf32_powerpcle_vec;
 
-  return targ == &bfd_elf32_powerpc_vec || targ == &bfd_elf32_powerpcle_vec;
+  return (targ == &bfd_elf32_powerpc_vec
+         || targ == &bfd_elf32_powerpc_vxworks_vec
+         || targ == &bfd_elf32_powerpcle_vec);
 }
 
 /* Hook called by the linker routine which adds symbols from an object
@@ -3245,7 +3255,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_REL16_LO:
        case R_PPC_REL16_HI:
        case R_PPC_REL16_HA:
-         htab->new_plt = 1;
+         htab->can_use_new_plt = 1;
          break;
 
          /* These are just markers.  */
@@ -3273,8 +3283,8 @@ ppc_elf_check_relocs (bfd *abfd,
 
          /* This refers only to functions defined in the shared library.  */
        case R_PPC_LOCAL24PC:
-         if (h && h == htab->elf.hgot)
-           htab->old_plt = 1;
+         if (h && h == htab->elf.hgot && htab->plt_type == PLT_UNSET)
+           htab->plt_type = PLT_OLD;
          break;
 
          /* This relocation describes the C++ object vtable hierarchy.
@@ -3315,7 +3325,7 @@ ppc_elf_check_relocs (bfd *abfd,
              && got2 != NULL
              && (sec->flags & SEC_CODE) != 0
              && (info->shared || info->pie)
-             && !htab->old_plt)
+             && htab->plt_type == PLT_UNSET)
            {
              /* Old -fPIC gcc code has .long LCTOC1-LCFx just before
                 the start of a function, which assembles to a REL32
@@ -3328,9 +3338,11 @@ ppc_elf_check_relocs (bfd *abfd,
              s = bfd_section_from_r_symndx (abfd, &htab->sym_sec, sec,
                                             r_symndx);
              if (s == got2)
-               htab->old_plt = 1;
+               htab->plt_type = PLT_OLD;
            }
-         /* fall through */
+         if (h == NULL || h == htab->elf.hgot)
+           break;
+         goto dodyn1;
 
        case R_PPC_REL24:
        case R_PPC_REL14:
@@ -3340,7 +3352,8 @@ ppc_elf_check_relocs (bfd *abfd,
            break;
          if (h == htab->elf.hgot)
            {
-             htab->old_plt = 1;
+             if (htab->plt_type == PLT_UNSET)
+               htab->plt_type = PLT_OLD;
              break;
            }
          /* fall through */
@@ -3356,6 +3369,7 @@ ppc_elf_check_relocs (bfd *abfd,
        case R_PPC_ADDR14_BRNTAKEN:
        case R_PPC_UADDR32:
        case R_PPC_UADDR16:
+       dodyn1:
          if (h != NULL && !info->shared)
            {
              /* We may need a plt entry if the symbol turns out to be
@@ -3600,22 +3614,16 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
   flagword flags;
 
   htab = ppc_elf_hash_table (info);
-  if (force_old_plt || !htab->new_plt)
-    htab->old_plt = 1;
+
+  if (htab->plt_type == PLT_UNSET)
+    htab->plt_type = (force_old_plt || !htab->can_use_new_plt
+                     ? PLT_OLD : PLT_NEW);
 
   htab->emit_stub_syms = emit_stub_syms;
 
-  if (htab->is_vxworks)
-    {
-      /* The VxWorks PLT is a loaded section with contents.  */
-      flags = SEC_ALLOC | SEC_CODE | SEC_IN_MEMORY | SEC_LINKER_CREATED
-             | SEC_HAS_CONTENTS | SEC_LOAD | SEC_READONLY;
+  BFD_ASSERT (htab->plt_type != PLT_VXWORKS);
 
-      if (htab->plt != NULL
-         && !bfd_set_section_flags (htab->elf.dynobj, htab->plt, flags))
-       return -1;
-    }
-  else if (!htab->old_plt)
+  if (htab->plt_type == PLT_NEW)
     {
       flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
               | SEC_IN_MEMORY | SEC_LINKER_CREATED);
@@ -3637,7 +3645,7 @@ ppc_elf_select_plt_layout (bfd *output_bfd ATTRIBUTE_UNUSED,
          && !bfd_set_section_alignment (htab->elf.dynobj, htab->glink, 0))
        return -1;
     }
-  return !htab->old_plt;
+  return htab->plt_type == PLT_NEW;
 }
 \f
 /* Return the section that should be marked against GC for a given
@@ -3825,7 +3833,7 @@ ppc_elf_tls_setup (bfd *obfd, struct bfd_link_info *info)
   struct ppc_elf_link_hash_table *htab;
 
   htab = ppc_elf_hash_table (info);
-  if (!htab->old_plt
+  if (htab->plt_type == PLT_NEW
       && htab->plt != NULL
       && htab->plt->output_section != NULL)
     {
@@ -4269,31 +4277,32 @@ static bfd_vma
 allocate_got (struct ppc_elf_link_hash_table *htab, unsigned int need)
 {
   bfd_vma where;
-  unsigned int max_before_header = 32768;
-
-  if (htab->old_plt)
-    max_before_header = 32764;
+  unsigned int max_before_header;
 
-  if (htab->is_vxworks)
+  if (htab->plt_type == PLT_VXWORKS)
     {
       where = htab->got->size;
       htab->got->size += need;
     }
-  else if (need <= htab->got_gap)
-    {
-      where = max_before_header - htab->got_gap;
-      htab->got_gap -= need;
-    }
   else
     {
-      if (htab->got->size + need > max_before_header
-         && htab->got->size <= max_before_header)
+      max_before_header = htab->plt_type == PLT_NEW ? 32768 : 32764;
+      if (need <= htab->got_gap)
        {
-         htab->got_gap = max_before_header - htab->got->size;
-         htab->got->size = max_before_header + htab->got_header_size;
+         where = max_before_header - htab->got_gap;
+         htab->got_gap -= need;
+       }
+      else
+       {
+         if (htab->got->size + need > max_before_header
+             && htab->got->size <= max_before_header)
+           {
+             htab->got_gap = max_before_header - htab->got->size;
+             htab->got->size = max_before_header + htab->got_header_size;
+           }
+         where = htab->got->size;
+         htab->got->size += need;
        }
-      where = htab->got->size;
-      htab->got->size += need;
     }
   return where;
 }
@@ -4340,7 +4349,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
              {
                asection *s = htab->plt;
 
-               if (!(htab->old_plt || htab->is_vxworks))
+               if (htab->plt_type == PLT_NEW)
                  {
                    if (!doneone)
                      {
@@ -4404,7 +4413,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                        s->size += htab->plt_entry_size;
                        /* After the 8192nd entry, room for two entries
                           is allocated.  */
-                       if (!htab->is_vxworks
+                       if (htab->plt_type == PLT_OLD
                            && (s->size - htab->plt_initial_entry_size)
                                / htab->plt_entry_size
                               > PLT_NUM_SINGLE_ENTRIES)
@@ -4418,7 +4427,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                  {
                    htab->relplt->size += sizeof (Elf32_External_Rela);
 
-                   if (htab->is_vxworks)
+                   if (htab->plt_type == PLT_VXWORKS)
                      {
                        /* Allocate space for the unloaded relocations.  */
                        if (!info->shared)
@@ -4659,9 +4668,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
 
-  if (htab->old_plt)
+  if (htab->plt_type == PLT_OLD)
     htab->got_header_size = 16;
-  else
+  else if (htab->plt_type == PLT_NEW)
     htab->got_header_size = 12;
 
   /* Set up .got offsets for local syms, and space for local dynamic
@@ -4757,25 +4766,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   else
     htab->tlsld_got.offset = (bfd_vma) -1;
 
-  if (htab->is_vxworks)
-    {
-      /* Mark the GOT and PLT symbols as having relocations; they might
-        not, but we won't know for sure until we build the GOT in
-        finish_dynamic_symbol.  */
-      if (htab->elf.hgot)
-       htab->elf.hgot->indx = -2;
-      if (htab->elf.hplt)
-       {
-         htab->elf.hplt->indx = -2;
-         if (htab->plt->flags & SEC_CODE)
-           htab->elf.hplt->type = STT_FUNC;
-       }
-    }
-
   /* Allocate space for global sym dynamic relocs.  */
   elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
 
-  if (htab->got != NULL && !htab->is_vxworks)
+  if (htab->got != NULL && htab->plt_type != PLT_VXWORKS)
     {
       unsigned int g_o_t = 32768;
 
@@ -4786,7 +4780,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       if (htab->got->size <= 32768)
        {
          g_o_t = htab->got->size;
-         if (htab->old_plt)
+         if (htab->plt_type == PLT_OLD)
            g_o_t += 4;
          htab->got->size += htab->got_header_size;
        }
@@ -5122,7 +5116,7 @@ ppc_elf_relax_section (bfd *abfd,
 
              if (ent != NULL)
                {
-                 if (!htab->old_plt)
+                 if (htab->plt_type == PLT_NEW)
                    {
                      tsec = htab->glink;
                      toff = ent->glink_offset;
@@ -5191,6 +5185,10 @@ ppc_elf_relax_section (bfd *abfd,
       else if (r_type != R_PPC_PLTREL24)
        toff += irel->r_addend;
 
+      /* Attempted -shared link of non-pic code loses.  */
+      if (tsec->output_section == NULL)
+       continue;
+
       symaddr = tsec->output_section->vma + tsec->output_offset + toff;
 
       roff = irel->r_offset;
@@ -5778,6 +5776,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                      insn1 |= 32 << 26;        /* lwz */
                      insn2 = 0x7c631214;       /* add 3,3,2 */
                      rel[1].r_info = ELF32_R_INFO (r_symndx2, R_PPC_NONE);
+                     rel[1].r_addend = 0;
                      r_type = (((r_type - (R_PPC_GOT_TLSGD16 & 3)) & 3)
                                + R_PPC_GOT_TPREL16);
                      rel->r_info = ELF32_R_INFO (r_symndx, r_type);
@@ -5792,13 +5791,13 @@ ppc_elf_relocate_section (bfd *output_bfd,
                          /* Was an LD reloc.  */
                          r_symndx = 0;
                          rel->r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
-                         rel[1].r_addend = htab->elf.tls_sec->vma + DTP_OFFSET;
                        }
                      r_type = R_PPC_TPREL16_HA;
                      rel->r_info = ELF32_R_INFO (r_symndx, r_type);
                      rel[1].r_info = ELF32_R_INFO (r_symndx,
                                                    R_PPC_TPREL16_LO);
                      rel[1].r_offset += 2;
+                     rel[1].r_addend = rel->r_addend;
                    }
                  bfd_put_32 (output_bfd, insn1, contents + rel->r_offset - 2);
                  bfd_put_32 (output_bfd, insn2, contents + offset);
@@ -6302,7 +6301,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
                          BFD_ASSERT (indx > 0);
 #ifdef DEBUG
                          if (indx <= 0)
-                           printf ("indx=%d section=%s flags=%08x name=%s\n",
+                           printf ("indx=%ld section=%s flags=%08x name=%s\n",
                                    indx, osec->name, osec->flags,
                                    h->root.root.string);
 #endif
@@ -6337,7 +6336,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
          {
            struct plt_entry *ent = find_plt_ent (h, got2, addend);
 
-           if (!htab->old_plt)
+           if (htab->plt_type == PLT_NEW)
              relocation = (htab->glink->output_section->vma
                            + htab->glink->output_offset
                            + ent->glink_offset);
@@ -6427,7 +6426,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
              }
 
            unresolved_reloc = FALSE;
-           if (!htab->old_plt)
+           if (htab->plt_type == PLT_NEW)
              relocation = (htab->glink->output_section->vma
                            + htab->glink->output_offset
                            + ent->glink_offset);
@@ -6610,25 +6609,28 @@ ppc_elf_relocate_section (bfd *output_bfd,
 
        case R_PPC_ADDR16_HA:
        case R_PPC_REL16_HA:
-       case R_PPC_GOT16_HA:
-       case R_PPC_PLT16_HA:
        case R_PPC_SECTOFF_HA:
        case R_PPC_TPREL16_HA:
        case R_PPC_DTPREL16_HA:
-       case R_PPC_GOT_TLSGD16_HA:
-       case R_PPC_GOT_TLSLD16_HA:
-       case R_PPC_GOT_TPREL16_HA:
-       case R_PPC_GOT_DTPREL16_HA:
        case R_PPC_EMB_NADDR16_HA:
        case R_PPC_EMB_RELST_HA:
          /* It's just possible that this symbol is a weak symbol
             that's not actually defined anywhere.  In that case,
             'sec' would be NULL, and we should leave the symbol
             alone (it will be set to zero elsewhere in the link).  */
-         if (sec != NULL)
-           /* Add 0x10000 if sign bit in 0:15 is set.
-              Bits 0:15 are not used.  */
-           addend += 0x8000;
+         if (sec == NULL)
+           break;
+         /* Fall thru */
+
+       case R_PPC_PLT16_HA:
+       case R_PPC_GOT16_HA:
+       case R_PPC_GOT_TLSGD16_HA:
+       case R_PPC_GOT_TLSLD16_HA:
+       case R_PPC_GOT_TPREL16_HA:
+       case R_PPC_GOT_DTPREL16_HA:
+         /* Add 0x10000 if sign bit in 0:15 is set.
+            Bits 0:15 are not used.  */
+         addend += 0x8000;
          break;
        }
 
@@ -6747,20 +6749,20 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
            bfd_byte *loc;
            bfd_vma reloc_index;
 
-           if (!(htab->old_plt || htab->is_vxworks))
+           if (htab->plt_type == PLT_NEW)
              reloc_index = ent->plt.offset / 4;
            else
              {
                reloc_index = ((ent->plt.offset - htab->plt_initial_entry_size)
                               / htab->plt_slot_size);
                if (reloc_index > PLT_NUM_SINGLE_ENTRIES
-                   && !htab->is_vxworks)
+                   && htab->plt_type == PLT_OLD)
                  reloc_index -= (reloc_index - PLT_NUM_SINGLE_ENTRIES) / 2;
              }
 
            /* This symbol has an entry in the procedure linkage table.
               Set it up.  */
-           if (htab->is_vxworks)
+           if (htab->plt_type == PLT_VXWORKS)
              {
                bfd_vma got_offset;
                const bfd_vma *plt_entry;
@@ -6894,7 +6896,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
                rela.r_offset = (htab->plt->output_section->vma
                                 + htab->plt->output_offset
                                 + ent->plt.offset);
-               if (htab->old_plt)
+               if (htab->plt_type == PLT_OLD)
                  {
                    /* We don't need to fill in the .plt.  The ppc dynamic
                       linker will fill it in.  */
@@ -6932,7 +6934,7 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
            doneone = TRUE;
          }
 
-       if (!htab->old_plt)
+       if (htab->plt_type == PLT_NEW)
          {
            bfd_vma plt;
            unsigned char *p;
@@ -7154,7 +7156,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
       bfd_vma val;
 
       p += htab->elf.hgot->root.u.def.value;
-      if (htab->old_plt && !htab->is_vxworks)
+      if (htab->plt_type == PLT_OLD)
        bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, p - 4);
 
       val = 0;
@@ -7441,6 +7443,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
 #define ELF_MAXPAGESIZE                0x10000
 #endif
 #define ELF_MINPAGESIZE                0x1000
+#define ELF_COMMONPAGESIZE     0x1000
 #define elf_info_to_howto      ppc_elf_info_to_howto
 
 #ifdef  EM_CYGNUS_POWERPC
@@ -7526,6 +7529,7 @@ ppc_elf_vxworks_link_hash_table_create (bfd *abfd)
       struct ppc_elf_link_hash_table *htab
         = (struct ppc_elf_link_hash_table *)ret;
       htab->is_vxworks = 1;
+      htab->plt_type = PLT_VXWORKS;
       htab->plt_entry_size = VXWORKS_PLT_ENTRY_SIZE;
       htab->plt_slot_size = VXWORKS_PLT_ENTRY_SIZE;
       htab->plt_initial_entry_size = VXWORKS_PLT_INITIAL_ENTRY_SIZE;
@@ -7550,23 +7554,6 @@ ppc_elf_vxworks_add_symbol_hook (bfd *abfd,
   return ppc_elf_add_symbol_hook(abfd, info, sym,namep, flagsp, secp, valp);
 }
 
-/* Tweak magic VxWorks symbols as they are written to the output file.  */
-static bfd_boolean
-elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info
-                                          ATTRIBUTE_UNUSED,
-                                        const char *name,
-                                        Elf_Internal_Sym *sym,
-                                        asection *input_sec ATTRIBUTE_UNUSED,
-                                        struct elf_link_hash_entry *h
-                                          ATTRIBUTE_UNUSED)
-{
-  /* Ignore the first dummy symbol.  */
-  if (!name)
-    return TRUE;
-
-  return elf_vxworks_link_output_symbol_hook (name, sym);
-}
-
 static void
 ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
 {
@@ -7597,7 +7584,7 @@ ppc_elf_vxworks_final_write_processing (bfd *abfd, bfd_boolean linker)
   ppc_elf_vxworks_add_symbol_hook
 #undef elf_backend_link_output_symbol_hook
 #define elf_backend_link_output_symbol_hook \
-  elf_i386_vxworks_link_output_symbol_hook
+  elf_vxworks_link_output_symbol_hook
 #undef elf_backend_final_write_processing
 #define elf_backend_final_write_processing \
   ppc_elf_vxworks_final_write_processing
This page took 0.031975 seconds and 4 git commands to generate.