* 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.
This commit is contained in:
parent
2f23e1502e
commit
b3fac117e3
|
@ -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>
|
2006-11-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* libbfd-in.h (_bfd_clear_contents): New prototype.
|
* libbfd-in.h (_bfd_clear_contents): New prototype.
|
||||||
|
|
160
bfd/elf64-ppc.c
160
bfd/elf64-ppc.c
|
@ -2377,14 +2377,9 @@ struct ppc64_elf_obj_tdata
|
||||||
asection *got;
|
asection *got;
|
||||||
asection *relgot;
|
asection *relgot;
|
||||||
|
|
||||||
union {
|
/* Used during garbage collection. We attach global symbols defined
|
||||||
/* Used during garbage collection. We attach global symbols defined
|
on removed .opd entries to this section so that the sym is removed. */
|
||||||
on removed .opd entries to this section so that the sym is removed. */
|
asection *deleted_section;
|
||||||
asection *deleted_section;
|
|
||||||
|
|
||||||
/* Used when adding symbols. */
|
|
||||||
bfd_boolean has_dotsym;
|
|
||||||
} u;
|
|
||||||
|
|
||||||
/* TLS local dynamic got entry handling. Suppose for multiple GOT
|
/* TLS local dynamic got entry handling. Suppose for multiple GOT
|
||||||
sections means we potentially need one of these for each input bfd. */
|
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;
|
struct elf_link_hash_entry elf;
|
||||||
|
|
||||||
/* A pointer to the most recently used stub hash entry against this
|
union {
|
||||||
symbol. */
|
/* A pointer to the most recently used stub hash entry against this
|
||||||
struct ppc_stub_hash_entry *stub_cache;
|
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. */
|
/* Track dynamic relocs copied for this symbol. */
|
||||||
struct ppc_dyn_relocs *dyn_relocs;
|
struct ppc_dyn_relocs *dyn_relocs;
|
||||||
|
@ -3321,6 +3321,9 @@ struct ppc_link_hash_table
|
||||||
/* Highest output section index. */
|
/* Highest output section index. */
|
||||||
int top_index;
|
int top_index;
|
||||||
|
|
||||||
|
/* Used when adding symbols. */
|
||||||
|
struct ppc_link_hash_entry *dot_syms;
|
||||||
|
|
||||||
/* List of input sections for each output section. */
|
/* List of input sections for each output section. */
|
||||||
asection **input_list;
|
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;
|
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)
|
(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;
|
return entry;
|
||||||
|
@ -3625,11 +3653,11 @@ ppc_get_stub_entry (const asection *input_section,
|
||||||
distinguish between them. */
|
distinguish between them. */
|
||||||
id_sec = htab->stub_group[input_section->id].link_sec;
|
id_sec = htab->stub_group[input_section->id].link_sec;
|
||||||
|
|
||||||
if (h != NULL && h->stub_cache != NULL
|
if (h != NULL && h->u.stub_cache != NULL
|
||||||
&& h->stub_cache->h == h
|
&& h->u.stub_cache->h == h
|
||||||
&& h->stub_cache->id_sec == id_sec)
|
&& h->u.stub_cache->id_sec == id_sec)
|
||||||
{
|
{
|
||||||
stub_entry = h->stub_cache;
|
stub_entry = h->u.stub_cache;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3642,7 +3670,7 @@ ppc_get_stub_entry (const asection *input_section,
|
||||||
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
|
stub_entry = ppc_stub_hash_lookup (&htab->stub_hash_table,
|
||||||
stub_name, FALSE, FALSE);
|
stub_name, FALSE, FALSE);
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
h->stub_cache = stub_entry;
|
h->u.stub_cache = stub_entry;
|
||||||
|
|
||||||
free (stub_name);
|
free (stub_name);
|
||||||
}
|
}
|
||||||
|
@ -4051,29 +4079,14 @@ make_fdh (struct bfd_link_info *info,
|
||||||
return fdh;
|
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
|
/* Fix function descriptor symbols defined in .opd sections to be
|
||||||
function type. */
|
function type. */
|
||||||
|
|
||||||
static bfd_boolean
|
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,
|
struct bfd_link_info *info ATTRIBUTE_UNUSED,
|
||||||
Elf_Internal_Sym *isym,
|
Elf_Internal_Sym *isym,
|
||||||
const char **name,
|
const char **name ATTRIBUTE_UNUSED,
|
||||||
flagword *flags ATTRIBUTE_UNUSED,
|
flagword *flags ATTRIBUTE_UNUSED,
|
||||||
asection **sec,
|
asection **sec,
|
||||||
bfd_vma *value ATTRIBUTE_UNUSED)
|
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)
|
&& strcmp (bfd_get_section_name (ibfd, *sec), ".opd") == 0)
|
||||||
isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4136,35 +4143,25 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
|
||||||
most restrictive visibility of the function descriptor and the
|
most restrictive visibility of the function descriptor and the
|
||||||
function entry symbol is used. */
|
function entry symbol is used. */
|
||||||
|
|
||||||
struct add_symbol_adjust_data
|
|
||||||
{
|
|
||||||
struct bfd_link_info *info;
|
|
||||||
bfd_boolean ok;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bfd_boolean
|
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_table *htab;
|
||||||
struct ppc_link_hash_entry *eh;
|
|
||||||
struct ppc_link_hash_entry *fdh;
|
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;
|
return TRUE;
|
||||||
|
|
||||||
if (h->root.type == bfd_link_hash_warning)
|
if (eh->elf.root.type == bfd_link_hash_warning)
|
||||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
eh = (struct ppc_link_hash_entry *) eh->elf.root.u.i.link;
|
||||||
|
|
||||||
if (h->root.root.string[0] != '.')
|
if (eh->elf.root.root.string[0] != '.')
|
||||||
return TRUE;
|
abort ();
|
||||||
|
|
||||||
data = inf;
|
htab = ppc_hash_table (info);
|
||||||
htab = ppc_hash_table (data->info);
|
|
||||||
eh = (struct ppc_link_hash_entry *) h;
|
|
||||||
fdh = get_fdh (eh, htab);
|
fdh = get_fdh (eh, htab);
|
||||||
if (fdh == NULL
|
if (fdh == NULL
|
||||||
&& !data->info->relocatable
|
&& !info->relocatable
|
||||||
&& (eh->elf.root.type == bfd_link_hash_undefined
|
&& (eh->elf.root.type == bfd_link_hash_undefined
|
||||||
|| eh->elf.root.type == bfd_link_hash_undefweak)
|
|| eh->elf.root.type == bfd_link_hash_undefweak)
|
||||||
&& eh->elf.ref_regular)
|
&& 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
|
/* Make an undefweak function descriptor sym, which is enough to
|
||||||
pull in an --as-needed shared lib, but won't cause link
|
pull in an --as-needed shared lib, but won't cause link
|
||||||
errors. Archives are handled elsewhere. */
|
errors. Archives are handled elsewhere. */
|
||||||
fdh = make_fdh (data->info, eh);
|
fdh = make_fdh (info, eh);
|
||||||
if (fdh == NULL)
|
if (fdh == NULL)
|
||||||
data->ok = FALSE;
|
return FALSE;
|
||||||
else
|
else
|
||||||
fdh->elf.ref_regular = 1;
|
fdh->elf.ref_regular = 1;
|
||||||
}
|
}
|
||||||
|
@ -4200,26 +4197,37 @@ add_symbol_adjust (struct elf_link_hash_entry *h, void *inf)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Process list of dot-symbols we made in link_hash_newfunc. */
|
||||||
|
|
||||||
static bfd_boolean
|
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 ppc_link_hash_table *htab;
|
||||||
struct add_symbol_adjust_data data;
|
struct ppc_link_hash_entry **p, *eh;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
htab = ppc_hash_table (info);
|
htab = ppc_hash_table (info);
|
||||||
if (!is_ppc64_elf_target (htab->elf.root.creator))
|
if (!is_ppc64_elf_target (htab->elf.root.creator))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
data.info = info;
|
if (is_ppc64_elf_target (ibfd->xvec))
|
||||||
data.ok = TRUE;
|
{
|
||||||
elf_link_hash_traverse (&htab->elf, add_symbol_adjust, &data);
|
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
|
/* We need to fix the undefs list for any syms we have twiddled to
|
||||||
undef_weak. */
|
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);
|
bfd_link_repair_undef_list (&htab->elf.root);
|
||||||
htab->twiddled_syms = 0;
|
htab->twiddled_syms = 0;
|
||||||
}
|
}
|
||||||
return data.ok;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_boolean
|
static bfd_boolean
|
||||||
|
@ -6103,13 +6111,13 @@ adjust_opd_syms (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
|
||||||
if (adjust == -1)
|
if (adjust == -1)
|
||||||
{
|
{
|
||||||
/* This entry has been deleted. */
|
/* 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)
|
if (dsec == NULL)
|
||||||
{
|
{
|
||||||
for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
|
for (dsec = sym_sec->owner->sections; dsec; dsec = dsec->next)
|
||||||
if (elf_discarded_section (dsec))
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue