SHT_SYMTAB_SHNDX handling

.symtab_shndx section contents is an array, one entry for each symbol
in .symtab, present when the number of symbols exceeds a little less
than 64k.  Since the mapping is 1-1 with symbols there is no need to
keep both dest_index and destshndx_index in elf_sym_strtab.  Instead,
just make sure that the shndx pointers to the swap functions are kept
NULL when .symtab_shndx does not exist.  Also, strtabcount in the
linker's elf hash table is incremented in lock-step with the output
symcount, so that can disappear too.
This commit is contained in:
Alan Modra
2021-09-02 09:56:11 +09:30
parent 36f61bf2ad
commit b03b65e2aa
3 changed files with 13 additions and 30 deletions

@ -538,7 +538,6 @@ struct elf_sym_strtab
{ {
Elf_Internal_Sym sym; Elf_Internal_Sym sym;
unsigned long dest_index; unsigned long dest_index;
unsigned long destshndx_index;
}; };
struct bfd_link_needed_list struct bfd_link_needed_list
@ -622,10 +621,6 @@ struct elf_link_hash_table
section. */ section. */
struct elf_strtab_hash *dynstr; struct elf_strtab_hash *dynstr;
/* The number of symbol strings found in the link which must be put
into the .strtab section. */
bfd_size_type strtabcount;
/* The array size of the symbol string table, which becomes the /* The array size of the symbol string table, which becomes the
.strtab section. */ .strtab section. */
bfd_size_type strtabsize; bfd_size_type strtabsize;

@ -8095,7 +8095,6 @@ swap_out_syms (bfd *abfd,
bfd_byte *outbound_syms; bfd_byte *outbound_syms;
bfd_byte *outbound_shndx; bfd_byte *outbound_shndx;
unsigned long outbound_syms_index; unsigned long outbound_syms_index;
unsigned long outbound_shndx_index;
unsigned int idx; unsigned int idx;
unsigned int num_locals; unsigned int num_locals;
size_t amt; size_t amt;
@ -8144,7 +8143,6 @@ swap_out_syms (bfd *abfd,
outbound_syms_index = 0; outbound_syms_index = 0;
outbound_shndx = NULL; outbound_shndx = NULL;
outbound_shndx_index = 0;
if (elf_symtab_shndx_list (abfd)) if (elf_symtab_shndx_list (abfd))
{ {
@ -8180,10 +8178,7 @@ swap_out_syms (bfd *abfd,
sym.st_target_internal = 0; sym.st_target_internal = 0;
symstrtab[0].sym = sym; symstrtab[0].sym = sym;
symstrtab[0].dest_index = outbound_syms_index; symstrtab[0].dest_index = outbound_syms_index;
symstrtab[0].destshndx_index = outbound_shndx_index;
outbound_syms_index++; outbound_syms_index++;
if (outbound_shndx != NULL)
outbound_shndx_index++;
} }
name_local_sections name_local_sections
@ -8415,11 +8410,8 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."),
idx++; idx++;
symstrtab[idx].sym = sym; symstrtab[idx].sym = sym;
symstrtab[idx].dest_index = outbound_syms_index; symstrtab[idx].dest_index = outbound_syms_index;
symstrtab[idx].destshndx_index = outbound_shndx_index;
outbound_syms_index++; outbound_syms_index++;
if (outbound_shndx != NULL)
outbound_shndx_index++;
} }
/* Finalize the .strtab section. */ /* Finalize the .strtab section. */
@ -8444,8 +8436,8 @@ Unable to handle section index %x in ELF symbol. Using ABS instead."),
(outbound_syms (outbound_syms
+ (elfsym->dest_index + (elfsym->dest_index
* bed->s->sizeof_sym)), * bed->s->sizeof_sym)),
(outbound_shndx NPTR_ADD (outbound_shndx,
+ (elfsym->destshndx_index (elfsym->dest_index
* sizeof (Elf_External_Sym_Shndx)))); * sizeof (Elf_External_Sym_Shndx))));
} }
free (symstrtab); free (symstrtab);

