| /* ELF linking support for BFD. |
| Copyright (C) 1995-2024 Free Software Foundation, Inc. |
| |
| 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 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| 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., 51 Franklin Street - Fifth Floor, Boston, |
| MA 02110-1301, USA. */ |
| |
| #include "sysdep.h" |
| #include "bfd.h" |
| #include "bfdlink.h" |
| #include "libbfd.h" |
| #define ARCH_SIZE 0 |
| #include "elf-bfd.h" |
| #include "safe-ctype.h" |
| #include "libiberty.h" |
| #include "objalloc.h" |
| #if BFD_SUPPORTS_PLUGINS |
| #include "plugin-api.h" |
| #include "plugin.h" |
| #endif |
| |
| #include <limits.h> |
| #ifndef CHAR_BIT |
| #define CHAR_BIT 8 |
| #endif |
| |
| /* This struct is used to pass information to routines called via |
| elf_link_hash_traverse which must return failure. */ |
| |
| struct elf_info_failed |
| { |
| struct bfd_link_info *info; |
| bool failed; |
| }; |
| |
| static bool _bfd_elf_fix_symbol_flags |
| (struct elf_link_hash_entry *, struct elf_info_failed *); |
| |
| /* Return false if linker should avoid caching relocation information |
| and symbol tables of input files in memory. */ |
| |
| static bool |
| _bfd_elf_link_keep_memory (struct bfd_link_info *info) |
| { |
| #ifdef USE_MMAP |
| /* Don't cache symbol nor relocation tables if they are mapped in. |
| NB: Since the --no-keep-memory linker option causes: |
| |
| https://sourceware.org/bugzilla/show_bug.cgi?id=31458 |
| |
| this is opt-in by each backend. */ |
| const struct elf_backend_data *bed |
| = get_elf_backend_data (info->output_bfd); |
| if (bed != NULL && bed->use_mmap) |
| return false; |
| #endif |
| bfd *abfd; |
| bfd_size_type size; |
| |
| if (!info->keep_memory) |
| return false; |
| |
| if (info->max_cache_size == (bfd_size_type) -1) |
| return true; |
| |
| abfd = info->input_bfds; |
| size = info->cache_size; |
| do |
| { |
| if (size >= info->max_cache_size) |
| { |
| /* Over the limit. Reduce the memory usage. */ |
| info->keep_memory = false; |
| return false; |
| } |
| if (!abfd) |
| break; |
| size += abfd->alloc_size; |
| abfd = abfd->link.next; |
| } |
| while (1); |
| |
| return true; |
| } |
| |
| asection * |
| _bfd_elf_section_for_symbol (struct elf_reloc_cookie *cookie, |
| unsigned long r_symndx, |
| bool discard) |
| { |
| if (r_symndx >= cookie->locsymcount |
| || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) |
| { |
| struct elf_link_hash_entry *h; |
| |
| h = cookie->sym_hashes[r_symndx - cookie->extsymoff]; |
| |
| while (h->root.type == bfd_link_hash_indirect |
| || h->root.type == bfd_link_hash_warning) |
| h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| |
| if ((h->root.type == bfd_link_hash_defined |
| || h->root.type == bfd_link_hash_defweak) |
| && discarded_section (h->root.u.def.section)) |
| return h->root.u.def.section; |
| else |
| return NULL; |
| } |
| else |
| { |
| /* It's not a relocation against a global symbol, |
| but it could be a relocation against a local |
| symbol for a discarded section. */ |
| asection *isec; |
| Elf_Internal_Sym *isym; |
| |
| /* Need to: get the symbol; get the section. */ |
| isym = &cookie->locsyms[r_symndx]; |
| isec = bfd_section_from_elf_index (cookie->abfd, isym->st_shndx); |
| if (isec != NULL |
| && discard ? discarded_section (isec) : 1) |
| return isec; |
| } |
| return NULL; |
| } |
| |
| /* Define a symbol in a dynamic linkage section. */ |
| |
| struct elf_link_hash_entry * |
| _bfd_elf_define_linkage_sym (bfd *abfd, |
| struct bfd_link_info *info, |
| asection *sec, |
| const char *name) |
| { |
| struct elf_link_hash_entry *h; |
| struct bfd_link_hash_entry *bh; |
| const struct elf_backend_data *bed; |
| |
| h = elf_link_hash_lookup (elf_hash_table (info), name, false, false, false); |
| if (h != NULL) |
| { |
| /* Zap symbol defined in an as-needed lib that wasn't linked. |
| This is a symptom of a larger problem: Absolute symbols |
| defined in shared libraries can't be overridden, because we |
| lose the link to the bfd which is via the symbol section. */ |
| h->root.type = bfd_link_hash_new; |
| bh = &h->root; |
| } |
| else |
| bh = NULL; |
| |
| bed = get_elf_backend_data (abfd); |
| if (!_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL, |
| sec, 0, NULL, false, bed->collect, |
| &bh)) |
| return NULL; |
| h = (struct elf_link_hash_entry *) bh; |
| BFD_ASSERT (h != NULL); |
| h->def_regular = 1; |
| h->non_elf = 0; |
| h->root.linker_def = 1; |
| h->type = STT_OBJECT; |
| if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL) |
| h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; |
| |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| return h; |
| } |
| |
| bool |
| _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) |
| { |
| flagword flags; |
| asection *s; |
| struct elf_link_hash_entry *h; |
| const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
| struct elf_link_hash_table *htab = elf_hash_table (info); |
| |
| /* This function may be called more than once. */ |
| if (htab->sgot != NULL) |
| return true; |
| |
| flags = bed->dynamic_sec_flags; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, |
| (bed->rela_plts_and_copies_p |
| ? ".rela.got" : ".rel.got"), |
| (bed->dynamic_sec_flags |
| | SEC_READONLY)); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->srelgot = s; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->sgot = s; |
| |
| if (bed->want_got_plt) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->sgotplt = s; |
| } |
| |
| /* The first bit of the global offset table is the header. */ |
| s->size += bed->got_header_size; |
| |
| if (bed->want_got_sym) |
| { |
| /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got |
| (or .got.plt) section. We don't do this in the linker script |
| because we don't want to define the symbol if we are not creating |
| a global offset table. */ |
| h = _bfd_elf_define_linkage_sym (abfd, info, s, |
| "_GLOBAL_OFFSET_TABLE_"); |
| elf_hash_table (info)->hgot = h; |
| if (h == NULL) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* Create a strtab to hold the dynamic symbol names. */ |
| static bool |
| _bfd_elf_link_create_dynstrtab (bfd *abfd, struct bfd_link_info *info) |
| { |
| struct elf_link_hash_table *hash_table; |
| |
| hash_table = elf_hash_table (info); |
| if (hash_table->dynobj == NULL) |
| { |
| /* 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; |
| asection *s; |
| for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) |
| if ((ibfd->flags |
| & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0 |
| && bfd_get_flavour (ibfd) == bfd_target_elf_flavour |
| && elf_object_id (ibfd) == elf_hash_table_id (hash_table) |
| && !((s = ibfd->sections) != NULL |
| && s->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)) |
| { |
| abfd = ibfd; |
| break; |
| } |
| } |
| hash_table->dynobj = abfd; |
| } |
| |
| if (hash_table->dynstr == NULL) |
| { |
| hash_table->dynstr = _bfd_elf_strtab_init (); |
| if (hash_table->dynstr == NULL) |
| return false; |
| } |
| return true; |
| } |
| |
| /* Create some sections which will be filled in with dynamic linking |
| information. ABFD is an input file which requires dynamic sections |
| to be created. The dynamic sections take up virtual memory space |
| when the final executable is run, so we need to create them before |
| addresses are assigned to the output sections. We work out the |
| actual contents and size of these sections later. */ |
| |
| bool |
| _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
| { |
| flagword flags; |
| asection *s; |
| const struct elf_backend_data *bed; |
| struct elf_link_hash_entry *h; |
| |
| if (! is_elf_hash_table (info->hash)) |
| return false; |
| |
| if (elf_hash_table (info)->dynamic_sections_created) |
| return true; |
| |
| if (!_bfd_elf_link_create_dynstrtab (abfd, info)) |
| return false; |
| |
| abfd = elf_hash_table (info)->dynobj; |
| bed = get_elf_backend_data (abfd); |
| |
| flags = bed->dynamic_sec_flags; |
| |
| /* A dynamically linked executable has a .interp section, but a |
| shared library does not. */ |
| if (bfd_link_executable (info) && !info->nointerp) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, ".interp", |
| flags | SEC_READONLY); |
| if (s == NULL) |
| return false; |
| } |
| |
| /* Create sections to hold version informations. These are removed |
| if they are not needed. */ |
| s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_d", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, 1)) |
| return false; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".dynsym", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| elf_hash_table (info)->dynsym = s; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".dynstr", |
| flags | SEC_READONLY); |
| if (s == NULL) |
| return false; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| elf_hash_table (info)->dynamic = s; |
| |
| /* The special symbol _DYNAMIC is always set to the start of the |
| .dynamic section. We could set _DYNAMIC in a linker script, but we |
| only want to define it if we are, in fact, creating a .dynamic |
| section. We don't want to define it if there is no .dynamic |
| section, since on some ELF platforms the start up code examines it |
| to decide how to initialize the process. */ |
| h = _bfd_elf_define_linkage_sym (abfd, info, s, "_DYNAMIC"); |
| elf_hash_table (info)->hdynamic = h; |
| if (h == NULL) |
| return false; |
| |
| if (info->emit_hash) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, ".hash", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| elf_section_data (s)->this_hdr.sh_entsize = bed->s->sizeof_hash_entry; |
| } |
| |
| if (info->emit_gnu_hash && bed->record_xhash_symbol == NULL) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, ".gnu.hash", |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| /* For 64-bit ELF, .gnu.hash is a non-uniform entity size section: |
| 4 32-bit words followed by variable count of 64-bit words, then |
| variable count of 32-bit words. */ |
| if (bed->s->arch_size == 64) |
| elf_section_data (s)->this_hdr.sh_entsize = 0; |
| else |
| elf_section_data (s)->this_hdr.sh_entsize = 4; |
| } |
| |
| if (info->enable_dt_relr) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, ".relr.dyn", |
| (bed->dynamic_sec_flags |
| | SEC_READONLY)); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| elf_hash_table (info)->srelrdyn = s; |
| } |
| |
| /* Let the backend create the rest of the sections. This lets the |
| backend set the right flags. The backend will normally create |
| the .got and .plt sections. */ |
| if (bed->elf_backend_create_dynamic_sections == NULL |
| || ! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) |
| return false; |
| |
| elf_hash_table (info)->dynamic_sections_created = true; |
| |
| return true; |
| } |
| |
| /* Create dynamic sections when linking against a dynamic object. */ |
| |
| bool |
| _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) |
| { |
| flagword flags, pltflags; |
| struct elf_link_hash_entry *h; |
| asection *s; |
| const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
| struct elf_link_hash_table *htab = elf_hash_table (info); |
| |
| /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and |
| .rel[a].bss sections. */ |
| flags = bed->dynamic_sec_flags; |
| |
| pltflags = flags; |
| if (bed->plt_not_loaded) |
| /* We do not clear SEC_ALLOC here because we still want the OS to |
| allocate space for the section; it's just that there's nothing |
| to read in from the object file. */ |
| pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS); |
| else |
| pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD; |
| if (bed->plt_readonly) |
| pltflags |= SEC_READONLY; |
| |
| s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->plt_alignment)) |
| return false; |
| htab->splt = s; |
| |
| /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the |
| .plt section. */ |
| if (bed->want_plt_sym) |
| { |
| h = _bfd_elf_define_linkage_sym (abfd, info, s, |
| "_PROCEDURE_LINKAGE_TABLE_"); |
| elf_hash_table (info)->hplt = h; |
| if (h == NULL) |
| return false; |
| } |
| |
| s = bfd_make_section_anyway_with_flags (abfd, |
| (bed->rela_plts_and_copies_p |
| ? ".rela.plt" : ".rel.plt"), |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->srelplt = s; |
| |
| if (! _bfd_elf_create_got_section (abfd, info)) |
| return false; |
| |
| if (bed->want_dynbss) |
| { |
| /* The .dynbss section is a place to put symbols which are defined |
| by dynamic objects, are referenced by regular objects, and are |
| not functions. We must allocate space for them in the process |
| image and use a R_*_COPY reloc to tell the dynamic linker to |
| initialize them at run time. The linker script puts the .dynbss |
| section into the .bss section of the final image. */ |
| s = bfd_make_section_anyway_with_flags (abfd, ".dynbss", |
| SEC_ALLOC | SEC_LINKER_CREATED); |
| if (s == NULL) |
| return false; |
| htab->sdynbss = s; |
| |
| if (bed->want_dynrelro) |
| { |
| /* Similarly, but for symbols that were originally in read-only |
| sections. This section doesn't really need to have contents, |
| but make it like other .data.rel.ro sections. */ |
| s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro", |
| flags); |
| if (s == NULL) |
| return false; |
| htab->sdynrelro = s; |
| } |
| |
| /* The .rel[a].bss section holds copy relocs. This section is not |
| normally needed. We need to create it here, though, so that the |
| linker will map it to an output section. We can't just create it |
| only if we need it, because we will not know whether we need it |
| until we have seen all the input files, and the first time the |
| main linker code calls BFD after examining all the input files |
| (size_dynamic_sections) the input sections have already been |
| mapped to the output sections. If the section turns out not to |
| be needed, we can discard it later. We will never need this |
| section when generating a shared object, since they do not use |
| copy relocs. */ |
| if (bfd_link_executable (info)) |
| { |
| s = bfd_make_section_anyway_with_flags (abfd, |
| (bed->rela_plts_and_copies_p |
| ? ".rela.bss" : ".rel.bss"), |
| flags | SEC_READONLY); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->srelbss = s; |
| |
| if (bed->want_dynrelro) |
| { |
| s = (bfd_make_section_anyway_with_flags |
| (abfd, (bed->rela_plts_and_copies_p |
| ? ".rela.data.rel.ro" : ".rel.data.rel.ro"), |
| flags | SEC_READONLY)); |
| if (s == NULL |
| || !bfd_set_section_alignment (s, bed->s->log_file_align)) |
| return false; |
| htab->sreldynrelro = s; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /* Record a new dynamic symbol. We record the dynamic symbols as we |
| read the input files, since we need to have a list of all of them |
| before we can determine the final sizes of the output sections. |
| Note that we may actually call this function even though we are not |
| going to output any dynamic symbols; in some cases we know that a |
| symbol should be in the dynamic symbol table, but only if there is |
| one. */ |
| |
| bool |
| bfd_elf_link_record_dynamic_symbol (struct bfd_link_info *info, |
| struct elf_link_hash_entry *h) |
| { |
| if (h->dynindx == -1) |
| { |
| struct elf_strtab_hash *dynstr; |
| char *p; |
| const char *name; |
| size_t indx; |
| |
| if (h->root.type == bfd_link_hash_defined |
| || h->root.type == bfd_link_hash_defweak) |
| { |
| /* An IR symbol should not be made dynamic. */ |
| if (h->root.u.def.section != NULL |
| && h->root.u.def.section->owner != NULL |
| && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0) |
| return true; |
| } |
| |
| /* XXX: The ABI draft says the linker must turn hidden and |
| internal symbols into STB_LOCAL symbols when producing the |
| DSO. However, if ld.so honors st_other in the dynamic table, |
| this would not be necessary. */ |
| switch (ELF_ST_VISIBILITY (h->other)) |
| { |
| case STV_INTERNAL: |
| case STV_HIDDEN: |
| if (h->root.type != bfd_link_hash_undefined |
| && h->root.type != bfd_link_hash_undefweak) |
| { |
| h->forced_local = 1; |
| return true; |
| } |
| |
| default: |
| break; |
| } |
| |
| h->dynindx = elf_hash_table (info)->dynsymcount; |
| ++elf_hash_table (info)->dynsymcount; |
| |
| dynstr = elf_hash_table (info)->dynstr; |
| if (dynstr == NULL) |
| { |
| /* Create a strtab to hold the dynamic symbol names. */ |
| elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init (); |
| if (dynstr == NULL) |
| return false; |
| } |
| |
| char *unversioned_name = NULL; |
| |
| /* We don't put any version information in the dynamic string |
| table. */ |
| name = h->root.root.string; |
| p = strchr (name, ELF_VER_CHR); |
| if (p != NULL) |
| { |
| unversioned_name = bfd_malloc (p - name + 1); |
| memcpy (unversioned_name, name, p - name); |
| unversioned_name[p - name] = 0; |
| name = unversioned_name; |
| } |
| |
| indx = _bfd_elf_strtab_add (dynstr, name, p != NULL); |
| |
| if (p != NULL) |
| free (unversioned_name); |
| |
| if (indx == (size_t) -1) |
| return false; |
| h->dynstr_index = indx; |
| } |
| |
| return true; |
| } |
| |
| /* Mark a symbol dynamic. */ |
| |
| static void |
| bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info, |
| struct elf_link_hash_entry *h, |
| Elf_Internal_Sym *sym) |
| { |
| struct bfd_elf_dynamic_list *d = info->dynamic_list; |
| |
| /* It may be called more than once on the same H. */ |
| if(h->dynamic || bfd_link_relocatable (info)) |
| return; |
| |
| 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_COMMON)))) |
| || (d != NULL |
| && h->non_elf |
| && (*d->match) (&d->head, NULL, h->root.root.string))) |
| { |
| h->dynamic = 1; |
| /* NB: If a symbol is made dynamic by --dynamic-list, it has |
| non-IR reference. */ |
| h->root.non_ir_ref_dynamic = 1; |
| } |
| } |
| |
| /* Record an assignment to a symbol made by a linker script. We need |
| this in case some dynamic object refers to this symbol. */ |
| |
| bool |
| bfd_elf_record_link_assignment (bfd *output_bfd, |
| struct bfd_link_info *info, |
| const char *name, |
| bool provide, |
| bool hidden) |
| { |
| struct elf_link_hash_entry *h, *hv; |
| struct elf_link_hash_table *htab; |
| const struct elf_backend_data *bed; |
| |
| if (!is_elf_hash_table (info->hash)) |
| return true; |
| |
| htab = elf_hash_table (info); |
| h = elf_link_hash_lookup (htab, name, !provide, true, false); |
| if (h == NULL) |
| return provide; |
| |
| if (h->root.type == bfd_link_hash_warning) |
| h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| |
| 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; |
| } |
| } |
| |
| /* Symbols defined in a linker script but not referenced anywhere |
| else will have non_elf set. */ |
| if (h->non_elf) |
| { |
| bfd_elf_link_mark_dynamic_symbol (info, h, NULL); |
| h->non_elf = 0; |
| } |
| |
| switch (h->root.type) |
| { |
| case bfd_link_hash_defined: |
| case bfd_link_hash_defweak: |
| case bfd_link_hash_common: |
| break; |
| case bfd_link_hash_undefweak: |
| case bfd_link_hash_undefined: |
| /* Since we're defining the symbol, don't let it seem to have not |
| been defined. record_dynamic_symbol and size_dynamic_sections |
| may depend on this. */ |
| h->root.type = bfd_link_hash_new; |
| if (h->root.u.undef.next != NULL || htab->root.undefs_tail == &h->root) |
| bfd_link_repair_undef_list (&htab->root); |
| break; |
| case bfd_link_hash_new: |
| break; |
| case bfd_link_hash_indirect: |
| /* We had a versioned symbol in a dynamic library. We make the |
| the versioned symbol point to this one. */ |
| bed = get_elf_backend_data (output_bfd); |
| hv = h; |
| while (hv->root.type == bfd_link_hash_indirect |
| || hv->root.type == bfd_link_hash_warning) |
| hv = (struct elf_link_hash_entry *) hv->root.u.i.link; |
| /* We don't need to update h->root.u since linker will set them |
| later. */ |
| h->root.type = bfd_link_hash_undefined; |
| hv->root.type = bfd_link_hash_indirect; |
| hv->root.u.i.link = (struct bfd_link_hash_entry *) h; |
| (*bed->elf_backend_copy_indirect_symbol) (info, h, hv); |
| break; |
| default: |
| BFD_FAIL (); |
| return false; |
| } |
| |
| /* If this symbol is being provided by the linker script, and it is |
| currently defined by a dynamic object, but not by a regular |
| object, then mark it as undefined so that the generic linker will |
| force the correct value. */ |
| if (provide |
| && h->def_dynamic |
| && !h->def_regular) |
| h->root.type = bfd_link_hash_undefined; |
| |
| /* If this symbol is currently defined by a dynamic object, but not |
| by a regular object, then clear out any version information because |
| the symbol will not be associated with the dynamic object any |
| more. */ |
| if (h->def_dynamic && !h->def_regular) |
| h->verinfo.verdef = NULL; |
| |
| /* Make sure this symbol is not garbage collected. */ |
| h->mark = 1; |
| |
| h->def_regular = 1; |
| |
| if (hidden) |
| { |
| bed = get_elf_backend_data (output_bfd); |
| if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL) |
| h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN; |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| } |
| |
| /* STV_HIDDEN and STV_INTERNAL symbols must be STB_LOCAL in shared objects |
| and executables. */ |
| if (!bfd_link_relocatable (info) |
| && h->dynindx != -1 |
| && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN |
| || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)) |
| h->forced_local = 1; |
| |
| if ((h->def_dynamic |
| || h->ref_dynamic |
| || bfd_link_dll (info)) |
| && !h->forced_local |
| && h->dynindx == -1) |
| { |
| if (! bfd_elf_link_record_dynamic_symbol (info, h)) |
| return false; |
| |
| /* If this is a weak defined symbol, and we know a corresponding |
| real symbol from the same dynamic object, make sure the real |
| symbol is also made into a dynamic symbol. */ |
| if (h->is_weakalias) |
| { |
| struct elf_link_hash_entry *def = weakdef (h); |
| |
| if (def->dynindx == -1 |
| && !bfd_elf_link_record_dynamic_symbol (info, def)) |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /* Record a new local dynamic symbol. Returns 0 on failure, 1 on |
| success, and 2 on a failure caused by attempting to record a symbol |
| in a discarded section, eg. a discarded link-once section symbol. */ |
| |
| int |
| bfd_elf_link_record_local_dynamic_symbol (struct bfd_link_info *info, |
| bfd *input_bfd, |
| long input_indx) |
| { |
| size_t amt; |
| struct elf_link_local_dynamic_entry *entry; |
| struct elf_link_hash_table *eht; |
| struct elf_strtab_hash *dynstr; |
| size_t dynstr_index; |
| char *name; |
| Elf_External_Sym_Shndx eshndx; |
| char esym[sizeof (Elf64_External_Sym)]; |
| |
| if (! is_elf_hash_table (info->hash)) |
| return 0; |
| |
| /* See if the entry exists already. */ |
| for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) |
| if (entry->input_bfd == input_bfd && entry->input_indx == input_indx) |
| return 1; |
| |
| amt = sizeof (*entry); |
| entry = (struct elf_link_local_dynamic_entry *) bfd_alloc (input_bfd, amt); |
| if (entry == NULL) |
| return 0; |
| |
| /* Go find the symbol, so that we can find it's name. */ |
| if (!bfd_elf_get_elf_syms (input_bfd, &elf_tdata (input_bfd)->symtab_hdr, |
| 1, input_indx, &entry->isym, esym, &eshndx)) |
| { |
| bfd_release (input_bfd, entry); |
| return 0; |
| } |
| |
| if (entry->isym.st_shndx != SHN_UNDEF |
| && entry->isym.st_shndx < SHN_LORESERVE) |
| { |
| asection *s; |
| |
| s = bfd_section_from_elf_index (input_bfd, entry->isym.st_shndx); |
| if (s == NULL || bfd_is_abs_section (s->output_section)) |
| { |
| /* We can still bfd_release here as nothing has done another |
| bfd_alloc. We can't do this later in this function. */ |
| bfd_release (input_bfd, entry); |
| return 2; |
| } |
| } |
| |
| name = (bfd_elf_string_from_elf_section |
| (input_bfd, elf_tdata (input_bfd)->symtab_hdr.sh_link, |
| entry->isym.st_name)); |
| |
| dynstr = elf_hash_table (info)->dynstr; |
| if (dynstr == NULL) |
| { |
| /* Create a strtab to hold the dynamic symbol names. */ |
| elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init (); |
| if (dynstr == NULL) |
| return 0; |
| } |
| |
| dynstr_index = _bfd_elf_strtab_add (dynstr, name, false); |
| if (dynstr_index == (size_t) -1) |
| return 0; |
| entry->isym.st_name = dynstr_index; |
| |
| eht = elf_hash_table (info); |
| |
| entry->next = eht->dynlocal; |
| eht->dynlocal = entry; |
| entry->input_bfd = input_bfd; |
| entry->input_indx = input_indx; |
| eht->dynsymcount++; |
| |
| /* Whatever binding the symbol had before, it's now local. */ |
| entry->isym.st_info |
| = ELF_ST_INFO (STB_LOCAL, ELF_ST_TYPE (entry->isym.st_info)); |
| |
| /* The dynindx will be set at the end of size_dynamic_sections. */ |
| |
| return 1; |
| } |
| |
| /* Return the dynindex of a local dynamic symbol. */ |
| |
| long |
| _bfd_elf_link_lookup_local_dynindx (struct bfd_link_info *info, |
| bfd *input_bfd, |
| long input_indx) |
| { |
| struct elf_link_local_dynamic_entry *e; |
| |
| for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) |
| if (e->input_bfd == input_bfd && e->input_indx == input_indx) |
| return e->dynindx; |
| return -1; |
| } |
| |
| /* This function is used to renumber the dynamic symbols, if some of |
| them are removed because they are marked as local. This is called |
| via elf_link_hash_traverse. */ |
| |
| static bool |
| elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h, |
| void *data) |
| { |
| size_t *count = (size_t *) data; |
| |
| if (h->forced_local) |
| return true; |
| |
| if (h->dynindx != -1) |
| h->dynindx = ++(*count); |
| |
| return true; |
| } |
| |
| |
| /* Like elf_link_renumber_hash_table_dynsyms, but just number symbols with |
| STB_LOCAL binding. */ |
| |
| static bool |
| elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h, |
| void *data) |
| { |
| size_t *count = (size_t *) data; |
| |
| if (!h->forced_local) |
| return true; |
| |
| if (h->dynindx != -1) |
| h->dynindx = ++(*count); |
| |
| return true; |
| } |
| |
| /* Return true if the dynamic symbol for a given section should be |
| omitted when creating a shared library. */ |
| bool |
| _bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED, |
| struct bfd_link_info *info, |
| asection *p) |
| { |
| struct elf_link_hash_table *htab; |
| asection *ip; |
| |
| switch (elf_section_data (p)->this_hdr.sh_type) |
| { |
| case SHT_PROGBITS: |
| case SHT_NOBITS: |
| /* If sh_type is yet undecided, assume it could be |
| SHT_PROGBITS/SHT_NOBITS. */ |
| case SHT_NULL: |
| htab = elf_hash_table (info); |
| if (htab->text_index_section != NULL) |
| return p != htab->text_index_section && p != htab->data_index_section; |
| |
| return (htab->dynobj != NULL |
| && (ip = bfd_get_linker_section (htab->dynobj, p->name)) != NULL |
| && ip->output_section == p); |
| |
| /* There shouldn't be section relative relocations |
| against any other section. */ |
| default: |
| return true; |
| } |
| } |
| |
| bool |
| _bfd_elf_omit_section_dynsym_all |
| (bfd *output_bfd ATTRIBUTE_UNUSED, |
| struct bfd_link_info *info ATTRIBUTE_UNUSED, |
| asection *p ATTRIBUTE_UNUSED) |
| { |
| return true; |
| } |
| |
| /* Assign dynsym indices. In a shared library we generate a section |
| symbol for each output section, which come first. Next come symbols |
| which have been forced to local binding. Then all of the back-end |
| allocated local dynamic syms, followed by the rest of the global |
| symbols. If SECTION_SYM_COUNT is NULL, section dynindx is not set. |
| (This prevents the early call before elf_backend_init_index_section |
| and strip_excluded_output_sections setting dynindx for sections |
| that are stripped.) */ |
| |
| static unsigned long |
| _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, |
| struct bfd_link_info *info, |
| unsigned long *section_sym_count) |
| { |
| unsigned long dynsymcount = 0; |
| bool do_sec = section_sym_count != NULL; |
| |
| if (bfd_link_pic (info) |
| || elf_hash_table (info)->is_relocatable_executable) |
| { |
| const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); |
| asection *p; |
| for (p = output_bfd->sections; p ; p = p->next) |
| if ((p->flags & SEC_EXCLUDE) == 0 |
| && (p->flags & SEC_ALLOC) != 0 |
| && elf_hash_table (info)->dynamic_relocs |
| && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p)) |
| { |
| ++dynsymcount; |
| if (do_sec) |
| elf_section_data (p)->dynindx = dynsymcount; |
| } |
| else if (do_sec) |
| elf_section_data (p)->dynindx = 0; |
| } |
| if (do_sec) |
| *section_sym_count = dynsymcount; |
| |
| elf_link_hash_traverse (elf_hash_table (info), |
| elf_link_renumber_local_hash_table_dynsyms, |
| &dynsymcount); |
| |
| if (elf_hash_table (info)->dynlocal) |
| { |
| struct elf_link_local_dynamic_entry *p; |
| for (p = elf_hash_table (info)->dynlocal; p ; p = p->next) |
| p->dynindx = ++dynsymcount; |
| } |
| elf_hash_table (info)->local_dynsymcount = dynsymcount; |
| |
| elf_link_hash_traverse (elf_hash_table (info), |
| 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 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; |
| } |
| |
| /* Merge st_other field. */ |
| |
| static void |
| elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, |
| unsigned int st_other, asection *sec, |
| bool definition, bool dynamic) |
| { |
| const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
| |
| /* If st_other has a processor-specific meaning, specific |
| code might be needed here. */ |
| if (bed->elf_backend_merge_symbol_attribute) |
| (*bed->elf_backend_merge_symbol_attribute) (h, st_other, definition, |
| dynamic); |
| |
| if (!dynamic) |
| { |
| unsigned symvis = ELF_ST_VISIBILITY (st_other); |
| unsigned hvis = ELF_ST_VISIBILITY (h->other); |
| |
| /* Keep the most constraining visibility. Leave the remainder |
| of the st_other field to elf_backend_merge_symbol_attribute. */ |
| if (symvis - 1 < hvis - 1) |
| h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1)); |
| } |
| else if (definition |
| && ELF_ST_VISIBILITY (st_other) != STV_DEFAULT |
| && (sec->flags & SEC_READONLY) == 0) |
| h->protected_def = 1; |
| } |
| |
| /* This function is called when we want to merge a new symbol with an |
| existing symbol. It handles the various cases which arise when we |
| find a definition in a dynamic object, or when there is already a |
| definition in a dynamic object. The new symbol is described by |
| NAME, SYM, PSEC, and PVALUE. We set SYM_HASH to the hash table |
| entry. We set POLDBFD to the old symbol's BFD. We set POLD_WEAK |
| if the old symbol was weak. We set POLD_ALIGNMENT to the alignment |
| of an old common symbol. We set OVERRIDE if the old symbol is |
| overriding a new definition. We set TYPE_CHANGE_OK if it is OK for |
| the type to change. We set SIZE_CHANGE_OK if it is OK for the size |
| to change. By OK to change, we mean that we shouldn't warn if the |
| type or size does change. */ |
| |
| static bool |
| _bfd_elf_merge_symbol (bfd *abfd, |
| struct bfd_link_info *info, |
| const char *name, |
| Elf_Internal_Sym *sym, |
| asection **psec, |
| bfd_vma *pvalue, |
| struct elf_link_hash_entry **sym_hash, |
| bfd **poldbfd, |
| bool *pold_weak, |
| unsigned int *pold_alignment, |
| bool *skip, |
| bfd **override, |
| bool *type_change_ok, |
| bool *size_change_ok, |
| bool *matched) |
| { |
| asection *sec, *oldsec; |
| struct elf_link_hash_entry *h; |
| struct elf_link_hash_entry *hi; |
| struct elf_link_hash_entry *flip; |
| int bind; |
| bfd *oldbfd; |
| bool newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon; |
| bool newweak, oldweak, newfunc, oldfunc; |
| const struct elf_backend_data *bed; |
| char *new_version; |
| bool default_sym = *matched; |
| struct elf_link_hash_table *htab; |
| |
| *skip = false; |
| *override = NULL; |
| |
| sec = *psec; |
| bind = ELF_ST_BIND (sym->st_info); |
| |
| if (! bfd_is_und_section (sec)) |
| h = elf_link_hash_lookup (elf_hash_table (info), name, true, false, false); |
| else |
| h = ((struct elf_link_hash_entry *) |
| bfd_wrapped_link_hash_lookup (abfd, info, name, true, false, false)); |
| if (h == NULL) |
| return false; |
| *sym_hash = h; |
| |
| bed = get_elf_backend_data (abfd); |
| |
| /* NEW_VERSION is the symbol version of the new symbol. */ |
| if (h->versioned != unversioned) |
| { |
| /* Symbol version is unknown or versioned. */ |
| new_version = strrchr (name, ELF_VER_CHR); |
| if (new_version) |
| { |
| if (h->versioned == unknown) |
| { |
| if (new_version > name && new_version[-1] != ELF_VER_CHR) |
| h->versioned = versioned_hidden; |
| else |
| h->versioned = versioned; |
| } |
| new_version += 1; |
| if (new_version[0] == '\0') |
| new_version = NULL; |
| } |
| else |
| h->versioned = unversioned; |
| } |
| else |
| new_version = NULL; |
| |
| /* For merging, we only care about real symbols. But we need to make |
| sure that indirect symbol dynamic flags are updated. */ |
| hi = h; |
| while (h->root.type == bfd_link_hash_indirect |
| || h->root.type == bfd_link_hash_warning) |
| h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| |
| if (!*matched) |
| { |
| if (hi == h || h->root.type == bfd_link_hash_new) |
| *matched = true; |
| else |
| { |
| /* OLD_HIDDEN is true if the existing symbol is only visible |
| to the symbol with the same symbol version. NEW_HIDDEN is |
| true if the new symbol is only visible to the symbol with |
| the same symbol version. */ |
| bool old_hidden = h->versioned == versioned_hidden; |
| bool new_hidden = hi->versioned == versioned_hidden; |
| if (!old_hidden && !new_hidden) |
| /* The new symbol matches the existing symbol if both |
| aren't hidden. */ |
| *matched = true; |
| else |
| { |
| /* OLD_VERSION is the symbol version of the existing |
| symbol. */ |
| char *old_version; |
| |
| if (h->versioned >= versioned) |
| old_version = strrchr (h->root.root.string, |
| ELF_VER_CHR) + 1; |
| else |
| old_version = NULL; |
| |
| /* The new symbol matches the existing symbol if they |
| have the same symbol version. */ |
| *matched = (old_version == new_version |
| || (old_version != NULL |
| && new_version != NULL |
| && strcmp (old_version, new_version) == 0)); |
| } |
| } |
| } |
| |
| /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the |
| existing symbol. */ |
| |
| oldbfd = NULL; |
| oldsec = NULL; |
| switch (h->root.type) |
| { |
| default: |
| break; |
| |
| case bfd_link_hash_undefined: |
| case bfd_link_hash_undefweak: |
| oldbfd = h->root.u.undef.abfd; |
| break; |
| |
| case bfd_link_hash_defined: |
| case bfd_link_hash_defweak: |
| oldbfd = h->root.u.def.section->owner; |
| oldsec = h->root.u.def.section; |
| break; |
| |
| case bfd_link_hash_common: |
| oldbfd = h->root.u.c.p->section->owner; |
| oldsec = h->root.u.c.p->section; |
| if (pold_alignment) |
| *pold_alignment = h->root.u.c.p->alignment_power; |
| break; |
| } |
| if (poldbfd && *poldbfd == NULL) |
| *poldbfd = oldbfd; |
| |
| /* Differentiate strong and weak symbols. */ |
| newweak = bind == STB_WEAK; |
| oldweak = (h->root.type == bfd_link_hash_defweak |
| || h->root.type == bfd_link_hash_undefweak); |
| if (pold_weak) |
| *pold_weak = oldweak; |
| |
| /* We have to check it for every instance since the first few may be |
| references and not all compilers emit symbol type for undefined |
| symbols. */ |
| bfd_elf_link_mark_dynamic_symbol (info, h, sym); |
| |
| htab = elf_hash_table (info); |
| |
| /* NEWDYN and OLDDYN indicate whether the new or old symbol, |
| respectively, is from a dynamic object. */ |
| |
| newdyn = (abfd->flags & DYNAMIC) != 0; |
| |
| /* ref_dynamic_nonweak and dynamic_def flags track actual undefined |
| syms and defined syms in dynamic libraries respectively. |
| ref_dynamic on the other hand can be set for a symbol defined in |
| a dynamic library, and def_dynamic may not be set; When the |
| definition in a dynamic lib is overridden by a definition in the |
| executable use of the symbol in the dynamic lib becomes a |
| reference to the executable symbol. */ |
| if (newdyn) |
| { |
| if (bfd_is_und_section (sec)) |
| { |
| if (bind != STB_WEAK) |
| { |
| h->ref_dynamic_nonweak = 1; |
| hi->ref_dynamic_nonweak = 1; |
| } |
| } |
| else |
| { |
| /* Update the existing symbol only if they match. */ |
| if (*matched) |
| h->dynamic_def = 1; |
| hi->dynamic_def = 1; |
| } |
| } |
| |
| /* If we just created the symbol, mark it as being an ELF symbol. |
| Other than that, there is nothing to do--there is no merge issue |
| with a newly defined symbol--so we just return. */ |
| |
| if (h->root.type == bfd_link_hash_new) |
| { |
| h->non_elf = 0; |
| return true; |
| } |
| |
| /* In cases involving weak versioned symbols, we may wind up trying |
| to merge a symbol with itself. Catch that here, to avoid the |
| confusion that results if we try to override a symbol with |
| itself. The additional tests catch cases like |
| _GLOBAL_OFFSET_TABLE_, which are regular symbols defined in a |
| dynamic object, which we do want to handle here. */ |
| if (abfd == oldbfd |
| && (newweak || oldweak) |
| && ((abfd->flags & DYNAMIC) == 0 |
| || !h->def_regular)) |
| return true; |
| |
| olddyn = false; |
| if (oldbfd != NULL) |
| olddyn = (oldbfd->flags & DYNAMIC) != 0; |
| else if (oldsec != NULL) |
| { |
| /* This handles the special SHN_MIPS_{TEXT,DATA} section |
| indices used by MIPS ELF. */ |
| olddyn = (oldsec->symbol->flags & BSF_DYNAMIC) != 0; |
| } |
| |
| /* Set non_ir_ref_dynamic only when not handling DT_NEEDED entries. */ |
| if (!htab->handling_dt_needed |
| && oldbfd != NULL |
| && (oldbfd->flags & BFD_PLUGIN) != (abfd->flags & BFD_PLUGIN)) |
| { |
| if (newdyn != olddyn) |
| { |
| /* Handle a case where plugin_notice won't be called and thus |
| won't set the non_ir_ref flags on the first pass over |
| symbols. */ |
| h->root.non_ir_ref_dynamic = true; |
| hi->root.non_ir_ref_dynamic = true; |
| } |
| else if ((oldbfd->flags & BFD_PLUGIN) != 0 |
| && hi->root.type == bfd_link_hash_indirect) |
| { |
| /* Change indirect symbol from IR to undefined. */ |
| hi->root.type = bfd_link_hash_undefined; |
| hi->root.u.undef.abfd = oldbfd; |
| } |
| } |
| |
| /* NEWDEF and OLDDEF indicate whether the new or old symbol, |
| respectively, appear to be a definition rather than reference. */ |
| |
| newdef = !bfd_is_und_section (sec) && !bfd_is_com_section (sec); |
| |
| olddef = (h->root.type != bfd_link_hash_undefined |
| && h->root.type != bfd_link_hash_undefweak |
| && h->root.type != bfd_link_hash_common); |
| |
| /* NEWFUNC and OLDFUNC indicate whether the new or old symbol, |
| respectively, appear to be a function. */ |
| |
| newfunc = (ELF_ST_TYPE (sym->st_info) != STT_NOTYPE |
| && bed->is_function_type (ELF_ST_TYPE (sym->st_info))); |
| |
| oldfunc = (h->type != STT_NOTYPE |
| && bed->is_function_type (h->type)); |
| |
| if (!(newfunc && oldfunc) |
| && ELF_ST_TYPE (sym->st_info) != h->type |
| && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE |
| && h->type != STT_NOTYPE |
| && (newdef || bfd_is_com_section (sec)) |
| && (olddef || h->root.type == bfd_link_hash_common)) |
| { |
| /* If creating a default indirect symbol ("foo" or "foo@") from |
| a dynamic versioned definition ("foo@@") skip doing so if |
| there is an existing regular definition with a different |
| type. We don't want, for example, a "time" variable in the |
| executable overriding a "time" function in a shared library. */ |
| if (newdyn |
| && !olddyn) |
| { |
| *skip = true; |
| return true; |
| } |
| |
| /* When adding a symbol from a regular object file after we have |
| created indirect symbols, undo the indirection and any |
| dynamic state. */ |
| if (hi != h |
| && !newdyn |
| && olddyn) |
| { |
| h = hi; |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| h->forced_local = 0; |
| h->ref_dynamic = 0; |
| h->def_dynamic = 0; |
| h->dynamic_def = 0; |
| if (h->root.u.undef.next || info->hash->undefs_tail == &h->root) |
| { |
| h->root.type = bfd_link_hash_undefined; |
| h->root.u.undef.abfd = abfd; |
| } |
| else |
| { |
| h->root.type = bfd_link_hash_new; |
| h->root.u.undef.abfd = NULL; |
| } |
| return true; |
| } |
| } |
| |
| /* Check TLS symbols. We don't check undefined symbols introduced |
| by "ld -u" which have no type (and oldbfd NULL), and we don't |
| check symbols from plugins because they also have no type. */ |
| if (oldbfd != NULL |
| && (oldbfd->flags & BFD_PLUGIN) == 0 |
| && (abfd->flags & BFD_PLUGIN) == 0 |
| && ELF_ST_TYPE (sym->st_info) != h->type |
| && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) |
| { |
| bfd *ntbfd, *tbfd; |
| bool ntdef, tdef; |
| asection *ntsec, *tsec; |
| |
| if (h->type == STT_TLS) |
| { |
| ntbfd = abfd; |
| ntsec = sec; |
| ntdef = newdef; |
| tbfd = oldbfd; |
| tsec = oldsec; |
| tdef = olddef; |
| } |
| else |
| { |
| ntbfd = oldbfd; |
| ntsec = oldsec; |
| ntdef = olddef; |
| tbfd = abfd; |
| tsec = sec; |
| tdef = newdef; |
| } |
| |
| if (tdef && ntdef) |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%s: TLS definition in %pB section %pA " |
| "mismatches non-TLS definition in %pB section %pA"), |
| h->root.root.string, tbfd, tsec, ntbfd, ntsec); |
| else if (!tdef && !ntdef) |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%s: TLS reference in %pB " |
| "mismatches non-TLS reference in %pB"), |
| h->root.root.string, tbfd, ntbfd); |
| else if (tdef) |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%s: TLS definition in %pB section %pA " |
| "mismatches non-TLS reference in %pB"), |
| h->root.root.string, tbfd, tsec, ntbfd); |
| else |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%s: TLS reference in %pB " |
| "mismatches non-TLS definition in %pB section %pA"), |
| h->root.root.string, tbfd, ntbfd, ntsec); |
| |
| bfd_set_error (bfd_error_bad_value); |
| return false; |
| } |
| |
| /* If the old symbol has non-default visibility, we ignore the new |
| definition from a dynamic object. */ |
| if (newdyn |
| && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT |
| && !bfd_is_und_section (sec)) |
| { |
| *skip = true; |
| /* Make sure this symbol is dynamic. */ |
| h->ref_dynamic = 1; |
| hi->ref_dynamic = 1; |
| /* A protected symbol has external availability. Make sure it is |
| recorded as dynamic. |
| |
| FIXME: Should we check type and size for protected symbol? */ |
| if (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED) |
| return bfd_elf_link_record_dynamic_symbol (info, h); |
| else |
| return true; |
| } |
| else if (!newdyn |
| && ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT |
| && h->def_dynamic) |
| { |
| /* If the new symbol with non-default visibility comes from a |
| relocatable file and the old definition comes from a dynamic |
| object, we remove the old definition. */ |
| if (hi->root.type == bfd_link_hash_indirect) |
| { |
| /* Handle the case where the old dynamic definition is |
| default versioned. We need to copy the symbol info from |
| the symbol with default version to the normal one if it |
| was referenced before. */ |
| if (h->ref_regular) |
| { |
| hi->root.type = h->root.type; |
| h->root.type = bfd_link_hash_indirect; |
| (*bed->elf_backend_copy_indirect_symbol) (info, hi, h); |
| |
| h->root.u.i.link = (struct bfd_link_hash_entry *) hi; |
| if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED) |
| { |
| /* If the new symbol is hidden or internal, completely undo |
| any dynamic link state. */ |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| h->forced_local = 0; |
| h->ref_dynamic = 0; |
| } |
| else |
| h->ref_dynamic = 1; |
| |
| h->def_dynamic = 0; |
| /* FIXME: Should we check type and size for protected symbol? */ |
| h->size = 0; |
| h->type = 0; |
| |
| h = hi; |
| } |
| else |
| h = hi; |
| } |
| |
| /* If the old symbol was undefined before, then it will still be |
| on the undefs list. If the new symbol is undefined or |
| common, we can't make it bfd_link_hash_new here, because new |
| undefined or common symbols will be added to the undefs list |
| by _bfd_generic_link_add_one_symbol. Symbols may not be |
| added twice to the undefs list. Also, if the new symbol is |
| undefweak then we don't want to lose the strong undef. */ |
| if (h->root.u.undef.next || info->hash->undefs_tail == &h->root) |
| { |
| h->root.type = bfd_link_hash_undefined; |
| h->root.u.undef.abfd = abfd; |
| } |
| else |
| { |
| h->root.type = bfd_link_hash_new; |
| h->root.u.undef.abfd = NULL; |
| } |
| |
| if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED) |
| { |
| /* If the new symbol is hidden or internal, completely undo |
| any dynamic link state. */ |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| h->forced_local = 0; |
| h->ref_dynamic = 0; |
| } |
| else |
| h->ref_dynamic = 1; |
| h->def_dynamic = 0; |
| /* FIXME: Should we check type and size for protected symbol? */ |
| h->size = 0; |
| h->type = 0; |
| return true; |
| } |
| |
| /* If a new weak symbol definition comes from a regular file and the |
| old symbol comes from a dynamic library, we treat the new one as |
| strong. Similarly, an old weak symbol definition from a regular |
| file is treated as strong when the new symbol comes from a dynamic |
| library. Further, an old weak symbol from a dynamic library is |
| treated as strong if the new symbol is from a dynamic library. |
| This reflects the way glibc's ld.so works. |
| |
| Also allow a weak symbol to override a linker script symbol |
| defined by an early pass over the script. This is done so the |
| linker knows the symbol is defined in an object file, for the |
| DEFINED script function. |
| |
| Do this before setting *type_change_ok or *size_change_ok so that |
| we warn properly when dynamic library symbols are overridden. */ |
| |
| if (newdef && !newdyn && (olddyn || h->root.ldscript_def)) |
| newweak = false; |
| if (olddef && newdyn) |
| oldweak = false; |
| |
| /* Allow changes between different types of function symbol. */ |
| if (newfunc && oldfunc) |
| *type_change_ok = true; |
| |
| /* It's OK to change the type if either the existing symbol or the |
| new symbol is weak. A type change is also OK if the old symbol |
| is undefined and the new symbol is defined. */ |
| |
| if (oldweak |
| || newweak |
| || (newdef |
| && h->root.type == bfd_link_hash_undefined)) |
| *type_change_ok = true; |
| |
| /* It's OK to change the size if either the existing symbol or the |
| new symbol is weak, or if the old symbol is undefined. */ |
| |
| if (*type_change_ok |
| || h->root.type == bfd_link_hash_undefined) |
| *size_change_ok = true; |
| |
| /* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old |
| symbol, respectively, appears to be a common symbol in a dynamic |
| object. If a symbol appears in an uninitialized section, and is |
| not weak, and is not a function, then it may be a common symbol |
| which was resolved when the dynamic object was created. We want |
| to treat such symbols specially, because they raise special |
| considerations when setting the symbol size: if the symbol |
| appears as a common symbol in a regular object, and the size in |
| the regular object is larger, we must make sure that we use the |
| larger size. This problematic case can always be avoided in C, |
| but it must be handled correctly when using Fortran shared |
| libraries. |
| |
| Note that if NEWDYNCOMMON is set, NEWDEF will be set, and |
| likewise for OLDDYNCOMMON and OLDDEF. |
| |
| Note that this test is just a heuristic, and that it is quite |
| possible to have an uninitialized symbol in a shared object which |
| is really a definition, rather than a common symbol. This could |
| lead to some minor confusion when the symbol really is a common |
| symbol in some regular object. However, I think it will be |
| harmless. */ |
| |
| if (newdyn |
| && newdef |
| && !newweak |
| && (sec->flags & SEC_ALLOC) != 0 |
| && (sec->flags & SEC_LOAD) == 0 |
| && sym->st_size > 0 |
| && !newfunc) |
| newdyncommon = true; |
| else |
| newdyncommon = false; |
| |
| if (olddyn |
| && olddef |
| && h->root.type == bfd_link_hash_defined |
| && h->def_dynamic |
| && (h->root.u.def.section->flags & SEC_ALLOC) != 0 |
| && (h->root.u.def.section->flags & SEC_LOAD) == 0 |
| && h->size > 0 |
| && !oldfunc) |
| olddyncommon = true; |
| else |
| olddyncommon = false; |
| |
| /* We now know everything about the old and new symbols. We ask the |
| backend to check if we can merge them. */ |
| if (bed->merge_symbol != NULL) |
| { |
| if (!bed->merge_symbol (h, sym, psec, newdef, olddef, oldbfd, oldsec)) |
| return false; |
| sec = *psec; |
| } |
| |
| /* There are multiple definitions of a normal symbol. Skip the |
| default symbol as well as definition from an IR object. */ |
| if (olddef && !olddyn && !oldweak && newdef && !newdyn && !newweak |
| && !default_sym && h->def_regular |
| && !(oldbfd != NULL |
| && (oldbfd->flags & BFD_PLUGIN) != 0 |
| && (abfd->flags & BFD_PLUGIN) == 0)) |
| { |
| /* Handle a multiple definition. */ |
| (*info->callbacks->multiple_definition) (info, &h->root, |
| abfd, sec, *pvalue); |
| *skip = true; |
| return true; |
| } |
| |
| /* If both the old and the new symbols look like common symbols in a |
| dynamic object, set the size of the symbol to the larger of the |
| two. */ |
| |
| if (olddyncommon |
| && newdyncommon |
| && sym->st_size != h->size) |
| { |
| /* Since we think we have two common symbols, issue a multiple |
| common warning if desired. Note that we only warn if the |
| size is different. If the size is the same, we simply let |
| the old symbol override the new one as normally happens with |
| symbols defined in dynamic objects. */ |
| |
| (*info->callbacks->multiple_common) (info, &h->root, abfd, |
| bfd_link_hash_common, sym->st_size); |
| if (sym->st_size > h->size) |
| h->size = sym->st_size; |
| |
| *size_change_ok = true; |
| } |
| |
| /* If we are looking at a dynamic object, and we have found a |
| definition, we need to see if the symbol was already defined by |
| some other object. If so, we want to use the existing |
| definition, and we do not want to report a multiple symbol |
| definition error; we do this by clobbering *PSEC to be |
| bfd_und_section_ptr. |
| |
| We treat a common symbol as a definition if the symbol in the |
| shared library is a function, since common symbols always |
| 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. */ |
| |
| if (newdyn |
| && newdef |
| && (olddef |
| || (h->root.type == bfd_link_hash_common |
| && (newweak || newfunc)))) |
| { |
| *override = abfd; |
| newdef = false; |
| newdyncommon = false; |
| |
| *psec = sec = bfd_und_section_ptr; |
| *size_change_ok = true; |
| |
| /* If we get here when the old symbol is a common symbol, then |
| we are explicitly letting it override a weak symbol or |
| function in a dynamic object, and we don't want to warn about |
| a type change. If the old symbol is a defined symbol, a type |
| change warning may still be appropriate. */ |
| |
| if (h->root.type == bfd_link_hash_common) |
| *type_change_ok = true; |
| } |
| |
| /* Handle the special case of an old common symbol merging with a |
| new symbol which looks like a common symbol in a shared object. |
| We change *PSEC and *PVALUE to make the new symbol look like a |
| common symbol, and let _bfd_generic_link_add_one_symbol do the |
| right thing. */ |
| |
| if (newdyncommon |
| && h->root.type == bfd_link_hash_common) |
| { |
| *override = oldbfd; |
| newdef = false; |
| newdyncommon = false; |
| *pvalue = sym->st_size; |
| *psec = sec = bed->common_section (oldsec); |
| *size_change_ok = true; |
| } |
| |
| /* Skip weak definitions of symbols that are already defined. */ |
| if (newdef && olddef && newweak) |
| { |
| /* Don't skip new non-IR weak syms. */ |
| if (!(oldbfd != NULL |
| && (oldbfd->flags & BFD_PLUGIN) != 0 |
| && (abfd->flags & BFD_PLUGIN) == 0)) |
| { |
| newdef = false; |
| *skip = true; |
| } |
| |
| /* Merge st_other. If the symbol already has a dynamic index, |
| but visibility says it should not be visible, turn it into a |
| local symbol. */ |
| elf_merge_st_other (abfd, h, sym->st_other, sec, newdef, newdyn); |
| if (h->dynindx != -1) |
| switch (ELF_ST_VISIBILITY (h->other)) |
| { |
| case STV_INTERNAL: |
| case STV_HIDDEN: |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| break; |
| } |
| } |
| |
| /* If the old symbol is from a dynamic object, and the new symbol is |
| a definition which is not from a dynamic object, then the new |
| symbol overrides the old symbol. Symbols from regular files |
| always take precedence over symbols from dynamic objects, even if |
| they are defined after the dynamic object in the link. |
| |
| As above, we again permit a common symbol in a regular object to |
| override a definition in a shared object if the shared object |
| symbol is a function or is weak. */ |
| |
| flip = NULL; |
| if (!newdyn |
| && (newdef |
| || (bfd_is_com_section (sec) |
| && (oldweak || oldfunc))) |
| && olddyn |
| && olddef |
| && h->def_dynamic) |
| { |
| /* Change the hash table entry to undefined, and let |
| _bfd_generic_link_add_one_symbol do the right thing with the |
| new definition. */ |
| |
| h->root.type = bfd_link_hash_undefined; |
| h->root.u.undef.abfd = h->root.u.def.section->owner; |
| *size_change_ok = true; |
| |
| olddef = false; |
| olddyncommon = false; |
| |
| /* We again permit a type change when a common symbol may be |
| overriding a function. */ |
| |
| if (bfd_is_com_section (sec)) |
| { |
| if (oldfunc) |
| { |
| /* If a common symbol overrides a function, make sure |
| that it isn't defined dynamically nor has type |
| function. */ |
| h->def_dynamic = 0; |
| h->type = STT_NOTYPE; |
| } |
| *type_change_ok = true; |
| } |
| |
| if (hi->root.type == bfd_link_hash_indirect) |
| flip = hi; |
| else |
| /* This union may have been set to be non-NULL when this symbol |
| was seen in a dynamic object. We must force the union to be |
| NULL, so that it is correct for a regular symbol. */ |
| h->verinfo.vertree = NULL; |
| } |
| |
| /* Handle the special case of a new common symbol merging with an |
| old symbol that looks like it might be a common symbol defined in |
| a shared object. Note that we have already handled the case in |
| which a new common symbol should simply override the definition |
| in the shared library. */ |
| |
| if (! newdyn |
| && bfd_is_com_section (sec) |
| && olddyncommon) |
| { |
| /* It would be best if we could set the hash table entry to a |
| common symbol, but we don't know what to use for the section |
| or the alignment. */ |
| (*info->callbacks->multiple_common) (info, &h->root, abfd, |
| bfd_link_hash_common, sym->st_size); |
| |
| /* If the presumed common symbol in the dynamic object is |
| larger, pretend that the new symbol has its size. */ |
| |
| if (h->size > *pvalue) |
| *pvalue = h->size; |
| |
| /* We need to remember the alignment required by the symbol |
| in the dynamic object. */ |
| BFD_ASSERT (pold_alignment); |
| *pold_alignment = h->root.u.def.section->alignment_power; |
| |
| olddef = false; |
| olddyncommon = false; |
| |
| h->root.type = bfd_link_hash_undefined; |
| h->root.u.undef.abfd = h->root.u.def.section->owner; |
| |
| *size_change_ok = true; |
| *type_change_ok = true; |
| |
| if (hi->root.type == bfd_link_hash_indirect) |
| flip = hi; |
| else |
| h->verinfo.vertree = NULL; |
| } |
| |
| if (flip != NULL) |
| { |
| /* Handle the case where we had a versioned symbol in a dynamic |
| library and now find a definition in a normal object. In this |
| case, we make the versioned symbol point to the normal one. */ |
| flip->root.type = h->root.type; |
| flip->root.u.undef.abfd = h->root.u.undef.abfd; |
| h->root.type = bfd_link_hash_indirect; |
| h->root.u.i.link = (struct bfd_link_hash_entry *) flip; |
| (*bed->elf_backend_copy_indirect_symbol) (info, flip, h); |
| if (h->def_dynamic) |
| { |
| h->def_dynamic = 0; |
| flip->ref_dynamic = 1; |
| } |
| } |
| |
| return true; |
| } |
| |
| /* This function is called to create an indirect symbol from the |
| default for the symbol with the default version if needed. The |
| symbol is described by H, NAME, SYM, SEC, and VALUE. We |
| set DYNSYM if the new indirect symbol is dynamic. */ |
| |
| static bool |
| _bfd_elf_add_default_symbol (bfd *abfd, |
| struct bfd_link_info *info, |
| struct elf_link_hash_entry *h, |
| const char *name, |
| Elf_Internal_Sym *sym, |
| asection *sec, |
| bfd_vma value, |
| bfd **poldbfd, |
| bool *dynsym) |
| { |
| bool type_change_ok; |
| bool size_change_ok; |
| bool skip; |
| char *shortname; |
| struct elf_link_hash_entry *hi; |
| struct bfd_link_hash_entry *bh; |
| const struct elf_backend_data *bed; |
| bool collect; |
| bool dynamic; |
| bfd *override; |
| char *p; |
| size_t len, shortlen; |
| asection *tmp_sec; |
| bool matched; |
| |
| if (h->versioned == unversioned || h->versioned == versioned_hidden) |
| return true; |
| |
| /* If this symbol has a version, and it is the default version, we |
| create an indirect symbol from the default name to the fully |
| decorated name. This will cause external references which do not |
| specify a version to be bound to this version of the symbol. */ |
| p = strchr (name, ELF_VER_CHR); |
| if (h->versioned == unknown) |
| { |
| if (p == NULL) |
| { |
| h->versioned = unversioned; |
| return true; |
| } |
| else |
| { |
| if (p[1] != ELF_VER_CHR) |
| { |
| h->versioned = versioned_hidden; |
| return true; |
| } |
| else |
| h->versioned = versioned; |
| } |
| } |
| else |
| { |
| /* PR ld/19073: We may see an unversioned definition after the |
| default version. */ |
| if (p == NULL) |
| return true; |
| } |
| |
| bed = get_elf_backend_data (abfd); |
| collect = bed->collect; |
| dynamic = (abfd->flags & DYNAMIC) != 0; |
| |
| shortlen = p - name; |
| shortname = (char *) bfd_hash_allocate (&info->hash->table, shortlen + 1); |
| if (shortname == NULL) |
| return false; |
| memcpy (shortname, name, shortlen); |
| shortname[shortlen] = '\0'; |
| |
| /* We are going to create a new symbol. Merge it with any existing |
| symbol with this name. For the purposes of the merge, act as |
| though we were defining the symbol we just defined, although we |
| actually going to define an indirect symbol. */ |
| type_change_ok = false; |
| size_change_ok = false; |
| matched = true; |
| tmp_sec = sec; |
| if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, |
| &hi, poldbfd, NULL, NULL, &skip, &override, |
| &type_change_ok, &size_change_ok, &matched)) |
| return false; |
| |
| if (skip) |
| goto nondefault; |
| |
| if (hi->def_regular || ELF_COMMON_DEF_P (hi)) |
| { |
| /* If the undecorated symbol will have a version added by a |
| script different to H, then don't indirect to/from the |
| undecorated symbol. This isn't ideal because we may not yet |
| have seen symbol versions, if given by a script on the |
| command line rather than via --version-script. */ |
| if (hi->verinfo.vertree == NULL && info->version_info != NULL) |
| { |
| bool hide; |
| |
| hi->verinfo.vertree |
| = bfd_find_version_for_sym (info->version_info, |
| hi->root.root.string, &hide); |
| if (hi->verinfo.vertree != NULL && hide) |
| { |
| (*bed->elf_backend_hide_symbol) (info, hi, true); |
| goto nondefault; |
| } |
| } |
| if (hi->verinfo.vertree != NULL |
| && strcmp (p + 1 + (p[1] == '@'), hi->verinfo.vertree->name) != 0) |
| goto nondefault; |
| } |
| |
| if (! override) |
| { |
| /* Add the default symbol if not performing a relocatable link. */ |
| if (! bfd_link_relocatable (info)) |
| { |
| bh = &hi->root; |
| if (bh->type == bfd_link_hash_defined |
| && bh->u.def.section->owner != NULL |
| && (bh->u.def.section->owner->flags & BFD_PLUGIN) != 0) |
| { |
| /* Mark the previous definition from IR object as |
| undefined so that the generic linker will override |
| it. */ |
| bh->type = bfd_link_hash_undefined; |
| bh->u.undef.abfd = bh->u.def.section->owner; |
| } |
| if (! (_bfd_generic_link_add_one_symbol |
| (info, abfd, shortname, BSF_INDIRECT, |
| bfd_ind_section_ptr, |
| 0, name, false, collect, &bh))) |
| return false; |
| hi = (struct elf_link_hash_entry *) bh; |
| } |
| } |
| else |
| { |
| /* In this case the symbol named SHORTNAME is overriding the |
| indirect symbol we want to add. We were planning on making |
| SHORTNAME an indirect symbol referring to NAME. SHORTNAME |
| is the name without a version. NAME is the fully versioned |
| name, and it is the default version. |
| |
| Overriding means that we already saw a definition for the |
| symbol SHORTNAME in a regular object, and it is overriding |
| the symbol defined in the dynamic object. |
| |
| When this happens, we actually want to change NAME, the |
| symbol we just added, to refer to SHORTNAME. This will cause |
| references to NAME in the shared object to become references |
| to SHORTNAME in the regular object. This is what we expect |
| when we override a function in a shared object: that the |
| references in the shared object will be mapped to the |
| definition in the regular object. */ |
| |
| while (hi->root.type == bfd_link_hash_indirect |
| || hi->root.type == bfd_link_hash_warning) |
| hi = (struct elf_link_hash_entry *) hi->root.u.i.link; |
| |
| h->root.type = bfd_link_hash_indirect; |
| h->root.u.i.link = (struct bfd_link_hash_entry *) hi; |
| if (h->def_dynamic) |
| { |
| h->def_dynamic = 0; |
| hi->ref_dynamic = 1; |
| if (hi->ref_regular |
| || hi->def_regular) |
| { |
| if (! bfd_elf_link_record_dynamic_symbol (info, hi)) |
| return false; |
| } |
| } |
| |
| /* Now set HI to H, so that the following code will set the |
| other fields correctly. */ |
| hi = h; |
| } |
| |
| /* Check if HI is a warning symbol. */ |
| if (hi->root.type == bfd_link_hash_warning) |
| hi = (struct elf_link_hash_entry *) hi->root.u.i.link; |
| |
| /* If there is a duplicate definition somewhere, then HI may not |
| point to an indirect symbol. We will have reported an error to |
| the user in that case. */ |
| |
| if (hi->root.type == bfd_link_hash_indirect) |
| { |
| struct elf_link_hash_entry *ht; |
| |
| ht = (struct elf_link_hash_entry *) hi->root.u.i.link; |
| (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi); |
| |
| /* If we first saw a reference to SHORTNAME with non-default |
| visibility, merge that visibility to the @@VER symbol. */ |
| elf_merge_st_other (abfd, ht, hi->other, sec, true, dynamic); |
| |
| /* A reference to the SHORTNAME symbol from a dynamic library |
| will be satisfied by the versioned symbol at runtime. In |
| effect, we have a reference to the versioned symbol. */ |
| ht->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak; |
| hi->dynamic_def |= ht->dynamic_def; |
| |
| /* See if the new flags lead us to realize that the symbol must |
| be dynamic. */ |
| if (! *dynsym) |
| { |
| if (! dynamic) |
| { |
| if (! bfd_link_executable (info) |
| || hi->def_dynamic |
| || hi->ref_dynamic) |
| *dynsym = true; |
| } |
| else |
| { |
| if (hi->ref_regular) |
| *dynsym = true; |
| } |
| } |
| } |
| |
| /* We also need to define an indirection from the nondefault version |
| of the symbol. */ |
| |
| nondefault: |
| len = strlen (name); |
| shortname = (char *) bfd_hash_allocate (&info->hash->table, len); |
| if (shortname == NULL) |
| return false; |
| memcpy (shortname, name, shortlen); |
| memcpy (shortname + shortlen, p + 1, len - shortlen); |
| |
| /* Once again, merge with any existing symbol. */ |
| type_change_ok = false; |
| size_change_ok = false; |
| tmp_sec = sec; |
| if (!_bfd_elf_merge_symbol (abfd, info, shortname, sym, &tmp_sec, &value, |
| &hi, poldbfd, NULL, NULL, &skip, &override, |
| &type_change_ok, &size_change_ok, &matched)) |
| return false; |
| |
| if (skip) |
| { |
| if (!dynamic |
| && h->root.type == bfd_link_hash_defweak |
| && hi->root.type == bfd_link_hash_defined) |
| { |
| /* We are handling a weak sym@@ver and attempting to define |
| a weak sym@ver, but _bfd_elf_merge_symbol said to skip the |
| new weak sym@ver because there is already a strong sym@ver. |
| However, sym@ver and sym@@ver are really the same symbol. |
| The existing strong sym@ver ought to override sym@@ver. */ |
| h->root.type = bfd_link_hash_defined; |
| h->root.u.def.section = hi->root.u.def.section; |
| h->root.u.def.value = hi->root.u.def.value; |
| hi->root.type = bfd_link_hash_indirect; |
| hi->root.u.i.link = &h->root; |
| } |
| else |
| return true; |
| } |
| else if (override) |
| { |
| /* Here SHORTNAME is a versioned name, so we don't expect to see |
| the type of override we do in the case above unless it is |
| overridden by a versioned definition. */ |
| if (hi->root.type != bfd_link_hash_defined |
| && hi->root.type != bfd_link_hash_defweak) |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%pB: unexpected redefinition of indirect versioned symbol `%s'"), |
| abfd, shortname); |
| return true; |
| } |
| else |
| { |
| bh = &hi->root; |
| if (! (_bfd_generic_link_add_one_symbol |
| (info, abfd, shortname, BSF_INDIRECT, |
| bfd_ind_section_ptr, 0, name, false, collect, &bh))) |
| return false; |
| hi = (struct elf_link_hash_entry *) bh; |
| } |
| |
| /* If there is a duplicate definition somewhere, then HI may not |
| point to an indirect symbol. We will have reported an error |
| to the user in that case. */ |
| if (hi->root.type == bfd_link_hash_indirect) |
| { |
| (*bed->elf_backend_copy_indirect_symbol) (info, h, hi); |
| h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak; |
| hi->dynamic_def |= h->dynamic_def; |
| |
| /* If we first saw a reference to @VER symbol with |
| non-default visibility, merge that visibility to the |
| @@VER symbol. */ |
| elf_merge_st_other (abfd, h, hi->other, sec, true, dynamic); |
| |
| /* See if the new flags lead us to realize that the symbol |
| must be dynamic. */ |
| if (! *dynsym) |
| { |
| if (! dynamic) |
| { |
| if (! bfd_link_executable (info) |
| || hi->ref_dynamic) |
| *dynsym = true; |
| } |
| else |
| { |
| if (hi->ref_regular) |
| *dynsym = true; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| /* This routine is used to export all defined symbols into the dynamic |
| symbol table. It is called via elf_link_hash_traverse. */ |
| |
| static bool |
| _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data) |
| { |
| struct elf_info_failed *eif = (struct elf_info_failed *) data; |
| |
| /* Ignore indirect symbols. These are added by the versioning code. */ |
| if (h->root.type == bfd_link_hash_indirect) |
| return true; |
| |
| /* Ignore this if we won't export it. */ |
| if (!eif->info->export_dynamic && !h->dynamic) |
| return true; |
| |
| if (h->dynindx == -1 |
| && (h->def_regular || h->ref_regular) |
| && ! bfd_hide_sym_by_version (eif->info->version_info, |
| h->root.root.string)) |
| { |
| if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) |
| { |
| eif->failed = true; |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /* Return the glibc version reference if VERSION_DEP is added to the |
| list of glibc version dependencies successfully. VERSION_DEP will |
| be put into the .gnu.version_r section. GLIBC_MINOR_BASE is the |
| pointer to the glibc minor base version. */ |
| |
| static Elf_Internal_Verneed * |
| elf_link_add_glibc_verneed (struct elf_find_verdep_info *rinfo, |
| Elf_Internal_Verneed *glibc_verref, |
| const char *version_dep, |
| int *glibc_minor_base) |
| { |
| Elf_Internal_Verneed *t; |
| Elf_Internal_Vernaux *a; |
| size_t amt; |
| int minor_version = -1; |
| |
| if (glibc_verref != NULL) |
| { |
| t = glibc_verref; |
| |
| for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) |
| { |
| /* Return if VERSION_DEP dependency has been added. */ |
| if (a->vna_nodename == version_dep |
| || strcmp (a->vna_nodename, version_dep) == 0) |
| return t; |
| } |
| } |
| else |
| { |
| for (t = elf_tdata (rinfo->info->output_bfd)->verref; |
| t != NULL; |
| t = t->vn_nextref) |
| { |
| const char *soname = bfd_elf_get_dt_soname (t->vn_bfd); |
| if (soname != NULL && startswith (soname, "libc.so.")) |
| break; |
| } |
| |
| /* Skip the shared library if it isn't libc.so. */ |
| if (t == NULL) |
| return t; |
| |
| for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) |
| { |
| /* Return if VERSION_DEP dependency has been added. */ |
| if (a->vna_nodename == version_dep |
| || strcmp (a->vna_nodename, version_dep) == 0) |
| return t; |
| |
| /* Check if libc.so provides GLIBC_2.XX version. */ |
| if (startswith (a->vna_nodename, "GLIBC_2.")) |
| { |
| minor_version = strtol (a->vna_nodename + 8, NULL, 10); |
| if (minor_version < *glibc_minor_base) |
| *glibc_minor_base = minor_version; |
| } |
| } |
| |
| /* Skip if it isn't linked against glibc. */ |
| if (minor_version < 0) |
| return NULL; |
| } |
| |
| /* Skip if 2.GLIBC_MINOR_BASE includes VERSION_DEP. */ |
| if (startswith (version_dep, "GLIBC_2.")) |
| { |
| minor_version = strtol (version_dep + 8, NULL, 10); |
| if (minor_version <= *glibc_minor_base) |
| return NULL; |
| } |
| |
| amt = sizeof *a; |
| a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt); |
| if (a == NULL) |
| { |
| rinfo->failed = true; |
| return NULL; |
| } |
| |
| a->vna_nodename = version_dep; |
| a->vna_flags = 0; |
| a->vna_nextptr = t->vn_auxptr; |
| a->vna_other = rinfo->vers + 1; |
| ++rinfo->vers; |
| |
| t->vn_auxptr = a; |
| |
| return t; |
| } |
| |
| /* Add VERSION_DEP to the list of version dependencies when linked |
| against glibc. */ |
| |
| void |
| _bfd_elf_link_add_glibc_version_dependency |
| (struct elf_find_verdep_info *rinfo, |
| const char *version_dep[]) |
| { |
| Elf_Internal_Verneed *t = NULL; |
| int glibc_minor_base = INT_MAX; |
| |
| do |
| { |
| t = elf_link_add_glibc_verneed (rinfo, t, *version_dep, |
| &glibc_minor_base); |
| /* Return if there is no glibc version reference. */ |
| if (t == NULL) |
| return; |
| version_dep++; |
| } |
| while (*version_dep != NULL); |
| } |
| |
| /* Add GLIBC_ABI_DT_RELR to the list of version dependencies when |
| linked against glibc. */ |
| |
| void |
| _bfd_elf_link_add_dt_relr_dependency (struct elf_find_verdep_info *rinfo) |
| { |
| if (rinfo->info->enable_dt_relr) |
| { |
| const char *version[] = |
| { |
| "GLIBC_ABI_DT_RELR", |
| NULL |
| }; |
| _bfd_elf_link_add_glibc_version_dependency (rinfo, version); |
| } |
| } |
| |
| /* Look through the symbols which are defined in other shared |
| libraries and referenced here. Update the list of version |
| dependencies. This will be put into the .gnu.version_r section. |
| This function is called via elf_link_hash_traverse. */ |
| |
| static bool |
| _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h, |
| void *data) |
| { |
| struct elf_find_verdep_info *rinfo = (struct elf_find_verdep_info *) data; |
| Elf_Internal_Verneed *t; |
| Elf_Internal_Vernaux *a; |
| size_t amt; |
| |
| /* We only care about symbols defined in shared objects with version |
| information. */ |
| if (!h->def_dynamic |
| || h->def_regular |
| || h->dynindx == -1 |
| || h->verinfo.verdef == NULL |
| || (elf_dyn_lib_class (h->verinfo.verdef->vd_bfd) |
| & (DYN_AS_NEEDED | DYN_DT_NEEDED | DYN_NO_NEEDED))) |
| return true; |
| |
| /* See if we already know about this version. */ |
| for (t = elf_tdata (rinfo->info->output_bfd)->verref; |
| t != NULL; |
| t = t->vn_nextref) |
| { |
| if (t->vn_bfd != h->verinfo.verdef->vd_bfd) |
| continue; |
| |
| for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) |
| if (a->vna_nodename == h->verinfo.verdef->vd_nodename) |
| return true; |
| |
| break; |
| } |
| |
| /* This is a new version. Add it to tree we are building. */ |
| |
| if (t == NULL) |
| { |
| amt = sizeof *t; |
| t = (Elf_Internal_Verneed *) bfd_zalloc (rinfo->info->output_bfd, amt); |
| if (t == NULL) |
| { |
| rinfo->failed = true; |
| return false; |
| } |
| |
| t->vn_bfd = h->verinfo.verdef->vd_bfd; |
| t->vn_nextref = elf_tdata (rinfo->info->output_bfd)->verref; |
| elf_tdata (rinfo->info->output_bfd)->verref = t; |
| } |
| |
| amt = sizeof *a; |
| a = (Elf_Internal_Vernaux *) bfd_zalloc (rinfo->info->output_bfd, amt); |
| if (a == NULL) |
| { |
| rinfo->failed = true; |
| return false; |
| } |
| |
| /* Note that we are copying a string pointer here, and testing it |
| above. If bfd_elf_string_from_elf_section is ever changed to |
| discard the string data when low in memory, this will have to be |
| fixed. */ |
| a->vna_nodename = h->verinfo.verdef->vd_nodename; |
| |
| a->vna_flags = h->verinfo.verdef->vd_flags; |
| a->vna_nextptr = t->vn_auxptr; |
| |
| h->verinfo.verdef->vd_exp_refno = rinfo->vers; |
| ++rinfo->vers; |
| |
| a->vna_other = h->verinfo.verdef->vd_exp_refno + 1; |
| |
| t->vn_auxptr = a; |
| |
| return true; |
| } |
| |
| /* Return TRUE and set *HIDE to TRUE if the versioned symbol is |
| hidden. Set *T_P to NULL if there is no match. */ |
| |
| static bool |
| _bfd_elf_link_hide_versioned_symbol (struct bfd_link_info *info, |
| struct elf_link_hash_entry *h, |
| const char *version_p, |
| struct bfd_elf_version_tree **t_p, |
| bool *hide) |
| { |
| struct bfd_elf_version_tree *t; |
| |
| /* Look for the version. If we find it, it is no longer weak. */ |
| for (t = info->version_info; t != NULL; t = t->next) |
| { |
| if (strcmp (t->name, version_p) == 0) |
| { |
| size_t len; |
| char *alc; |
| struct bfd_elf_version_expr *d; |
| |
| len = version_p - h->root.root.string; |
| alc = (char *) bfd_malloc (len); |
| if (alc == NULL) |
| return false; |
| memcpy (alc, h->root.root.string, len - 1); |
| alc[len - 1] = '\0'; |
| if (alc[len - 2] == ELF_VER_CHR) |
| alc[len - 2] = '\0'; |
| |
| h->verinfo.vertree = t; |
| t->used = true; |
| d = NULL; |
| |
| if (t->globals.list != NULL) |
| d = (*t->match) (&t->globals, NULL, alc); |
| |
| /* See if there is anything to force this symbol to |
| local scope. */ |
| if (d == NULL && t->locals.list != NULL) |
| { |
| d = (*t->match) (&t->locals, NULL, alc); |
| if (d != NULL |
| && h->dynindx != -1 |
| && ! info->export_dynamic) |
| *hide = true; |
| } |
| |
| free (alc); |
| break; |
| } |
| } |
| |
| *t_p = t; |
| |
| return true; |
| } |
| |
| /* Return TRUE if the symbol H is hidden by version script. */ |
| |
| bool |
| _bfd_elf_link_hide_sym_by_version (struct bfd_link_info *info, |
| struct elf_link_hash_entry *h) |
| { |
| const char *p; |
| bool hide = false; |
| const struct elf_backend_data *bed |
| = get_elf_backend_data (info->output_bfd); |
| |
| /* Version script only hides symbols defined in regular objects. */ |
| if (!h->def_regular && !ELF_COMMON_DEF_P (h)) |
| return true; |
| |
| p = strchr (h->root.root.string, ELF_VER_CHR); |
| if (p != NULL && h->verinfo.vertree == NULL) |
| { |
| struct bfd_elf_version_tree *t; |
| |
| ++p; |
| if (*p == ELF_VER_CHR) |
| ++p; |
| |
| if (*p != '\0' |
| && _bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide) |
| && hide) |
| { |
| if (hide) |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| return true; |
| } |
| } |
| |
| /* If we don't have a version for this symbol, see if we can find |
| something. */ |
| if (h->verinfo.vertree == NULL && info->version_info != NULL) |
| { |
| h->verinfo.vertree |
| = bfd_find_version_for_sym (info->version_info, |
| h->root.root.string, &hide); |
| if (h->verinfo.vertree != NULL && hide) |
| { |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| /* Figure out appropriate versions for all the symbols. We may not |
| have the version number script until we have read all of the input |
| files, so until that point we don't know which symbols should be |
| local. This function is called via elf_link_hash_traverse. */ |
| |
| static bool |
| _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) |
| { |
| struct elf_info_failed *sinfo; |
| struct bfd_link_info *info; |
| const struct elf_backend_data *bed; |
| struct elf_info_failed eif; |
| char *p; |
| bool hide; |
| |
| sinfo = (struct elf_info_failed *) data; |
| info = sinfo->info; |
| |
| /* Fix the symbol flags. */ |
| eif.failed = false; |
| eif.info = info; |
| if (! _bfd_elf_fix_symbol_flags (h, &eif)) |
| { |
| if (eif.failed) |
| sinfo->failed = true; |
| return false; |
| } |
| |
| bed = get_elf_backend_data (info->output_bfd); |
| |
| /* We only need version numbers for symbols defined in regular |
| objects. */ |
| if (!h->def_regular && !ELF_COMMON_DEF_P (h)) |
| { |
| /* Hide symbols defined in discarded input sections. */ |
| if ((h->root.type == bfd_link_hash_defined |
| || h->root.type == bfd_link_hash_defweak) |
| && discarded_section (h->root.u.def.section)) |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| return true; |
| } |
| |
| hide = false; |
| p = strchr (h->root.root.string, ELF_VER_CHR); |
| if (p != NULL && h->verinfo.vertree == NULL) |
| { |
| struct bfd_elf_version_tree *t; |
| |
| ++p; |
| if (*p == ELF_VER_CHR) |
| ++p; |
| |
| /* If there is no version string, we can just return out. */ |
| if (*p == '\0') |
| return true; |
| |
| if (!_bfd_elf_link_hide_versioned_symbol (info, h, p, &t, &hide)) |
| { |
| sinfo->failed = true; |
| return false; |
| } |
| |
| if (hide) |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| |
| /* If we are building an application, we need to create a |
| version node for this version. */ |
| if (t == NULL && bfd_link_executable (info)) |
| { |
| struct bfd_elf_version_tree **pp; |
| int version_index; |
| |
| /* If we aren't going to export this symbol, we don't need |
| to worry about it. */ |
| if (h->dynindx == -1) |
| return true; |
| |
| t = (struct bfd_elf_version_tree *) bfd_zalloc (info->output_bfd, |
| sizeof *t); |
| if (t == NULL) |
| { |
| sinfo->failed = true; |
| return false; |
| } |
| |
| t->name = p; |
| t->name_indx = (unsigned int) -1; |
| t->used = true; |
| |
| version_index = 1; |
| /* Don't count anonymous version tag. */ |
| if (sinfo->info->version_info != NULL |
| && sinfo->info->version_info->vernum == 0) |
| version_index = 0; |
| for (pp = &sinfo->info->version_info; |
| *pp != NULL; |
| pp = &(*pp)->next) |
| ++version_index; |
| t->vernum = version_index; |
| |
| *pp = t; |
| |
| h->verinfo.vertree = t; |
| } |
| else if (t == NULL) |
| { |
| /* We could not find the version for a symbol when |
| generating a shared archive. Return an error. */ |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%pB: version node not found for symbol %s"), |
| info->output_bfd, h->root.root.string); |
| bfd_set_error (bfd_error_bad_value); |
| sinfo->failed = true; |
| return false; |
| } |
| } |
| |
| /* If we don't have a version for this symbol, see if we can find |
| something. */ |
| if (!hide |
| && h->verinfo.vertree == NULL |
| && sinfo->info->version_info != NULL) |
| { |
| h->verinfo.vertree |
| = bfd_find_version_for_sym (sinfo->info->version_info, |
| h->root.root.string, &hide); |
| if (h->verinfo.vertree != NULL && hide) |
| (*bed->elf_backend_hide_symbol) (info, h, true); |
| } |
| |
| return true; |
| } |
| |
| /* Read and swap the relocs from the section indicated by SHDR. This |
| may be either a REL or a RELA section. The relocations are |
| translated into RELA relocations and stored in INTERNAL_RELOCS, |
| which should have already been allocated to contain enough space. |
| The *EXTERNAL_RELOCS_P are a buffer where the external form of the |
| relocations should be stored. If *EXTERNAL_RELOCS_ADDR is NULL, |
| *EXTERNAL_RELOCS_ADDR and *EXTERNAL_RELOCS_SIZE returns the mmap |
| memory address and size. Otherwise, *EXTERNAL_RELOCS_ADDR is |
| unchanged and *EXTERNAL_RELOCS_SIZE returns 0. |
| |
| Returns FALSE if something goes wrong. */ |
| |
| static bool |
| elf_link_read_relocs_from_section (bfd *abfd, |
| const asection *sec, |
| Elf_Internal_Shdr *shdr, |
| void **external_relocs_addr, |
| size_t *external_relocs_size, |
| Elf_Internal_Rela *internal_relocs) |
| { |
| const struct elf_backend_data *bed; |
| void (*swap_in) (bfd *, const bfd_byte *, Elf_Internal_Rela *); |
| const bfd_byte *erela; |
| const bfd_byte *erelaend; |
| Elf_Internal_Rela *irela; |
| Elf_Internal_Shdr *symtab_hdr; |
| size_t nsyms; |
| void *external_relocs = *external_relocs_addr; |
| |
| /* Position ourselves at the start of the section. */ |
| if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0) |
| return false; |
| |
| /* Read the relocations. */ |
| *external_relocs_size = shdr->sh_size; |
| if (!_bfd_mmap_read_temporary (&external_relocs, |
| external_relocs_size, |
| external_relocs_addr, abfd, true)) |
| return false; |
| |
| symtab_hdr = &elf_tdata (abfd)->symtab_hdr; |
| nsyms = NUM_SHDR_ENTRIES (symtab_hdr); |
| |
| bed = get_elf_backend_data (abfd); |
| |
| /* Convert the external relocations to the internal format. */ |
| if (shdr->sh_entsize == bed->s->sizeof_rel) |
| swap_in = bed->s->swap_reloc_in; |
| else if (shdr->sh_entsize == bed->s->sizeof_rela) |
| swap_in = bed->s->swap_reloca_in; |
| else |
| { |
| bfd_set_error (bfd_error_wrong_format); |
| return false; |
| } |
| |
| erela = (const bfd_byte *) external_relocs; |
| /* Setting erelaend like this and comparing with <= handles case of |
| a fuzzed object with sh_size not a multiple of sh_entsize. */ |
| erelaend = erela + shdr->sh_size - shdr->sh_entsize; |
| irela = internal_relocs; |
| while (erela <= erelaend) |
| { |
| bfd_vma r_symndx; |
| |
| (*swap_in) (abfd, erela, irela); |
| r_symndx = ELF32_R_SYM (irela->r_info); |
| if (bed->s->arch_size == 64) |
| r_symndx >>= 24; |
| if (nsyms > 0) |
| { |
| if ((size_t) r_symndx >= nsyms) |
| { |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%pB: bad reloc symbol index (%#" PRIx64 " >= %#lx)" |
| " for offset %#" PRIx64 " in section `%pA'"), |
| abfd, (uint64_t) r_symndx, (unsigned long) nsyms, |
| (uint64_t) irela->r_offset, sec); |
| bfd_set_error (bfd_error_bad_value); |
| return false; |
| } |
| } |
| else if (r_symndx != STN_UNDEF) |
| { |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%pB: non-zero symbol index (%#" PRIx64 ")" |
| " for offset %#" PRIx64 " in section `%pA'" |
| " when the object file has no symbol table"), |
| abfd, (uint64_t) r_symndx, |
| (uint64_t) irela->r_offset, sec); |
| bfd_set_error (bfd_error_bad_value); |
| return false; |
| } |
| irela += bed->s->int_rels_per_ext_rel; |
| erela += shdr->sh_entsize; |
| } |
| |
| return true; |
| } |
| |
| /* Read and swap the relocs for a section O. They may have been |
| cached. If the EXTERNAL_RELOCS and INTERNAL_RELOCS arguments are |
| not NULL, they are used as buffers to read into. They are known to |
| be large enough. If the INTERNAL_RELOCS relocs argument is NULL, |
| the return value is allocated using either malloc or bfd_alloc, |
| according to the KEEP_MEMORY argument. If O has two relocation |
| sections (both REL and RELA relocations), then the REL_HDR |
| relocations will appear first in INTERNAL_RELOCS, followed by the |
| RELA_HDR relocations. If INFO isn't NULL and KEEP_MEMORY is true, |
| update cache_size. */ |
| |
| Elf_Internal_Rela * |
| _bfd_elf_link_info_read_relocs (bfd *abfd, |
| struct bfd_link_info *info, |
| const asection *o, |
| void *external_relocs, |
| Elf_Internal_Rela *internal_relocs, |
| bool keep_memory) |
| { |
| void *alloc1 = NULL; |
| size_t alloc1_size; |
| Elf_Internal_Rela *alloc2 = NULL; |
| const struct elf_backend_data *bed = get_elf_backend_data (abfd); |
| struct bfd_elf_section_data *esdo = elf_section_data (o); |
| Elf_Internal_Rela *internal_rela_relocs; |
| |
| if (esdo->relocs != NULL) |
| return esdo->relocs; |
| |
| if (o->reloc_count == 0) |
| return NULL; |
| |
| if (internal_relocs == NULL) |
| { |
| bfd_size_type size; |
| |
| size = (bfd_size_type) o->reloc_count * sizeof (Elf_Internal_Rela); |
| if (keep_memory) |
| { |
| internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_alloc (abfd, size); |
| if (info) |
| info->cache_size += size; |
| } |
| else |
| internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size); |
| if (internal_relocs == NULL) |
| return NULL; |
| } |
| |
| alloc1 = external_relocs; |
| internal_rela_relocs = internal_relocs; |
| if (esdo->rel.hdr) |
| { |
| if (!elf_link_read_relocs_from_section (abfd, o, esdo->rel.hdr, |
| &alloc1, &alloc1_size, |
| internal_relocs)) |
| goto error_return; |
| external_relocs = (((bfd_byte *) external_relocs) |
| + esdo->rel.hdr->sh_size); |
| internal_rela_relocs += (NUM_SHDR_ENTRIES (esdo->rel.hdr) |
| * bed->s->int_rels_per_ext_rel); |
| } |
| |
| if (esdo->rela.hdr |
| && (!elf_link_read_relocs_from_section (abfd, o, esdo->rela.hdr, |
| &alloc1, &alloc1_size, |
| internal_rela_relocs))) |
| goto error_return; |
| |
| /* Cache the results for next time, if we can. */ |
| if (keep_memory) |
| esdo->relocs = internal_relocs; |
| |
| _bfd_munmap_readonly_temporary (alloc1, alloc1_size); |
| |
| /* Don't free alloc2, since if it was allocated we are passing it |
| back (under the name of internal_relocs). */ |
| |
| return internal_relocs; |
| |
| error_return: |
| _bfd_munmap_readonly_temporary (alloc1, alloc1_size); |
| if (alloc2 != NULL) |
| { |
| if (keep_memory) |
| bfd_release (abfd, alloc2); |
| else |
| free (alloc2); |
| } |
| return NULL; |
| } |
| |
| /* This is similar to _bfd_elf_link_info_read_relocs, except for that |
| NULL is passed to _bfd_elf_link_info_read_relocs for pointer to |
| struct bfd_link_info. */ |
| |
| Elf_Internal_Rela * |
| _bfd_elf_link_read_relocs (bfd *abfd, |
| const asection *o, |
| void *external_relocs, |
| Elf_Internal_Rela *internal_relocs, |
| bool keep_memory) |
| { |
| return _bfd_elf_link_info_read_relocs (abfd, NULL, o, external_relocs, |
| internal_relocs, keep_memory); |
| |
| } |
| |
| /* Compute the size of, and allocate space for, REL_HDR which is the |
| section header for a section containing relocations for O. */ |
| |
| static bool |
| _bfd_elf_link_size_reloc_section (bfd *abfd, |
| struct bfd_elf_section_reloc_data *reldata) |
| { |
| Elf_Internal_Shdr *rel_hdr = reldata->hdr; |
| |
| /* That allows us to calculate the size of the section. */ |
| rel_hdr->sh_size = rel_hdr->sh_entsize * reldata->count; |
| |
| /* The contents field must last into write_object_contents, so we |
| allocate it with bfd_alloc rather than malloc. Also since we |
| cannot be sure that the contents will actually be filled in, |
| we zero the allocated space. */ |
| rel_hdr->contents = (unsigned char *) bfd_zalloc (abfd, rel_hdr->sh_size); |
| if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0) |
| return false; |
| |
| if (reldata->hashes == NULL && reldata->count) |
| { |
| struct elf_link_hash_entry **p; |
| |
| p = ((struct elf_link_hash_entry **) |
| bfd_zmalloc (reldata->count * sizeof (*p))); |
| if (p == NULL) |
| return false; |
| |
| reldata->hashes = p; |
| } |
| |
| return true; |
| } |
| |
| /* Copy the relocations indicated by the INTERNAL_RELOCS (which |
| originated from the section given by INPUT_REL_HDR) to the |
| OUTPUT_BFD. */ |
| |
| bool |
| _bfd_elf_link_output_relocs (bfd *output_bfd, |
| asection *input_section, |
| Elf_Internal_Shdr *input_rel_hdr, |
| Elf_Internal_Rela *internal_relocs, |
| struct elf_link_hash_entry **rel_hash) |
| { |
| Elf_Internal_Rela *irela; |
| Elf_Internal_Rela *irelaend; |
| bfd_byte *erel; |
| struct bfd_elf_section_reloc_data *output_reldata; |
| asection *output_section; |
| const struct elf_backend_data *bed; |
| void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *); |
| struct bfd_elf_section_data *esdo; |
| |
| output_section = input_section->output_section; |
| |
| bed = get_elf_backend_data (output_bfd); |
| esdo = elf_section_data (output_section); |
| if (esdo->rel.hdr && esdo->rel.hdr->sh_entsize == input_rel_hdr->sh_entsize) |
| { |
| output_reldata = &esdo->rel; |
| swap_out = bed->s->swap_reloc_out; |
| } |
| else if (esdo->rela.hdr |
| && esdo->rela.hdr->sh_entsize == input_rel_hdr->sh_entsize) |
| { |
| output_reldata = &esdo->rela; |
| swap_out = bed->s->swap_reloca_out; |
| } |
| else |
| { |
| _bfd_error_handler |
| /* xgettext:c-format */ |
| (_("%pB: relocation size mismatch in %pB section %pA"), |
| output_bfd, input_section->owner, input_section); |
| bfd_set_error (bfd_error_wrong_format); |
| return false; |
| } |
| |
| erel = output_reldata->hdr->contents; |
| erel += output_reldata->count * input_rel_hdr->sh_entsize; |
| irela = internal_relocs; |
| irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr) |
| * bed->s->int_rels_per_ext_rel); |
| while (irela < irelaend) |
| { |
| if (rel_hash && *rel_hash) |
| (*rel_hash)->has_reloc = 1; |
| (*swap_out) (output_bfd, irela, erel); |
| irela += bed->s->int_rels_per_ext_rel; |
| erel += input_rel_hdr->sh_entsize; |
| if (rel_hash) |
| rel_hash++; |
| } |
| |
| /* Bump the counter, so that we know where to add the next set of |
| relocations. */ |
| output_reldata->count += NUM_SHDR_ENTRIES (input_rel_hdr); |
| |
| return true; |
| } |
| |
| /* Make weak undefined symbols in PIE dynamic. */ |
| |
| bool |
| _bfd_elf_link_hash_fixup_symbol (struct bfd_link_info *info, |
| struct elf_link_hash_entry *h) |
| { |
| if (bfd_link_pie (info) |
| && h->dynindx == -1 |
| && h->root.type == bfd_link_hash_undefweak) |
| return bfd_elf_link_record_dynamic_symbol (info, h); |
| |
| return true; |
| } |
| |
| /* Fix up the flags for a symbol. This handles various cases which |
| can only be fixed after all the input files are seen. This is |
| currently called by both adjust_dynamic_symbol and |
| assign_sym_version, which is unnecessary but perhaps more robust in |
| the face of future changes. */ |
| |
| static bool |
| _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, |
| struct elf_info_failed *eif) |
| { |
| const struct elf_backend_data *bed; |
| |
| /* If this symbol was mentioned in a non-ELF file, try to set |
| DEF_REGULAR and REF_REGULAR correctly. This is the only way to |
| permit a non-ELF file to correctly refer to a symbol defined in |
| an ELF dynamic object. */ |
| if (h->non_elf) |
| { |
| while (h->root.type == bfd_link_hash_indirect) |
| h = (struct elf_link_hash_entry *) h->root.u.i.link; |
| |
| if (h->root.type != bfd_link_hash_defined |
| && h->root.type != bfd_link_hash_defweak) |
| { |
| h->ref_regular = 1; |
| h->ref_regular_nonweak = 1; |
| } |
| else |
| { |
| if (h->root.u.def.section->owner != NULL |
| && (bfd_get_flavour (h->root.u.def.section->owner) |
| == bfd_target_elf_flavour)) |
| { |
| h->ref_regular = 1; |
| h->ref_regular_nonweak = 1; |
| } |
| else |
| h->def_regular = 1; |
| } |
| |
| if (h->dynindx == -1 |
| && (h->def_dynamic |
| || h->ref_dynamic)) |
| { |
| if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) |
| { |
| eif->failed = true; |
| return false; |
| } |
| } |
| } |
| else |
| { |
| /* Unfortunately, NON_ELF is only correct if the symbol |
| was first seen in a non-ELF file. Fortunately, if the symbol |
| was first seen in an ELF file, we're probably OK unless the |
| symbol was defined in a non-ELF file. Catch that case here. |
| FIXME: We're still in trouble if the symbol was first seen in |
| a dynamic object, and then later in a non-ELF regular object. */ |
| if ((h->root.type == bfd_link_hash_defined |
| || h->root.type == bfd_link_hash_defweak) |
| && !h->def_regular |
|