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. */
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;
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)
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)
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)
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;
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);
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)
{
free (contents);
}
+ done:
free (syms);
return count;
}
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);
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)
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)
{
}
/* 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