X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Flinker.c;h=d3ef9a43a5bca8096221870248daf58007c6ef78;hb=9417cd2f8cd6a3404e214eccbdf9982536ae8d0a;hp=5868b955d1379d47a4422ac7733ae05f416fa67e;hpb=11f25ea6caba4354a6c58653e92e125313d5a659;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/linker.c b/bfd/linker.c index 5868b955d1..d3ef9a43a5 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1,13 +1,14 @@ /* linker.c -- BFD linker routines Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 + Free Software Foundation, Inc. Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support This file is part of BFD, the Binary File Descriptor library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,10 +18,11 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "bfdlink.h" #include "genlink.h" @@ -149,9 +151,9 @@ SUBSUBSECTION Sometimes the <<_bfd_link_add_symbols>> function must store some information in the hash table entry to be used by the - <<_bfd_final_link>> function. In such a case the <> - field of the hash table must be checked to make sure that the - hash table was created by an object file of the same format. + <<_bfd_final_link>> function. In such a case the output bfd + xvec must be checked to make sure that the hash table was + created by an object file of the same format. The <<_bfd_final_link>> routine must be prepared to handle a hash entry without any extra information added by the @@ -163,7 +165,7 @@ SUBSUBSECTION initialization function. See <> for an example of how to - check the <> field before saving information (in this + check the output bfd before saving information (in this case, the ECOFF external symbol debugging information) in a hash table entry. @@ -221,7 +223,10 @@ SUBSUBSECTION archive and decide which elements of the archive should be included in the link. For each such element it must call the <> linker callback, and it must add the - symbols from the object file to the linker hash table. + symbols from the object file to the linker hash table. (The + callback may in fact indicate that a replacement BFD should be + used, in which case the symbols from that BFD should be added + to the linker hash table instead.) @findex _bfd_generic_link_add_archive_symbols In most cases the work of looking through the symbols in the @@ -241,9 +246,13 @@ SUBSUBSECTION element should be included in the link. If the element is to be included, the <> linker callback routine must be called with the element as an argument, and - the elements symbols must be added to the linker hash table + the element's symbols must be added to the linker hash table just as though the element had itself been passed to the - <<_bfd_link_add_symbols>> function. + <<_bfd_link_add_symbols>> function. The <> + callback has the option to indicate that it would like to + replace the element archive with a substitute BFD, in which + case it is the symbols of that substitute BFD that must be + added to the linker hash table instead. When the a.out <<_bfd_link_add_symbols>> function receives an archive, it calls <<_bfd_generic_link_add_archive_symbols>> @@ -255,7 +264,8 @@ SUBSUBSECTION symbol) it calls the <> callback and then <> calls <> to actually add the symbols to the - linker hash table. + linker hash table - possibly those of a substitute BFD, if the + <> callback avails itself of that option. The ECOFF back end is unusual in that it does not normally call <<_bfd_generic_link_add_archive_symbols>>, because ECOFF @@ -309,7 +319,7 @@ SUBSUBSECTION of the <> structure. Each section in the output file will have a list of - <> structures attached to the <> + <> structures attached to the <> field (the <> structure is defined in <>). These structures describe how to create the contents of the output section in terms of the contents of @@ -442,7 +452,8 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry, 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; } @@ -454,8 +465,8 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry; /* Initialize the local fields. */ - h->type = bfd_link_hash_new; - h->u.undef.next = NULL; + memset ((char *) &h->root + sizeof (h->root), 0, + sizeof (*h) - sizeof (h->root)); } return entry; @@ -467,17 +478,17 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry, bfd_boolean _bfd_link_hash_table_init (struct bfd_link_hash_table *table, - bfd *abfd, + bfd *abfd ATTRIBUTE_UNUSED, struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *, struct bfd_hash_table *, - const char *)) + const char *), + unsigned int entsize) { - table->creator = abfd->xvec; table->undefs = NULL; table->undefs_tail = NULL; table->type = bfd_link_generic_hash_table; - return bfd_hash_table_init (&table->table, newfunc); + return bfd_hash_table_init (&table->table, newfunc, entsize); } /* Look up a symbol in a link hash table. If follow is TRUE, we @@ -544,7 +555,7 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, 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; @@ -559,11 +570,11 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, #undef WRAP -#undef REAL +#undef REAL #define REAL "__real_" if (*l == '_' - && strncmp (l, REAL, sizeof REAL - 1) == 0 + && CONST_STRNEQ (l, REAL) && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1, FALSE, FALSE) != NULL) { @@ -575,7 +586,7 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, 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; @@ -593,21 +604,32 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, return bfd_link_hash_lookup (info->hash, string, create, copy, follow); } -/* Traverse a generic link hash table. The only reason this is not a - macro is to do better type checking. This code presumes that an - argument passed as a struct bfd_hash_entry * may be caught as a - struct bfd_link_hash_entry * with no explicit cast required on the - call. */ +/* Traverse a generic link hash table. Differs from bfd_hash_traverse + in the treatment of warning symbols. When warning symbols are + created they replace the real symbol, so you don't get to see the + real symbol in a bfd_hash_travere. This traversal calls func with + the real symbol. */ void bfd_link_hash_traverse - (struct bfd_link_hash_table *table, + (struct bfd_link_hash_table *htab, bfd_boolean (*func) (struct bfd_link_hash_entry *, void *), void *info) { - bfd_hash_traverse (&table->table, - (bfd_boolean (*) (struct bfd_hash_entry *, void *)) func, - info); + unsigned int i; + + htab->table.frozen = 1; + for (i = 0; i < htab->table.size; i++) + { + struct bfd_link_hash_entry *p; + + p = (struct bfd_link_hash_entry *) htab->table.table[i]; + for (; p != NULL; p = (struct bfd_link_hash_entry *) p->root.next) + if (!(*func) (p->type == bfd_link_hash_warning ? p->u.i.link : p, info)) + goto out; + } + out: + htab->table.frozen = 0; } /* Add a symbol to the linker hash table undefs list. */ @@ -674,7 +696,7 @@ _bfd_generic_link_hash_newfunc (struct bfd_hash_entry *entry, 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; @@ -703,11 +725,12 @@ _bfd_generic_link_hash_table_create (bfd *abfd) 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, - _bfd_generic_link_hash_newfunc)) + _bfd_generic_link_hash_newfunc, + sizeof (struct generic_link_hash_entry))) { free (ret); return NULL; @@ -732,8 +755,8 @@ _bfd_generic_link_hash_table_free (struct bfd_link_hash_table *hash) the hash table pointing to different instances of the symbol structure. */ -static bfd_boolean -generic_link_read_symbols (bfd *abfd) +bfd_boolean +bfd_generic_link_read_symbols (bfd *abfd) { if (bfd_get_outsymbols (abfd) == NULL) { @@ -743,7 +766,8 @@ generic_link_read_symbols (bfd *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)); @@ -786,10 +810,22 @@ void _bfd_generic_link_just_syms (asection *sec, struct bfd_link_info *info ATTRIBUTE_UNUSED) { + sec->sec_info_type = SEC_INFO_TYPE_JUST_SYMS; sec->output_section = bfd_abs_section_ptr; 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 @@ -829,7 +865,7 @@ generic_link_add_object_symbols (bfd *abfd, bfd_size_type symcount; struct bfd_symbol **outsyms; - if (! generic_link_read_symbols (abfd)) + if (!bfd_generic_link_read_symbols (abfd)) return FALSE; symcount = _bfd_generic_link_get_symcount (abfd); outsyms = _bfd_generic_link_get_symbols (abfd); @@ -875,7 +911,8 @@ archive_hash_newfunc (struct bfd_hash_entry *entry, /* 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; @@ -899,9 +936,10 @@ archive_hash_table_init (struct archive_hash_table *table, struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *, struct bfd_hash_table *, - const char *)) + const char *), + unsigned int entsize) { - return bfd_hash_table_init (&table->table, newfunc); + return bfd_hash_table_init (&table->table, newfunc, entsize); } /* Look up an entry in an archive hash table. */ @@ -937,8 +975,10 @@ archive_hash_table_init included. CHECKFN should set *PNEEDED to TRUE if the object file should be included, and must also call the bfd_link_info add_archive_element callback function and handle adding the symbols - to the global hash table. CHECKFN should only return FALSE if some - sort of error occurs. + to the global hash table. CHECKFN must notice if the callback + indicates a substitute BFD, and arrange to add those symbols instead + if it does so. CHECKFN should only return FALSE if some sort of + error occurs. For some formats, such as a.out, it is possible to look through an object file but not actually include it in the link. The @@ -979,7 +1019,8 @@ _bfd_generic_link_add_archive_symbols /* In order to quickly determine whether an symbol is defined in this archive, we build a hash table of the symbols. */ - if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc)) + if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc, + sizeof (struct archive_hash_entry))) return FALSE; for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++) { @@ -1044,7 +1085,7 @@ _bfd_generic_link_add_archive_symbols 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; @@ -1157,7 +1198,7 @@ generic_link_check_archive_element (bfd *abfd, *pneeded = FALSE; - if (! generic_link_read_symbols (abfd)) + if (!bfd_generic_link_read_symbols (abfd)) return FALSE; pp = _bfd_generic_link_get_symbols (abfd); @@ -1192,10 +1233,17 @@ generic_link_check_archive_element (bfd *abfd, { bfd_size_type symcount; asymbol **symbols; + bfd *oldbfd = abfd; /* This object file defines this symbol, so pull it in. */ - if (! (*info->callbacks->add_archive_element) (info, abfd, - bfd_asymbol_name (p))) + if (!(*info->callbacks + ->add_archive_element) (info, abfd, bfd_asymbol_name (p), + &abfd)) + return FALSE; + /* Potentially, the add_archive_element hook may have set a + substitute BFD for us. */ + if (abfd != oldbfd + && !bfd_generic_link_read_symbols (abfd)) return FALSE; symcount = _bfd_generic_link_get_symcount (abfd); symbols = _bfd_generic_link_get_symbols (abfd); @@ -1220,9 +1268,13 @@ generic_link_check_archive_element (bfd *abfd, /* This symbol was created as undefined from outside BFD. We assume that we should link in the object file. This is for the -u option in the linker. */ - if (! (*info->callbacks->add_archive_element) - (info, abfd, bfd_asymbol_name (p))) + if (!(*info->callbacks + ->add_archive_element) (info, abfd, bfd_asymbol_name (p), + &abfd)) return FALSE; + /* Potentially, the add_archive_element hook may have set a + substitute BFD for us. But no symbols are going to get + registered by anything we're returning to from here. */ *pneeded = TRUE; return TRUE; } @@ -1235,7 +1287,7 @@ generic_link_check_archive_element (bfd *abfd, 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) @@ -1254,7 +1306,7 @@ generic_link_check_archive_element (bfd *abfd, else h->u.c.p->section = bfd_make_section_old_way (symbfd, p->section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else { @@ -1308,7 +1360,7 @@ generic_link_add_symbol_list (bfd *abfd, struct generic_link_hash_entry *h; struct bfd_link_hash_entry *bh; - name = bfd_asymbol_name (p); + string = name = bfd_asymbol_name (p); if (((p->flags & BSF_INDIRECT) != 0 || bfd_is_ind_section (p->section)) && pp + 1 < ppend) @@ -1321,12 +1373,9 @@ generic_link_add_symbol_list (bfd *abfd, { /* The name of P is actually the warning string, and the next symbol is the one to warn about. */ - string = name; pp++; name = bfd_asymbol_name (*pp); } - else - string = NULL; bh = NULL; if (! (_bfd_generic_link_add_one_symbol @@ -1354,7 +1403,7 @@ generic_link_add_symbol_list (bfd *abfd, hash table other than the generic hash table, so we only do this if we are certain that the hash table is a generic one. */ - if (info->hash->creator == abfd->xvec) + if (info->output_bfd->xvec == abfd->xvec) { if (h->sym == NULL || (! bfd_is_und_section (bfd_get_section (p)) @@ -1529,6 +1578,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, struct bfd_link_hash_entry *h; bfd_boolean cycle; + BFD_ASSERT (section != NULL); + if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) row = INDR_ROW; @@ -1570,8 +1621,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) { - if (! (*info->callbacks->notice) (info, h->root.string, abfd, section, - value)) + if (! (*info->callbacks->notice) (info, h, + abfd, section, value, flags, string)) return FALSE; } @@ -1604,7 +1655,6 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Make a new weak undefined symbol. */ h->type = bfd_link_hash_undefweak; h->u.undef.abfd = abfd; - h->u.undef.weak = abfd; break; case CDEF: @@ -1612,9 +1662,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, previously common. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_defined, 0))) + (info, h, abfd, bfd_link_hash_defined, 0))) return FALSE; /* Fall through. */ case DEF: @@ -1653,8 +1701,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, s = name + 1; while (*s == '_') ++s; - if (s[0] == 'G' - && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0) + if (s[0] == 'G' && CONST_STRNEQ (s, CONS_PREFIX)) { char c; @@ -1688,7 +1735,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, 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) @@ -1720,13 +1767,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, if (section == bfd_com_section_ptr) { h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON"); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else if (section->owner != abfd) { h->u.c.p->section = bfd_make_section_old_way (abfd, section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else h->u.c.p->section = section; @@ -1744,9 +1791,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, two sizes, and use the section required by the larger symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_common, value))) + (info, h, abfd, bfd_link_hash_common, value))) return FALSE; if (value > h->u.c.size) { @@ -1769,13 +1814,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, { h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON"); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else if (section->owner != abfd) { h->u.c.p->section = bfd_make_section_old_way (abfd, section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else h->u.c.p->section = section; @@ -1783,23 +1828,11 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, break; case CREF: - { - bfd *obfd; - - /* We have found a common definition for a symbol which - was already defined. FIXME: It would nice if we could - report the BFD which defined an indirect symbol, but we - don't have anywhere to store the information. */ - if (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak) - obfd = h->u.def.section->owner; - else - obfd = NULL; - if (! ((*info->callbacks->multiple_common) - (info, h->root.string, obfd, h->type, 0, - abfd, bfd_link_hash_common, value))) - return FALSE; - } + /* We have found a common definition for a symbol which + was already defined. */ + if (! ((*info->callbacks->multiple_common) + (info, h, abfd, bfd_link_hash_common, value))) + return FALSE; break; case MIND: @@ -1810,47 +1843,16 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Fall through. */ case MDEF: /* Handle a multiple definition. */ - if (!info->allow_multiple_definition) - { - asection *msec = NULL; - bfd_vma mval = 0; - - switch (h->type) - { - case bfd_link_hash_defined: - msec = h->u.def.section; - mval = h->u.def.value; - break; - case bfd_link_hash_indirect: - msec = bfd_ind_section_ptr; - mval = 0; - break; - default: - abort (); - } - - /* Ignore a redefinition of an absolute symbol to the - same value; it's harmless. */ - if (h->type == bfd_link_hash_defined - && bfd_is_abs_section (msec) - && bfd_is_abs_section (section) - && value == mval) - break; - - if (! ((*info->callbacks->multiple_definition) - (info, h->root.string, msec->owner, msec, mval, - abfd, section, value))) - return FALSE; - } + if (! ((*info->callbacks->multiple_definition) + (info, h, abfd, section, value))) + return FALSE; break; case CIND: /* Create an indirect symbol from an existing common symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_indirect, 0))) + (info, h, abfd, bfd_link_hash_indirect, 0))) return FALSE; /* Fall through. */ case IND: @@ -1969,7 +1971,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, 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); @@ -2007,7 +2009,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) /* Mark all sections which will be included in the output file. */ for (o = abfd->sections; o != NULL; o = o->next) - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) if (p->type == bfd_indirect_link_order) p->u.indirect.section->linker_mark = TRUE; @@ -2036,7 +2038,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) for (o = abfd->sections; o != NULL; o = o->next) { o->reloc_count = 0; - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { if (p->type == bfd_section_reloc_link_order || p->type == bfd_symbol_reloc_link_order) @@ -2056,7 +2058,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) 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); @@ -2078,7 +2080,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) 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; @@ -2092,7 +2094,7 @@ _bfd_generic_final_link (bfd *abfd, struct bfd_link_info *info) /* Handle all the link order information for the sections. */ for (o = abfd->sections; o != NULL; o = o->next) { - for (p = o->link_order_head; p != NULL; p = p->next) + for (p = o->map_head.link_order; p != NULL; p = p->next) { switch (p->type) { @@ -2132,7 +2134,7 @@ generic_add_output_symbol (bfd *output_bfd, size_t *psymalloc, asymbol *sym) *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; @@ -2156,7 +2158,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, asymbol **sym_ptr; asymbol **sym_end; - if (! generic_link_read_symbols (input_bfd)) + if (!bfd_generic_link_read_symbols (input_bfd)) return FALSE; /* Create a filename symbol if we are supposed to. */ @@ -2209,7 +2211,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, || 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 @@ -2239,7 +2241,7 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, this routine will be called with a hash table other than a generic hash table, so we double check that. */ - if (info->hash->creator == input_bfd->xvec) + if (info->output_bfd->xvec == input_bfd->xvec) { if (h->sym != NULL) *sym_ptr = sym = h->sym; @@ -2357,16 +2359,21 @@ _bfd_generic_link_output_symbols (bfd *output_bfd, else output = FALSE; } + else if (sym->flags == 0 + && (sym->section->owner->flags & BFD_PLUGIN) != 0) + /* LTO doesn't set symbol information. We get here with the + generic linker for a symbol that was "common" but no longer + needs to be global. */ + output = FALSE; else abort (); /* If this symbol is in a section which is not being included - in the output file, then we don't want to output the symbol. - - Gross. .bss and similar sections won't have the linker_mark - field set. */ - if ((sym->section->flags & SEC_HAS_CONTENTS) != 0 - && ! sym->section->linker_mark) + in the output file, then we don't want to output the + symbol. */ + if (!bfd_is_abs_section (sym->section) + && bfd_section_removed_from_list (output_bfd, + sym->section->output_section)) output = FALSE; if (output) @@ -2449,12 +2456,10 @@ bfd_boolean _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) - h = (struct generic_link_hash_entry *) h->root.u.i.link; - if (h->written) return TRUE; @@ -2506,7 +2511,7 @@ _bfd_generic_reloc_link_order (bfd *abfd, if (sec->orelocation == NULL) abort (); - r = bfd_alloc (abfd, sizeof (arelent)); + r = (arelent *) bfd_alloc (abfd, sizeof (arelent)); if (r == NULL) return FALSE; @@ -2554,7 +2559,7 @@ _bfd_generic_reloc_link_order (bfd *abfd, 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, @@ -2602,21 +2607,21 @@ struct bfd_link_order * 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->link_order_tail != NULL) - section->link_order_tail->next = new; + if (section->map_tail.link_order != NULL) + section->map_tail.link_order->next = new_lo; else - section->link_order_head = new; - section->link_order_tail = 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 @@ -2666,10 +2671,17 @@ default_data_link_order (bfd *abfd, fill = link_order->u.data.contents; fill_size = link_order->u.data.size; - if (fill_size != 0 && fill_size < size) + if (fill_size == 0) + { + fill = abfd->arch_info->fill (size, bfd_big_endian (abfd), + (sec->flags & SEC_CODE) != 0); + if (fill == NULL) + return FALSE; + } + else if (fill_size < size) { bfd_byte *p; - fill = bfd_malloc (size); + fill = (bfd_byte *) bfd_malloc (size); if (fill == NULL) return FALSE; p = fill; @@ -2716,11 +2728,10 @@ default_indirect_link_order (bfd *output_bfd, BFD_ASSERT ((output_section->flags & SEC_HAS_CONTENTS) != 0); - if (link_order->size == 0) - return TRUE; - input_section = link_order->u.indirect.section; input_bfd = input_section->owner; + if (input_section->size == 0) + return TRUE; BFD_ASSERT (input_section->output_section == output_section); BFD_ASSERT (input_section->output_offset == link_order->offset); @@ -2751,7 +2762,7 @@ default_indirect_link_order (bfd *output_bfd, have retrieved them by this point, but we are being called by a specific linker, presumably because we are linking different types of object files together. */ - if (! generic_link_read_symbols (input_bfd)) + if (!bfd_generic_link_read_symbols (input_bfd)) return FALSE; /* Since we have been called by a specific linker, rather than @@ -2780,7 +2791,7 @@ default_indirect_link_order (bfd *output_bfd, /* 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), @@ -2795,23 +2806,41 @@ default_indirect_link_order (bfd *output_bfd, } } - /* Get and relocate the section contents. */ - sec_size = (input_section->rawsize > input_section->size - ? input_section->rawsize - : input_section->size); - contents = bfd_malloc (sec_size); - if (contents == NULL && sec_size != 0) - goto error_return; - new_contents = (bfd_get_relocated_section_contents - (output_bfd, info, link_order, contents, info->relocatable, - _bfd_generic_link_get_symbols (input_bfd))); - if (!new_contents) - goto error_return; + if ((output_section->flags & (SEC_GROUP | SEC_LINKER_CREATED)) == SEC_GROUP + && input_section->size != 0) + { + /* Group section contents are set by bfd_elf_set_group_contents. */ + if (!output_bfd->output_has_begun) + { + /* FIXME: This hack ensures bfd_elf_set_group_contents is called. */ + if (!bfd_set_section_contents (output_bfd, output_section, "", 0, 1)) + goto error_return; + } + new_contents = output_section->contents; + BFD_ASSERT (new_contents != NULL); + BFD_ASSERT (input_section->output_offset == 0); + } + else + { + /* Get and relocate the section contents. */ + sec_size = (input_section->rawsize > input_section->size + ? input_section->rawsize + : input_section->size); + contents = (bfd_byte *) bfd_malloc (sec_size); + if (contents == NULL && sec_size != 0) + goto error_return; + new_contents = (bfd_get_relocated_section_contents + (output_bfd, info, link_order, contents, + info->relocatable, + _bfd_generic_link_get_symbols (input_bfd))); + if (!new_contents) + goto error_return; + } /* Output the section contents. */ - loc = link_order->offset * bfd_octets_per_byte (output_bfd); + loc = input_section->output_offset * bfd_octets_per_byte (output_bfd); if (! bfd_set_section_contents (output_bfd, output_section, - new_contents, loc, link_order->size)) + new_contents, loc, input_section->size)) goto error_return; if (contents != NULL) @@ -2873,14 +2902,16 @@ FUNCTION bfd_section_already_linked SYNOPSIS - void bfd_section_already_linked (bfd *abfd, asection *sec); + bfd_boolean bfd_section_already_linked (bfd *abfd, + asection *sec, + struct bfd_link_info *info); DESCRIPTION - Check if @var{sec} has been already linked during a reloceatable - or final link. + Check if @var{data} has been already linked during a reloceatable + or final link. Return TRUE if it has. -.#define bfd_section_already_linked(abfd, sec) \ -. BFD_SEND (abfd, _section_already_linked, (abfd, sec)) +.#define bfd_section_already_linked(abfd, sec, info) \ +. BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) . */ @@ -2920,7 +2951,7 @@ bfd_section_already_linked_table_lookup (const char *name) TRUE, FALSE)); } -void +bfd_boolean bfd_section_already_linked_table_insert (struct bfd_section_already_linked_hash_entry *already_linked_list, asection *sec) @@ -2929,10 +2960,14 @@ bfd_section_already_linked_table_insert /* 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; l->next = already_linked_list->entry; already_linked_list->entry = l; + return TRUE; } static struct bfd_hash_entry * @@ -2941,7 +2976,11 @@ already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED, 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; ret->entry = NULL; @@ -2952,7 +2991,9 @@ bfd_boolean bfd_section_already_linked_table_init (void) { return bfd_hash_table_init_n (&_bfd_section_already_linked_table, - already_linked_newfunc, 42); + already_linked_newfunc, + sizeof (struct bfd_section_already_linked_hash_entry), + 42); } void @@ -2961,19 +3002,109 @@ bfd_section_already_linked_table_free (void) bfd_hash_table_free (&_bfd_section_already_linked_table); } +/* Report warnings as appropriate for duplicate section SEC. + Return FALSE if we decide to keep SEC after all. */ + +bfd_boolean +_bfd_handle_already_linked (asection *sec, + struct bfd_section_already_linked *l, + struct bfd_link_info *info) +{ + switch (sec->flags & SEC_LINK_DUPLICATES) + { + default: + abort (); + + case SEC_LINK_DUPLICATES_DISCARD: + /* If we found an LTO IR match for this comdat group on + the first pass, replace it with the LTO output on the + second pass. We can't simply choose real object + files over IR because the first pass may contain a + mix of LTO and normal objects and we must keep the + first match, be it IR or real. */ + if (info->loading_lto_outputs + && (l->sec->owner->flags & BFD_PLUGIN) != 0) + { + l->sec = sec; + return FALSE; + } + break; + + case SEC_LINK_DUPLICATES_ONE_ONLY: + info->callbacks->einfo + (_("%B: ignoring duplicate section `%A'\n"), + sec->owner, sec); + break; + + case SEC_LINK_DUPLICATES_SAME_SIZE: + if ((l->sec->owner->flags & BFD_PLUGIN) != 0) + ; + else if (sec->size != l->sec->size) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different size\n"), + sec->owner, sec); + break; + + case SEC_LINK_DUPLICATES_SAME_CONTENTS: + if ((l->sec->owner->flags & BFD_PLUGIN) != 0) + ; + else if (sec->size != l->sec->size) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different size\n"), + sec->owner, sec); + else if (sec->size != 0) + { + bfd_byte *sec_contents, *l_sec_contents = NULL; + + if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents)) + info->callbacks->einfo + (_("%B: could not read contents of section `%A'\n"), + sec->owner, sec); + else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec, + &l_sec_contents)) + info->callbacks->einfo + (_("%B: could not read contents of section `%A'\n"), + l->sec->owner, l->sec); + else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different contents\n"), + sec->owner, sec); + + if (sec_contents) + free (sec_contents); + if (l_sec_contents) + free (l_sec_contents); + } + break; + } + + /* Set the output_section field so that lang_add_section + does not create a lang_input_section structure for this + section. Since there might be a symbol in the section + being discarded, we must retain a pointer to the section + which we are really going to use. */ + sec->output_section = bfd_abs_section_ptr; + sec->kept_section = l->sec; + return TRUE; +} + /* This is used on non-ELF inputs. */ -void -_bfd_generic_section_already_linked (bfd *abfd, asection *sec) +bfd_boolean +_bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + struct bfd_link_info *info) { - flagword flags; const char *name; struct bfd_section_already_linked *l; struct bfd_section_already_linked_hash_entry *already_linked_list; - flags = sec->flags; - if ((flags & SEC_LINK_ONCE) == 0) - return; + if ((sec->flags & SEC_LINK_ONCE) == 0) + return FALSE; + + /* The generic linker doesn't handle section groups. */ + if ((sec->flags & SEC_GROUP) != 0) + return FALSE; /* FIXME: When doing a relocatable link, we may have trouble copying relocations in other sections that refer to local symbols @@ -2992,78 +3123,309 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec) already_linked_list = bfd_section_already_linked_table_lookup (name); - for (l = already_linked_list->entry; l != NULL; l = l->next) + l = already_linked_list->entry; + if (l != NULL) { - bfd_boolean skip = FALSE; - struct coff_comdat_info *s_comdat - = bfd_coff_get_comdat_section (abfd, sec); - struct coff_comdat_info *l_comdat - = bfd_coff_get_comdat_section (l->sec->owner, l->sec); - - /* We may have 3 different sections on the list: group section, - comdat section and linkonce section. SEC may be a linkonce or - comdat section. We always ignore group section. For non-COFF - inputs, we also ignore comdat section. - - FIXME: Is that safe to match a linkonce section with a comdat - section for COFF inputs? */ - if ((l->sec->flags & SEC_GROUP) != 0) - skip = TRUE; - else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour) + /* The section has already been linked. See if we should + issue a warning. */ + return _bfd_handle_already_linked (sec, l, info); + } + + /* This is the first section with this name. Record it. */ + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) + info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return FALSE; +} + +/* Choose a neighbouring section to S in OBFD that will be output, or + the absolute section if ADDR is out of bounds of the neighbours. */ + +asection * +_bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr) +{ + asection *next, *prev, *best; + + /* Find preceding kept section. */ + for (prev = s->prev; prev != NULL; prev = prev->prev) + if ((prev->flags & SEC_EXCLUDE) == 0 + && !bfd_section_removed_from_list (obfd, prev)) + break; + + /* Find following kept section. Start at prev->next because + other sections may have been added after S was removed. */ + if (s->prev != NULL) + next = s->prev->next; + else + next = s->owner->sections; + for (; next != NULL; next = next->next) + if ((next->flags & SEC_EXCLUDE) == 0 + && !bfd_section_removed_from_list (obfd, next)) + break; + + /* Choose better of two sections, based on flags. The idea + is to choose a section that will be in the same segment + as S would have been if it was kept. */ + best = next; + if (prev == NULL) + { + if (next == NULL) + best = bfd_abs_section_ptr; + } + else if (next == NULL) + best = prev; + else if (((prev->flags ^ next->flags) + & (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_LOAD)) != 0) + { + if (((next->flags ^ s->flags) + & (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 NEXT and PREV. */ + || ((prev->flags & SEC_LOAD) != 0 + && (next->flags & SEC_LOAD) == 0)) + best = prev; + } + else if (((prev->flags ^ next->flags) & SEC_READONLY) != 0) + { + if (((next->flags ^ s->flags) & SEC_READONLY) != 0) + best = prev; + } + else if (((prev->flags ^ next->flags) & SEC_CODE) != 0) + { + if (((next->flags ^ s->flags) & SEC_CODE) != 0) + best = prev; + } + else + { + /* Flags we care about are the same. Prefer the following + section if that will result in a positive valued sym. */ + if (addr < next->vma) + best = prev; + } + + return best; +} + +/* Convert symbols in excluded output sections to use a kept section. */ + +static bfd_boolean +fix_syms (struct bfd_link_hash_entry *h, void *data) +{ + bfd *obfd = (bfd *) data; + + if (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak) + { + asection *s = h->u.def.section; + if (s != NULL + && s->output_section != NULL + && (s->output_section->flags & SEC_EXCLUDE) != 0 + && bfd_section_removed_from_list (obfd, s->output_section)) { - if (s_comdat != NULL - && l_comdat != NULL - && strcmp (s_comdat->name, l_comdat->name) != 0) - skip = TRUE; + asection *op; + + h->u.def.value += s->output_offset + s->output_section->vma; + op = _bfd_nearby_section (obfd, s->output_section, h->u.def.value); + h->u.def.value -= op->vma; + h->u.def.section = op; } - else if (l_comdat != NULL) - skip = TRUE; + } + + return TRUE; +} + +void +_bfd_fix_excluded_sec_syms (bfd *obfd, struct bfd_link_info *info) +{ + bfd_link_hash_traverse (info->hash, fix_syms, obfd); +} + +/* +FUNCTION + bfd_generic_define_common_symbol + +SYNOPSIS + bfd_boolean bfd_generic_define_common_symbol + (bfd *output_bfd, struct bfd_link_info *info, + struct bfd_link_hash_entry *h); + +DESCRIPTION + Convert common symbol @var{h} into a defined symbol. + Return TRUE on success and FALSE on failure. + +.#define bfd_define_common_symbol(output_bfd, info, h) \ +. BFD_SEND (output_bfd, _bfd_define_common_symbol, (output_bfd, info, h)) +. +*/ + +bfd_boolean +bfd_generic_define_common_symbol (bfd *output_bfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *h) +{ + unsigned int power_of_two; + bfd_vma alignment, size; + asection *section; + + BFD_ASSERT (h != NULL && h->type == bfd_link_hash_common); + + size = h->u.c.size; + power_of_two = h->u.c.p->alignment_power; + section = h->u.c.p->section; + + /* Increase the size of the section to align the common symbol. + The alignment must be a power of two. */ + alignment = bfd_octets_per_byte (output_bfd) << power_of_two; + BFD_ASSERT (alignment != 0 && (alignment & -alignment) == alignment); + section->size += alignment - 1; + section->size &= -alignment; + + /* Adjust the section's overall alignment if necessary. */ + if (power_of_two > section->alignment_power) + section->alignment_power = power_of_two; + + /* Change the symbol from common to defined. */ + h->type = bfd_link_hash_defined; + h->u.def.section = section; + h->u.def.value = section->size; + + /* Increase the size of the section. */ + section->size += size; + + /* Make sure the section is allocated in memory, and make sure that + it is no longer a common section. */ + section->flags |= SEC_ALLOC; + section->flags &= ~SEC_IS_COMMON; + return TRUE; +} - if (!skip) +/* +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) { - /* The section has already been linked. See if we should - issue a warning. */ - switch (flags & SEC_LINK_DUPLICATES) + struct bfd_elf_version_expr *d = NULL; + + while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL) { - default: - abort (); + 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; + } - case SEC_LINK_DUPLICATES_DISCARD: - break; + if (d != NULL) + break; + } - case SEC_LINK_DUPLICATES_ONE_ONLY: - (*_bfd_error_handler) - (_("%B: warning: ignoring duplicate section `%A'\n"), - abfd, sec); - break; + if (t->locals.list != NULL) + { + struct bfd_elf_version_expr *d = NULL; - case SEC_LINK_DUPLICATES_SAME_CONTENTS: - /* FIXME: We should really dig out the contents of both - sections and memcmp them. The COFF/PE spec says that - the Microsoft linker does not implement this - correctly, so I'm not going to bother doing it - either. */ - /* Fall through. */ - case SEC_LINK_DUPLICATES_SAME_SIZE: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: warning: duplicate section `%A' has different size\n"), - abfd, sec); - break; + 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; + } } - /* Set the output_section field so that lang_add_section - does not create a lang_input_section structure for this - section. Since there might be a symbol in the section - being discarded, we must retain a pointer to the section - which we are really going to use. */ - sec->output_section = bfd_abs_section_ptr; - sec->kept_section = l->sec; - - return; + if (d != NULL) + break; } } - /* This is the first section with this name. Record it. */ - bfd_section_already_linked_table_insert (already_linked_list, sec); + 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; +} + +/* +FUNCTION + bfd_hide_sym_by_version + +SYNOPSIS + bfd_boolean bfd_hide_sym_by_version + (struct bfd_elf_version_tree *verdefs, const char *sym_name); + +DESCRIPTION + Search an elf version script tree for symbol versioning + info for a given symbol. Return TRUE if the symbol is hidden. + +*/ + +bfd_boolean +bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs, + const char *sym_name) +{ + bfd_boolean hidden = FALSE; + bfd_find_version_for_sym (verdefs, sym_name, &hidden); + return hidden; }