* elf64-ppc.c (is_ppc64_target): New function, extracted from..
[deliverable/binutils-gdb.git] / bfd / elf64-ppc.c
index 61a42cb3d4a3e05b865283d7b2362b75c5808753..865460575360e087545dacf9d67f62b56c15cfb3 100644 (file)
@@ -2400,6 +2400,15 @@ ppc64_elf_mkobject (bfd *abfd)
   return TRUE;
 }
 
+static bfd_boolean
+is_ppc64_target (const struct bfd_target *targ)
+{
+  extern const bfd_target bfd_elf64_powerpc_vec;
+  extern const bfd_target bfd_elf64_powerpcle_vec;
+
+  return targ == &bfd_elf64_powerpc_vec || targ == &bfd_elf64_powerpcle_vec;
+}
+
 /* Fix bad default arch selected for a 64 bit input bfd when the
    default is 32 bit.  */
 
@@ -2645,16 +2654,19 @@ sym_exists_at (asymbol **syms, long lo, long hi, int id, bfd_vma value)
    entry syms.  */
 
 static long
-ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
+ppc64_elf_get_synthetic_symtab (bfd *abfd,
+                               long static_count, asymbol **static_syms,
+                               long dyn_count, asymbol **dyn_syms,
+                               asymbol **ret)
 {
   asymbol *s;
   long i;
   long count;
   char *names;
-  asymbol **syms = NULL;
-  long symcount = 0, codesecsym, codesecsymend, secsymend, opdsymend;
+  long symcount, codesecsym, codesecsymend, secsymend, opdsymend;
   asection *opd;
   bfd_boolean relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
+  asymbol **syms;
 
   *ret = NULL;
 
@@ -2662,60 +2674,43 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
   if (opd == NULL)
     return 0;
 
-  if ((bfd_get_file_flags (abfd) & HAS_SYMS))
-    {
-      long storage;
-      storage = bfd_get_symtab_upper_bound (abfd);
-      if (storage < 0)
-       return 0;
-
-      if (storage)
-       {
-         syms = bfd_malloc (storage);
-         if (syms == NULL)
-           return 0;
-       }
-
-      symcount = bfd_canonicalize_symtab (abfd, syms);
-      if (symcount < 0)
-       {
-         free (syms);
-         return 0;
-       }
-
-      if (symcount == 0)
-       {
-         free (syms);
-         syms = NULL;
-       }
-    }
-
+  symcount = static_count;
+  if (!relocatable)
+    symcount += dyn_count;
   if (symcount == 0)
-    {
-      long storage;
-
-      storage = bfd_get_dynamic_symtab_upper_bound (abfd);
-      if (storage < 0)
-       return 0;
+    return 0;
 
-      if (storage)
-       {
-         syms = bfd_malloc (storage);
-         if (syms == NULL)
-           return 0;
-       }
+  syms = bfd_malloc ((symcount + 1) * sizeof (*syms));
+  if (syms == NULL)
+    return 0;
 
-      symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
-      if (symcount < 0)
-       {
-         free (syms);
-         return 0;
-       }
+  if (!relocatable && static_count != 0 && dyn_count != 0)
+    {
+      /* Use both symbol tables.  */
+      memcpy (syms, static_syms, static_count * sizeof (*syms));
+      memcpy (syms + static_count, dyn_syms, (dyn_count + 1) * sizeof (*syms));
     }
+  else if (!relocatable && static_count == 0)
+    memcpy (syms, dyn_syms, (symcount + 1) * sizeof (*syms));
+  else
+    memcpy (syms, static_syms, (symcount + 1) * sizeof (*syms));
 
   synthetic_opd = opd;
   synthetic_relocatable = relocatable;
-  qsort (syms, symcount, sizeof (asymbol *), compare_symbols);
+  qsort (syms, symcount, sizeof (*syms), compare_symbols);
+
+  if (!relocatable && symcount > 1)
+    {
+      long j;
+      /* Trim duplicate syms, since we may have merged the normal and
+        dynamic symbols.  Actually, we only care about syms that have
+        different values, so trim any with the same value.  */ 
+      for (i = 1, j = 1; i < symcount; ++i)
+       if (syms[i - 1]->value + syms[i - 1]->section->vma
+           != syms[i]->value + syms[i]->section->vma)
+         syms[j++] = syms[i];
+      symcount = j;
+    }
 
   i = 0;
   if (syms[i]->section == opd)
@@ -2745,42 +2740,34 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
       break;
   symcount = i;
 
+  count = 0;
   if (opdsymend == secsymend)
-    {
-      free (syms);
-      return 0;
-    }
+    goto done;
 
-  count = 0;
   if (relocatable)
     {
       bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
       arelent *r;
       size_t size;
       long relcount;
-      asection *relopd;
 
       slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
-      relopd = opd;
       relcount = (opd->flags & SEC_RELOC) ? opd->reloc_count : 0;
 
       if (! relcount
-         || ! (*slurp_relocs) (abfd, relopd, relsyms, FALSE))
-       {
-         free (syms);
-         return 0;
-       }
+         || ! (*slurp_relocs) (abfd, opd, static_syms, FALSE))
+       goto done;
 
       size = 0;
-      for (i = secsymend, r = relopd->relocation; i < opdsymend; ++i)
+      for (i = secsymend, r = opd->relocation; i < opdsymend; ++i)
        {
          asymbol *sym;
 
-         while (r < relopd->relocation + relcount
+         while (r < opd->relocation + relcount
                 && r->address < syms[i]->value + opd->vma)
            ++r;
 
-         if (r == relopd->relocation + relcount)
+         if (r == opd->relocation + relcount)
            break;
 
          if (r->address != syms[i]->value + opd->vma)
@@ -2802,21 +2789,21 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
       s = *ret = bfd_malloc (size);
       if (s == NULL)
        {
-         free (syms);
-         return 0;
+         count = 0;
+         goto done;
        }
 
       names = (char *) (s + count);
 
-      for (i = secsymend, r = relopd->relocation; i < opdsymend; ++i)
+      for (i = secsymend, r = opd->relocation; i < opdsymend; ++i)
        {
          asymbol *sym;
 
-         while (r < relopd->relocation + relcount
+         while (r < opd->relocation + relcount
                 && r->address < syms[i]->value + opd->vma)
            ++r;
 
-         if (r == relopd->relocation + relcount)
+         if (r == opd->relocation + relcount)
            break;
 
          if (r->address != syms[i]->value + opd->vma)
@@ -2851,9 +2838,11 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
       if (!bfd_malloc_and_get_section (abfd, opd, &contents))
        {
          if (contents)
-           free (contents);
-         free (syms);
-         return 0;
+           {
+           free_contents_and_exit:
+             free (contents);
+           }
+         goto done;
        }
 
       size = 0;
@@ -2873,9 +2862,8 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
       s = *ret = bfd_malloc (size);
       if (s == NULL)
        {
-         free (contents);
-         free (syms);
-         return 0;
+         count = 0;
+         goto free_contents_and_exit;
        }
 
       names = (char *) (s + count);
@@ -2887,30 +2875,29 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
          ent = bfd_get_64 (abfd, contents + syms[i]->value);
          if (!sym_exists_at (syms, opdsymend, symcount, -1, ent))
            {
-             long lo, hi, mid;
+             long lo, hi;
              size_t len;
-             asection *sec;
+             asection *sec = abfd->sections;
 
              *s = *syms[i];
              lo = codesecsym;
              hi = codesecsymend;
              while (lo < hi)
                {
-                 mid = (lo + hi) >> 1;
+                 long mid = (lo + hi) >> 1;
                  if (syms[mid]->section->vma < ent)
                    lo = mid + 1;
                  else if (syms[mid]->section->vma > ent)
                    hi = mid;
                  else
-                   break;
+                   {
+                     sec = syms[mid]->section;
+                     break;
+                   }
                }
 
-             if (lo < hi)
-               sec = syms[mid]->section;
-             else if (lo > codesecsym)
+             if (lo >= hi && lo > codesecsym)
                sec = syms[lo - 1]->section;
-             else
-               sec = abfd->sections;
 
              for (; sec != NULL; sec = sec->next)
                {
@@ -2934,6 +2921,7 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd, asymbol **relsyms, asymbol **ret)
       free (contents);
     }
 
+ done:
   free (syms);
   return count;
 }
@@ -4048,12 +4036,9 @@ ppc64_elf_check_directives (bfd *abfd ATTRIBUTE_UNUSED,
                            struct bfd_link_info *info)
 {
   struct ppc_link_hash_table *htab;
-  extern const bfd_target bfd_elf64_powerpc_vec;
-  extern const bfd_target bfd_elf64_powerpcle_vec;
 
   htab = ppc_hash_table (info);
-  if (htab->elf.root.creator != &bfd_elf64_powerpc_vec
-      && htab->elf.root.creator != &bfd_elf64_powerpcle_vec)
+  if (!is_ppc64_target (htab->elf.root.creator))
     return TRUE;
 
   elf_link_hash_traverse (&htab->elf, add_symbol_adjust, info);
@@ -6913,7 +6898,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
       Elf_Internal_Shdr *symtab_hdr;
       asection *srel;
 
-      if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
+      if (!is_ppc64_target (ibfd->xvec))
        continue;
 
       if (ppc64_tlsld_got (ibfd)->refcount > 0)
@@ -7083,6 +7068,9 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
     {
+      if (!is_ppc64_target (ibfd->xvec))
+       continue;
+
       s = ppc64_elf_tdata (ibfd)->got;
       if (s != NULL && s != htab->got)
        {
@@ -10122,10 +10110,15 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
     }
 
   /* We need to handle writing out multiple GOT sections ourselves,
-     since we didn't add them to DYNOBJ.  */
+     since we didn't add them to DYNOBJ.  We know dynobj is the first
+     bfd.  */
   while ((dynobj = dynobj->link_next) != NULL)
     {
       asection *s;
+
+      if (!is_ppc64_target (dynobj->xvec))
+       continue;
+
       s = ppc64_elf_tdata (dynobj)->got;
       if (s != NULL
          && s->size != 0
This page took 0.030466 seconds and 4 git commands to generate.