/* ELF executable support for BFD.
- Copyright (C) 1993-2015 Free Software Foundation, Inc.
+ Copyright (C) 1993-2016 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "elf-bfd.h"
#include "libiberty.h"
#include "safe-ctype.h"
-#include "elf-linux-psinfo.h"
+#include "elf-linux-core.h"
#ifdef CORE_HEADER
#include CORE_HEADER
/* 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;
for (i = 0; i < num_group; i++)
{
Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
- Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
- unsigned int n_elt = shdr->sh_size / 4;
+ Elf_Internal_Group *idx;
+ unsigned int n_elt;
+
+ /* PR binutils/18758: Beware of corrupt binaries with invalid group data. */
+ if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%B: section group entry number %u is corrupt"),
+ abfd, i);
+ result = FALSE;
+ continue;
+ }
+
+ idx = (Elf_Internal_Group *) shdr->contents;
+ n_elt = shdr->sh_size / 4;
while (--n_elt != 0)
if ((++idx)->shdr->bfd_section)
for (j = 0; j < elf_numsections (ibfd); j++)
{
Elf_Internal_Shdr * iheader = iheaders[j];
-
- if (iheader->sh_type != SHT_NOBITS
+
+ /* Since --only-keep-debug turns all non-debug sections
+ into SHT_NOBITS sections, the output SHT_NOBITS type
+ matches any input type. */
+ if ((oheader->sh_type == SHT_NOBITS
+ || iheader->sh_type == oheader->sh_type)
+ && iheader->sh_flags == oheader->sh_flags
+ && iheader->sh_addralign == oheader->sh_addralign
+ && iheader->sh_entsize == oheader->sh_entsize
&& iheader->sh_size == oheader->sh_size
&& iheader->sh_addr == oheader->sh_addr
&& (iheader->sh_info != oheader->sh_info
goto success;
}
- BFD_ASSERT (elf_onesymtab (abfd) == 0);
+ /* PR 18854: A binary might contain more than one symbol table.
+ Unusual, but possible. Warn, but continue. */
+ if (elf_onesymtab (abfd) != 0)
+ {
+ (*_bfd_error_handler)
+ (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
+ abfd, 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
/* 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)
goto success;
}
- BFD_ASSERT (elf_dynsymtab (abfd) == 0);
+ /* PR 18854: A binary might contain more than one dynamic symbol table.
+ Unusual, but possible. Warn, but continue. */
+ if (elf_dynsymtab (abfd) != 0)
+ {
+ (*_bfd_error_handler)
+ (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
+ abfd, shindex);
+ goto success;
+ }
elf_dynsymtab (abfd) = shindex;
elf_tdata (abfd)->dynsymtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr;
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)
if (arg->link_info
/* Do the normal setup if we wouldn't create any sections here. */
&& esd->rel.count + esd->rela.count > 0
- && (arg->link_info->relocatable || arg->link_info->emitrelocations))
+ && (bfd_link_relocatable (arg->link_info)
+ || arg->link_info->emitrelocations))
{
if (esd->rel.count && esd->rel.hdr == NULL
&& !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE,
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
/* SHT_GROUP sections are in relocatable files only. */
- if (link_info == NULL || link_info->relocatable)
+ if (link_info == NULL || bfd_link_relocatable (link_info))
{
/* Put SHT_GROUP sections first. */
for (sec = abfd->sections; sec != NULL; sec = sec->next)
_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++;
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);
unsigned int num_globals = 0;
unsigned int num_locals2 = 0;
unsigned int num_globals2 = 0;
- int max_index = 0;
+ unsigned int max_index = 0;
unsigned int idx;
asection *asect;
asymbol **new_syms;
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);
goto error_return;
m->next = NULL;
m->p_type = PT_GNU_RELRO;
- m->p_flags = PF_R;
- m->p_flags_valid = 1;
-
*pm = m;
pm = &m->next;
}
&& (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;
if (!m->p_align_valid)
p->p_align = 1;
if (!m->p_flags_valid)
- p->p_flags = (lp->p_flags & ~PF_W);
+ p->p_flags = PF_R;
}
else
{
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.
&& (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))
{
}
/* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */
- if (link_info != NULL
- && link_info->executable
- && link_info->shared)
+ if (link_info != NULL && bfd_link_pie (link_info))
{
unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
first_matching_lma = TRUE;
first_suggested_lma = TRUE;
- for (section = ibfd->sections;
+ for (section = first_section, j = 0;
section != NULL;
section = section->next)
- if (section == first_section)
- break;
-
- for (j = 0; section != NULL; section = section->next)
{
if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
{
{
Elf_Internal_Shdr *ihdr, *ohdr;
- bfd_boolean final_link = link_info != NULL && !link_info->relocatable;
+ bfd_boolean final_link = (link_info != NULL
+ && !bfd_link_relocatable (link_info));
if (ibfd->xvec->flavour != bfd_target_elf_flavour
|| obfd->xvec->flavour != bfd_target_elf_flavour)
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;
}
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"). */
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;
goto error_return_bad_verdef;
iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
- memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
+ memcpy (iverdef, &iverdefmem, offsetof (Elf_Internal_Verdef, vd_bfd));
iverdef->vd_bfd = abfd;
((bfd_byte *) everdaux + iverdaux->vda_next));
}
+ iverdef->vd_nodename = NULL;
if (iverdef->vd_cnt)
iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
int ret = bed->s->sizeof_ehdr;
- if (!info->relocatable)
+ if (!bfd_link_relocatable (info))
{
bfd_size_type phdr_size = elf_program_header_size (abfd);
case NT_SIGINFO:
return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
note);
+
+ case NT_FREEBSD_THRMISC:
+ if (note->namesz == 8
+ && strcmp (note->namedata, "FreeBSD") == 0)
+ return elfcore_make_note_pseudosection (abfd, ".thrmisc", note);
+ else
+ return TRUE;
}
}
{
struct elf_external_linux_prpsinfo32 data;
- memset (&data, 0, sizeof (data));
- LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
-
+ swap_linux_prpsinfo32_out (abfd, prpsinfo, &data);
return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
&data, sizeof (data));
}
{
struct elf_external_linux_prpsinfo64 data;
- memset (&data, 0, sizeof (data));
- LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data);
-
+ swap_linux_prpsinfo64_out (abfd, prpsinfo, &data);
return elfcore_write_note (abfd, buf, bufsiz,
"CORE", NT_PRPSINFO, &data, sizeof (data));
}