diff options
author | Jakub Jelinek <jakub@redhat.com> | 2001-11-07 16:50:38 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2001-11-07 16:50:38 +0000 |
commit | 2b0f7ef92ee30445837f86ca0149ec6c6c01dc93 (patch) | |
tree | ce6ae15166b1586424ca4f6032a9ab72d98e61c7 /bfd/elflink.h | |
parent | ef5cdfc7ddd53e80fed2c3b6e6ee9c57f7b29c35 (diff) | |
download | gdb-2b0f7ef92ee30445837f86ca0149ec6c6c01dc93.zip gdb-2b0f7ef92ee30445837f86ca0149ec6c6c01dc93.tar.gz gdb-2b0f7ef92ee30445837f86ca0149ec6c6c01dc93.tar.bz2 |
* Makefile.am (BFD32_BACKENDS): Add elf-strtab.lo.
(BFD32_BACKENDS_CFILES): Add elf-strtab.c.
(elf-strtab.lo): Add rule.
* Makefile.in: Rebuilt.
* configure.in (elf): Add elf-strtab.lo.
* configure: Rebuilt.
* elf-bfd.h (elf_strtab_hash): Forward declare.
(struct elf_link_hash_table): Change dynstr type to
struct elf_strtab_hash *.
(struct elf_obj_tdata): Change strtab_ptr type to
struct elf_strtab_hash *.
(_bfd_elf_strtab_init, _bfd_elf_strtab_free, _bfd_elf_strtab_add,
_bfd_elf_strtab_addref, _bfd_elf_strtab_delref,
_bfd_elf_strtab_clear_all_refs, _bfd_elf_strtab_size,
_bfd_elf_strtab_offset, _bfd_elf_strtab_emit,
_bfd_elf_strtab_finalize): New prototypes.
* elf-strtab.c: New file.
* elflink.h (elf_link_add_object_symbols): Use _bfd_elf_strtab_add
and _bfd_elf_strtab_size instead of _bfd_stringtab calls.
Call _bfd_elf_strtab_delref if DT_NEEDED entry is not needed or
when forcing dynamic symbol to local.
(elf_link_create_dynamic_sections): Call
_bfd_elf_strtab_init instead of elf_stringtab_init.
(elf_link_record_local_dynamic_symbol): Likewise, change
dynstr type. Use _bfd_elf_strtab functions instead of
_bfd_stringtab calls.
(size_dynamic_sections): Use _bfd_elf_strtab functions instead of
_bfd_stringtab calls. For DT_RUNPATH and Verdaux vda_name fields,
call _bfd_elf_strtab_addref. Call elf_finalize_dynstr.
(elf_adjust_dynstr_offsets, elf_finalize_dynstr): New functions.
(elf_fix_symbol_flags): Call _bfd_elf_strtab_delref when forcing
dynamic symbol to local.
(elf_link_assign_sym_version): Likewise.
(elf_bfd_final_link): Call _bfd_elf_strtab_emit instead of
_bfd_stringtab_emit.
* elflink.c (_bfd_elf_link_record_dynamic_symbol): Change dynstr
type. Call _bfd_elf_strtab functions instead of
_bfd_stringtab functions.
* elf64-sparc.c (sparc64_elf_size_dynamic_sections): Likewise.
* elf.c (_bfd_elf_init_reloc_shdr): Likewise.
(elf_fake_sections): Likewise.
(assign_section_numbers): Call _bfd_elf_strtab_clear_all_refs
on shstrtab hash table, call _bfd_elf_strtab_addref on each section
name in the output. Call _bfd_elf_strtab_finalize and
use _bfd_elf_strtab_offset to finalize sh_name section header fields.
(_bfd_elf_compute_section_file_positions): Use _bfd_elf_strtab_size
instead of _bfd_stringtab_size.
(prep_headers): Change shstrtab type.
Use _bfd_elf_strtab calls instead of _bfd_stringtab calls.
Diffstat (limited to 'bfd/elflink.h')
-rw-r--r-- | bfd/elflink.h | 254 |
1 files changed, 206 insertions, 48 deletions
diff --git a/bfd/elflink.h b/bfd/elflink.h index bc85175..d1db64a 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -44,6 +44,8 @@ static boolean elf_merge_symbol boolean *, boolean *, boolean *, boolean)); static boolean elf_export_symbol PARAMS ((struct elf_link_hash_entry *, PTR)); +static boolean elf_finalize_dynstr + PARAMS ((bfd *, struct bfd_link_info *)); static boolean elf_fix_symbol_flags PARAMS ((struct elf_link_hash_entry *, struct elf_info_failed *)); static boolean elf_adjust_dynamic_symbol @@ -1294,13 +1296,12 @@ elf_link_add_object_symbols (abfd, info) if (add_needed) { /* Add a DT_NEEDED entry for this dynamic object. */ - oldsize = _bfd_stringtab_size (hash_table->dynstr); - strindex = _bfd_stringtab_add (hash_table->dynstr, name, - true, false); + oldsize = _bfd_elf_strtab_size (hash_table->dynstr); + strindex = _bfd_elf_strtab_add (hash_table->dynstr, name, false); if (strindex == (bfd_size_type) -1) goto error_return; - if (oldsize == _bfd_stringtab_size (hash_table->dynstr)) + if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) { asection *sdyn; Elf_External_Dyn *dyncon, *dynconend; @@ -1328,6 +1329,7 @@ elf_link_add_object_symbols (abfd, info) free (buf); if (extversym != NULL) free (extversym); + _bfd_elf_strtab_delref (hash_table->dynstr, strindex); return true; } } @@ -1965,6 +1967,8 @@ elf_link_add_object_symbols (abfd, info) case STV_HIDDEN: h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; (*bed->elf_backend_hide_symbol) (info, h); + _bfd_elf_strtab_delref (hash_table->dynstr, + h->dynstr_index); break; } @@ -1983,15 +1987,13 @@ elf_link_add_object_symbols (abfd, info) have to make sure there is a DT_NEEDED entry for it. */ dt_needed = false; - oldsize = _bfd_stringtab_size (hash_table->dynstr); - strindex = _bfd_stringtab_add (hash_table->dynstr, - elf_dt_soname (abfd), - true, false); + oldsize = _bfd_elf_strtab_size (hash_table->dynstr); + strindex = _bfd_elf_strtab_add (hash_table->dynstr, + elf_dt_soname (abfd), false); if (strindex == (bfd_size_type) -1) goto error_return; - if (oldsize - == _bfd_stringtab_size (hash_table->dynstr)) + if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) { asection *sdyn; Elf_External_Dyn *dyncon, *dynconend; @@ -2290,7 +2292,7 @@ elf_link_create_dynamic_sections (abfd, info) /* Create a strtab to hold the dynamic symbol names. */ if (elf_hash_table (info)->dynstr == NULL) { - elf_hash_table (info)->dynstr = elf_stringtab_init (); + elf_hash_table (info)->dynstr = _bfd_elf_strtab_init (); if (elf_hash_table (info)->dynstr == NULL) return false; } @@ -2390,7 +2392,7 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) { struct elf_link_local_dynamic_entry *entry; struct elf_link_hash_table *eht; - struct bfd_strtab_hash *dynstr; + struct elf_strtab_hash *dynstr; Elf_External_Sym esym; unsigned long dynstr_index; char *name; @@ -2426,12 +2428,12 @@ elf_link_record_local_dynamic_symbol (info, input_bfd, input_indx) if (dynstr == NULL) { /* Create a strtab to hold the dynamic symbol names. */ - elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init (); + elf_hash_table (info)->dynstr = dynstr = _bfd_elf_strtab_init (); if (dynstr == NULL) return false; } - dynstr_index = _bfd_stringtab_add (dynstr, name, true, false); + dynstr_index = _bfd_elf_strtab_add (dynstr, name, false); if (dynstr_index == (unsigned long) -1) return false; entry->isym.st_name = dynstr_index; @@ -2949,8 +2951,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (soname != NULL) { - soname_indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - soname, true, true); + soname_indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + soname, true); if (soname_indx == (bfd_size_type) -1 || ! elf_add_dynamic_entry (info, (bfd_vma) DT_SONAME, soname_indx)) @@ -2969,8 +2971,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, { bfd_size_type indx; - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath, - true, true); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, rpath, + true); + if (info->new_dtags) + _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, indx); if (indx == (bfd_size_type) -1 || ! elf_add_dynamic_entry (info, (bfd_vma) DT_RPATH, indx) || (info->new_dtags @@ -2983,8 +2987,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, { bfd_size_type indx; - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - filter_shlib, true, true); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + filter_shlib, true); if (indx == (bfd_size_type) -1 || ! elf_add_dynamic_entry (info, (bfd_vma) DT_FILTER, indx)) return false; @@ -2998,8 +3002,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, { bfd_size_type indx; - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - *p, true, true); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + *p, true); if (indx == (bfd_size_type) -1 || ! elf_add_dynamic_entry (info, (bfd_vma) DT_AUXILIARY, indx)) @@ -3081,7 +3085,7 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, { bfd_size_type strsize; - strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr); + strsize = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); if (! elf_add_dynamic_entry (info, (bfd_vma) DT_HASH, (bfd_vma) 0) || ! elf_add_dynamic_entry (info, (bfd_vma) DT_STRTAB, (bfd_vma) 0) || ! elf_add_dynamic_entry (info, (bfd_vma) DT_SYMTAB, (bfd_vma) 0) @@ -3164,6 +3168,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, if (soname_indx != (bfd_size_type) -1) { + _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, + soname_indx); def.vd_hash = bfd_elf_hash (soname); defaux.vda_name = soname_indx; } @@ -3174,8 +3180,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, name = basename (output_bfd->filename); def.vd_hash = bfd_elf_hash (name); - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - name, true, false); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + name, false); if (indx == (bfd_size_type) -1) return false; defaux.vda_name = indx; @@ -3234,6 +3240,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, p += sizeof (Elf_External_Verdef); defaux.vda_name = h->dynstr_index; + _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, + h->dynstr_index); if (t->deps == NULL) defaux.vda_next = 0; else @@ -3253,7 +3261,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, defaux.vda_name = 0; } else - defaux.vda_name = n->version_needed->name_indx; + { + defaux.vda_name = n->version_needed->name_indx; + _bfd_elf_strtab_addref (elf_hash_table (info)->dynstr, + defaux.vda_name); + } if (n->next == NULL) defaux.vda_next = 0; else @@ -3352,14 +3364,11 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, t->vn_version = VER_NEED_CURRENT; t->vn_cnt = caux; - if (elf_dt_name (t->vn_bfd) != NULL) - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - elf_dt_name (t->vn_bfd), - true, false); - else - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - basename (t->vn_bfd->filename), - true, false); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + elf_dt_name (t->vn_bfd) != NULL + ? elf_dt_name (t->vn_bfd) + : basename (t->vn_bfd->filename), + false); if (indx == (bfd_size_type) -1) return false; t->vn_file = indx; @@ -3377,8 +3386,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr) { a->vna_hash = bfd_elf_hash (a->vna_nodename); - indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, - a->vna_nodename, true, false); + indx = _bfd_elf_strtab_add (elf_hash_table (info)->dynstr, + a->vna_nodename, false); if (indx == (bfd_size_type) -1) return false; a->vna_name = indx; @@ -3482,7 +3491,10 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, s = bfd_get_section_by_name (dynobj, ".dynstr"); BFD_ASSERT (s != NULL); - s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr); + + elf_finalize_dynstr (output_bfd, info); + + s->_raw_size = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); for (dtagcount = 0; dtagcount <= info->spare_dynamic_tags; ++dtagcount) if (! elf_add_dynamic_entry (info, (bfd_vma) DT_NULL, (bfd_vma) 0)) @@ -3492,6 +3504,150 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, return true; } +/* This function is used to adjust offsets into .dynstr for + dynamic symbols. This is called via elf_link_hash_traverse. */ + +static boolean elf_adjust_dynstr_offsets +PARAMS ((struct elf_link_hash_entry *, PTR)); + +static boolean +elf_adjust_dynstr_offsets (h, data) + struct elf_link_hash_entry *h; + PTR data; +{ + struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data; + + if (h->dynindx != -1) + h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index); + return true; +} + +/* Assign string offsets in .dynstr, update all structures referencing + them. */ + +static boolean +elf_finalize_dynstr (output_bfd, info) + bfd *output_bfd; + struct bfd_link_info *info; +{ + struct elf_link_local_dynamic_entry *entry; + struct elf_strtab_hash *dynstr = elf_hash_table (info)->dynstr; + bfd *dynobj = elf_hash_table (info)->dynobj; + asection *sdyn; + bfd_size_type size; + Elf_External_Dyn *dyncon, *dynconend; + + _bfd_elf_strtab_finalize (dynstr); + size = _bfd_elf_strtab_size (dynstr); + + /* Update all .dynamic entries referencing .dynstr strings. */ + sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + BFD_ASSERT (sdyn != NULL); + + dyncon = (Elf_External_Dyn *) sdyn->contents; + dynconend = (Elf_External_Dyn *) (sdyn->contents + + sdyn->_raw_size); + for (; dyncon < dynconend; dyncon++) + { + Elf_Internal_Dyn dyn; + + elf_swap_dyn_in (dynobj, dyncon, & dyn); + switch (dyn.d_tag) + { + case DT_STRSZ: + dyn.d_un.d_val = size; + elf_swap_dyn_out (dynobj, & dyn, dyncon); + break; + case DT_NEEDED: + case DT_SONAME: + case DT_RPATH: + case DT_RUNPATH: + case DT_FILTER: + case DT_AUXILIARY: + dyn.d_un.d_val = _bfd_elf_strtab_offset (dynstr, dyn.d_un.d_val); + elf_swap_dyn_out (dynobj, & dyn, dyncon); + break; + default: + break; + } + } + + /* Now update local dynamic symbols. */ + for (entry = elf_hash_table (info)->dynlocal; entry ; entry = entry->next) + entry->isym.st_name = _bfd_elf_strtab_offset (dynstr, + entry->isym.st_name); + + /* And the rest of dynamic symbols. */ + elf_link_hash_traverse (elf_hash_table (info), + elf_adjust_dynstr_offsets, dynstr); + + /* Adjust version definitions. */ + if (elf_tdata (output_bfd)->cverdefs) + { + asection *s; + bfd_byte *p; + bfd_size_type i; + Elf_Internal_Verdef def; + Elf_Internal_Verdaux defaux; + + s = bfd_get_section_by_name (dynobj, ".gnu.version_d"); + p = (bfd_byte *) s->contents; + do + { + _bfd_elf_swap_verdef_in (output_bfd, (Elf_External_Verdef *) p, + &def); + p += sizeof (Elf_External_Verdef); + for (i = 0; i < def.vd_cnt; ++i) + { + _bfd_elf_swap_verdaux_in (output_bfd, + (Elf_External_Verdaux *) p, &defaux); + defaux.vda_name = _bfd_elf_strtab_offset (dynstr, + defaux.vda_name); + _bfd_elf_swap_verdaux_out (output_bfd, + &defaux, (Elf_External_Verdaux *) p); + p += sizeof (Elf_External_Verdaux); + } + } + while (def.vd_next); + } + + /* Adjust version references. */ + if (elf_tdata (output_bfd)->verref) + { + asection *s; + bfd_byte *p; + bfd_size_type i; + Elf_Internal_Verneed need; + Elf_Internal_Vernaux needaux; + + s = bfd_get_section_by_name (dynobj, ".gnu.version_r"); + p = (bfd_byte *) s->contents; + do + { + _bfd_elf_swap_verneed_in (output_bfd, (Elf_External_Verneed *) p, + &need); + need.vn_file = _bfd_elf_strtab_offset (dynstr, need.vn_file); + _bfd_elf_swap_verneed_out (output_bfd, &need, + (Elf_External_Verneed *) p); + p += sizeof (Elf_External_Verneed); + for (i = 0; i < need.vn_cnt; ++i) + { + _bfd_elf_swap_vernaux_in (output_bfd, + (Elf_External_Vernaux *) p, &needaux); + needaux.vna_name = _bfd_elf_strtab_offset (dynstr, + needaux.vna_name); + _bfd_elf_swap_vernaux_out (output_bfd, + &needaux, + (Elf_External_Vernaux *) p); + p += sizeof (Elf_External_Vernaux); + } + } + while (need.vn_next); + } + + 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 @@ -3591,7 +3747,11 @@ elf_fix_symbol_flags (h, eif) bed = get_elf_backend_data (elf_hash_table (eif->info)->dynobj); if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL || ELF_ST_VISIBILITY (h->other) == STV_HIDDEN) - h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; + { + h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; + _bfd_elf_strtab_delref (elf_hash_table (eif->info)->dynstr, + h->dynstr_index); + } (*bed->elf_backend_hide_symbol) (eif->info, h); } @@ -3976,9 +4136,8 @@ elf_link_assign_sym_version (h, data) { h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; (*bed->elf_backend_hide_symbol) (info, h); - /* FIXME: The name of the symbol has - already been recorded in the dynamic - string table section. */ + _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, + h->dynstr_index); } break; @@ -4089,9 +4248,8 @@ elf_link_assign_sym_version (h, data) { h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; (*bed->elf_backend_hide_symbol) (info, h); - /* FIXME: The name of the symbol has already - been recorded in the dynamic string table - section. */ + _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, + h->dynstr_index); } break; } @@ -4111,8 +4269,8 @@ elf_link_assign_sym_version (h, data) { h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL; (*bed->elf_backend_hide_symbol) (info, h); - /* FIXME: The name of the symbol has already been - recorded in the dynamic string table section. */ + _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr, + h->dynstr_index); } } } @@ -5308,8 +5466,8 @@ elf_bfd_final_link (abfd, info) stringtab. */ off = elf_section_data (o->output_section)->this_hdr.sh_offset; if (bfd_seek (abfd, off, SEEK_SET) != 0 - || ! _bfd_stringtab_emit (abfd, - elf_hash_table (info)->dynstr)) + || ! _bfd_elf_strtab_emit (abfd, + elf_hash_table (info)->dynstr)) goto error_return; } } |