]> oss.titaniummirror.com Git - msp430-binutils.git/blobdiff - bfd/elf32-hppa.c
Imported binutils-2.20
[msp430-binutils.git] / bfd / elf32-hppa.c
index a99cf0a02ef786e66e5ed8b79a718b44cfe8df7d..cac0a215f4d6261c28e92ebc23080d98a353d097 100644 (file)
@@ -1,6 +1,7 @@
 /* BFD back-end for HP PA-RISC ELF files.
    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
    Original code by
        Center for Software Science
@@ -300,8 +301,8 @@ struct elf32_hppa_link_hash_table
   /* Set if we need a .plt stub to support lazy dynamic linking.  */
   unsigned int need_plt_stub:1;
 
-  /* Small local sym to section mapping cache.  */
-  struct sym_sec_cache sym_sec;
+  /* Small local sym cache.  */
+  struct sym_cache sym_cache;
 
   /* Data for LDM relocations.  */
   union
@@ -334,6 +335,15 @@ struct elf32_hppa_link_hash_table
 #define eh_name(eh) \
   (eh ? eh->root.root.string : "<undef>")
 
+/* Override the generic function because we want to mark our BFDs.  */
+
+static bfd_boolean
+elf32_hppa_mkobject (bfd *abfd)
+{
+  return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
+                                 HPPA_ELF_TDATA);
+}
+
 /* Assorted hash table functions.  */
 
 /* Initialize an entry in the stub hash table.  */
@@ -450,7 +460,7 @@ elf32_hppa_link_hash_table_create (bfd *abfd)
   htab->has_17bit_branch = 0;
   htab->has_22bit_branch = 0;
   htab->need_plt_stub = 0;
-  htab->sym_sec.abfd = NULL;
+  htab->sym_cache.abfd = NULL;
   htab->tls_ldm_got.refcount = 0;
 
   return &htab->etab.root;
@@ -1001,16 +1011,7 @@ elf32_hppa_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
 
   htab->sgot = bfd_get_section_by_name (abfd, ".got");
-  htab->srelgot = bfd_make_section_with_flags (abfd, ".rela.got",
-                                              (SEC_ALLOC
-                                               | SEC_LOAD
-                                               | SEC_HAS_CONTENTS
-                                               | SEC_IN_MEMORY
-                                               | SEC_LINKER_CREATED
-                                               | SEC_READONLY));
-  if (htab->srelgot == NULL
-      || ! bfd_set_section_alignment (abfd, htab->srelgot, 2))
-    return FALSE;
+  htab->srelgot = bfd_get_section_by_name (abfd, ".rela.got");
 
   htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
   htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
@@ -1103,6 +1104,38 @@ elf32_hppa_optimized_tls_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED,
   return r_type;
 }
 
+/* Return a pointer to the local GOT, PLT and TLS reference counts
+   for ABFD.  Returns NULL if the storage allocation fails.  */
+
+static bfd_signed_vma *
+hppa32_elf_local_refcounts (bfd *abfd)
+{
+  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  bfd_signed_vma *local_refcounts;
+                  
+  local_refcounts = elf_local_got_refcounts (abfd);
+  if (local_refcounts == NULL)
+    {
+      bfd_size_type size;
+
+      /* Allocate space for local GOT and PLT reference
+        counts.  Done this way to save polluting elf_obj_tdata
+        with another target specific pointer.  */
+      size = symtab_hdr->sh_info;
+      size *= 2 * sizeof (bfd_signed_vma);
+      /* Add in space to store the local GOT TLS types.  */
+      size += symtab_hdr->sh_info;
+      local_refcounts = bfd_zalloc (abfd, size);
+      if (local_refcounts == NULL)
+       return NULL;
+      elf_local_got_refcounts (abfd) = local_refcounts;
+      memset (hppa_elf_local_got_tls_type (abfd), GOT_UNKNOWN,
+             symtab_hdr->sh_info);
+    }
+  return local_refcounts;
+}
+
+
 /* Look through the relocs for a section during the first phase, and
    calculate needed space in the global offset table, procedure linkage
    table, and dynamic reloc sections.  At this point we haven't
@@ -1278,7 +1311,9 @@ elf32_hppa_check_relocs (bfd *abfd,
          /* This relocation describes which C++ vtable entries are actually
             used.  Record for later use during GC.  */
        case R_PARISC_GNU_VTENTRY:
-         if (!bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rela->r_addend))
+         BFD_ASSERT (hh != NULL);
+         if (hh != NULL
+             && !bfd_elf_gc_record_vtentry (abfd, sec, &hh->eh, rela->r_addend))
            return FALSE;
          continue;
 
