/* linker.c -- BFD linker routines
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support
subclass. */
if (entry == NULL)
{
- entry = bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
+ entry = (struct bfd_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry));
if (entry == NULL)
return entry;
}
references to SYM with references to __wrap_SYM. */
amt = strlen (l) + sizeof WRAP + 1;
- n = bfd_malloc (amt);
+ n = (char *) bfd_malloc (amt);
if (n == NULL)
return NULL;
with references to SYM. */
amt = strlen (l + sizeof REAL - 1) + 2;
- n = bfd_malloc (amt);
+ n = (char *) bfd_malloc (amt);
if (n == NULL)
return NULL;
subclass. */
if (entry == NULL)
{
- entry =
+ entry = (struct bfd_hash_entry *)
bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry));
if (entry == NULL)
return entry;
struct generic_link_hash_table *ret;
bfd_size_type amt = sizeof (struct generic_link_hash_table);
- ret = bfd_malloc (amt);
+ ret = (struct generic_link_hash_table *) bfd_malloc (amt);
if (ret == NULL)
return NULL;
if (! _bfd_link_hash_table_init (&ret->root, abfd,
symsize = bfd_get_symtab_upper_bound (abfd);
if (symsize < 0)
return FALSE;
- bfd_get_outsymbols (abfd) = bfd_alloc (abfd, symsize);
+ bfd_get_outsymbols (abfd) = (struct bfd_symbol **) bfd_alloc (abfd,
+ symsize);
if (bfd_get_outsymbols (abfd) == NULL && symsize != 0)
return FALSE;
symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd));
sec->output_offset = sec->vma;
}
+/* Copy the type of a symbol assiciated with a linker hast table entry.
+ Override this so that symbols created in linker scripts get their
+ type from the RHS of the assignment.
+ The default implementation does nothing. */
+void
+_bfd_generic_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry * hdest ATTRIBUTE_UNUSED,
+ struct bfd_link_hash_entry * hsrc ATTRIBUTE_UNUSED)
+{
+}
+
/* Add symbols from an object file to the global hash table. */
static bfd_boolean
/* Allocate the structure if it has not already been allocated by a
subclass. */
if (ret == NULL)
- ret = bfd_hash_allocate (table, sizeof (struct archive_hash_entry));
+ ret = (struct archive_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct archive_hash_entry));
if (ret == NULL)
return NULL;
if (info->pei386_auto_import)
{
bfd_size_type amt = strlen (h->root.string) + 10;
- char *buf = bfd_malloc (amt);
+ char *buf = (char *) bfd_malloc (amt);
if (buf == NULL)
return FALSE;
attached to symbfd to ensure that it is in a BFD which
will be linked in. */
h->type = bfd_link_hash_common;
- h->u.c.p =
+ h->u.c.p = (struct bfd_link_hash_common_entry *)
bfd_hash_allocate (&info->hash->table,
sizeof (struct bfd_link_hash_common_entry));
if (h->u.c.p == NULL)
if (h->type == bfd_link_hash_new)
bfd_link_add_undef (info->hash, h);
h->type = bfd_link_hash_common;
- h->u.c.p =
+ h->u.c.p = (struct bfd_link_hash_common_entry *)
bfd_hash_allocate (&info->hash->table,
sizeof (struct bfd_link_hash_common_entry));
if (h->u.c.p == NULL)
char *w;
size_t len = strlen (string) + 1;
- w = bfd_hash_allocate (&info->hash->table, len);
+ w = (char *) bfd_hash_allocate (&info->hash->table, len);
if (w == NULL)
return FALSE;
memcpy (w, string, len);
input_section);
if (relsize < 0)
return FALSE;
- relocs = bfd_malloc (relsize);
+ relocs = (arelent **) bfd_malloc (relsize);
if (!relocs && relsize != 0)
return FALSE;
symbols = _bfd_generic_link_get_symbols (input_bfd);
amt = o->reloc_count;
amt *= sizeof (arelent *);
- o->orelocation = bfd_alloc (abfd, amt);
+ o->orelocation = (struct reloc_cache_entry **) bfd_alloc (abfd, amt);
if (!o->orelocation)
return FALSE;
o->flags |= SEC_RELOC;
*psymalloc *= 2;
amt = *psymalloc;
amt *= sizeof (asymbol *);
- newsyms = bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
+ newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), amt);
if (newsyms == NULL)
return FALSE;
bfd_get_outsymbols (output_bfd) = newsyms;
|| bfd_is_ind_section (bfd_get_section (sym)))
{
if (sym->udata.p != NULL)
- h = sym->udata.p;
+ h = (struct generic_link_hash_entry *) sym->udata.p;
else if ((sym->flags & BSF_CONSTRUCTOR) != 0)
{
/* This case normally means that the main linker code
_bfd_generic_link_write_global_symbol (struct generic_link_hash_entry *h,
void *data)
{
- struct generic_write_global_symbol_info *wginfo = data;
+ struct generic_write_global_symbol_info *wginfo =
+ (struct generic_write_global_symbol_info *) data;
asymbol *sym;
if (h->root.type == bfd_link_hash_warning)
if (sec->orelocation == NULL)
abort ();
- r = bfd_alloc (abfd, sizeof (arelent));
+ r = (arelent *) bfd_alloc (abfd, sizeof (arelent));
if (r == NULL)
return FALSE;
file_ptr loc;
size = bfd_get_reloc_size (r->howto);
- buf = bfd_zmalloc (size);
+ buf = (bfd_byte *) bfd_zmalloc (size);
if (buf == NULL)
return FALSE;
rstat = _bfd_relocate_contents (r->howto, abfd,
bfd_new_link_order (bfd *abfd, asection *section)
{
bfd_size_type amt = sizeof (struct bfd_link_order);
- struct bfd_link_order *new;
+ struct bfd_link_order *new_lo;
- new = bfd_zalloc (abfd, amt);
- if (!new)
+ new_lo = (struct bfd_link_order *) bfd_zalloc (abfd, amt);
+ if (!new_lo)
return NULL;
- new->type = bfd_undefined_link_order;
+ new_lo->type = bfd_undefined_link_order;
if (section->map_tail.link_order != NULL)
- section->map_tail.link_order->next = new;
+ section->map_tail.link_order->next = new_lo;
else
- section->map_head.link_order = new;
- section->map_tail.link_order = new;
+ section->map_head.link_order = new_lo;
+ section->map_tail.link_order = new_lo;
- return new;
+ return new_lo;
}
/* Default link order processing routine. Note that we can not handle
if (fill_size != 0 && fill_size < size)
{
bfd_byte *p;
- fill = bfd_malloc (size);
+ fill = (bfd_byte *) bfd_malloc (size);
if (fill == NULL)
return FALSE;
p = fill;
/* sym->udata may have been set by
generic_link_add_symbol_list. */
if (sym->udata.p != NULL)
- h = sym->udata.p;
+ h = (struct bfd_link_hash_entry *) sym->udata.p;
else if (bfd_is_und_section (bfd_get_section (sym)))
h = bfd_wrapped_link_hash_lookup (output_bfd, info,
bfd_asymbol_name (sym),
sec_size = (input_section->rawsize > input_section->size
? input_section->rawsize
: input_section->size);
- contents = bfd_malloc (sec_size);
+ contents = (bfd_byte *) bfd_malloc (sec_size);
if (contents == NULL && sec_size != 0)
goto error_return;
new_contents = (bfd_get_relocated_section_contents
/* Allocate the memory from the same obstack as the hash table is
kept in. */
- l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+ l = (struct bfd_section_already_linked *)
+ bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
if (l == NULL)
return FALSE;
l->sec = sec;
const char *string ATTRIBUTE_UNUSED)
{
struct bfd_section_already_linked_hash_entry *ret =
- bfd_hash_allocate (table, sizeof *ret);
+ (struct bfd_section_already_linked_hash_entry *)
+ bfd_hash_allocate (table, sizeof *ret);
if (ret == NULL)
return NULL;
else if (op == NULL)
op = op1;
else if (((op1->flags ^ op->flags)
- & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0)
+ & (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_LOAD)) != 0)
{
if (((op->flags ^ s->flags)
- & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0)
+ & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0
+ /* We prefer to choose a loaded section. Section S
+ doesn't have SEC_LOAD set (it being excluded, that
+ part of the flag processing didn't happen) so we
+ can't compare that flag to those of OP and OP1. */
+ || ((op1->flags & SEC_LOAD) != 0
+ && (op->flags & SEC_LOAD) == 0))
op = op1;
}
else if (((op1->flags ^ op->flags) & SEC_READONLY) != 0)
section->flags &= ~SEC_IS_COMMON;
return TRUE;
}
+
+/*
+FUNCTION
+ bfd_find_version_for_sym
+
+SYNOPSIS
+ struct bfd_elf_version_tree * bfd_find_version_for_sym
+ (struct bfd_elf_version_tree *verdefs,
+ const char *sym_name, bfd_boolean *hide);
+
+DESCRIPTION
+ Search an elf version script tree for symbol versioning
+ info and export / don't-export status for a given symbol.
+ Return non-NULL on success and NULL on failure; also sets
+ the output @samp{hide} boolean parameter.
+
+*/
+
+struct bfd_elf_version_tree *
+bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs,
+ const char *sym_name,
+ bfd_boolean *hide)
+{
+ struct bfd_elf_version_tree *t;
+ struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver;
+ struct bfd_elf_version_tree *star_local_ver, *star_global_ver;
+
+ local_ver = NULL;
+ global_ver = NULL;
+ star_local_ver = NULL;
+ star_global_ver = NULL;
+ exist_ver = NULL;
+ for (t = verdefs; t != NULL; t = t->next)
+ {
+ if (t->globals.list != NULL)
+ {
+ struct bfd_elf_version_expr *d = NULL;
+
+ while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL)
+ {
+ if (d->literal || strcmp (d->pattern, "*") != 0)
+ global_ver = t;
+ else
+ star_global_ver = t;
+ if (d->symver)
+ exist_ver = t;
+ d->script = 1;
+ /* If the match is a wildcard pattern, keep looking for
+ a more explicit, perhaps even local, match. */
+ if (d->literal)
+ break;
+ }
+
+ if (d != NULL)
+ break;
+ }
+
+ if (t->locals.list != NULL)
+ {
+ struct bfd_elf_version_expr *d = NULL;
+
+ while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL)
+ {
+ if (d->literal || strcmp (d->pattern, "*") != 0)
+ local_ver = t;
+ else
+ star_local_ver = t;
+ /* If the match is a wildcard pattern, keep looking for
+ a more explicit, perhaps even global, match. */
+ if (d->literal)
+ {
+ /* An exact match overrides a global wildcard. */
+ global_ver = NULL;
+ star_global_ver = NULL;
+ break;
+ }
+ }
+
+ if (d != NULL)
+ break;
+ }
+ }
+
+ if (global_ver == NULL && local_ver == NULL)
+ global_ver = star_global_ver;
+
+ if (global_ver != NULL)
+ {
+ /* If we already have a versioned symbol that matches the
+ node for this symbol, then we don't want to create a
+ duplicate from the unversioned symbol. Instead hide the
+ unversioned symbol. */
+ *hide = exist_ver == global_ver;
+ return global_ver;
+ }
+
+ if (local_ver == NULL)
+ local_ver = star_local_ver;
+
+ if (local_ver != NULL)
+ {
+ *hide = TRUE;
+ return local_ver;
+ }
+
+ return NULL;
+}