aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c173
1 files changed, 120 insertions, 53 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 35c0f6c..6c878bd 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -400,8 +400,28 @@ bfd_elf_get_elf_syms (bfd *ibfd,
/* Normal syms might have section extension entries. */
shndx_hdr = NULL;
- if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
- shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+ if (elf_symtab_shndx_list (ibfd) != NULL)
+ {
+ elf_section_list * entry;
+ Elf_Internal_Shdr **sections = elf_elfsections (ibfd);
+
+ /* Find an index section that is linked to this symtab section. */
+ for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next)
+ if (sections[entry->hdr.sh_link] == symtab_hdr)
+ {
+ shndx_hdr = & entry->hdr;
+ break;
+ };
+
+ if (shndx_hdr == NULL)
+ {
+ if (symtab_hdr == & elf_symtab_hdr (ibfd))
+ /* Not really accurate, but this was how the old code used to work. */
+ shndx_hdr = & elf_symtab_shndx_list (ibfd)->hdr;
+ /* Otherwise we do nothing. The assumption is that
+ the index table will not be needed. */
+ }
+ }
/* Read the symbols. */
alloc_ext = NULL;
@@ -1843,8 +1863,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
goto success;
}
elf_onesymtab (abfd) = shindex;
- elf_tdata (abfd)->symtab_hdr = *hdr;
- elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
+ elf_symtab_hdr (abfd) = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr = & elf_symtab_hdr (abfd);
abfd->flags |= HAS_SYMS;
/* Sometimes a shared object will map in the symbol table. If
@@ -1862,30 +1882,39 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
/* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
can't read symbols without that section loaded as well. It
is most likely specified by the next section header. */
- if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex)
- {
- unsigned int i, num_sec;
+ {
+ elf_section_list * entry;
+ unsigned int i, num_sec;
- num_sec = elf_numsections (abfd);
- for (i = shindex + 1; i < num_sec; i++)
+ for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+ if (entry->hdr.sh_link == shindex)
+ goto success;
+
+ num_sec = elf_numsections (abfd);
+ for (i = shindex + 1; i < num_sec; i++)
+ {
+ Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
+ if (hdr2->sh_type == SHT_SYMTAB_SHNDX
+ && hdr2->sh_link == shindex)
+ break;
+ }
+
+ if (i == num_sec)
+ for (i = 1; i < shindex; i++)
{
Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
if (hdr2->sh_type == SHT_SYMTAB_SHNDX
&& hdr2->sh_link == shindex)
break;
}
- if (i == num_sec)
- for (i = 1; i < shindex; i++)
- {
- Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
- if (hdr2->sh_type == SHT_SYMTAB_SHNDX
- && hdr2->sh_link == shindex)
- break;
- }
- if (i != shindex)
- ret = bfd_section_from_shdr (abfd, i);
- }
- goto success;
+
+ if (i != shindex)
+ ret = bfd_section_from_shdr (abfd, i);
+ /* else FIXME: we have failed to find the symbol table - should we issue an error ? */
+ goto success;
+ }
case SHT_DYNSYM: /* A dynamic symbol table. */
if (elf_dynsymtab (abfd) == shindex)
@@ -1926,14 +1955,23 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
goto success;
case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */
- if (elf_symtab_shndx (abfd) == shindex)
- goto success;
+ {
+ elf_section_list * entry;
- BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
- elf_symtab_shndx (abfd) = shindex;
- elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
- elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
- goto success;
+ for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+ if (entry->ndx == shindex)
+ goto success;
+
+ entry = bfd_alloc (abfd, sizeof * entry);
+ if (entry == NULL)
+ goto fail;
+ entry->ndx = shindex;
+ entry->hdr = * hdr;
+ entry->next = elf_symtab_shndx_list (abfd);
+ elf_symtab_shndx_list (abfd) = entry;
+ elf_elfsections (abfd)[shindex] = & entry->hdr;
+ goto success;
+ }
case SHT_STRTAB: /* A string table. */
if (hdr->bfd_section != NULL)
@@ -3377,11 +3415,17 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
_bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
{
- elf_symtab_shndx (abfd) = section_number++;
- t->symtab_shndx_hdr.sh_name
+ elf_section_list * entry;
+
+ BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
+
+ entry = bfd_zalloc (abfd, sizeof * entry);
+ entry->ndx = section_number++;
+ elf_symtab_shndx_list (abfd) = entry;
+ entry->hdr.sh_name
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
".symtab_shndx", FALSE);
- if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
+ if (entry->hdr.sh_name == (unsigned int) -1)
return FALSE;
}
elf_strtab_sec (abfd) = section_number++;
@@ -3421,8 +3465,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr;
if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
{
- i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr;
- t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd);
+ elf_section_list * entry = elf_symtab_shndx_list (abfd);
+ BFD_ASSERT (entry != NULL);
+ i_shdrp[entry->ndx] = & entry->hdr;
+ entry->hdr.sh_link = elf_onesymtab (abfd);
}
i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr;
t->symtab_hdr.sh_link = elf_strtab_sec (abfd);
@@ -3883,12 +3929,16 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
off = elf_next_file_pos (abfd);
- hdr = &elf_tdata (abfd)->symtab_hdr;
+ hdr = & elf_symtab_hdr (abfd);
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
- hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (hdr->sh_size != 0)
- off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+ if (elf_symtab_shndx_list (abfd) != NULL)
+ {
+ hdr = & elf_symtab_shndx_list (abfd)->hdr;
+ if (hdr->sh_size != 0)
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+ /* FIXME: What about other symtab_shndx sections in the list ? */
+ }
hdr = &elf_tdata (abfd)->strtab_hdr;
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -5286,7 +5336,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
&& (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
/* Compress DWARF debug sections. */
|| hdr == i_shdrpp[elf_onesymtab (abfd)]
- || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
+ || (elf_symtab_shndx_list (abfd) != NULL
+ && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
|| hdr == i_shdrpp[elf_strtab_sec (abfd)]
|| hdr == i_shdrpp[elf_shstrtab_sec (abfd)])
hdr->sh_offset = -1;
@@ -5492,6 +5543,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
return TRUE;
}
+static elf_section_list *
+find_section_in_list (unsigned int i, elf_section_list * list)
+{
+ for (;list != NULL; list = list->next)
+ if (list->ndx == i)
+ break;
+ return list;
+}
+
/* Work out the file positions of all the sections. This is called by
_bfd_elf_compute_section_file_positions. All the section sizes and
VMAs must be known before this is called.
@@ -5540,7 +5600,8 @@ assign_file_positions_except_relocs (bfd *abfd,
&& (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
/* Compress DWARF debug sections. */
|| i == elf_onesymtab (abfd)
- || i == elf_symtab_shndx (abfd)
+ || (elf_symtab_shndx_list (abfd) != NULL
+ && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
|| i == elf_strtab_sec (abfd)
|| i == elf_shstrtab_sec (abfd))
{
@@ -7130,7 +7191,7 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
shndx = MAP_STRTAB;
else if (shndx == elf_shstrtab_sec (ibfd))
shndx = MAP_SHSTRTAB;
- else if (shndx == elf_symtab_shndx (ibfd))
+ else if (find_section_in_list (shndx, elf_symtab_shndx_list (ibfd)))
shndx = MAP_SYM_SHNDX;
osym->internal_elf_sym.st_shndx = shndx;
}
@@ -7205,20 +7266,25 @@ error_return:
outbound_shndx = NULL;
outbound_shndx_index = 0;
- symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (symtab_shndx_hdr->sh_name != 0)
+
+ if (elf_symtab_shndx_list (abfd))
{
- amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
- outbound_shndx = (bfd_byte *)
- bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
- if (outbound_shndx == NULL)
- goto error_return;
+ symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+ if (symtab_shndx_hdr->sh_name != 0)
+ {
+ amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
+ outbound_shndx = (bfd_byte *)
+ bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
+ if (outbound_shndx == NULL)
+ goto error_return;
- symtab_shndx_hdr->contents = outbound_shndx;
- symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
- symtab_shndx_hdr->sh_size = amt;
- symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
- symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->contents = outbound_shndx;
+ symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+ symtab_shndx_hdr->sh_size = amt;
+ symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+ symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+ }
+ /* FIXME: What about any other headers in the list ? */
}
/* Now generate the data (for "contents"). */
@@ -7327,7 +7393,8 @@ error_return:
shndx = elf_shstrtab_sec (abfd);
break;
case MAP_SYM_SHNDX:
- shndx = elf_symtab_shndx (abfd);
+ if (elf_symtab_shndx_list (abfd))
+ shndx = elf_symtab_shndx_list (abfd)->ndx;
break;
default:
shndx = SHN_ABS;