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 | |
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')
-rw-r--r-- | bfd/ChangeLog | 52 | ||||
-rw-r--r-- | bfd/Makefile.am | 3 | ||||
-rw-r--r-- | bfd/Makefile.in | 3 | ||||
-rwxr-xr-x | bfd/configure | 2 | ||||
-rw-r--r-- | bfd/configure.in | 2 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 28 | ||||
-rw-r--r-- | bfd/elf-strtab.c | 459 | ||||
-rw-r--r-- | bfd/elf.c | 50 | ||||
-rw-r--r-- | bfd/elf64-sparc.c | 2 | ||||
-rw-r--r-- | bfd/elflink.c | 6 | ||||
-rw-r--r-- | bfd/elflink.h | 254 |
11 files changed, 788 insertions, 73 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b5009f9..9aa309a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,55 @@ +2001-11-07 Jakub Jelinek <jakub@redhat.com> + + * 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. + 2001-11-07 Alan Modra <amodra@bigpond.net.au> * elflink.h (elf_link_input_bfd <removed linkonce relocs>): Fix diff --git a/bfd/Makefile.am b/bfd/Makefile.am index a1f737f..b675368 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -215,6 +215,7 @@ BFD32_BACKENDS = \ elf32-v850.lo \ elf32.lo \ elflink.lo \ + elf-strtab.lo \ epoc-pe-arm.lo \ epoc-pei-arm.lo \ hp300bsd.lo \ @@ -355,6 +356,7 @@ BFD32_BACKENDS_CFILES = \ elf32-v850.c \ elf32.c \ elflink.c \ + elf-strtab.c \ epoc-pe-arm.c \ epoc-pei-arm.c \ hp300bsd.c \ @@ -1129,6 +1131,7 @@ elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h +elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \ coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index efaae62..379c942 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -342,6 +342,7 @@ BFD32_BACKENDS = \ elf32-v850.lo \ elf32.lo \ elflink.lo \ + elf-strtab.lo \ epoc-pe-arm.lo \ epoc-pei-arm.lo \ hp300bsd.lo \ @@ -483,6 +484,7 @@ BFD32_BACKENDS_CFILES = \ elf32-v850.c \ elf32.c \ elflink.c \ + elf-strtab.c \ epoc-pe-arm.c \ epoc-pei-arm.c \ hp300bsd.c \ @@ -1672,6 +1674,7 @@ elf32.lo: elf32.c elfcode.h $(INCDIR)/filenames.h $(INCDIR)/libiberty.h \ elflink.lo: elflink.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \ $(INCDIR)/elf/external.h +elf-strtab.lo: elf-strtab.c $(INCDIR)/filenames.h $(INCDIR)/hashtab.h epoc-pe-arm.lo: epoc-pe-arm.c pe-arm.c $(INCDIR)/filenames.h \ coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/external.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \ diff --git a/bfd/configure b/bfd/configure index df9ba47..4a34b1a 100755 --- a/bfd/configure +++ b/bfd/configure @@ -5923,7 +5923,7 @@ selarchs="$f" # Target backend .o files. tb= -elf="elf.lo elflink.lo dwarf1.lo" +elf="elf.lo elflink.lo elf-strtab.lo dwarf1.lo" for vec in $selvecs do diff --git a/bfd/configure.in b/bfd/configure.in index abbd790..0ae2b62 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -503,7 +503,7 @@ selarchs="$f" # Target backend .o files. tb= -elf="elf.lo elflink.lo dwarf1.lo" +elf="elf.lo elflink.lo elf-strtab.lo dwarf1.lo" for vec in $selvecs do diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index fdb69c6..e9a8b83 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -79,6 +79,8 @@ typedef struct } elf_symbol_type; +struct elf_strtab_hash; + /* ELF linker hash table entries. */ struct elf_link_hash_entry @@ -248,7 +250,7 @@ struct elf_link_hash_table /* The string table of dynamic symbols, which becomes the .dynstr section. */ - struct bfd_strtab_hash *dynstr; + struct elf_strtab_hash *dynstr; /* The number of buckets in the hash table in the .hash section. This is based on the number of dynamic symbols. */ @@ -891,7 +893,7 @@ struct elf_obj_tdata Elf_Internal_Shdr **elf_sect_ptr; Elf_Internal_Phdr *phdr; struct elf_segment_map *segment_map; - struct bfd_strtab_hash *strtab_ptr; + struct elf_strtab_hash *strtab_ptr; int num_locals; int num_globals; int num_section_syms; @@ -1202,6 +1204,28 @@ extern boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *)); extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void)); + +extern struct elf_strtab_hash * _bfd_elf_strtab_init + PARAMS ((void)); +extern void _bfd_elf_strtab_free + PARAMS ((struct elf_strtab_hash *)); +extern bfd_size_type _bfd_elf_strtab_add + PARAMS ((struct elf_strtab_hash *, const char *, boolean)); +extern void _bfd_elf_strtab_addref + PARAMS ((struct elf_strtab_hash *, bfd_size_type)); +extern void _bfd_elf_strtab_delref + PARAMS ((struct elf_strtab_hash *, bfd_size_type)); +extern void _bfd_elf_strtab_clear_all_refs + PARAMS ((struct elf_strtab_hash *)); +extern bfd_size_type _bfd_elf_strtab_size + PARAMS ((struct elf_strtab_hash *)); +extern bfd_size_type _bfd_elf_strtab_offset + PARAMS ((struct elf_strtab_hash *, bfd_size_type)); +extern boolean _bfd_elf_strtab_emit + PARAMS ((bfd *, struct elf_strtab_hash *)); +extern void _bfd_elf_strtab_finalize + PARAMS ((struct elf_strtab_hash *)); + extern boolean _bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *)); extern long _bfd_elf_link_lookup_local_dynindx diff --git a/bfd/elf-strtab.c b/bfd/elf-strtab.c new file mode 100644 index 0000000..59a25a5 --- /dev/null +++ b/bfd/elf-strtab.c @@ -0,0 +1,459 @@ +/* ELF strtab with GC and suffix merging support. + Copyright 2001 Free Software Foundation, Inc. + Written by Jakub Jelinek <jakub@redhat.com>. + +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 +(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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "elf-bfd.h" +#include "hashtab.h" + +/* An entry in the strtab hash table. */ + +struct elf_strtab_hash_entry +{ + struct bfd_hash_entry root; + /* Length of this entry. */ + unsigned int len; + unsigned int refcount; + union { + /* Index within the merged section. */ + bfd_size_type index; + /* Entry this is a suffix of (if len is 0). */ + struct elf_strtab_hash_entry *suffix; + } u; +}; + +/* The strtab hash table. */ + +struct elf_strtab_hash +{ + struct bfd_hash_table table; + /* Next available index. */ + bfd_size_type size; + /* Number of array entries alloced. */ + bfd_size_type alloced; + /* Final strtab size. */ + bfd_size_type sec_size; + /* Array of pointers to strtab entries. */ + struct elf_strtab_hash_entry **array; +}; + +static struct bfd_hash_entry *elf_strtab_hash_newfunc + PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *)); +static int cmplengthentry PARAMS ((const PTR, const PTR)); +static int last4_eq PARAMS ((const PTR, const PTR)); +static int last_eq PARAMS ((const PTR, const PTR)); + +/* Routine to create an entry in a section merge hashtab. */ + +static struct bfd_hash_entry * +elf_strtab_hash_newfunc (entry, table, string) + struct bfd_hash_entry *entry; + struct bfd_hash_table *table; + const char *string; +{ + struct elf_strtab_hash_entry *ret = (struct elf_strtab_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a + subclass. */ + if (ret == (struct elf_strtab_hash_entry *) NULL) + ret = ((struct elf_strtab_hash_entry *) + bfd_hash_allocate (table, sizeof (struct elf_strtab_hash_entry))); + if (ret == (struct elf_strtab_hash_entry *) NULL) + return NULL; + + /* Call the allocation method of the superclass. */ + ret = ((struct elf_strtab_hash_entry *) + bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + + if (ret) + { + /* Initialize the local fields. */ + ret->u.index = -1; + ret->refcount = 0; + ret->len = 0; + } + + return (struct bfd_hash_entry *)ret; +} + +/* Create a new hash table. */ + +struct elf_strtab_hash * +_bfd_elf_strtab_init () +{ + struct elf_strtab_hash *table; + bfd_size_type amt = sizeof (struct elf_strtab_hash); + + table = (struct elf_strtab_hash *) bfd_malloc (amt); + if (table == NULL) + return NULL; + + if (! bfd_hash_table_init (&table->table, elf_strtab_hash_newfunc)) + { + free (table); + return NULL; + } + + table->sec_size = 0; + table->size = 1; + table->alloced = 64; + amt = sizeof (struct elf_strtab_hasn_entry *); + table->array = (struct elf_strtab_hash_entry **) + bfd_malloc (table->alloced * amt); + if (table->array == NULL) + { + free (table); + return NULL; + } + + table->array[0] = NULL; + + return table; +} + +/* Free a strtab. */ + +void +_bfd_elf_strtab_free (tab) + struct elf_strtab_hash *tab; +{ + bfd_hash_table_free (&tab->table); + free (tab->array); + free (tab); +} + +/* Get the index of an entity in a hash table, adding it if it is not + already present. */ + +bfd_size_type +_bfd_elf_strtab_add (tab, str, copy) + struct elf_strtab_hash *tab; + const char *str; + boolean copy; +{ + register struct elf_strtab_hash_entry *entry; + + /* We handle this specially, since we don't want to do refcounting + on it. */ + if (*str == '\0') + return 0; + + BFD_ASSERT (tab->sec_size == 0); + entry = (struct elf_strtab_hash_entry *) + bfd_hash_lookup (&tab->table, str, true, copy); + + if (entry == NULL) + return (bfd_size_type) -1; + + entry->refcount++; + if (entry->len == 0) + { + entry->len = strlen (str) + 1; + if (tab->size == tab->alloced) + { + bfd_size_type amt = sizeof (struct elf_strtab_hash_entry *); + tab->alloced *= 2; + tab->array = (struct elf_strtab_hash_entry **) + bfd_realloc (tab->array, tab->alloced * amt); + if (tab->array == NULL) + return (bfd_size_type) -1; + } + + entry->u.index = tab->size++; + tab->array[entry->u.index] = entry; + } + return entry->u.index; +} + +void +_bfd_elf_strtab_addref (tab, idx) + struct elf_strtab_hash *tab; + bfd_size_type idx; +{ + if (idx == 0 || idx == (bfd_size_type) -1) + return; + BFD_ASSERT (tab->sec_size == 0); + BFD_ASSERT (idx < tab->size); + ++tab->array[idx]->refcount; +} + +void +_bfd_elf_strtab_delref (tab, idx) + struct elf_strtab_hash *tab; + bfd_size_type idx; +{ + if (idx == 0 || idx == (bfd_size_type) -1) + return; + BFD_ASSERT (tab->sec_size == 0); + BFD_ASSERT (idx < tab->size); + BFD_ASSERT (tab->array[idx]->refcount > 0); + --tab->array[idx]->refcount; +} + +void +_bfd_elf_strtab_clear_all_refs (tab) + struct elf_strtab_hash *tab; +{ + bfd_size_type idx; + + for (idx = 1; idx < tab->size; ++idx) + tab->array[idx]->refcount = 0; +} + +bfd_size_type +_bfd_elf_strtab_size (tab) + struct elf_strtab_hash *tab; +{ + return tab->sec_size ? tab->sec_size : tab->size; +} + +bfd_size_type +_bfd_elf_strtab_offset (tab, idx) + struct elf_strtab_hash *tab; + bfd_size_type idx; +{ + struct elf_strtab_hash_entry *entry; + + if (idx == 0) + return 0; + BFD_ASSERT (idx < tab->size); + BFD_ASSERT (tab->sec_size); + entry = tab->array[idx]; + BFD_ASSERT (entry->refcount > 0); + entry->refcount--; + return tab->array[idx]->u.index; +} + +boolean +_bfd_elf_strtab_emit (abfd, tab) + register bfd *abfd; + struct elf_strtab_hash *tab; +{ + bfd_size_type off = 1, i; + + if (bfd_bwrite ("", 1, abfd) != 1) + return false; + + for (i = 1; i < tab->size; ++i) + { + register const char *str; + register size_t len; + + str = tab->array[i]->root.string; + len = tab->array[i]->len; + BFD_ASSERT (tab->array[i]->refcount == 0); + if (len == 0) + continue; + + if (bfd_bwrite ((PTR) str, (bfd_size_type) len, abfd) != len) + return false; + + off += len; + } + + BFD_ASSERT (off == tab->sec_size); + return true; +} + +/* Compare two elf_strtab_hash_entry structures. This is called via qsort. */ + +static int +cmplengthentry (a, b) + const PTR a; + const PTR b; +{ + struct elf_strtab_hash_entry * A = *(struct elf_strtab_hash_entry **) a; + struct elf_strtab_hash_entry * B = *(struct elf_strtab_hash_entry **) b; + + if (A->len < B->len) + return 1; + else if (A->len > B->len) + return -1; + + return memcmp (A->root.string, B->root.string, A->len); +} + +static int +last4_eq (a, b) + const PTR a; + const PTR b; +{ + struct elf_strtab_hash_entry * A = (struct elf_strtab_hash_entry *) a; + struct elf_strtab_hash_entry * B = (struct elf_strtab_hash_entry *) b; + + if (memcmp (A->root.string + A->len - 5, B->root.string + B->len - 5, 4) + != 0) + /* This was a hashtable collision. */ + return 0; + + if (A->len <= B->len) + /* B cannot be a suffix of A unless A is equal to B, which is guaranteed + not to be equal by the hash table. */ + return 0; + + return memcmp (A->root.string + (A->len - B->len), + B->root.string, B->len - 5) == 0; +} + +static int +last_eq (a, b) + const PTR a; + const PTR b; +{ + struct elf_strtab_hash_entry * A = (struct elf_strtab_hash_entry *) a; + struct elf_strtab_hash_entry * B = (struct elf_strtab_hash_entry *) b; + + if (B->len >= 5) + /* Longer strings are just pushed into the hash table, + they'll be used when looking up for very short strings. */ + return 0; + + if (memcmp (A->root.string + A->len - 2, B->root.string + B->len - 2, 1) + != 0) + /* This was a hashtable collision. */ + return 0; + + if (A->len <= B->len) + /* B cannot be a suffix of A unless A is equal to B, which is guaranteed + not to be equal by the hash table. */ + return 0; + + return memcmp (A->root.string + (A->len - B->len), + B->root.string, B->len - 2) == 0; +} + +/* This function assigns final string table offsets for used strings, + merging strings matching suffixes of longer strings if possible. */ + +void +_bfd_elf_strtab_finalize (tab) + struct elf_strtab_hash *tab; +{ + struct elf_strtab_hash_entry **array, **a, **end, *e; + htab_t lasttab = NULL, last4tab = NULL; + bfd_size_type size, amt, i; + + /* Now sort the strings by length, longest first. */ + array = NULL; + amt = tab->size * sizeof (struct elf_strtab_hash_entry *); + array = (struct elf_strtab_hash_entry **) bfd_malloc (amt); + if (array == NULL) + goto alloc_failure; + + for (i = 1, a = array; i < tab->size; ++i) + if (tab->array[i]->refcount) + *a++ = tab->array[i]; + else + tab->array[i]->len = 0; + + size = a - array; + + qsort (array, size, sizeof (struct elf_strtab_hash_entry *), cmplengthentry); + + last4tab = htab_create (size * 4, NULL, last4_eq, NULL); + lasttab = htab_create (size * 4, NULL, last_eq, NULL); + if (lasttab == NULL || last4tab == NULL) + goto alloc_failure; + + /* Now insert the strings into hash tables (strings with last 4 characters + and strings with last character equal), look for longer strings which + we're suffix of. */ + for (a = array, end = array + size; a < end; a++) + { + register hashval_t hash; + unsigned int c; + unsigned int i; + const unsigned char *s; + PTR *p; + + e = *a; + if (e->len > 4) + { + s = e->root.string + e->len - 1; + hash = 0; + for (i = 0; i < 4; i++) + { + c = *--s; + hash += c + (c << 17); + hash ^= hash >> 2; + } + p = htab_find_slot_with_hash (last4tab, e, hash, INSERT); + if (p == NULL) + goto alloc_failure; + if (*p) + { + struct elf_strtab_hash_entry *ent; + + ent = (struct elf_strtab_hash_entry *) *p; + e->u.suffix = ent; + e->len = 0; + continue; + } + else + *p = (PTR) e; + } + c = (unsigned char) e->root.string[e->len - 1]; + p = htab_find_slot_with_hash (lasttab, e, c, INSERT); + if (p == NULL) + goto alloc_failure; + if (*p) + { + struct elf_strtab_hash_entry *ent; + + ent = (struct elf_strtab_hash_entry *) *p; + e->u.suffix = ent; + e->len = 0; + } + else + *p = (PTR) e; + } + +alloc_failure: + if (array) + free (array); + if (lasttab) + htab_delete (lasttab); + if (last4tab) + htab_delete (last4tab); + + /* Now assign positions to the strings we want to keep. */ + size = 1; + for (i = 1; i < tab->size; ++i) + { + e = tab->array[i]; + if (e->refcount && e->len) + { + e->u.index = size; + size += e->len; + } + } + + tab->sec_size = size; + + /* And now adjust the rest. */ + for (i = 1; i < tab->size; ++i) + { + e = tab->array[i]; + if (e->refcount && ! e->len) + e->u.index = e->u.suffix->u.index + + (e->u.suffix->len - strlen (e->root.string) - 1); + } +} @@ -1939,8 +1939,8 @@ _bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p) return false; sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name); rel_hdr->sh_name = - (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name, - true, false); + (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name, + false); if (rel_hdr->sh_name == (unsigned int) -1) return false; rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; @@ -1977,9 +1977,8 @@ elf_fake_sections (abfd, asect, failedptrarg) this_hdr = &elf_section_data (asect)->this_hdr; - this_hdr->sh_name = (unsigned long) _bfd_stringtab_add (elf_shstrtab (abfd), - asect->name, - true, false); + this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd), + asect->name, false); if (this_hdr->sh_name == (unsigned long) -1) { *failedptr = true; @@ -2200,38 +2199,51 @@ assign_section_numbers (abfd) { struct elf_obj_tdata *t = elf_tdata (abfd); asection *sec; - unsigned int section_number; + unsigned int section_number, secn; Elf_Internal_Shdr **i_shdrp; bfd_size_type amt; section_number = 1; + _bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd)); + for (sec = abfd->sections; sec; sec = sec->next) { struct bfd_elf_section_data *d = elf_section_data (sec); d->this_idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name); if ((sec->flags & SEC_RELOC) == 0) d->rel_idx = 0; else - d->rel_idx = section_number++; + { + d->rel_idx = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name); + } if (d->rel_hdr2) - d->rel_idx2 = section_number++; + { + d->rel_idx2 = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name); + } else d->rel_idx2 = 0; } t->shstrtab_section = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name); elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; - t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd)); if (bfd_get_symcount (abfd) > 0) { t->symtab_section = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name); t->strtab_section = section_number++; + _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name); } + _bfd_elf_strtab_finalize (elf_shstrtab (abfd)); + t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); elf_elfheader (abfd)->e_shnum = section_number; /* Set up the list of section header pointers, in agreement with the @@ -2368,6 +2380,10 @@ assign_section_numbers (abfd) } } + for (secn = 1; secn < section_number; ++secn) + i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd), + i_shdrp[secn]->sh_name); + return true; } @@ -2629,7 +2645,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info) shstrtab_hdr->sh_type = SHT_STRTAB; shstrtab_hdr->sh_flags = 0; shstrtab_hdr->sh_addr = 0; - shstrtab_hdr->sh_size = _bfd_stringtab_size (elf_shstrtab (abfd)); + shstrtab_hdr->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd)); shstrtab_hdr->sh_entsize = 0; shstrtab_hdr->sh_link = 0; shstrtab_hdr->sh_info = 0; @@ -3620,13 +3636,13 @@ prep_headers (abfd) Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ int count; - struct bfd_strtab_hash *shstrtab; + struct elf_strtab_hash *shstrtab; struct elf_backend_data *bed = get_elf_backend_data (abfd); i_ehdrp = elf_elfheader (abfd); i_shdrp = elf_elfsections (abfd); - shstrtab = _bfd_elf_stringtab_init (); + shstrtab = _bfd_elf_strtab_init (); if (shstrtab == NULL) return false; @@ -3712,11 +3728,11 @@ prep_headers (abfd) } elf_tdata (abfd)->symtab_hdr.sh_name = - (unsigned int) _bfd_stringtab_add (shstrtab, ".symtab", true, false); + (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", false); elf_tdata (abfd)->strtab_hdr.sh_name = - (unsigned int) _bfd_stringtab_add (shstrtab, ".strtab", true, false); + (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", false); elf_tdata (abfd)->shstrtab_hdr.sh_name = - (unsigned int) _bfd_stringtab_add (shstrtab, ".shstrtab", true, false); + (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", false); if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1 || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1 || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1) @@ -3795,7 +3811,7 @@ _bfd_elf_write_object_contents (abfd) /* Write out the section header names. */ if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0 - || ! _bfd_stringtab_emit (abfd, elf_shstrtab (abfd))) + || ! _bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))) return false; if (bed->elf_backend_final_write_processing) @@ -5549,7 +5565,7 @@ _bfd_elf_close_and_cleanup (abfd) if (bfd_get_format (abfd) == bfd_object) { if (elf_shstrtab (abfd) != NULL) - _bfd_stringtab_free (elf_shstrtab (abfd)); + _bfd_elf_strtab_free (elf_shstrtab (abfd)); } return _bfd_generic_close_and_cleanup (abfd); diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c index cb03eeb..cd0d914 100644 --- a/bfd/elf64-sparc.c +++ b/bfd/elf64-sparc.c @@ -1840,7 +1840,7 @@ sparc64_elf_size_dynamic_sections (output_bfd, info) entry->isym.st_size = 0; if (*app_regs [reg].name != '\0') entry->isym.st_name - = _bfd_stringtab_add (dynstr, app_regs[reg].name, true, false); + = _bfd_elf_strtab_add (dynstr, app_regs[reg].name, false); else entry->isym.st_name = 0; entry->isym.st_other = 0; diff --git a/bfd/elflink.c b/bfd/elflink.c index 05a2288..fdc82b7 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -230,7 +230,7 @@ _bfd_elf_link_record_dynamic_symbol (info, h) { if (h->dynindx == -1) { - struct bfd_strtab_hash *dynstr; + struct elf_strtab_hash *dynstr; char *p, *alc; const char *name; boolean copy; @@ -262,7 +262,7 @@ _bfd_elf_link_record_dynamic_symbol (info, h) 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; } @@ -287,7 +287,7 @@ _bfd_elf_link_record_dynamic_symbol (info, h) copy = true; } - indx = _bfd_stringtab_add (dynstr, name, true, copy); + indx = _bfd_elf_strtab_add (dynstr, name, copy); if (alc != NULL) free (alc); 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; } } |