X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf-vxworks.c;h=0984cc83e6dc2f7aa9490024b30490a45429e006;hb=d2d1ea20aef6ed97232280b5e15a52b8d7dc7b7d;hp=90e620a905592f47a7a3421ca4c874d20e559a24;hpb=01f0fe5e0450edf168c1f612feb93cf588e4e7ea;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf-vxworks.c b/bfd/elf-vxworks.c index 90e620a905..0984cc83e6 100644 --- a/bfd/elf-vxworks.c +++ b/bfd/elf-vxworks.c @@ -1,11 +1,11 @@ /* VxWorks support for ELF - Copyright 2005 Free Software Foundation, Inc. + Copyright (C) 2005-2020 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 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -14,21 +14,39 @@ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ + along with this program. If not, see . */ /* This file provides routines used by all VxWorks targets. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "libbfd.h" #include "elf-bfd.h" #include "elf-vxworks.h" +#include "elf/vxworks.h" + +/* Return true if symbol NAME, as defined by ABFD, is one of the special + __GOTT_BASE__ or __GOTT_INDEX__ symbols. */ + +static bfd_boolean +elf_vxworks_gott_symbol_p (bfd *abfd, const char *name) +{ + char leading; + + leading = bfd_get_symbol_leading_char (abfd); + if (leading) + { + if (*name != leading) + return FALSE; + name++; + } + return (strcmp (name, "__GOTT_BASE__") == 0 + || strcmp (name, "__GOTT_INDEX__") == 0); +} /* Tweak magic VxWorks symbols as they are loaded. */ bfd_boolean -elf_vxworks_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED, +elf_vxworks_add_symbol_hook (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym, const char **namep, @@ -44,9 +62,8 @@ elf_vxworks_add_symbol_hook (bfd *abfd ATTRIBUTE_UNUSED, give the symbol weak binding to get the desired samantics. This transformation will be undone in elf_i386_vxworks_link_output_symbol_hook. */ - if ((info->shared || abfd->flags & DYNAMIC) - && (strcmp (*namep, "__GOTT_INDEX__") == 0 - || strcmp (*namep, "__GOTT_BASE__") == 0)) + if ((bfd_link_pic (info) || abfd->flags & DYNAMIC) + && elf_vxworks_gott_symbol_p (abfd, *namep)) { sym->st_info = ELF_ST_INFO (STB_WEAK, ELF_ST_TYPE (sym->st_info)); *flagsp |= BSF_WEAK; @@ -70,16 +87,17 @@ elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info, htab = elf_hash_table (info); bed = get_elf_backend_data (dynobj); - if (!info->shared) + if (!bfd_link_pic (info)) { - s = bfd_make_section_with_flags (dynobj, - bed->default_use_rela_p - ? ".rela.plt.unloaded" - : ".rel.plt.unloaded", - SEC_HAS_CONTENTS | SEC_IN_MEMORY - | SEC_READONLY | SEC_LINKER_CREATED); + s = bfd_make_section_anyway_with_flags (dynobj, + bed->default_use_rela_p + ? ".rela.plt.unloaded" + : ".rel.plt.unloaded", + SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_READONLY + | SEC_LINKER_CREATED); if (s == NULL - || !bfd_set_section_alignment (dynobj, s, bed->s->log_file_align)) + || !bfd_set_section_alignment (s, bed->s->log_file_align)) return FALSE; *srelplt2_out = s; @@ -108,29 +126,24 @@ elf_vxworks_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info, } /* Tweak magic VxWorks symbols as they are written to the output file. */ -bfd_boolean +int elf_vxworks_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, const char *name, Elf_Internal_Sym *sym, asection *input_sec ATTRIBUTE_UNUSED, - struct elf_link_hash_entry *h - ATTRIBUTE_UNUSED) + struct elf_link_hash_entry *h) { - /* Ignore the first dummy symbol. */ - if (!name) - return TRUE; - /* Reverse the effects of the hack in elf_vxworks_add_symbol_hook. */ - if (strcmp (name, "__GOTT_INDEX__") == 0 - || strcmp (name, "__GOTT_BASE__") == 0) + if (h + && h->root.type == bfd_link_hash_undefweak + && elf_vxworks_gott_symbol_p (h->root.u.undef.abfd, name)) sym->st_info = ELF_ST_INFO (STB_GLOBAL, ELF_ST_TYPE (sym->st_info)); - return TRUE; + return 1; } - -/* Copy relocations into the output file. Fixes up relocations againt PLT +/* Copy relocations into the output file. Fixes up relocations against PLT entries, then calls the generic routine. */ bfd_boolean @@ -141,49 +154,55 @@ elf_vxworks_emit_relocs (bfd *output_bfd, struct elf_link_hash_entry **rel_hash) { const struct elf_backend_data *bed; - Elf_Internal_Rela *irela; - Elf_Internal_Rela *irelaend; int j; bed = get_elf_backend_data (output_bfd); - irela = internal_relocs; - irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr) - * bed->s->int_rels_per_ext_rel); - while (irela < irelaend) + if (output_bfd->flags & (DYNAMIC|EXEC_P)) { - if ((output_bfd->flags & (DYNAMIC|EXEC_P)) - && *rel_hash - && (*rel_hash)->def_dynamic - && !(*rel_hash)->def_regular - && (*rel_hash)->root.type == bfd_link_hash_defined - && (*rel_hash)->root.u.def.section->output_section != NULL) + Elf_Internal_Rela *irela; + Elf_Internal_Rela *irelaend; + struct elf_link_hash_entry **hash_ptr; + + for (irela = internal_relocs, + irelaend = irela + (NUM_SHDR_ENTRIES (input_rel_hdr) + * bed->s->int_rels_per_ext_rel), + hash_ptr = rel_hash; + irela < irelaend; + irela += bed->s->int_rels_per_ext_rel, + hash_ptr++) { - /* This is a relocation from an executable or shared library - against a symbol in a different shared library. We are - creating a definition in the output file but it does not come - from any of our normal (.o) files. ie. a PLT stub. - Normally this would be a relocation against against SHN_UNDEF - with the VMA of the PLT stub. This upsets the VxWorks loader. - Convert it to a section-relative relocation. - This gets some other symbols (for instance .dynbss), - but is conservatively correct. */ - for (j = 0; j < bed->s->int_rels_per_ext_rel; j++) + if (*hash_ptr + && (*hash_ptr)->def_dynamic + && !(*hash_ptr)->def_regular + && ((*hash_ptr)->root.type == bfd_link_hash_defined + || (*hash_ptr)->root.type == bfd_link_hash_defweak) + && (*hash_ptr)->root.u.def.section->output_section != NULL) { - asection *sec = (*rel_hash)->root.u.def.section; - int this_idx = - elf_section_data (sec->output_section)->this_idx; - - irela[j].r_info = ELF32_R_INFO (this_idx, - ELF32_R_TYPE (irela[j].r_info)); - irela[j].r_addend += (*rel_hash)->root.u.def.value; - irela[j].r_addend += sec->output_offset; + /* This is a relocation from an executable or shared + library against a symbol in a different shared + library. We are creating a definition in the output + file but it does not come from any of our normal (.o) + files. ie. a PLT stub. Normally this would be a + relocation against against SHN_UNDEF with the VMA of + the PLT stub. This upsets the VxWorks loader. + Convert it to a section-relative relocation. This + gets some other symbols (for instance .dynbss), but + is conservatively correct. */ + for (j = 0; j < bed->s->int_rels_per_ext_rel; j++) + { + asection *sec = (*hash_ptr)->root.u.def.section; + int this_idx = sec->output_section->target_index; + + irela[j].r_info + = ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info)); + irela[j].r_addend += (*hash_ptr)->root.u.def.value; + irela[j].r_addend += sec->output_offset; + } + /* Stop the generic routine adjusting this entry. */ + *hash_ptr = NULL; } - /* Stop the generic routine adjusting this entry. */ - *rel_hash = NULL; } - irela += bed->s->int_rels_per_ext_rel; - rel_hash++; } return _bfd_elf_link_output_relocs (output_bfd, input_section, input_rel_hdr, internal_relocs, @@ -193,9 +212,8 @@ elf_vxworks_emit_relocs (bfd *output_bfd, /* Set the sh_link and sh_info fields on the static plt relocation secton. */ -void -elf_vxworks_final_write_processing (bfd *abfd, - bfd_boolean linker ATTRIBUTE_UNUSED) +bfd_boolean +elf_vxworks_final_write_processing (bfd *abfd) { asection * sec; struct bfd_elf_section_data *d; @@ -203,11 +221,78 @@ elf_vxworks_final_write_processing (bfd *abfd, sec = bfd_get_section_by_name (abfd, ".rel.plt.unloaded"); if (!sec) sec = bfd_get_section_by_name (abfd, ".rela.plt.unloaded"); - if (!sec) - return; - d = elf_section_data (sec); - d->this_hdr.sh_link = elf_tdata (abfd)->symtab_section; - sec = bfd_get_section_by_name (abfd, ".plt"); if (sec) - d->this_hdr.sh_info = elf_section_data (sec)->this_idx; + { + d = elf_section_data (sec); + d->this_hdr.sh_link = elf_onesymtab (abfd); + sec = bfd_get_section_by_name (abfd, ".plt"); + if (sec) + d->this_hdr.sh_info = elf_section_data (sec)->this_idx; + } + return _bfd_elf_final_write_processing (abfd); +} + +/* Add the dynamic entries required by VxWorks. These point to the + tls sections. */ + +bfd_boolean +elf_vxworks_add_dynamic_entries (bfd *output_bfd, struct bfd_link_info *info) +{ + if (bfd_get_section_by_name (output_bfd, ".tls_data")) + { + if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_START, 0) + || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_SIZE, 0) + || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_DATA_ALIGN, 0)) + return FALSE; + } + if (bfd_get_section_by_name (output_bfd, ".tls_vars")) + { + if (!_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_START, 0) + || !_bfd_elf_add_dynamic_entry (info, DT_VX_WRS_TLS_VARS_SIZE, 0)) + return FALSE; + } + return TRUE; +} + +/* If *DYN is one of the VxWorks-specific dynamic entries, then fill + in the value now and return TRUE. Otherwise return FALSE. */ + +bfd_boolean +elf_vxworks_finish_dynamic_entry (bfd *output_bfd, Elf_Internal_Dyn *dyn) +{ + asection *sec; + + switch (dyn->d_tag) + { + default: + return FALSE; + + case DT_VX_WRS_TLS_DATA_START: + sec = bfd_get_section_by_name (output_bfd, ".tls_data"); + dyn->d_un.d_ptr = sec->vma; + break; + + case DT_VX_WRS_TLS_DATA_SIZE: + sec = bfd_get_section_by_name (output_bfd, ".tls_data"); + dyn->d_un.d_val = sec->size; + break; + + case DT_VX_WRS_TLS_DATA_ALIGN: + sec = bfd_get_section_by_name (output_bfd, ".tls_data"); + dyn->d_un.d_val = (bfd_size_type) 1 << bfd_section_alignment (sec); + break; + + case DT_VX_WRS_TLS_VARS_START: + sec = bfd_get_section_by_name (output_bfd, ".tls_vars"); + dyn->d_un.d_ptr = sec->vma; + break; + + case DT_VX_WRS_TLS_VARS_SIZE: + sec = bfd_get_section_by_name (output_bfd, ".tls_vars"); + dyn->d_un.d_val = sec->size; + break; + } + return TRUE; } + +