summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2006-11-07 03:24:13 +0000
committerAlan Modra <amodra@bigpond.net.au>2006-11-07 03:24:13 +0000
commitd7f10c300715f248e9f4eb0cbcace44c1a971ce3 (patch)
treec71268c453d62dc42d758d121d3c5410e53efe55
parentc95eeb86c8f2ad4b9411bcd00242014dcc57a512 (diff)
downloadbinutils-redhat-d7f10c300715f248e9f4eb0cbcace44c1a971ce3.tar.gz
* elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
and union. (struct ppc_link_hash_entry): Add "next_dot_sym". (struct ppc_link_hash_table): Add "dot_syms". (link_hash_newfunc): Make list of syms starting with a dot. (ppc_get_stub_entry, adjust_opd_syms): Adjust. (ppc64_elf_add_symbol_hook): Don't set has_dotsym. (struct add_symbol_adjust_data): Delete. (add_symbol_adjust): Simplify params and return. (ppc64_elf_check_directives): Just process the "dot_syms" lists, not all syms.
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elf64-ppc.c160
2 files changed, 98 insertions, 76 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 3b97d52c9a..cd7e8f1497 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2006-11-07 Alan Modra <amodra@bigpond.net.au>
+
+ * elf64-ppc.c (struct ppc64_elf_obj_tdata): Remove "has_dotsym"
+ and union.
+ (struct ppc_link_hash_entry): Add "next_dot_sym".
+ (struct ppc_link_hash_table): Add "dot_syms".
+ (link_hash_newfunc): Make list of syms starting with a dot.
+ (ppc_get_stub_entry, adjust_opd_syms): Adjust.
+ (ppc64_elf_add_symbol_hook): Don't set has_dotsym.
+ (struct add_symbol_adjust_data): Delete.
+ (add_symbol_adjust): Simplify params and return.
+ (ppc64_elf_check_directives): Just process the "dot_syms" lists,
+ not all syms.
+
2006-11-02 Daniel Jacobowitz <dan@codesourcery.com>
* libbfd-in.h (_bfd_clear_contents): New prototype.
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 52b3e623fa..84a7b5f56b 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -2377,14 +2377,9 @@ struct ppc64_elf_obj_tdata
asection *got;
asection *relgot;
- union {
- /* Used during garbage collection. We attach global symbols defined
- on removed .opd entries to this section so that the sym is removed. */
- asection *deleted_section;
-
- /* Used when adding symbols. */
- bfd_boolean has_dotsym;
- } u;
+ /* Used during garbage collection. We attach global symbols defined
+ on removed .opd entries to this section so that the sym is removed. */
+ asection *deleted_section;
/* TLS local dynamic got entry handling. Suppose for multiple GOT
sections means we potentially need one of these for each input bfd. */
@@ -3241,9 +3236,14 @@ struct ppc_link_hash_entry
{
struct elf_link_hash_entry elf;
- /* A pointer to the most recently used stub hash entry against this
- symbol. */
- struct ppc_stub_hash_entry *stub_cache;
+ union {
+ /* A pointer to the most recently used stub hash entry against this
+ symbol. */
+ struct ppc_stub_hash_entry *stub_cache;
+
+ /* A pointer to the next symbol starting with a '.' */
+ struct ppc_link_hash_entry *next_dot_sym;
+ } u;
/* Track dynamic relocs copied for this symbol. */
struct ppc_dyn_relocs *dyn_relocs;
@@ -3321,6 +3321,9 @@ struct ppc_link_hash_table
/* Highest output section index. */
int top_index;
+ /* Used when adding symbols. */
+ struct ppc_link_hash_entry *dot_syms;
+
/* List of input sections for each output section. */
asection **input_list;
@@ -3477,9 +3480,34 @@ link_hash_newfunc (struct bfd_hash_entry *entry,
{
struct ppc_link_hash_entry *eh = (struct ppc_link_hash_entry *) entry;
- memset (&eh->stub_cache, 0,
+ memset (&eh->u.stub_cache, 0,
(sizeof (struct ppc_link_hash_entry)
- - offsetof (struct ppc_link_hash_entry, stub_cache)));
+ - offsetof (struct ppc_link_hash_entry, u.stub_cache)));
+
+ /* When making function calls, old ABI code references function entry
+ points (dot symbols), while new ABI code references the function
+ descriptor symbol. We need to make any combination of reference and
+ definition work together, without breaking archive linking.
+
+ For a defined function "foo" and an undefined call to "bar":
+ An old object defines "foo" and ".foo", references ".bar" (possibly
+ "bar" too).
+ A new object defines "foo" and references "bar".
+
+ A new object thus has no problem with its undefined symbols being
+ satisfied by definitions in an old object. On the other hand, the
+ old object won't have ".bar" satisfied by a new object.
+
+ Keep a list of newly added dot-symbols. */
+
+ if (string[0] == '.')
+ {
+ struct ppc_link_hash_table *htab;
+
+ htab = (struct ppc_link_hash_table *) table;
+ eh->u.next_dot_sym = htab->dot_syms;
+ htab->dot_syms = eh;
+ }
}
return entry;
@@ -3625,11 +3653,11 @@ ppc_get_stub_entry (const asection *input_section,
distinguish between them. */
id_sec = htab->stub_group[input_section->id].link_sec;
- if (h != NULL && h->stub_cache != NULL
- && h->stub_cache->h == h
- && h->stub_cache->id_sec == id_sec)
+ if (h != NULL && h->u.stub_cache != NULL
+ && h->u.stub_cache->h == h
+ && h->u.stub_cache->id_sec == id_sec)
{
- stub_entry = h->stub_cache;
+ stub_entry = h->u.stub_cache;
}
else
{
@@ -3642,7 +3670,7 @@ ppc_get_stub_entry (const asection *input_section,
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
stub_name, FALSE, FALSE);
if (h != NULL)
- h->stub_cache = stub_entry;
+ h->u.stub_cache = stub_entry;
free (stub_name);
}
@@ -4051,29 +4079,14 @@ make_fdh (struct bfd_link_info *info,
return fdh;
}
-/* Hacks to support old ABI code.
- When making function calls, old ABI code references function entry
- points (dot symbols), while new ABI code references the function
- descriptor symbol. We need to make any combination of reference and
- definition work together, without breaking archive linking.
-
- For a defined function "foo" and an undefined call to "bar":
- An old object defines "foo" and ".foo", references ".bar" (possibly
- "bar" too).
- A new object defines "foo" and references "bar".
-
- A new object thus has no problem with its undefined symbols being
- satisfied by definitions in an old object. On the other hand, the
- old object won't have ".bar" satisfied by a new object. */
-
/* Fix function descriptor symbols defined in .opd sections to be
function type. */
static bfd_boolean
-ppc64_elf_add_symbol_hook (bfd *ibfd,
+ppc64_elf_add_symbol_hook (bfd *ibfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
Elf_Internal_Sym *isym,
- const char **name,
+ const char **name ATTRIBUTE_UNUSED,
flagword *flags ATTRIBUTE_UNUSED,
asection **sec,
bfd_vma *value ATTRIBUTE_UNUSED)
@@ -4082,12 +4095,6 @@ ppc64_elf_add_symbol_hook (bfd *ibfd,
&& strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0)
isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
- if ((*name)[0] == '.'
- && ELF_ST_BIND (isym->st_info) == STB_GLOBAL
- && ELF_ST_TYPE (isym->st_info) < STT_SECTION
- && is_ppc64_elf_target (ibfd->xvec))
- ppc64_elf_tdata (ibfd)->u.has_dotsym = 1;
-
return TRUE;
}
@@ -4136,35 +4143,25 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
most restrictive visibility of the function descriptor and the
function entry symbol is used. */
-struct add_symbol_adjust_data
-{
- struct bfd_link_info *info;
- bfd_boolean ok;
-};
-
static bfd_boolean
-add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
+add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
{
- struct add_symbol_adjust_data *data;
struct ppc_link_hash_table *htab;
- struct ppc_link_hash_entry *eh;
struct ppc_link_hash_entry *fdh;
- if (h->root.type == bfd_link_hash_indirect)
+ if (eh->elf.root.type == bfd_link_hash_indirect)
return TRUE;
- if (h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (eh->elf.root.type == bfd_link_hash_warning)
+ eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
- if (h->root.root.string[0] != '.')
- return TRUE;
+ if (eh->elf.root.root.string[0] != '.')
+ abort ();
- data = inf;
- htab = ppc_hash_table (data->info);
- eh = (struct ppc_link_hash_entry *) h;
+ htab = ppc_hash_table (info);
fdh = get_fdh (eh, htab);
if (fdh == NULL
- && !data->info->relocatable
+ && !info->relocatable
&& (eh->elf.root.type == bfd_link_hash_undefined
|| eh->elf.root.type == bfd_link_hash_undefweak)
&& eh->elf.ref_regular)
@@ -4172,9 +4169,9 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
/* Make an undefweak function descriptor sym, which is enough to
pull in an --as-needed shared lib, but won't cause link
errors. Archives are handled elsewhere. */
- fdh = make_fdh (data->info, eh);
+ fdh = make_fdh (info, eh);
if (fdh == NULL)
- data->ok = FALSE;
+ return FALSE;
else
fdh->elf.ref_regular = 1;
}
@@ -4200,26 +4197,37 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
return TRUE;
}
+/* Process list of dot-symbols we made in link_hash_newfunc. */
+
static bfd_boolean
-ppc64_elf_check_directives (bfd *abfd, struct bfd_link_info *info)
+ppc64_elf_check_directives (bfd *ibfd, struct bfd_link_info *info)
{
struct ppc_link_hash_table *htab;
- struct add_symbol_adjust_data data;
-
- if (!is_ppc64_elf_target (abfd->xvec))
- return TRUE;
-
- if (!ppc64_elf_tdata (abfd)->u.has_dotsym)
- return TRUE;
- ppc64_elf_tdata (abfd)->u.deleted_section = NULL;
+ struct ppc_link_hash_entry **p, *eh;
htab = ppc_hash_table (info);
if (!is_ppc64_elf_target (htab->elf.root.creator))
return TRUE;
- data.info = info;
- data.ok = TRUE;
- elf_link_hash_traverse (&htab->elf, add_symbol_adjust, &data);
+ if (is_ppc64_elf_target (ibfd->xvec))
+ {
+ p = &htab->dot_syms;
+ while ((eh = *p) != NULL)
+ {
+ *p = NULL;
+ if (!add_symbol_adjust (eh, info))
+ return FALSE;
+ p = &eh->u.next_dot_sym;
+ }
+ }
+
+ /* Clear the list for non-ppc64 input files. */
+ p = &htab->dot_syms;
+ while ((eh = *p) != NULL)
+ {
+ *p = NULL;
+ p = &eh->u.next_dot_sym;
+ }
/* We need to fix the undefs list for any syms we have twiddled to
undef_weak. */
@@ -4228,7 +4236,7 @@ ppc64_elf_check_directives (bfd *abfd, struct bfd_link_info *info)
bfd_link_repair_undef_list (&htab->elf.root);
htab->twiddled_syms = 0;
}
- return data.ok;
+ return TRUE;
}
static bfd_boolean
@@ -6103,13 +6111,13 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
if (adjust == -1)
{
/* This entry has been deleted. */
- asection *dsec = ppc64_elf_tdata (sym_sec->owner)->u.deleted_section;
+ asection *dsec = ppc64_elf_tdata (sym_sec->owner)->deleted_section;
if (dsec == NULL)
{
for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
if (elf_discarded_section (dsec))
{
- ppc64_elf_tdata (sym_sec->owner)->u.deleted_section = dsec;
+ ppc64_elf_tdata (sym_sec->owner)->deleted_section = dsec;
break;
}
}