@@ -1347,26 +1382,9 @@ elf32_hppa_check_relocs (bfd *abfd,
                  bfd_signed_vma *local_got_refcounts;
                  
                  /* This is a global offset table entry for a local symbol.  */
-                 local_got_refcounts = elf_local_got_refcounts (abfd);
+                 local_got_refcounts = hppa32_elf_local_refcounts (abfd);
                  if (local_got_refcounts == NULL)
-                   {
-                     bfd_size_type size;
-
-                     /* Allocate space for local got offsets and local
-                        plt offsets.  Done this way to save polluting
-                        elf_obj_tdata with another target specific
-                        pointer.  */
-                     size = symtab_hdr->sh_info;
-                     size *= 2 * sizeof (bfd_signed_vma);
-                     /* Add in space to store the local GOT TLS types.  */
-                     size += symtab_hdr->sh_info;
-                     local_got_refcounts = bfd_zalloc (abfd, size);
-                     if (local_got_refcounts == NULL)
-                       return FALSE;
-                     elf_local_got_refcounts (abfd) = local_got_refcounts;
-                     memset (hppa_elf_local_got_tls_type (abfd),
-                         GOT_UNKNOWN, symtab_hdr->sh_info);
-                   }
+                   return FALSE;
                  local_got_refcounts[r_symndx] += 1;
 
                  old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
@@ -1413,22 +1431,9 @@ elf32_hppa_check_relocs (bfd *abfd,
                  bfd_signed_vma *local_got_refcounts;
                  bfd_signed_vma *local_plt_refcounts;
 
-                 local_got_refcounts = elf_local_got_refcounts (abfd);
+                 local_got_refcounts = hppa32_elf_local_refcounts (abfd);
                  if (local_got_refcounts == NULL)
-                   {
-                     bfd_size_type size;
-
-                     /* Allocate space for local got offsets and local
-                        plt offsets.  */
-                     size = symtab_hdr->sh_info;
-                     size *= 2 * sizeof (bfd_signed_vma);
-                     /* Add in space to store the local GOT TLS types.  */
-                     size += symtab_hdr->sh_info;
-                     local_got_refcounts = bfd_zalloc (abfd, size);
-                     if (local_got_refcounts == NULL)
-                       return FALSE;
-                     elf_local_got_refcounts (abfd) = local_got_refcounts;
-                   }
+                   return FALSE;
                  local_plt_refcounts = (local_got_refcounts
                                         + symtab_hdr->sh_info);
                  local_plt_refcounts[r_symndx] += 1;
@@ -1493,44 +1498,17 @@ elf32_hppa_check_relocs (bfd *abfd,
                 this reloc.  */
              if (sreloc == NULL)
                {
-                 char *name;
-                 bfd *dynobj;
-
-                 name = (bfd_elf_string_from_elf_section
-                         (abfd,
-                          elf_elfheader (abfd)->e_shstrndx,
-                          elf_section_data (sec)->rel_hdr.sh_name));
-                 if (name == NULL)
-                   {
-                     (*_bfd_error_handler)
-                       (_("Could not find relocation section for %s"),
-                        sec->name);
-                     bfd_set_error (bfd_error_bad_value);
-                     return FALSE;
-                   }
-
                  if (htab->etab.dynobj == NULL)
                    htab->etab.dynobj = abfd;
 
-                 dynobj = htab->etab.dynobj;
-                 sreloc = bfd_get_section_by_name (dynobj, name);
+                 sreloc = _bfd_elf_make_dynamic_reloc_section
+                   (sec, htab->etab.dynobj, 2, abfd, /*rela?*/ TRUE);
+
                  if (sreloc == NULL)
                    {
-                     flagword flags;
-
-                     flags = (SEC_HAS_CONTENTS | SEC_READONLY
-                              | SEC_IN_MEMORY | SEC_LINKER_CREATED);
-                     if ((sec->flags & SEC_ALLOC) != 0)
-                       flags |= SEC_ALLOC | SEC_LOAD;
-                     sreloc = bfd_make_section_with_flags (dynobj,
-                                                           name,
-                                                           flags);
-                     if (sreloc == NULL
-                         || !bfd_set_section_alignment (dynobj, sreloc, 2))
-                       return FALSE;
+                     bfd_set_error (bfd_error_bad_value);
+                     return FALSE;
                    }
-
-                 elf_section_data (sec)->sreloc = sreloc;
                }
 
              /* If this is a global symbol, we count the number of
@@ -1544,15 +1522,19 @@ elf32_hppa_check_relocs (bfd *abfd,
                  /* Track dynamic relocs needed for local syms too.
                     We really need local syms available to do this
                     easily.  Oh well.  */
-
                  asection *sr;
                  void *vpp;
+                 Elf_Internal_Sym *isym;
 
-                 sr = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
-                                                      sec, r_symndx);
-                 if (sr == NULL)
+                 isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+                                               abfd, r_symndx);
+                 if (isym == NULL)
                    return FALSE;
 
+                 sr = bfd_section_from_elf_index (abfd, isym->st_shndx);
+                 if (sr == NULL)
+                   sr = sec;
+
                  vpp = &elf_section_data (sr)->local_dynrel;
                  hdh_head = (struct elf32_hppa_dyn_reloc_entry **) vpp;
                }
