X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Flinker.c;h=edf96fe7efdf68d3f2a0f55aa6f0cd953fe70525;hb=3610d1317daaf338ec6ae4ae45bbfcd006ff03a8;hp=ef9469b28bcee5b7db85394726af75ce48f28442;hpb=e336470145cab9956a5e780edcc85f2471aadc36;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/linker.c b/bfd/linker.c index ef9469b28b..edf96fe7ef 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -1,5 +1,6 @@ /* linker.c -- BFD linker routines - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1993, 94, 95, 96, 97, 98, 1999 + 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. @@ -74,7 +75,7 @@ SUBSECTION @cindex target vector (_bfd_link_hash_table_create) The linker routines must create a hash table, which must be derived from <> described in - <>. @xref{Hash Tables} for information on how to + <>. @xref{Hash Tables}, for information on how to create a derived hash table. This entry point is called using the target vector of the linker output file. @@ -395,8 +396,7 @@ SUBSUBSECTION is used to further controls which local symbols are included in the output file. If the value is <>, then all local symbols which begin with a certain prefix are discarded; - this prefix is described by the <> and - <> fields of the <> structure. + this is controlled by the <> entry point. The a.out backend handles symbols by calling <> on each input BFD and then @@ -406,9 +406,6 @@ SUBSUBSECTION file at the end of <>. */ -static struct bfd_hash_entry *generic_link_hash_newfunc - PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, - const char *)); static boolean generic_link_read_symbols PARAMS ((bfd *)); static boolean generic_link_add_symbols @@ -424,6 +421,7 @@ static boolean generic_link_check_archive_element static boolean generic_link_add_symbol_list PARAMS ((bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **, boolean collect)); +static bfd *hash_entry_bfd PARAMS ((struct bfd_link_hash_entry *)); static void set_symbol_from_hash PARAMS ((asymbol *, struct bfd_link_hash_entry *)); static boolean generic_add_output_symbol @@ -455,10 +453,7 @@ _bfd_link_hash_newfunc (entry, table, string) ret = ((struct bfd_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry))); if (ret == (struct bfd_link_hash_entry *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } + return NULL; /* Call the allocation method of the superclass. */ ret = ((struct bfd_link_hash_entry *) @@ -518,6 +513,88 @@ bfd_link_hash_lookup (table, string, create, copy, follow) return ret; } +/* Look up a symbol in the main linker hash table if the symbol might + be wrapped. This should only be used for references to an + undefined symbol, not for definitions of a symbol. */ + +struct bfd_link_hash_entry * +bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow) + bfd *abfd; + struct bfd_link_info *info; + const char *string; + boolean create; + boolean copy; + boolean follow; +{ + if (info->wrap_hash != NULL) + { + const char *l; + + l = string; + if (*l == bfd_get_symbol_leading_char (abfd)) + ++l; + +#undef WRAP +#define WRAP "__wrap_" + + if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL) + { + char *n; + struct bfd_link_hash_entry *h; + + /* This symbol is being wrapped. We want to replace all + references to SYM with references to __wrap_SYM. */ + + n = (char *) bfd_malloc (strlen (l) + sizeof WRAP + 1); + if (n == NULL) + return NULL; + + /* Note that symbol_leading_char may be '\0'. */ + n[0] = bfd_get_symbol_leading_char (abfd); + n[1] = '\0'; + strcat (n, WRAP); + strcat (n, l); + h = bfd_link_hash_lookup (info->hash, n, create, true, follow); + free (n); + return h; + } + +#undef WRAP + +#undef REAL +#define REAL "__real_" + + if (*l == '_' + && strncmp (l, REAL, sizeof REAL - 1) == 0 + && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1, + false, false) != NULL) + { + char *n; + struct bfd_link_hash_entry *h; + + /* This is a reference to __real_SYM, where SYM is being + wrapped. We want to replace all references to __real_SYM + with references to SYM. */ + + n = (char *) bfd_malloc (strlen (l + sizeof REAL - 1) + 2); + if (n == NULL) + return NULL; + + /* Note that symbol_leading_char may be '\0'. */ + n[0] = bfd_get_symbol_leading_char (abfd); + n[1] = '\0'; + strcat (n, l + sizeof REAL - 1); + h = bfd_link_hash_lookup (info->hash, n, create, true, follow); + free (n); + return h; + } + +#undef REAL + } + + 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 @@ -553,8 +630,8 @@ bfd_link_add_undef (table, h) /* Routine to create an entry in an generic link hash table. */ -static struct bfd_hash_entry * -generic_link_hash_newfunc (entry, table, string) +struct bfd_hash_entry * +_bfd_generic_link_hash_newfunc (entry, table, string) struct bfd_hash_entry *entry; struct bfd_hash_table *table; const char *string; @@ -568,10 +645,7 @@ generic_link_hash_newfunc (entry, table, string) ret = ((struct generic_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry))); if (ret == (struct generic_link_hash_entry *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } + return NULL; /* Call the allocation method of the superclass. */ ret = ((struct generic_link_hash_entry *) @@ -599,12 +673,9 @@ _bfd_generic_link_hash_table_create (abfd) ret = ((struct generic_link_hash_table *) bfd_alloc (abfd, sizeof (struct generic_link_hash_table))); if (ret == NULL) - { - bfd_set_error (bfd_error_no_memory); - return (struct bfd_link_hash_table *) NULL; - } + return (struct bfd_link_hash_table *) NULL; if (! _bfd_link_hash_table_init (&ret->root, abfd, - generic_link_hash_newfunc)) + _bfd_generic_link_hash_newfunc)) { free (ret); return (struct bfd_link_hash_table *) NULL; @@ -623,7 +694,7 @@ static boolean generic_link_read_symbols (abfd) bfd *abfd; { - if (abfd->outsymbols == (asymbol **) NULL) + if (bfd_get_outsymbols (abfd) == (asymbol **) NULL) { long symsize; long symcount; @@ -631,16 +702,13 @@ generic_link_read_symbols (abfd) symsize = bfd_get_symtab_upper_bound (abfd); if (symsize < 0) return false; - abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize); - if (abfd->outsymbols == NULL && symsize != 0) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols); + bfd_get_outsymbols (abfd) = (asymbol **) bfd_alloc (abfd, symsize); + if (bfd_get_outsymbols (abfd) == NULL && symsize != 0) + return false; + symcount = bfd_canonicalize_symtab (abfd, bfd_get_outsymbols (abfd)); if (symcount < 0) return false; - abfd->symcount = symcount; + bfd_get_symcount (abfd) = symcount; } return true; @@ -770,10 +838,7 @@ archive_hash_newfunc (entry, table, string) ret = ((struct archive_hash_entry *) bfd_hash_allocate (table, sizeof (struct archive_hash_entry))); if (ret == (struct archive_hash_entry *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } + return NULL; /* Call the allocation method of the superclass. */ ret = ((struct archive_hash_entry *) @@ -1196,16 +1261,21 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect) struct generic_link_hash_entry *h; name = bfd_asymbol_name (p); - if ((p->flags & BSF_INDIRECT) != 0 - || bfd_is_ind_section (p->section)) - string = bfd_asymbol_name ((asymbol *) p->value); - else if ((p->flags & BSF_WARNING) != 0) + if (((p->flags & BSF_INDIRECT) != 0 + || bfd_is_ind_section (p->section)) + && pp + 1 < ppend) + { + pp++; + string = bfd_asymbol_name (*pp); + } + else if ((p->flags & BSF_WARNING) != 0 + && pp + 1 < ppend) { /* The name of P is actually the warning string, and the - value is actually a pointer to the symbol to warn - about. */ + next symbol is the one to warn about. */ string = name; - name = bfd_asymbol_name ((asymbol *) p->value); + pp++; + name = bfd_asymbol_name (*pp); } else string = NULL; @@ -1250,14 +1320,14 @@ generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect) if (bfd_is_com_section (bfd_get_section (p))) p->flags |= BSF_OLD_COMMON; } - - /* Store a back pointer from the symbol to the hash - table entry for the benefit of relaxation code until - it gets rewritten to not use asymbol structures. - Setting this is also used to check whether these - symbols were set up by the generic linker. */ - p->udata.p = (PTR) h; } + + /* Store a back pointer from the symbol to the hash + table entry for the benefit of relaxation code until + it gets rewritten to not use asymbol structures. + Setting this is also used to check whether these + symbols were set up by the generic linker. */ + p->udata.p = (PTR) h; } } @@ -1321,13 +1391,13 @@ enum link_action static const enum link_action link_action[8][8] = { /* current\prev new undef undefw def defw com indr warn */ - /* UNDEF_ROW */ {UND, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC }, + /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC }, /* UNDEFW_ROW */ {WEAK, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC }, /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE }, /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE }, - /* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, CREF, WARNC }, + /* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, REFC, WARNC }, /* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE }, - /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, CYCLE }, + /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, MWARN }, /* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE } }; @@ -1354,6 +1424,30 @@ static const enum link_action link_action[8][8] = Adding an entry to a set does not count as a reference to a set, and no warning is issued (SET_ROW/warn). */ +/* Return the BFD in which a hash entry has been defined, if known. */ + +static bfd * +hash_entry_bfd (h) + struct bfd_link_hash_entry *h; +{ + while (h->type == bfd_link_hash_warning) + h = h->u.i.link; + switch (h->type) + { + default: + return NULL; + case bfd_link_hash_undefined: + case bfd_link_hash_undefweak: + return h->u.undef.abfd; + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + return h->u.def.section->owner; + case bfd_link_hash_common: + return h->u.c.p->section->owner; + } + /*NOTREACHED*/ +} + /* Add a symbol to the global hash table. ABFD is the BFD the symbol comes from. NAME is the name of the symbol. @@ -1412,13 +1506,13 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, row = DEF_ROW; if (hashp != NULL && *hashp != NULL) - { - h = *hashp; - BFD_ASSERT (strcmp (h->root.string, name) == 0); - } + h = *hashp; else { - h = bfd_link_hash_lookup (info->hash, name, true, copy, false); + if (row == UNDEF_ROW || row == UNDEFW_ROW) + h = bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false); + else + h = bfd_link_hash_lookup (info->hash, name, true, copy, false); if (h == NULL) { if (hashp != NULL) @@ -1427,11 +1521,13 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, } } - if (info->notice_hash != (struct bfd_hash_table *) NULL - && (bfd_hash_lookup (info->notice_hash, name, false, false) - != (struct bfd_hash_entry *) NULL)) + if (info->notice_all + || (info->notice_hash != (struct bfd_hash_table *) NULL + && (bfd_hash_lookup (info->notice_hash, name, false, false) + != (struct bfd_hash_entry *) NULL))) { - if (! (*info->callbacks->notice) (info, name, abfd, section, value)) + if (! (*info->callbacks->notice) (info, h->root.string, abfd, section, + value)) return false; } @@ -1471,7 +1567,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, previously common. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, name, + (info, h->root.string, h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, abfd, bfd_link_hash_defined, (bfd_vma) 0))) return false; @@ -1479,7 +1575,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, case DEF: case DEFW: { - enum bfd_link_order_type oldtype; + enum bfd_link_hash_type oldtype; /* Define a symbol. */ oldtype = h->type; @@ -1534,7 +1630,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, if (! ((*info->callbacks->constructor) (info, c == 'I' ? true : false, - name, abfd, section, value))) + h->root.string, abfd, section, value))) return false; } } @@ -1605,7 +1701,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, two sizes. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, name, + (info, h->root.string, h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, abfd, bfd_link_hash_common, value))) return false; @@ -1638,7 +1734,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, else obfd = NULL; if (! ((*info->callbacks->multiple_common) - (info, name, obfd, h->type, (bfd_vma) 0, + (info, h->root.string, obfd, h->type, (bfd_vma) 0, abfd, bfd_link_hash_common, value))) return false; } @@ -1653,8 +1749,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, case MDEF: /* Handle a multiple definition. */ { - asection *msec; - bfd_vma mval; + asection *msec = NULL; + bfd_vma mval = 0; switch (h->type) { @@ -1679,8 +1775,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, break; if (! ((*info->callbacks->multiple_definition) - (info, name, msec->owner, msec, mval, abfd, section, - value))) + (info, h->root.string, msec->owner, msec, mval, abfd, + section, value))) return false; } break; @@ -1689,7 +1785,7 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, /* Create an indirect symbol from an existing common symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, name, + (info, h->root.string, h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, abfd, bfd_link_hash_indirect, (bfd_vma) 0))) return false; @@ -1701,8 +1797,8 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, /* STRING is the name of the symbol we want to indirect to. */ - inh = bfd_link_hash_lookup (info->hash, string, true, copy, - false); + inh = bfd_wrapped_link_hash_lookup (abfd, info, string, true, + copy, false); if (inh == (struct bfd_link_hash_entry *) NULL) return false; if (inh->type == bfd_link_hash_new) @@ -1737,7 +1833,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, /* Issue a warning and cycle. */ if (h->u.i.warning != NULL) { - if (! (*info->callbacks->warning) (info, h->u.i.warning)) + if (! (*info->callbacks->warning) (info, h->u.i.warning, + h->root.string, abfd, + (asection *) NULL, + (bfd_vma) 0)) return false; /* Only issue a warning once. */ h->u.i.warning = NULL; @@ -1759,7 +1858,9 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, case WARN: /* Issue a warning. */ - if (! (*info->callbacks->warning) (info, string)) + if (! (*info->callbacks->warning) (info, string, h->root.string, + hash_entry_bfd (h), + (asection *) NULL, (bfd_vma) 0)) return false; break; @@ -1771,7 +1872,10 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, ensure this. */ if (h->next != NULL || info->hash->undefs_tail == h) { - if (! (*info->callbacks->warning) (info, string)) + if (! (*info->callbacks->warning) (info, string, h->root.string, + hash_entry_bfd (h), + (asection *) NULL, + (bfd_vma) 0)) return false; break; } @@ -1783,27 +1887,33 @@ _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value, /* STRING is the warning to give. */ sub = ((struct bfd_link_hash_entry *) - bfd_hash_allocate (&info->hash->table, - sizeof (struct bfd_link_hash_entry))); - if (!sub) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + ((*info->hash->table.newfunc) + ((struct bfd_hash_entry *) NULL, &info->hash->table, + h->root.string))); + if (sub == NULL) + return false; *sub = *h; - h->type = bfd_link_hash_warning; - h->u.i.link = sub; + sub->type = bfd_link_hash_warning; + sub->u.i.link = h; if (! copy) - h->u.i.warning = string; + sub->u.i.warning = string; else { char *w; w = bfd_hash_allocate (&info->hash->table, strlen (string) + 1); + if (w == NULL) + return false; strcpy (w, string); - h->u.i.warning = w; + sub->u.i.warning = w; } + + bfd_hash_replace (&info->hash->table, + (struct bfd_hash_entry *) h, + (struct bfd_hash_entry *) sub); + if (hashp != NULL) + *hashp = sub; } break; } @@ -1826,10 +1936,16 @@ _bfd_generic_final_link (abfd, info) size_t outsymalloc; struct generic_write_global_symbol_info wginfo; - abfd->outsymbols = (asymbol **) NULL; - abfd->symcount = 0; + bfd_get_outsymbols (abfd) = (asymbol **) NULL; + bfd_get_symcount (abfd) = 0; outsymalloc = 0; + /* 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) + if (p->type == bfd_indirect_link_order) + p->u.indirect.section->linker_mark = true; + /* Build the output symbol table. */ for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next) if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc)) @@ -1843,6 +1959,12 @@ _bfd_generic_final_link (abfd, info) _bfd_generic_link_write_global_symbol, (PTR) &wginfo); + /* Make sure we have a trailing NULL pointer on OUTSYMBOLS. We + shouldn't really need one, since we have SYMCOUNT, but some old + code still expects one. */ + if (! generic_add_output_symbol (abfd, &outsymalloc, NULL)) + return false; + if (info->relocateable) { /* Allocate space for the output relocs for each section. */ @@ -1873,12 +1995,9 @@ _bfd_generic_final_link (abfd, info) input_section); if (relsize < 0) return false; - relocs = (arelent **) malloc ((size_t) relsize); + relocs = (arelent **) bfd_malloc ((size_t) relsize); if (!relocs && relsize != 0) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return false; symbols = _bfd_generic_link_get_symbols (input_bfd); reloc_count = bfd_canonicalize_reloc (input_bfd, input_section, @@ -1886,7 +2005,8 @@ _bfd_generic_final_link (abfd, info) symbols); if (reloc_count < 0) return false; - BFD_ASSERT (reloc_count == input_section->reloc_count); + BFD_ASSERT ((unsigned long) reloc_count + == input_section->reloc_count); o->reloc_count += reloc_count; free (relocs); } @@ -1898,10 +2018,7 @@ _bfd_generic_final_link (abfd, info) (o->reloc_count * sizeof (arelent *)))); if (!o->orelocation) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return false; o->flags |= SEC_RELOC; /* Reset the count so that it can be used as an index when putting in the output relocs. */ @@ -1937,7 +2054,7 @@ _bfd_generic_final_link (abfd, info) } } } - + return true; } @@ -1949,7 +2066,7 @@ generic_add_output_symbol (output_bfd, psymalloc, sym) size_t *psymalloc; asymbol *sym; { - if (output_bfd->symcount >= *psymalloc) + if (bfd_get_symcount (output_bfd) >= *psymalloc) { asymbol **newsyms; @@ -1957,21 +2074,16 @@ generic_add_output_symbol (output_bfd, psymalloc, sym) *psymalloc = 124; else *psymalloc *= 2; - if (output_bfd->outsymbols == (asymbol **) NULL) - newsyms = (asymbol **) malloc (*psymalloc * sizeof (asymbol *)); - else - newsyms = (asymbol **) realloc (output_bfd->outsymbols, - *psymalloc * sizeof (asymbol *)); + newsyms = (asymbol **) bfd_realloc (bfd_get_outsymbols (output_bfd), + *psymalloc * sizeof (asymbol *)); if (newsyms == (asymbol **) NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } - output_bfd->outsymbols = newsyms; + return false; + bfd_get_outsymbols (output_bfd) = newsyms; } - output_bfd->outsymbols[output_bfd->symcount] = sym; - ++output_bfd->symcount; + bfd_get_outsymbols (output_bfd) [bfd_get_symcount (output_bfd)] = sym; + if (sym != NULL) + ++ bfd_get_symcount (output_bfd); return true; } @@ -2056,6 +2168,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) the relocs in the output format being used. */ h = NULL; } + else if (bfd_is_und_section (bfd_get_section (sym))) + h = ((struct generic_link_hash_entry *) + bfd_wrapped_link_hash_lookup (output_bfd, info, + bfd_asymbol_name (sym), + false, false, true)); else h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info), bfd_asymbol_name (sym), @@ -2120,10 +2237,11 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) /* This switch is straight from the old code in write_file_locals in ldsym.c. */ - if (info->strip == strip_some - && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym), - false, false) - == (struct bfd_hash_entry *) NULL)) + if (info->strip == strip_all + || (info->strip == strip_some + && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym), + false, false) + == (struct bfd_hash_entry *) NULL))) output = false; else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0) { @@ -2162,10 +2280,7 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) output = false; break; case discard_l: - if (bfd_asymbol_name (sym)[0] == info->lprefix[0] - && (info->lprefix_len == 1 - || strncmp (bfd_asymbol_name (sym), info->lprefix, - info->lprefix_len) == 0)) + if (bfd_is_local_label (input_bfd, sym)) output = false; else output = true; @@ -2186,6 +2301,15 @@ _bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc) 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 == false) + output = false; + if (output) { if (! generic_add_output_symbol (output_bfd, psymalloc, sym)) @@ -2209,8 +2333,22 @@ set_symbol_from_hash (sym, h) switch (h->type) { default: - case bfd_link_hash_new: abort (); + break; + case bfd_link_hash_new: + /* This can happen when a constructor symbol is seen but we are + not building constructors. */ + if (sym->section != NULL) + { + BFD_ASSERT ((sym->flags & BSF_CONSTRUCTOR) != 0); + } + else + { + sym->flags |= BSF_CONSTRUCTOR; + sym->section = bfd_abs_section_ptr; + sym->value = 0; + } + break; case bfd_link_hash_undefined: sym->section = bfd_und_section_ptr; sym->value = 0; @@ -2271,10 +2409,7 @@ _bfd_generic_link_write_global_symbol (h, data) return true; if (h->sym != (asymbol *) NULL) - { - sym = h->sym; - BFD_ASSERT (strcmp (bfd_asymbol_name (sym), h->root.root.string) == 0); - } + sym = h->sym; else { sym = bfd_make_empty_symbol (wginfo->output_bfd); @@ -2316,10 +2451,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order) r = (arelent *) bfd_alloc (abfd, sizeof (arelent)); if (r == (arelent *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return false; r->address = link_order->offset; r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc); @@ -2336,9 +2468,10 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order) { struct generic_link_hash_entry *h; - h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info), + h = ((struct generic_link_hash_entry *) + bfd_wrapped_link_hash_lookup (abfd, info, link_order->u.reloc.p->u.name, - false, false, true); + false, false, true)); if (h == (struct generic_link_hash_entry *) NULL || ! h->written) { @@ -2366,10 +2499,7 @@ _bfd_generic_reloc_link_order (abfd, info, sec, link_order) size = bfd_get_reloc_size (r->howto); buf = (bfd_byte *) bfd_zmalloc (size); if (buf == (bfd_byte *) NULL) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return false; rstat = _bfd_relocate_contents (r->howto, abfd, link_order->u.reloc.p->addend, buf); switch (rstat) @@ -2418,12 +2548,9 @@ bfd_new_link_order (abfd, section) struct bfd_link_order *new; new = ((struct bfd_link_order *) - bfd_alloc_by_size_t (abfd, sizeof (struct bfd_link_order))); + bfd_alloc (abfd, sizeof (struct bfd_link_order))); if (!new) - { - bfd_set_error (bfd_error_no_memory); - return NULL; - } + return NULL; new->type = bfd_undefined_link_order; new->offset = 0; @@ -2476,7 +2603,7 @@ _bfd_default_link_order (abfd, info, sec, link_order) static boolean default_fill_link_order (abfd, info, sec, link_order) bfd *abfd; - struct bfd_link_info *info; + struct bfd_link_info *info ATTRIBUTE_UNUSED; asection *sec; struct bfd_link_order *link_order; { @@ -2489,12 +2616,9 @@ default_fill_link_order (abfd, info, sec, link_order) BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0); size = (size_t) link_order->size; - space = (char *) malloc (size); + space = (char *) bfd_malloc (size); if (space == NULL && size != 0) - { - bfd_set_error (bfd_error_no_memory); - return false; - } + return false; fill = link_order->u.fill.value; for (i = 0; i < size; i += 2) @@ -2545,7 +2669,11 @@ default_indirect_link_order (output_bfd, info, output_section, link_order, because somebody is attempting to link together different types of object files. Handling this case correctly is difficult, and sometimes impossible. */ - abort (); + (*_bfd_error_handler) + (_("Attempt to do relocateable link with %s input and %s output"), + bfd_get_target (input_bfd), bfd_get_target (output_bfd)); + bfd_set_error (bfd_error_wrong_format); + return false; } if (! generic_linker) @@ -2587,6 +2715,10 @@ default_indirect_link_order (output_bfd, info, output_section, link_order, generic_link_add_symbol_list. */ if (sym->udata.p != NULL) 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), + false, false, true); else h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (sym), @@ -2598,12 +2730,10 @@ default_indirect_link_order (output_bfd, info, output_section, link_order, } /* Get and relocate the section contents. */ - contents = (bfd_byte *) malloc (bfd_section_size (input_bfd, input_section)); + contents = ((bfd_byte *) + bfd_malloc (bfd_section_size (input_bfd, input_section))); if (contents == NULL && bfd_section_size (input_bfd, input_section) != 0) - { - bfd_set_error (bfd_error_no_memory); - goto error_return; - } + goto error_return; new_contents = (bfd_get_relocated_section_contents (output_bfd, info, link_order, contents, info->relocateable, _bfd_generic_link_get_symbols (input_bfd))); @@ -2668,8 +2798,8 @@ DESCRIPTION boolean _bfd_generic_link_split_section (abfd, sec) - bfd *abfd; - asection *sec; + bfd *abfd ATTRIBUTE_UNUSED; + asection *sec ATTRIBUTE_UNUSED; { return false; }