@ -9916,7 +9916,7 @@ elf_link_output_symstrtab (void *finf,
hash_table = elf_hash_table (flinfo->info); hash_table = elf_hash_table (flinfo->info);
strtabsize = hash_table->strtabsize; strtabsize = hash_table->strtabsize;
if (strtabsize <= hash_table->strtabcount) if (strtabsize <= flinfo->output_bfd->symcount)
{ {
strtabsize += strtabsize; strtabsize += strtabsize;
hash_table->strtabsize = strtabsize; hash_table->strtabsize = strtabsize;
@ -9927,14 +9927,10 @@ elf_link_output_symstrtab (void *finf,
if (hash_table->strtab == NULL) if (hash_table->strtab == NULL)
return 0; return 0;
} }
hash_table->strtab[hash_table->strtabcount].sym = *elfsym; hash_table->strtab[flinfo->output_bfd->symcount].sym = *elfsym;
hash_table->strtab[hash_table->strtabcount].dest_index hash_table->strtab[flinfo->output_bfd->symcount].dest_index
= hash_table->strtabcount; = flinfo->output_bfd->symcount;
hash_table->strtab[hash_table->strtabcount].destshndx_index
= flinfo->symshndxbuf ? bfd_get_symcount (flinfo->output_bfd) : 0;
flinfo->output_bfd->symcount += 1; flinfo->output_bfd->symcount += 1;
hash_table->strtabcount += 1;
return 1; return 1;
} }
@ -9954,14 +9950,14 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
file_ptr pos; file_ptr pos;
bool ret; bool ret;
if (!hash_table->strtabcount) if (flinfo->output_bfd->symcount == 0)
return true; return true;
BFD_ASSERT (elf_onesymtab (flinfo->output_bfd)); BFD_ASSERT (elf_onesymtab (flinfo->output_bfd));
bed = get_elf_backend_data (flinfo->output_bfd); bed = get_elf_backend_data (flinfo->output_bfd);
amt = bed->s->sizeof_sym * hash_table->strtabcount; amt = bed->s->sizeof_sym * flinfo->output_bfd->symcount;
symbuf = (bfd_byte *) bfd_malloc (amt); symbuf = (bfd_byte *) bfd_malloc (amt);
if (symbuf == NULL) if (symbuf == NULL)
return false; return false;
@ -9979,7 +9975,7 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
} }
/* Now swap out the symbols. */ /* Now swap out the symbols. */
for (i = 0; i < hash_table->strtabcount; i++) for (i = 0; i < flinfo->output_bfd->symcount; i++)
{ {
struct elf_sym_strtab *elfsym = &hash_table->strtab[i]; struct elf_sym_strtab *elfsym = &hash_table->strtab[i];
if (elfsym->sym.st_name == (unsigned long) -1) if (elfsym->sym.st_name == (unsigned long) -1)
@ -9999,13 +9995,13 @@ elf_link_swap_symbols_out (struct elf_final_link_info *flinfo)
((bfd_byte *) symbuf ((bfd_byte *) symbuf
+ (elfsym->dest_index + (elfsym->dest_index
* bed->s->sizeof_sym)), * bed->s->sizeof_sym)),
(flinfo->symshndxbuf NPTR_ADD (flinfo->symshndxbuf,
+ elfsym->destshndx_index)); elfsym->dest_index));
} }
hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr; hdr = &elf_tdata (flinfo->output_bfd)->symtab_hdr;
pos = hdr->sh_offset + hdr->sh_size; pos = hdr->sh_offset + hdr->sh_size;
amt = hash_table->strtabcount * bed->s->sizeof_sym; amt = bed->s->sizeof_sym * flinfo->output_bfd->symcount;
if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) == 0 if (bfd_seek (flinfo->output_bfd, pos, SEEK_SET) == 0
&& bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt) && bfd_bwrite (symbuf, amt, flinfo->output_bfd) == amt)
{ {