@@ -1620,6 +1602,9 @@ elf32_hppa_gc_sweep_hook (bfd *abfd,
   bfd_signed_vma *local_plt_refcounts;
   const Elf_Internal_Rela *rela, *relend;
 
+  if (info->relocatable)
+    return TRUE;
+
   elf_section_data (sec)->local_dynrel = NULL;
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -2962,15 +2947,20 @@ elf32_hppa_size_stubs
                      /* It's a local symbol.  */
                      Elf_Internal_Sym *sym;
                      Elf_Internal_Shdr *hdr;
+                     unsigned int shndx;
 
                      sym = local_syms + r_indx;
-                     hdr = elf_elfsections (input_bfd)[sym->st_shndx];
-                     sym_sec = hdr->bfd_section;
                      if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
                        sym_value = sym->st_value;
-                     destination = (sym_value + irela->r_addend
-                                    + sym_sec->output_offset
-                                    + sym_sec->output_section->vma);
+                     shndx = sym->st_shndx;
+                     if (shndx < elf_numsections (input_bfd))
+                       {
+                         hdr = elf_elfsections (input_bfd)[shndx];
+                         sym_sec = hdr->bfd_section;
+                         destination = (sym_value + irela->r_addend
+                                        + sym_sec->output_offset
+                                        + sym_sec->output_section->vma);
+                       }
                    }
                  else
                    {
@@ -3254,9 +3244,7 @@ elf32_hppa_final_link (bfd *abfd, struct bfd_link_info *info)
 /* Record the lowest address for the data and text segments.  */
 
 static void
-hppa_record_segment_addr (bfd *abfd ATTRIBUTE_UNUSED,
-                         asection *section,
-                         void *data)
+hppa_record_segment_addr (bfd *abfd, asection *section, void *data)
 {
   struct elf32_hppa_link_hash_table *htab;
 
@@ -3264,7 +3252,12 @@ hppa_record_segment_addr (bfd *abfd ATTRIBUTE_UNUSED,
 
   if ((section->flags & (SEC_ALLOC | SEC_LOAD)) == (SEC_ALLOC | SEC_LOAD))
     {
-      bfd_vma value = section->vma - section->filepos;
+      bfd_vma value;
+      Elf_Internal_Phdr *p;
+
+      p = _bfd_elf_find_segment_containing_section (abfd, section->output_section);
+      BFD_ASSERT (p != NULL);
+      value = p->p_vaddr;
 
       if ((section->flags & SEC_READONLY) != 0)
        {
@@ -3413,7 +3406,7 @@ final_link_relocate (asection *input_section,
              (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
               input_bfd,
               input_section,
-              offset,
+              (long) offset,
               howto->name,
               insn);
        }
@@ -3577,7 +3570,7 @@ final_link_relocate (asection *input_section,
        (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
         input_bfd,
         input_section,
-        offset,
+        (long) offset,
         hsh->bh_root.string);
       bfd_set_error (bfd_error_bad_value);
       return bfd_reloc_notsupported;
@@ -4594,11 +4587,12 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
 /* Misc BFD support code.  */
 #define bfd_elf32_bfd_is_local_label_name    elf_hppa_is_local_label_name
 #define bfd_elf32_bfd_reloc_type_lookup             elf_hppa_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_name_lookup elf_hppa_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup      elf_hppa_reloc_name_lookup
 #define elf_info_to_howto                   elf_hppa_info_to_howto
 #define elf_info_to_howto_rel               elf_hppa_info_to_howto_rel
 
 /* Stuff for the BFD linker.  */
+#define bfd_elf32_mkobject                  elf32_hppa_mkobject
 #define bfd_elf32_bfd_final_link            elf32_hppa_final_link
 #define bfd_elf32_bfd_link_hash_table_create elf32_hppa_link_hash_table_create
 #define bfd_elf32_bfd_link_hash_table_free   elf32_hppa_link_hash_table_free