X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felflink.c;h=1223d2770acfe1aeaefebd4fbe529766a70f0509;hb=4ade44b727ee77adaa9c22719935d012e253a5e6;hp=1b41c793a978dd5d974c8e73927a5b8d85416b33;hpb=199af1503922ce2134d774a78be0d9e2ae055ab1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elflink.c b/bfd/elflink.c index 1b41c793a9..1223d2770a 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1,5 +1,5 @@ /* ELF linking support for BFD. - Copyright (C) 1995-2015 Free Software Foundation, Inc. + Copyright (C) 1995-2016 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -204,7 +204,24 @@ _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info) hash_table = elf_hash_table (info); if (hash_table->dynobj == NULL) - hash_table->dynobj = abfd; + { + /* We may not set dynobj, an input file holding linker created + dynamic sections to abfd, which may be a dynamic object with + its own dynamic sections. We need to find a normal input file + to hold linker created sections if possible. */ + if ((abfd->flags & (DYNAMIC | BFD_PLUGIN)) != 0) + { + bfd *ibfd; + for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) + if ((ibfd->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + abfd = ibfd; + break; + } + } + hash_table->dynobj = abfd; + } if (hash_table->dynstr == NULL) { @@ -525,8 +542,10 @@ bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info, if ((info->dynamic_data && (h->type == STT_OBJECT + || h->type == STT_COMMON || (sym != NULL - && ELF_ST_TYPE (sym->st_info) == STT_OBJECT))) + && (ELF_ST_TYPE (sym->st_info) == STT_OBJECT + || ELF_ST_TYPE (sym->st_info) == STT_COMMON)))) || (d != NULL && h->root.type == bfd_link_hash_new && (*d->match) (&d->head, NULL, h->root.root.string))) @@ -555,6 +574,19 @@ bfd_elf_record_link_assignment (bfd *output_bfd, if (h == NULL) return provide; + if (h->versioned == unknown) + { + /* Set versioned if symbol version is unknown. */ + char *version = strrchr (name, ELF_VER_CHR); + if (version) + { + if (version > name && version[-1] != ELF_VER_CHR) + h->versioned = versioned_hidden; + else + h->versioned = versioned; + } + } + switch (h->root.type) { case bfd_link_hash_defined: @@ -632,9 +664,8 @@ bfd_elf_record_link_assignment (bfd *output_bfd, if ((h->def_dynamic || h->ref_dynamic - || bfd_link_pic (info) - || (bfd_link_pde (info) - && elf_hash_table (info)->is_relocatable_executable)) + || bfd_link_dll (info) + || elf_hash_table (info)->is_relocatable_executable) && h->dynindx == -1) { if (! bfd_elf_link_record_dynamic_symbol (info, h)) @@ -874,11 +905,11 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, elf_link_renumber_hash_table_dynsyms, &dynsymcount); - /* There is an unused NULL entry at the head of the table which - we must account for in our count. Unless there weren't any - symbols, which means we'll have no table at all. */ - if (dynsymcount != 0) - ++dynsymcount; + /* There is an unused NULL entry at the head of the table which we + must account for in our count even if the table is empty since it + is intended for the mandatory DT_SYMTAB tag (.dynsym section) in + .dynamic section. */ + dynsymcount++; elf_hash_table (info)->dynsymcount = dynsymcount; return dynsymcount; @@ -1472,13 +1503,16 @@ _bfd_elf_merge_symbol (bfd *abfd, represent variables; this can cause confusion in principle, but any such confusion would seem to indicate an erroneous program or shared library. We also permit a common symbol in a regular - object to override a weak symbol in a shared object. */ + object to override a weak symbol in a shared object. A common + symbol in executable also overrides a symbol in a shared object. */ if (newdyn && newdef && (olddef || (h->root.type == bfd_link_hash_common - && (newweak || newfunc)))) + && (newweak + || newfunc + || (!olddyn && bfd_link_executable (info)))))) { *override = TRUE; newdef = FALSE; @@ -3228,12 +3262,26 @@ elf_add_dt_needed_tag (bfd *abfd, return 0; } +/* Return true if SONAME is on the needed list between NEEDED and STOP + (or the end of list if STOP is NULL), and needed by a library that + will be loaded. */ + static bfd_boolean -on_needed_list (const char *soname, struct bfd_link_needed_list *needed) -{ - for (; needed != NULL; needed = needed->next) - if ((elf_dyn_lib_class (needed->by) & DYN_AS_NEEDED) == 0 - && strcmp (soname, needed->name) == 0) +on_needed_list (const char *soname, + struct bfd_link_needed_list *needed, + struct bfd_link_needed_list *stop) +{ + struct bfd_link_needed_list *look; + for (look = needed; look != stop; look = look->next) + if (strcmp (soname, look->name) == 0 + && ((elf_dyn_lib_class (look->by) & DYN_AS_NEEDED) == 0 + /* If needed by a library that itself is not directly + needed, recursively check whether that library is + indirectly needed. Since we add DT_NEEDED entries to + the end of the list, library dependencies appear after + the library. Therefore search prior to the current + LOOK, preventing possible infinite recursion. */ + || on_needed_list (elf_dt_name (look->by), needed, look))) return TRUE; return FALSE; @@ -3449,6 +3497,71 @@ _bfd_elf_notice_as_needed (bfd *ibfd, return (*info->callbacks->notice) (info, NULL, NULL, ibfd, NULL, act, 0); } +/* Check relocations an ELF object file. */ + +bfd_boolean +_bfd_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_link_hash_table *htab = elf_hash_table (info); + + /* If this object is the same format as the output object, and it is + not a shared library, then let the backend look through the + relocs. + + This is required to build global offset table entries and to + arrange for dynamic relocs. It is not required for the + particular common case of linking non PIC code, even when linking + against shared libraries, but unfortunately there is no way of + knowing whether an object file has been compiled PIC or not. + Looking through the relocs is not particularly time consuming. + The problem is that we must either (1) keep the relocs in memory, + which causes the linker to require additional runtime memory or + (2) read the relocs twice from the input file, which wastes time. + This would be a good case for using mmap. + + I have no idea how to handle linking PIC code into a file of a + different format. It probably can't be done. */ + if ((abfd->flags & DYNAMIC) == 0 + && is_elf_hash_table (htab) + && bed->check_relocs != NULL + && elf_object_id (abfd) == elf_hash_table_id (htab) + && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) + { + asection *o; + + for (o = abfd->sections; o != NULL; o = o->next) + { + Elf_Internal_Rela *internal_relocs; + bfd_boolean ok; + + /* Don't check relocations in excluded sections. */ + if ((o->flags & SEC_RELOC) == 0 + || (o->flags & SEC_EXCLUDE) != 0 + || o->reloc_count == 0 + || ((info->strip == strip_all || info->strip == strip_debugger) + && (o->flags & SEC_DEBUGGING) != 0) + || bfd_is_abs_section (o->output_section)) + continue; + + internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, + info->keep_memory); + if (internal_relocs == NULL) + return FALSE; + + ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); + + if (elf_section_data (o)->relocs != internal_relocs) + free (internal_relocs); + + if (! ok) + return FALSE; + } + } + + return TRUE; +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -3598,11 +3711,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) /* If we are creating a shared library, create all the dynamic sections immediately. We need to attach them to something, so we attach them to this BFD, provided it is the right - format and is not from ld --just-symbols. FIXME: If there + format and is not from ld --just-symbols. Always create the + dynamic sections for -E/--dynamic-list. FIXME: If there are no input BFD's of the same format as the output, we can't make a shared library. */ if (!just_syms - && bfd_link_pic (info) + && (bfd_link_pic (info) + || (!bfd_link_relocatable (info) + && (info->export_dynamic || info->dynamic))) && is_elf_hash_table (htab) && info->output_bfd->xvec == abfd->xvec && !htab->dynamic_sections_created) @@ -3966,6 +4082,7 @@ error_free_dyn: bfd_boolean old_weak; bfd_boolean override; bfd_boolean common; + bfd_boolean discarded; unsigned int old_alignment; bfd *old_bfd; bfd_boolean matched; @@ -3976,6 +4093,7 @@ error_free_dyn: sec = NULL; value = isym->st_value; common = bed->common_definition (isym); + discarded = FALSE; bind = ELF_ST_BIND (isym->st_info); switch (bind) @@ -4026,6 +4144,7 @@ error_free_dyn: /* Symbols from discarded section are undefined. We keep its visibility. */ sec = bfd_und_section_ptr; + discarded = TRUE; isym->st_shndx = SHN_UNDEF; } else if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) @@ -4269,6 +4388,11 @@ error_free_dyn: || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Setting the index to -3 tells elf_link_output_extsym that + this symbol is defined in a discarded section. */ + if (discarded) + h->indx = -3; + *sym_hash = h; new_weak = (flags & BSF_WEAK) != 0; @@ -4549,7 +4673,7 @@ error_free_dyn: goto error_free_vers; } } - else if (dynsym && h->dynindx != -1) + else if (h->dynindx != -1) /* If the symbol already has a dynamic index, but visibility says it should not be visible, turn it into a local symbol. */ @@ -4562,8 +4686,10 @@ error_free_dyn: break; } - /* Don't add DT_NEEDED for references from the dummy bfd. */ + /* Don't add DT_NEEDED for references from the dummy bfd nor + for unmatched symbol. */ if (!add_needed + && matched && definition && ((dynsym && h->ref_regular_nonweak @@ -4571,7 +4697,8 @@ error_free_dyn: || (old_bfd->flags & BFD_PLUGIN) == 0)) || (h->ref_dynamic_nonweak && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0 - && !on_needed_list (elf_dt_name (abfd), htab->needed)))) + && !on_needed_list (elf_dt_name (abfd), + htab->needed, NULL)))) { int ret; const char *soname = elf_dt_name (abfd); @@ -4913,57 +5040,9 @@ error_free_dyn: && !(*bed->check_directives) (abfd, info)) return FALSE; - /* If this object is the same format as the output object, and it is - not a shared library, then let the backend look through the - relocs. - - This is required to build global offset table entries and to - arrange for dynamic relocs. It is not required for the - particular common case of linking non PIC code, even when linking - against shared libraries, but unfortunately there is no way of - knowing whether an object file has been compiled PIC or not. - Looking through the relocs is not particularly time consuming. - The problem is that we must either (1) keep the relocs in memory, - which causes the linker to require additional runtime memory or - (2) read the relocs twice from the input file, which wastes time. - This would be a good case for using mmap. - - I have no idea how to handle linking PIC code into a file of a - different format. It probably can't be done. */ - if (! dynamic - && is_elf_hash_table (htab) - && bed->check_relocs != NULL - && elf_object_id (abfd) == elf_hash_table_id (htab) - && (*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec)) - { - asection *o; - - for (o = abfd->sections; o != NULL; o = o->next) - { - Elf_Internal_Rela *internal_relocs; - bfd_boolean ok; - - if ((o->flags & SEC_RELOC) == 0 - || o->reloc_count == 0 - || ((info->strip == strip_all || info->strip == strip_debugger) - && (o->flags & SEC_DEBUGGING) != 0) - || bfd_is_abs_section (o->output_section)) - continue; - - internal_relocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, - info->keep_memory); - if (internal_relocs == NULL) - goto error_return; - - ok = (*bed->check_relocs) (abfd, info, o, internal_relocs); - - if (elf_section_data (o)->relocs != internal_relocs) - free (internal_relocs); - - if (! ok) - goto error_return; - } - } + if (!info->check_relocs_after_open_input + && !_bfd_elf_link_check_relocs (abfd, info)) + return FALSE; /* If this is a non-traditional link, try to optimize the handling of the .stab/.stabstr sections. */ @@ -6535,8 +6614,7 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) /* Work out the size of the symbol version section. */ s = bfd_get_linker_section (dynobj, ".gnu.version"); BFD_ASSERT (s != NULL); - if (dynsymcount != 0 - && (s->flags & SEC_EXCLUDE) == 0) + if ((s->flags & SEC_EXCLUDE) == 0) { s->size = dynsymcount * sizeof (Elf_External_Versym); s->contents = (unsigned char *) bfd_zalloc (output_bfd, s->size); @@ -6557,17 +6635,14 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) BFD_ASSERT (s != NULL); s->size = dynsymcount * bed->s->sizeof_sym; - if (dynsymcount != 0) - { - s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size); - if (s->contents == NULL) - return FALSE; + s->contents = (unsigned char *) bfd_alloc (output_bfd, s->size); + if (s->contents == NULL) + return FALSE; - /* The first entry in .dynsym is a dummy symbol. - Clear all the section syms, in case we don't output them all. */ - ++section_sym_count; - memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); - } + /* The first entry in .dynsym is a dummy symbol. Clear all the + section syms, in case we don't output them all. */ + ++section_sym_count; + memset (s->contents, 0, section_sym_count * bed->s->sizeof_sym); elf_hash_table (info)->bucketcount = 0; @@ -7729,10 +7804,15 @@ resolve_symbol (const char *name, return FALSE; } +/* Looks up NAME in SECTIONS. If found sets RESULT to NAME's address (in + bytes) and returns TRUE, otherwise returns FALSE. Accepts pseudo-section + names like "foo.end" which is the end address of section "foo". */ + static bfd_boolean resolve_section (const char *name, asection *sections, - bfd_vma *result) + bfd_vma *result, + bfd * abfd) { asection *curr; unsigned int len; @@ -7745,6 +7825,7 @@ resolve_section (const char *name, } /* Hmm. still haven't found it. try pseudo-section names. */ + /* FIXME: This could be coded more efficiently... */ for (curr = sections; curr; curr = curr->next) { len = strlen (curr->name); @@ -7755,7 +7836,7 @@ resolve_section (const char *name, { if (strncmp (".end", name + len, 4) == 0) { - *result = curr->vma + curr->size; + *result = curr->vma + curr->size / bfd_octets_per_byte (abfd); return TRUE; } @@ -7837,7 +7918,7 @@ eval_symbol (bfd_vma *result, if (symbol_is_section) { - if (!resolve_section (symbuf, flinfo->output_bfd->sections, result) + if (!resolve_section (symbuf, flinfo->output_bfd->sections, result, input_bfd) && !resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount)) { @@ -7850,7 +7931,7 @@ eval_symbol (bfd_vma *result, if (!resolve_symbol (symbuf, input_bfd, flinfo, result, isymbuf, locsymcount) && !resolve_section (symbuf, flinfo->output_bfd->sections, - result)) + result, input_bfd)) { undefined_reference ("symbol", symbuf); return FALSE; @@ -8074,8 +8155,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, else shift = (8 * wordsz) - (start + len); - /* FIXME: octets_per_byte. */ - x = get_value (wordsz, chunksz, input_bfd, contents + rel->r_offset); + x = get_value (wordsz, chunksz, input_bfd, + contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); #ifdef DEBUG printf ("Doing complex reloc: " @@ -8107,8 +8188,8 @@ bfd_elf_perform_complex_relocation (bfd *input_bfd, (unsigned long) relocation, (unsigned long) (mask << shift), (unsigned long) ((relocation & mask) << shift), (unsigned long) x); #endif - /* FIXME: octets_per_byte. */ - put_value (wordsz, chunksz, input_bfd, x, contents + rel->r_offset); + put_value (wordsz, chunksz, input_bfd, x, + contents + rel->r_offset * bfd_octets_per_byte (input_bfd)); return r; } @@ -8445,6 +8526,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) struct elf_link_sort_rela *sq; const struct elf_backend_data *bed = get_elf_backend_data (abfd); int i2e = bed->s->int_rels_per_ext_rel; + unsigned int opb = bfd_octets_per_byte (abfd); void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); struct bfd_link_order *lo; @@ -8460,7 +8542,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) bfd_boolean use_rela_initialised = FALSE; /* This is just here to stop gcc from complaining. - It's initialization checking code is not perfect. */ + Its initialization checking code is not perfect. */ use_rela = TRUE; /* Both sections are present. Examine the sizes @@ -8481,8 +8563,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8498,8 +8581,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8511,9 +8595,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8535,8 +8620,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rela. */ if (use_rela_initialised && (use_rela == FALSE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8552,8 +8638,9 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) /* Section size is only divisible by rel. */ if (use_rela_initialised && (use_rela == TRUE)) { - _bfd_error_handler - (_("%B: Unable to sort relocs - they are in more than one size"), abfd); + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are in more than one size"), + abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8565,9 +8652,10 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } else { - /* The section size is not divisible by either - something is wrong. */ - _bfd_error_handler - (_("%B: Unable to sort relocs - they are of an unknown size"), abfd); + /* The section size is not divisible by either - + something is wrong. */ + _bfd_error_handler (_("%B: Unable to sort relocs - " + "they are of an unknown size"), abfd); bfd_set_error (bfd_error_invalid_operation); return 0; } @@ -8643,8 +8731,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) } erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + p = sort + o->output_offset * opb / ext_size * sort_elt; while (erel < erelend) { @@ -8680,6 +8767,35 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) qsort (s_non_relative, count - ret, sort_elt, elf_link_sort_cmp2); + struct elf_link_hash_table *htab = elf_hash_table (info); + if (htab->srelplt && htab->srelplt->output_section == dynamic_relocs) + { + /* We have plt relocs in .rela.dyn. */ + sq = (struct elf_link_sort_rela *) sort; + for (i = 0; i < count; i++) + if (sq[count - i - 1].type != reloc_class_plt) + break; + if (i != 0 && htab->srelplt->size == i * ext_size) + { + struct bfd_link_order **plo; + /* Put srelplt link_order last. This is so the output_offset + set in the next loop is correct for DT_JMPREL. */ + for (plo = &dynamic_relocs->map_head.link_order; *plo != NULL; ) + if ((*plo)->type == bfd_indirect_link_order + && (*plo)->u.indirect.section == htab->srelplt) + { + lo = *plo; + *plo = lo->next; + } + else + plo = &(*plo)->next; + *plo = lo; + lo->next = NULL; + dynamic_relocs->map_tail.link_order = lo; + } + } + + p = sort; for (lo = dynamic_relocs->map_head.link_order; lo != NULL; lo = lo->next) if (lo->type == bfd_indirect_link_order) { @@ -8688,8 +8804,7 @@ elf_link_sort_relocs (bfd *abfd, struct bfd_link_info *info, asection **psec) erel = o->contents; erelend = o->contents + o->size; - /* FIXME: octets_per_byte. */ - p = sort + o->output_offset / ext_size * sort_elt; + o->output_offset = (p - sort) / sort_elt * ext_size / opb; while (erel < erelend) { struct elf_link_sort_rela *s = (struct elf_link_sort_rela *) p; @@ -9021,6 +9136,28 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, return FALSE; } +/* Convert ELF common symbol TYPE. */ + +static int +elf_link_convert_common_type (struct bfd_link_info *info, int type) +{ + /* Commom symbol can only appear in relocatable link. */ + if (!bfd_link_relocatable (info)) + abort (); + switch (info->elf_stt_common) + { + case unchanged: + break; + case elf_stt_common: + type = STT_COMMON; + break; + case no_elf_stt_common: + type = STT_OBJECT; + break; + } + return type; +} + /* Add an external symbol to the symbol table. This is called from the hash table traversal routine. When generating a shared object, we go through the symbol table twice. The first time we output @@ -9040,6 +9177,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) const struct elf_backend_data *bed; long indx; int ret; + unsigned int type; /* A symbol is bound locally if it is forced local or it is locally defined, hidden versioned, not referenced by shared library and not exported when linking executable. */ @@ -9105,6 +9243,10 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) return FALSE; } } + + /* Strip a global symbol defined in a discarded section. */ + if (h->indx == -3) + return TRUE; } /* We should also warn if a forced local symbol is referenced from @@ -9174,35 +9316,21 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0) strip = TRUE; + type = h->type; + /* If we're stripping it, and it's not a dynamic symbol, there's nothing else to do. However, if it is a forced local symbol or an ifunc symbol we need to give the backend finish_dynamic_symbol function a chance to make it dynamic. */ if (strip && h->dynindx == -1 - && h->type != STT_GNU_IFUNC + && type != STT_GNU_IFUNC && !h->forced_local) return TRUE; sym.st_value = 0; sym.st_size = h->size; sym.st_other = h->other; - if (local_bind) - { - sym.st_info = ELF_ST_INFO (STB_LOCAL, h->type); - /* Turn off visibility on local symbol. */ - sym.st_other &= ~ELF_ST_VISIBILITY (-1); - } - /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */ - else if (h->unique_global && h->def_regular) - sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, h->type); - else if (h->root.type == bfd_link_hash_undefweak - || h->root.type == bfd_link_hash_defweak) - sym.st_info = ELF_ST_INFO (STB_WEAK, h->type); - else - sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type); - sym.st_target_internal = h->target_internal; - switch (h->root.type) { default: @@ -9277,6 +9405,42 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) return TRUE; } + if (type == STT_COMMON || type == STT_OBJECT) + switch (h->root.type) + { + case bfd_link_hash_common: + type = elf_link_convert_common_type (flinfo->info, type); + break; + case bfd_link_hash_defined: + case bfd_link_hash_defweak: + if (bed->common_definition (&sym)) + type = elf_link_convert_common_type (flinfo->info, type); + else + type = STT_OBJECT; + break; + case bfd_link_hash_undefined: + case bfd_link_hash_undefweak: + break; + default: + abort (); + } + + if (local_bind) + { + sym.st_info = ELF_ST_INFO (STB_LOCAL, type); + /* Turn off visibility on local symbol. */ + sym.st_other &= ~ELF_ST_VISIBILITY (-1); + } + /* Set STB_GNU_UNIQUE only if symbol is defined in regular object. */ + else if (h->unique_global && h->def_regular) + sym.st_info = ELF_ST_INFO (STB_GNU_UNIQUE, type); + else if (h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_defweak) + sym.st_info = ELF_ST_INFO (STB_WEAK, type); + else + sym.st_info = ELF_ST_INFO (STB_GLOBAL, type); + sym.st_target_internal = h->target_internal; + /* Give the processor backend a chance to tweak the symbol value, and also to finish up anything that needs to be done for this symbol. FIXME: Not calling elf_backend_finish_dynamic_symbol for @@ -9313,7 +9477,7 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) || ELF_ST_BIND (sym.st_info) == STB_WEAK)) { int bindtype; - unsigned int type = ELF_ST_TYPE (sym.st_info); + type = ELF_ST_TYPE (sym.st_info); /* Turn an undefined IFUNC symbol into a normal FUNC symbol. */ if (type == STT_GNU_IFUNC) @@ -10468,11 +10632,13 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd) break; default: { - /* FIXME: octets_per_byte. */ if (! (o->flags & SEC_EXCLUDE)) { file_ptr offset = (file_ptr) o->output_offset; bfd_size_type todo = o->size; + + offset *= bfd_octets_per_byte (output_bfd); + if ((o->flags & SEC_ELF_REVERSE_COPY)) { /* Reverse-copy input section to output. */ @@ -10636,8 +10802,11 @@ elf_reloc_link_order (bfd *output_bfd, } break; } + ok = bfd_set_section_contents (output_bfd, output_section, buf, - link_order->offset, size); + link_order->offset + * bfd_octets_per_byte (output_bfd), + size); free (buf); if (! ok) return FALSE; @@ -10819,9 +10988,8 @@ elf_fixup_link_order (bfd *abfd, asection *o) { s = sections[n]->u.indirect.section; offset &= ~(bfd_vma) 0 << s->alignment_power; - s->output_offset = offset; + s->output_offset = offset / bfd_octets_per_byte (abfd); sections[n]->offset = offset; - /* FIXME: octets_per_byte. */ offset += sections[n]->size; } @@ -10988,6 +11156,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) for (p = o->map_head.link_order; p != NULL; p = p->next) { unsigned int reloc_count = 0; + unsigned int additional_reloc_count = 0; struct bfd_elf_section_data *esdi = NULL; if (p->type == bfd_section_reloc_link_order @@ -11016,7 +11185,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) reloc sections themselves can't have relocations. */ reloc_count = 0; else if (emit_relocs) - reloc_count = sec->reloc_count; + { + reloc_count = sec->reloc_count; + if (bed->elf_backend_count_additional_relocs) + { + int c; + c = (*bed->elf_backend_count_additional_relocs) (sec); + additional_reloc_count += c; + } + } else if (bed->elf_backend_count_relocs) reloc_count = (*bed->elf_backend_count_relocs) (info, sec); @@ -11065,14 +11242,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (reloc_count == 0) continue; + reloc_count += additional_reloc_count; o->reloc_count += reloc_count; if (p->type == bfd_indirect_link_order && emit_relocs) { if (esdi->rel.hdr) - esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + { + esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr); + esdo->rel.count += additional_reloc_count; + } if (esdi->rela.hdr) - esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + { + esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr); + esdo->rela.count += additional_reloc_count; + } } else { @@ -11379,15 +11563,20 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) { const char *iclass, *oclass; - if (bed->s->elfclass == ELFCLASS64) + switch (bed->s->elfclass) { - iclass = "ELFCLASS32"; - oclass = "ELFCLASS64"; + case ELFCLASS64: oclass = "ELFCLASS64"; break; + case ELFCLASS32: oclass = "ELFCLASS32"; break; + case ELFCLASSNONE: oclass = "ELFCLASSNONE"; break; + default: abort (); } - else + + switch (elf_elfheader (sub)->e_ident[EI_CLASS]) { - iclass = "ELFCLASS64"; - oclass = "ELFCLASS32"; + case ELFCLASS64: iclass = "ELFCLASS64"; break; + case ELFCLASS32: iclass = "ELFCLASS32"; break; + case ELFCLASSNONE: iclass = "ELFCLASSNONE"; break; + default: abort (); } bfd_set_error (bfd_error_wrong_format); @@ -11592,7 +11781,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; /* sh_name was set in prep_headers. */ symstrtab_hdr->sh_type = SHT_STRTAB; - symstrtab_hdr->sh_flags = 0; + symstrtab_hdr->sh_flags = bed->elf_strtab_flags; symstrtab_hdr->sh_addr = 0; symstrtab_hdr->sh_size = _bfd_elf_strtab_size (flinfo.symstrtab); symstrtab_hdr->sh_entsize = 0; @@ -11706,18 +11895,18 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_PREINIT_ARRAYSZ: name = ".preinit_array"; - goto get_size; + goto get_out_size; case DT_INIT_ARRAYSZ: name = ".init_array"; - goto get_size; + goto get_out_size; case DT_FINI_ARRAYSZ: name = ".fini_array"; - get_size: + get_out_size: o = bfd_get_section_by_name (abfd, name); if (o == NULL) { (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + (_("could not find section %s"), name); goto error_return; } if (o->size == 0) @@ -11728,13 +11917,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_PREINIT_ARRAY: name = ".preinit_array"; - goto get_vma; + goto get_out_vma; case DT_INIT_ARRAY: name = ".init_array"; - goto get_vma; + goto get_out_vma; case DT_FINI_ARRAY: name = ".fini_array"; - goto get_vma; + get_out_vma: + o = bfd_get_section_by_name (abfd, name); + goto do_vma; case DT_HASH: name = ".hash"; @@ -11757,11 +11948,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) case DT_VERSYM: name = ".gnu.version"; get_vma: - o = bfd_get_section_by_name (abfd, name); + o = bfd_get_linker_section (dynobj, name); + do_vma: if (o == NULL) { (*_bfd_error_handler) - (_("%B: could not find output section %s"), abfd, name); + (_("could not find section %s"), name); goto error_return; } if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) @@ -11771,7 +11963,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) bfd_set_error (bfd_error_nonrepresentable_section); goto error_return; } - dyn.d_un.d_ptr = o->vma; + dyn.d_un.d_ptr = o->output_section->vma + o->output_offset; break; case DT_REL: @@ -11860,10 +12052,10 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) continue; if (strcmp (o->name, ".dynstr") != 0) { - /* FIXME: octets_per_byte. */ if (! bfd_set_section_contents (abfd, o->output_section, o->contents, - (file_ptr) o->output_offset, + (file_ptr) o->output_offset + * bfd_octets_per_byte (abfd), o->size)) goto error_return; } @@ -12087,6 +12279,55 @@ _bfd_elf_gc_mark_hook (asection *sec, return NULL; } +/* For undefined __start_ and __stop_ symbols, return the + first input section matching . Return NULL otherwise. */ + +asection * +_bfd_elf_is_start_stop (const struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + asection *s; + const char *sec_name; + + if (h->root.type != bfd_link_hash_undefined + && h->root.type != bfd_link_hash_undefweak) + return NULL; + + s = h->root.u.undef.section; + if (s != NULL) + { + if (s == (asection *) 0 - 1) + return NULL; + return s; + } + + sec_name = NULL; + if (strncmp (h->root.root.string, "__start_", 8) == 0) + sec_name = h->root.root.string + 8; + else if (strncmp (h->root.root.string, "__stop_", 7) == 0) + sec_name = h->root.root.string + 7; + + if (sec_name != NULL && *sec_name != '\0') + { + bfd *i; + + for (i = info->input_bfds; i != NULL; i = i->link.next) + { + s = bfd_get_section_by_name (i, sec_name); + if (s != NULL) + { + h->root.u.undef.section = s; + break; + } + } + } + + if (s == NULL) + h->root.u.undef.section = (asection *) 0 - 1; + + return s; +} + /* COOKIE->rel describes a relocation against section SEC, which is a section we've decided to keep. Return the section that contains the relocation symbol, or NULL if no section contains it. */ @@ -12125,34 +12366,19 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, if (h->u.weakdef != NULL) h->u.weakdef->mark = 1; - if (start_stop != NULL - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak)) + if (start_stop != NULL) { /* To work around a glibc bug, mark all XXX input sections when there is an as yet undefined reference to __start_XXX or __stop_XXX symbols. The linker will later define such symbols for orphan input sections that have a name representable as a C identifier. */ - const char *sec_name = NULL; - if (strncmp (h->root.root.string, "__start_", 8) == 0) - sec_name = h->root.root.string + 8; - else if (strncmp (h->root.root.string, "__stop_", 7) == 0) - sec_name = h->root.root.string + 7; + asection *s = _bfd_elf_is_start_stop (info, h); - if (sec_name != NULL && *sec_name != '\0') + if (s != NULL) { - bfd *i; - - for (i = info->input_bfds; i != NULL; i = i->link.next) - { - asection *s = bfd_get_section_by_name (i, sec_name); - if (s != NULL && !s->gc_mark) - { - *start_stop = TRUE; - return s; - } - } + *start_stop = !s->gc_mark; + return s; } }