Use a hash table when writing out ELF symbol names.

* elfcode.h (elf_stringtab_init): New static function.
	(bfd_new_strtab, bfd_add_to_strtab, bfd_add_2_to_strtab): Remove.
	Change all callers to use elf_stringtab_init or
	_bfd_stringtab_add, and get stringtab lengths using
	_bfd_stringtab_size.
	(elf_fake_sections): Change ignored argument to pointer to
	boolean, and set the boolean to true if an error occurs.  If an
	error has already occurred, don't do anything.
	(assign_section_numbers): Just set sh_size, not contents.
	(elf_compute_section_file_positions): Pass the address of a
	boolean to elf_fake_sections.  Pass the address of a
	bfd_strtab_hash to swap_out_syms.  Write out the .strtab section.
	(prep_headers): Change shstrtab to bfd_strtab_hash.
	(swap_out_syms): Take a pointer to a bfd_strtab_hash as an
	argument.  Set it to the symbol names.
	(NAME(bfd_elf,write_object_contents)): Write out the section
	header names using _bfd_stringtab_emit.
	(elf_debug_section): Remove first argument; get the section name
	via the bfd_section pointer.  Change caller.
	(elf_bfd_final_link): Write out the symbol names using
	_bfd_stringtab_emit.  Likewise for the .dynstr section contents.
	Free the symbol names at the end of the function.
	(elf_link_input_bfd): Remove the last argument, output_names,
	from relocate_section.  Save the old symbol contents before
	calling elf_link_output_sym, and restore them afterward.
	* libelf.h (struct elf_link_hash_table): Change dynstr field to
	struct bfd_strtab_hash.
	(struct elf_backend_data): Remove last argument, output_names,
	from elf_backend_relocate_section field.
	(struct strtab): Don't define.
	(struct elf_obj_tdata): Change strtab_ptr field to struct
	bfd_strtab_hash.
	* elf32-hppa.c (elf32_hppa_relocate_section): Remove last
	argument, output_names.
	* elf32-i386.c (elf_i386_relocate_section): Likewise.
	* elf32-mips.c (mips_elf_relocate_section): Likewise.
	* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
This commit is contained in:
Ian Lance Taylor 1994-10-17 22:03:14 +00:00
parent 51bdfd9b22
commit eb4267a3f9
5 changed files with 1049 additions and 381 deletions

View file

@ -1,5 +1,44 @@
Mon Oct 17 11:38:16 1994 Ian Lance Taylor <ian@sanguine.cygnus.com> Mon Oct 17 11:38:16 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
Use a hash table when writing out ELF symbol names.
* elfcode.h (elf_stringtab_init): New static function.
(bfd_new_strtab, bfd_add_to_strtab, bfd_add_2_to_strtab): Remove.
Change all callers to use elf_stringtab_init or
_bfd_stringtab_add, and get stringtab lengths using
_bfd_stringtab_size.
(elf_fake_sections): Change ignored argument to pointer to
boolean, and set the boolean to true if an error occurs. If an
error has already occurred, don't do anything.
(assign_section_numbers): Just set sh_size, not contents.
(elf_compute_section_file_positions): Pass the address of a
boolean to elf_fake_sections. Pass the address of a
bfd_strtab_hash to swap_out_syms. Write out the .strtab section.
(prep_headers): Change shstrtab to bfd_strtab_hash.
(swap_out_syms): Take a pointer to a bfd_strtab_hash as an
argument. Set it to the symbol names.
(NAME(bfd_elf,write_object_contents)): Write out the section
header names using _bfd_stringtab_emit.
(elf_debug_section): Remove first argument; get the section name
via the bfd_section pointer. Change caller.
(elf_bfd_final_link): Write out the symbol names using
_bfd_stringtab_emit. Likewise for the .dynstr section contents.
Free the symbol names at the end of the function.
(elf_link_input_bfd): Remove the last argument, output_names,
from relocate_section. Save the old symbol contents before
calling elf_link_output_sym, and restore them afterward.
* libelf.h (struct elf_link_hash_table): Change dynstr field to
struct bfd_strtab_hash.
(struct elf_backend_data): Remove last argument, output_names,
from elf_backend_relocate_section field.
(struct strtab): Don't define.
(struct elf_obj_tdata): Change strtab_ptr field to struct
bfd_strtab_hash.
* elf32-hppa.c (elf32_hppa_relocate_section): Remove last
argument, output_names.
* elf32-i386.c (elf_i386_relocate_section): Likewise.
* elf32-mips.c (mips_elf_relocate_section): Likewise.
* elf32-sparc.c (elf32_sparc_relocate_section): Likewise.
* libbfd-in.h (DEFAULT_STRING_SPACE_SIZE): Don't define. * libbfd-in.h (DEFAULT_STRING_SPACE_SIZE): Don't define.
(bfd_add_to_string_table): Don't declare. (bfd_add_to_string_table): Don't declare.
* libbfd.h: Rebuild. * libbfd.h: Rebuild.

View file

@ -257,8 +257,7 @@ elf32_hppa_args_hash_newfunc
static boolean static boolean
elf32_hppa_relocate_section elf32_hppa_relocate_section
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
char *));
static boolean static boolean
elf32_hppa_stub_hash_table_init elf32_hppa_stub_hash_table_init
@ -762,8 +761,7 @@ hppa_elf_relocate_insn (abfd, input_sect, insn, address, sym_value,
static boolean static boolean
elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section, elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
contents, relocs, local_syms, local_sections, contents, relocs, local_syms, local_sections)
output_names)
bfd *output_bfd; bfd *output_bfd;
struct bfd_link_info *info; struct bfd_link_info *info;
bfd *input_bfd; bfd *input_bfd;
@ -772,7 +770,6 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
Elf_Internal_Rela *relocs; Elf_Internal_Rela *relocs;
Elf_Internal_Sym *local_syms; Elf_Internal_Sym *local_syms;
asection **local_sections; asection **local_sections;
char *output_names;
{ {
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *rel; Elf_Internal_Rela *rel;
@ -865,7 +862,9 @@ elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
sym_name = h->root.root.string; sym_name = h->root.root.string;
else else
{ {
sym_name = output_names + sym->st_name; sym_name = elf_string_from_elf_section (input_bfd,
symtab_hdr->sh_link,
sym->st_name);
if (sym_name == NULL) if (sym_name == NULL)
return false; return false;
if (*sym_name == '\0') if (*sym_name == '\0')

File diff suppressed because it is too large Load diff

View file

@ -140,8 +140,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Forward declarations of static functions */ /* Forward declarations of static functions */
static unsigned long bfd_add_to_strtab static struct bfd_strtab_hash *elf_stringtab_init PARAMS ((void));
PARAMS ((bfd *, struct strtab *, const char *));
static asection *section_from_elf_index PARAMS ((bfd *, unsigned int)); static asection *section_from_elf_index PARAMS ((bfd *, unsigned int));
static int elf_section_from_bfd_section PARAMS ((bfd *, struct sec *)); static int elf_section_from_bfd_section PARAMS ((bfd *, struct sec *));
@ -168,12 +167,12 @@ static file_ptr map_program_segments
PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, bfd_size_type)); PARAMS ((bfd *, file_ptr, Elf_Internal_Shdr *, bfd_size_type));
static boolean elf_map_symbols PARAMS ((bfd *)); static boolean elf_map_symbols PARAMS ((bfd *));
static boolean swap_out_syms PARAMS ((bfd *)); static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **));
static boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex)); static boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex));
#ifdef DEBUG #ifdef DEBUG
static void elf_debug_section PARAMS ((char *, int, Elf_Internal_Shdr *)); static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *));
static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *)); static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *));
#endif #endif
@ -427,85 +426,27 @@ elf_swap_dyn_out (abfd, src, dst)
put_word (abfd, src->d_un.d_val, dst->d_un.d_val); put_word (abfd, src->d_un.d_val, dst->d_un.d_val);
} }
/* String table creation/manipulation routines */ /* Allocate an ELF string table--force the first byte to be zero. */
static struct strtab * static struct bfd_strtab_hash *
bfd_new_strtab (abfd) elf_stringtab_init ()
bfd *abfd;
{ {
struct strtab *ss; struct bfd_strtab_hash *ret;
ss = (struct strtab *) malloc (sizeof (struct strtab)); ret = _bfd_stringtab_init ();
if (!ss) if (ret != NULL)
{ {
bfd_set_error (bfd_error_no_memory); bfd_size_type loc;
return NULL;
} loc = _bfd_stringtab_add (ret, "", true, false);
ss->tab = malloc (1); BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
if (!ss->tab) if (loc == (bfd_size_type) -1)
{ {
bfd_set_error (bfd_error_no_memory); _bfd_stringtab_free (ret);
return NULL; ret = NULL;
} }
*ss->tab = 0;
ss->nentries = 0;
ss->length = 1;
return ss;
}
static unsigned long
bfd_add_to_strtab (abfd, ss, str)
bfd *abfd;
struct strtab *ss;
const char *str;
{
/* should search first, but for now: */
/* include the trailing NUL */
int ln = strlen (str) + 1;
/* FIXME: This is slow. Also, we could combine this with the a.out
string table building and use a hash table, although it might not
be worth it since ELF symbols don't include debugging information
and thus have much less overlap. */
ss->tab = realloc (ss->tab, ss->length + ln);
if (ss->tab == NULL)
{
bfd_set_error (bfd_error_no_memory);
return (unsigned long) -1;
} }
return ret;
strcpy (ss->tab + ss->length, str);
ss->nentries++;
ss->length += ln;
return ss->length - ln;
}
static int
bfd_add_2_to_strtab (abfd, ss, str, str2)
bfd *abfd;
struct strtab *ss;
char *str;
CONST char *str2;
{
/* should search first, but for now: */
/* include the trailing NUL */
int ln = strlen (str) + strlen (str2) + 1;
/* should this be using obstacks? */
if (ss->length)
ss->tab = realloc (ss->tab, ss->length + ln);
else
ss->tab = malloc (ln);
BFD_ASSERT (ss->tab != 0); /* FIXME */
strcpy (ss->tab + ss->length, str);
strcpy (ss->tab + ss->length + strlen (str), str2);
ss->nentries++;
ss->length += ln;
return ss->length - ln;
} }
/* ELF .o/exec file reading */ /* ELF .o/exec file reading */
@ -1160,19 +1101,31 @@ write_relocs (abfd, sec, xxx)
/*ARGSUSED*/ /*ARGSUSED*/
static void static void
elf_fake_sections (abfd, asect, ignore) elf_fake_sections (abfd, asect, failedptrarg)
bfd *abfd; bfd *abfd;
asection *asect; asection *asect;
PTR ignore; PTR failedptrarg;
{ {
boolean *failedptr = (boolean *) failedptrarg;
Elf_Internal_Shdr *this_hdr; Elf_Internal_Shdr *this_hdr;
if (*failedptr)
{
/* We already failed; just get out of the bfd_map_over_sections
loop. */
return;
}
this_hdr = &elf_section_data (asect)->this_hdr; this_hdr = &elf_section_data (asect)->this_hdr;
this_hdr->sh_name = bfd_add_to_strtab (abfd, elf_shstrtab (abfd), this_hdr->sh_name = (unsigned long) _bfd_stringtab_add (elf_shstrtab (abfd),
asect->name); asect->name,
true, false);
if (this_hdr->sh_name == (unsigned long) -1) if (this_hdr->sh_name == (unsigned long) -1)
abort (); /* FIXME */ {
*failedptr = true;
return;
}
this_hdr->sh_flags = 0; this_hdr->sh_flags = 0;
if ((asect->flags & SEC_ALLOC) != 0) if ((asect->flags & SEC_ALLOC) != 0)
@ -1261,12 +1214,25 @@ elf_fake_sections (abfd, asect, ignore)
{ {
Elf_Internal_Shdr *rela_hdr; Elf_Internal_Shdr *rela_hdr;
int use_rela_p = get_elf_backend_data (abfd)->use_rela_p; int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
char *name;
rela_hdr = &elf_section_data (asect)->rel_hdr; rela_hdr = &elf_section_data (asect)->rel_hdr;
name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name));
if (name == NULL)
{
bfd_set_error (bfd_error_no_memory);
*failedptr = true;
return;
}
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
rela_hdr->sh_name = rela_hdr->sh_name =
bfd_add_2_to_strtab (abfd, elf_shstrtab (abfd), (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name,
use_rela_p ? ".rela" : ".rel", true, false);
asect->name); if (rela_hdr->sh_name == (unsigned int) -1)
{
*failedptr = true;
return;
}
rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL; rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
rela_hdr->sh_entsize = (use_rela_p rela_hdr->sh_entsize = (use_rela_p
? sizeof (Elf_External_Rela) ? sizeof (Elf_External_Rela)
@ -1307,8 +1273,7 @@ assign_section_numbers (abfd)
t->shstrtab_section = section_number++; t->shstrtab_section = section_number++;
elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
t->shstrtab_hdr.sh_size = elf_shstrtab (abfd)->length; t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
t->shstrtab_hdr.contents = (PTR) elf_shstrtab (abfd)->tab;
if (abfd->symcount > 0) if (abfd->symcount > 0)
{ {
@ -1645,6 +1610,8 @@ elf_compute_section_file_positions (abfd, link_info)
struct bfd_link_info *link_info; struct bfd_link_info *link_info;
{ {
struct elf_backend_data *bed = get_elf_backend_data (abfd); struct elf_backend_data *bed = get_elf_backend_data (abfd);
boolean failed;
struct bfd_strtab_hash *strtab;
Elf_Internal_Shdr *shstrtab_hdr; Elf_Internal_Shdr *shstrtab_hdr;
if (abfd->output_has_begun) if (abfd->output_has_begun)
@ -1657,7 +1624,10 @@ elf_compute_section_file_positions (abfd, link_info)
if (! prep_headers (abfd)) if (! prep_headers (abfd))
return false; return false;
bfd_map_over_sections (abfd, elf_fake_sections, 0); failed = false;
bfd_map_over_sections (abfd, elf_fake_sections, &failed);
if (failed)
return false;
if (!assign_section_numbers (abfd)) if (!assign_section_numbers (abfd))
return false; return false;
@ -1665,7 +1635,7 @@ elf_compute_section_file_positions (abfd, link_info)
/* The backend linker builds symbol table information itself. */ /* The backend linker builds symbol table information itself. */
if (link_info == NULL) if (link_info == NULL)
{ {
if (! swap_out_syms (abfd)) if (! swap_out_syms (abfd, &strtab))
return false; return false;
} }
@ -1674,18 +1644,28 @@ elf_compute_section_file_positions (abfd, link_info)
shstrtab_hdr->sh_type = SHT_STRTAB; shstrtab_hdr->sh_type = SHT_STRTAB;
shstrtab_hdr->sh_flags = 0; shstrtab_hdr->sh_flags = 0;
shstrtab_hdr->sh_addr = 0; shstrtab_hdr->sh_addr = 0;
shstrtab_hdr->sh_size = elf_shstrtab (abfd)->length; shstrtab_hdr->sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
shstrtab_hdr->sh_entsize = 0; shstrtab_hdr->sh_entsize = 0;
shstrtab_hdr->sh_link = 0; shstrtab_hdr->sh_link = 0;
shstrtab_hdr->sh_info = 0; shstrtab_hdr->sh_info = 0;
/* sh_offset is set in assign_file_positions_for_symtabs_and_strtabs. */ /* sh_offset is set in assign_file_positions_for_symtabs_and_strtabs. */
shstrtab_hdr->sh_addralign = 1; shstrtab_hdr->sh_addralign = 1;
shstrtab_hdr->contents = (PTR) elf_shstrtab (abfd)->tab;
if (!assign_file_positions_except_relocs (abfd, if (!assign_file_positions_except_relocs (abfd,
link_info == NULL ? true : false)) link_info == NULL ? true : false))
return false; return false;
if (link_info == NULL)
{
/* Now that we know where the .strtab section goes, write it
out. */
if ((bfd_seek (abfd, elf_tdata (abfd)->strtab_hdr.sh_offset, SEEK_SET)
!= 0)
|| ! _bfd_stringtab_emit (abfd, strtab))
return false;
_bfd_stringtab_free (strtab);
}
abfd->output_has_begun = true; abfd->output_has_begun = true;
return true; return true;
@ -2144,13 +2124,13 @@ prep_headers (abfd)
Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */ Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
int count; int count;
struct strtab *shstrtab; struct bfd_strtab_hash *shstrtab;
i_ehdrp = elf_elfheader (abfd); i_ehdrp = elf_elfheader (abfd);
i_shdrp = elf_elfsections (abfd); i_shdrp = elf_elfsections (abfd);
shstrtab = bfd_new_strtab (abfd); shstrtab = elf_stringtab_init ();
if (!shstrtab) if (shstrtab == NULL)
return false; return false;
elf_shstrtab (abfd) = shstrtab; elf_shstrtab (abfd) = shstrtab;
@ -2245,12 +2225,12 @@ prep_headers (abfd)
i_ehdrp->e_phoff = 0; i_ehdrp->e_phoff = 0;
} }
elf_tdata (abfd)->symtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, elf_tdata (abfd)->symtab_hdr.sh_name =
".symtab"); (unsigned int) _bfd_stringtab_add (shstrtab, ".symtab", true, false);
elf_tdata (abfd)->strtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, elf_tdata (abfd)->strtab_hdr.sh_name =
".strtab"); (unsigned int) _bfd_stringtab_add (shstrtab, ".strtab", true, false);
elf_tdata (abfd)->shstrtab_hdr.sh_name = bfd_add_to_strtab (abfd, shstrtab, elf_tdata (abfd)->shstrtab_hdr.sh_name =
".shstrtab"); (unsigned int) _bfd_stringtab_add (shstrtab, ".shstrtab", true, false);
if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1 if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
|| 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) || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
@ -2260,8 +2240,9 @@ prep_headers (abfd)
} }
static boolean static boolean
swap_out_syms (abfd) swap_out_syms (abfd, sttp)
bfd *abfd; bfd *abfd;
struct bfd_strtab_hash **sttp;
{ {
if (!elf_map_symbols (abfd)) if (!elf_map_symbols (abfd))
return false; return false;
@ -2270,14 +2251,16 @@ swap_out_syms (abfd)
{ {
int symcount = bfd_get_symcount (abfd); int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (abfd); asymbol **syms = bfd_get_outsymbols (abfd);
struct strtab *stt = bfd_new_strtab (abfd); struct bfd_strtab_hash *stt;
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Shdr *symstrtab_hdr; Elf_Internal_Shdr *symstrtab_hdr;
Elf_External_Sym *outbound_syms; Elf_External_Sym *outbound_syms;
int idx; int idx;
if (!stt) stt = elf_stringtab_init ();
if (stt == NULL)
return false; return false;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr; symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
symtab_hdr->sh_type = SHT_SYMTAB; symtab_hdr->sh_type = SHT_SYMTAB;
symtab_hdr->sh_entsize = sizeof (Elf_External_Sym); symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
@ -2318,7 +2301,9 @@ swap_out_syms (abfd)
sym.st_name = 0; sym.st_name = 0;
else else
{ {
sym.st_name = bfd_add_to_strtab (abfd, stt, syms[idx]->name); sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
syms[idx]->name,
true, false);
if (sym.st_name == (unsigned long) -1) if (sym.st_name == (unsigned long) -1)
return false; return false;
} }
@ -2406,8 +2391,9 @@ swap_out_syms (abfd)
} }
symtab_hdr->contents = (PTR) outbound_syms; symtab_hdr->contents = (PTR) outbound_syms;
symstrtab_hdr->contents = (PTR) stt->tab;
symstrtab_hdr->sh_size = stt->length; *sttp = stt;
symstrtab_hdr->sh_size = _bfd_stringtab_size (stt);
symstrtab_hdr->sh_type = SHT_STRTAB; symstrtab_hdr->sh_type = SHT_STRTAB;
symstrtab_hdr->sh_flags = 0; symstrtab_hdr->sh_flags = 0;
@ -2430,11 +2416,9 @@ write_shdrs_and_ehdr (abfd)
Elf_External_Shdr *x_shdrp; /* Section header table, external form */ Elf_External_Shdr *x_shdrp; /* Section header table, external form */
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
unsigned int count; unsigned int count;
struct strtab *shstrtab;
i_ehdrp = elf_elfheader (abfd); i_ehdrp = elf_elfheader (abfd);
i_shdrp = elf_elfsections (abfd); i_shdrp = elf_elfsections (abfd);
shstrtab = elf_shstrtab (abfd);
/* swap the header before spitting it out... */ /* swap the header before spitting it out... */
@ -2459,8 +2443,7 @@ write_shdrs_and_ehdr (abfd)
for (count = 0; count < i_ehdrp->e_shnum; count++) for (count = 0; count < i_ehdrp->e_shnum; count++)
{ {
#if DEBUG & 2 #if DEBUG & 2
elf_debug_section (shstrtab->tab + i_shdrp[count]->sh_name, count, elf_debug_section (count, i_shdrp[count]);
i_shdrp[count]);
#endif #endif
elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count); elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count);
} }
@ -2537,6 +2520,11 @@ NAME(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)))
return false;
if (bed->elf_backend_final_write_processing) if (bed->elf_backend_final_write_processing)
(*bed->elf_backend_final_write_processing) (abfd, (*bed->elf_backend_final_write_processing) (abfd,
elf_tdata (abfd)->linker); elf_tdata (abfd)->linker);
@ -3001,12 +2989,13 @@ elf_slurp_reloc_table (abfd, asect, symbols)
#ifdef DEBUG #ifdef DEBUG
static void static void
elf_debug_section (str, num, hdr) elf_debug_section (num, hdr)
char *str;
int num; int num;
Elf_Internal_Shdr *hdr; Elf_Internal_Shdr *hdr;
{ {
fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num, str, (long) hdr); fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num,
hdr->bfd_section != NULL ? hfd->bfd_section->name : "",
(long) hdr);
fprintf (stderr, fprintf (stderr,
"sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n", "sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
(long) hdr->sh_name, (long) hdr->sh_name,
@ -3895,9 +3884,10 @@ elf_link_record_dynamic_symbol (info, h)
{ {
h->dynindx = elf_hash_table (info)->dynsymcount; h->dynindx = elf_hash_table (info)->dynsymcount;
++elf_hash_table (info)->dynsymcount; ++elf_hash_table (info)->dynsymcount;
h->dynstr_index = bfd_add_to_strtab (elf_hash_table (info)->dynobj, h->dynstr_index =
elf_hash_table (info)->dynstr, (unsigned long) _bfd_stringtab_add (elf_hash_table (info)->dynstr,
h->root.root.string); h->root.root.string,
true, false);
if (h->dynstr_index == (unsigned long) -1) if (h->dynstr_index == (unsigned long) -1)
return false; return false;
} }
@ -4002,7 +3992,7 @@ elf_link_add_object_symbols (abfd, info)
{ {
asection *s; asection *s;
const char *name; const char *name;
unsigned long strindex; bfd_size_type strindex;
dynamic = true; dynamic = true;
@ -4091,10 +4081,9 @@ elf_link_add_object_symbols (abfd, info)
} }
/* Add a DT_NEEDED entry for this dynamic object. */ /* Add a DT_NEEDED entry for this dynamic object. */
strindex = bfd_add_to_strtab (abfd, strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
elf_hash_table (info)->dynstr, true, false);
name); if (strindex == (bfd_size_type) -1)
if (strindex == (unsigned long) -1)
goto error_return; goto error_return;
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex)) if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
goto error_return; goto error_return;
@ -4525,7 +4514,7 @@ elf_link_create_dynamic_sections (abfd, info)
return false; return false;
/* Create a strtab to hold the dynamic symbol names. */ /* Create a strtab to hold the dynamic symbol names. */
elf_hash_table (info)->dynstr = bfd_new_strtab (abfd); elf_hash_table (info)->dynstr = elf_stringtab_init ();
if (elf_hash_table (info)->dynstr == NULL) if (elf_hash_table (info)->dynstr == NULL)
return false; return false;
@ -4864,28 +4853,29 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
if (soname != NULL) if (soname != NULL)
{ {
unsigned long indx; bfd_size_type indx;
indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, soname); indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
if (indx == (unsigned long) -1 true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_SONAME, indx)) || ! elf_add_dynamic_entry (info, DT_SONAME, indx))
return false; return false;
} }
if (rpath != NULL) if (rpath != NULL)
{ {
unsigned long indx; bfd_size_type indx;
indx = bfd_add_to_strtab (dynobj, elf_hash_table (info)->dynstr, rpath); indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
if (indx == (unsigned long) -1 true, true);
if (indx == (bfd_size_type) -1
|| ! elf_add_dynamic_entry (info, DT_RPATH, indx)) || ! elf_add_dynamic_entry (info, DT_RPATH, indx))
return false; return false;
} }
s = bfd_get_section_by_name (dynobj, ".dynstr"); s = bfd_get_section_by_name (dynobj, ".dynstr");
BFD_ASSERT (s != NULL); BFD_ASSERT (s != NULL);
s->_raw_size = elf_hash_table (info)->dynstr->length; s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
s->contents = (unsigned char *) elf_hash_table (info)->dynstr->tab;
/* Find all symbols which were defined in a dynamic object and make /* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */ the backend pick a reasonable value for them. */
@ -4910,7 +4900,8 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath, info,
|| ! elf_add_dynamic_entry (info, DT_STRTAB, 0) || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_SYMTAB, 0) || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
|| ! elf_add_dynamic_entry (info, DT_STRSZ, || ! elf_add_dynamic_entry (info, DT_STRSZ,
elf_hash_table (info)->dynstr->length) _bfd_stringtab_size (elf_hash_table (info)
->dynstr))
|| ! elf_add_dynamic_entry (info, DT_SYMENT, || ! elf_add_dynamic_entry (info, DT_SYMENT,
sizeof (Elf_External_Sym))) sizeof (Elf_External_Sym)))
return false; return false;
@ -5032,7 +5023,7 @@ struct elf_final_link_info
/* Output BFD. */ /* Output BFD. */
bfd *output_bfd; bfd *output_bfd;
/* Symbol string table. */ /* Symbol string table. */
struct strtab *symstrtab; struct bfd_strtab_hash *symstrtab;
/* .dynsym section. */ /* .dynsym section. */
asection *dynsym_sec; asection *dynsym_sec;
/* .hash section. */ /* .hash section. */
@ -5106,7 +5097,7 @@ elf_bfd_final_link (abfd, info)
finfo.info = info; finfo.info = info;
finfo.output_bfd = abfd; finfo.output_bfd = abfd;
finfo.symstrtab = bfd_new_strtab (abfd); finfo.symstrtab = elf_stringtab_init ();
if (finfo.symstrtab == NULL) if (finfo.symstrtab == NULL)
return false; return false;
if (dynobj == NULL) if (dynobj == NULL)
@ -5443,23 +5434,27 @@ elf_bfd_final_link (abfd, info)
/* Now we know the size of the symtab section. */ /* Now we know the size of the symtab section. */
off += symtab_hdr->sh_size; off += symtab_hdr->sh_size;
/* Finish up the symbol string table (.strtab) section. */ /* Finish up and write out the symbol string table (.strtab)
section. */
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr; symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
/* sh_name was set in prep_headers. */ /* sh_name was set in prep_headers. */
symstrtab_hdr->sh_type = SHT_STRTAB; symstrtab_hdr->sh_type = SHT_STRTAB;
symstrtab_hdr->sh_flags = 0; symstrtab_hdr->sh_flags = 0;
symstrtab_hdr->sh_addr = 0; symstrtab_hdr->sh_addr = 0;
symstrtab_hdr->sh_size = finfo.symstrtab->length; symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab);
symstrtab_hdr->sh_entsize = 0; symstrtab_hdr->sh_entsize = 0;
symstrtab_hdr->sh_link = 0; symstrtab_hdr->sh_link = 0;
symstrtab_hdr->sh_info = 0; symstrtab_hdr->sh_info = 0;
/* sh_offset is set just below. */ /* sh_offset is set just below. */
symstrtab_hdr->sh_addralign = 1; symstrtab_hdr->sh_addralign = 1;
symstrtab_hdr->contents = (PTR) finfo.symstrtab->tab;
off = assign_file_position_for_section (symstrtab_hdr, off, true); off = assign_file_position_for_section (symstrtab_hdr, off, true);
elf_tdata (abfd)->next_file_pos = off; elf_tdata (abfd)->next_file_pos = off;
if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
|| ! _bfd_stringtab_emit (abfd, finfo.symstrtab))
return false;
/* Adjust the relocs to have the correct symbol indices. */ /* Adjust the relocs to have the correct symbol indices. */
for (o = abfd->sections; o != NULL; o = o->next) for (o = abfd->sections; o != NULL; o = o->next)
{ {
@ -5602,13 +5597,32 @@ elf_bfd_final_link (abfd, info)
This test is fragile. */ This test is fragile. */
continue; continue;
} }
if ((elf_section_data (o->output_section)->this_hdr.sh_type
!= SHT_STRTAB)
|| strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
{
if (! bfd_set_section_contents (abfd, o->output_section, if (! bfd_set_section_contents (abfd, o->output_section,
o->contents, o->output_offset, o->contents, o->output_offset,
o->_raw_size)) o->_raw_size))
goto error_return; goto error_return;
} }
else
{
file_ptr off;
/* The contents of the .dynstr section are actually in a
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))
goto error_return;
}
}
} }
if (finfo.symstrtab != NULL)
_bfd_stringtab_free (finfo.symstrtab);
if (finfo.contents != NULL) if (finfo.contents != NULL)
free (finfo.contents); free (finfo.contents);
if (finfo.external_relocs != NULL) if (finfo.external_relocs != NULL)
@ -5637,6 +5651,8 @@ elf_bfd_final_link (abfd, info)
return true; return true;
error_return: error_return:
if (finfo.symstrtab != NULL)
_bfd_stringtab_free (finfo.symstrtab);
if (finfo.contents != NULL) if (finfo.contents != NULL)
free (finfo.contents); free (finfo.contents);
if (finfo.external_relocs != NULL) if (finfo.external_relocs != NULL)
@ -5691,8 +5707,9 @@ elf_link_output_sym (finfo, name, elfsym, input_sec)
elfsym->st_name = 0; elfsym->st_name = 0;
else else
{ {
elfsym->st_name = bfd_add_to_strtab (finfo->output_bfd, elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
finfo->symstrtab, name); name, true,
false);
if (elfsym->st_name == (unsigned long) -1) if (elfsym->st_name == (unsigned long) -1)
return false; return false;
} }
@ -5802,11 +5819,11 @@ elf_link_output_extsym (h, data)
case bfd_link_hash_defined: case bfd_link_hash_defined:
{ {
input_sec = h->root.u.def.section; input_sec = h->root.u.def.section;
if (input_sec->output_section != NULL) if (input_sec->output_section != NULL)
{ {
sym.st_shndx = elf_section_from_bfd_section (finfo->output_bfd, sym.st_shndx =
elf_section_from_bfd_section (finfo->output_bfd,
input_sec->output_section); input_sec->output_section);
if (sym.st_shndx == (unsigned short) -1) if (sym.st_shndx == (unsigned short) -1)
{ {
@ -5912,8 +5929,7 @@ elf_link_input_bfd (finfo, input_bfd)
boolean (*relocate_section) PARAMS ((bfd *, struct bfd_link_info *, boolean (*relocate_section) PARAMS ((bfd *, struct bfd_link_info *,
bfd *, asection *, bfd_byte *, bfd *, asection *, bfd_byte *,
Elf_Internal_Rela *, Elf_Internal_Rela *,
Elf_Internal_Sym *, Elf_Internal_Sym *, asection **));
asection **, char *));
bfd *output_bfd; bfd *output_bfd;
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
size_t locsymcount; size_t locsymcount;
@ -5966,7 +5982,7 @@ elf_link_input_bfd (finfo, input_bfd)
{ {
asection *isec; asection *isec;
const char *name; const char *name;
bfd_vma oldval; Elf_Internal_Sym osym;
elf_swap_symbol_in (input_bfd, esym, isym); elf_swap_symbol_in (input_bfd, esym, isym);
*pindex = -1; *pindex = -1;
@ -6035,10 +6051,12 @@ elf_link_input_bfd (finfo, input_bfd)
/* If we get here, we are going to output this symbol. */ /* If we get here, we are going to output this symbol. */
osym = *isym;
/* Adjust the section index for the output file. */ /* Adjust the section index for the output file. */
isym->st_shndx = elf_section_from_bfd_section (output_bfd, osym.st_shndx = elf_section_from_bfd_section (output_bfd,
isec->output_section); isec->output_section);
if (isym->st_shndx == (unsigned short) -1) if (osym.st_shndx == (unsigned short) -1)
return false; return false;
*pindex = output_bfd->symcount; *pindex = output_bfd->symcount;
@ -6050,16 +6068,12 @@ elf_link_input_bfd (finfo, input_bfd)
we assume that they also have a reasonable value for we assume that they also have a reasonable value for
output_section. Any special sections must be set up to meet output_section. Any special sections must be set up to meet
these requirements. */ these requirements. */
oldval = isym->st_value; osym.st_value += isec->output_offset;
isym->st_value += isec->output_offset;
if (! finfo->info->relocateable) if (! finfo->info->relocateable)
isym->st_value += isec->output_section->vma; osym.st_value += isec->output_section->vma;
if (! elf_link_output_sym (finfo, name, isym, isec)) if (! elf_link_output_sym (finfo, name, &osym, isec))
return false; return false;
/* Restore the old value for reloc handling. */
isym->st_value = oldval;
} }
/* Relocate the contents of each section. */ /* Relocate the contents of each section. */
@ -6119,8 +6133,7 @@ elf_link_input_bfd (finfo, input_bfd)
finfo->contents, finfo->contents,
internal_relocs, internal_relocs,
finfo->internal_syms, finfo->internal_syms,
finfo->sections, finfo->sections))
finfo->symstrtab->tab))
return false; return false;
if (finfo->info->relocateable) if (finfo->info->relocateable)

View file

@ -137,7 +137,7 @@ struct elf_link_hash_table
size_t dynsymcount; size_t dynsymcount;
/* The string table of dynamic symbols, which becomes the .dynstr /* The string table of dynamic symbols, which becomes the .dynstr
section. */ section. */
struct strtab *dynstr; struct bfd_strtab_hash *dynstr;
/* The number of buckets in the hash table in the .hash section. /* The number of buckets in the hash table in the .hash section.
This is based on the number of dynamic symbols. */ This is based on the number of dynamic symbols. */
size_t bucketcount; size_t bucketcount;
@ -357,7 +357,7 @@ struct elf_backend_data
PARAMS ((bfd *output_bfd, struct bfd_link_info *info, PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
bfd *input_bfd, asection *input_section, bfd_byte *contents, bfd *input_bfd, asection *input_section, bfd_byte *contents,
Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms, Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
asection **local_sections, char *output_names)); asection **local_sections));
/* The FINISH_DYNAMIC_SYMBOL function is called by the ELF backend /* The FINISH_DYNAMIC_SYMBOL function is called by the ELF backend
linker just before it writes a symbol out to the .dynsym section. linker just before it writes a symbol out to the .dynsym section.
@ -429,13 +429,6 @@ struct bfd_elf_section_data {
#define get_elf_backend_data(abfd) \ #define get_elf_backend_data(abfd) \
((struct elf_backend_data *) (abfd)->xvec->backend_data) ((struct elf_backend_data *) (abfd)->xvec->backend_data)
struct strtab
{
char *tab;
int nentries;
int length;
};
/* Some private data is stashed away for future use using the tdata pointer /* Some private data is stashed away for future use using the tdata pointer
in the bfd structure. */ in the bfd structure. */
@ -444,7 +437,7 @@ struct elf_obj_tdata
Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */ Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */
Elf_Internal_Shdr **elf_sect_ptr; Elf_Internal_Shdr **elf_sect_ptr;
Elf_Internal_Phdr *phdr; Elf_Internal_Phdr *phdr;
struct strtab *strtab_ptr; struct bfd_strtab_hash *strtab_ptr;
int num_locals; int num_locals;
int num_globals; int num_globals;
Elf_Sym_Extra *sym_extra; Elf_Sym_Extra *sym_extra;