* 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.
This commit is contained in:
parent
ef5cdfc7dd
commit
2b0f7ef92e
11 changed files with 788 additions and 73 deletions
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 \
|
||||
|
|
2
bfd/configure
vendored
2
bfd/configure
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
459
bfd/elf-strtab.c
Normal file
459
bfd/elf-strtab.c
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
46
bfd/elf.c
46
bfd/elf.c
|
@ -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++;
|
||||
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
|
||||
}
|
||||
|
||||
if (d->rel_hdr2)
|
||||
{
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
248
bfd/elflink.h
248
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;
|
||||
_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;
|
||||
_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,7 +5466,7 @@ 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,
|
||||
|| ! _bfd_elf_strtab_emit (abfd,
|
||||
elf_hash_table (info)->dynstr))
|
||||
goto error_return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue