/* ELF executable support for BFD.
- Copyright 1993-2013 Free Software Foundation, Inc.
+ Copyright (C) 1993-2015 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Allocate and clear an extra byte at the end, to prevent crashes
in case the string table is not terminated. */
if (shstrtabsize + 1 <= 1
- || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
- || bfd_seek (abfd, offset, SEEK_SET) != 0)
+ || bfd_seek (abfd, offset, SEEK_SET) != 0
+ || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL)
shstrtab = NULL;
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_file_truncated);
+ bfd_release (abfd, shstrtab);
shstrtab = NULL;
/* Once we've failed to read it, make sure we don't keep
trying. Otherwise, we'll keep allocating space for
hdr = elf_elfsections (abfd)[shindex];
- if (hdr->contents == NULL
- && bfd_elf_get_str_section (abfd, shindex) == NULL)
- return NULL;
+ if (hdr->contents == NULL)
+ {
+ if (hdr->sh_type != SHT_STRTAB && hdr->sh_type < SHT_LOOS)
+ {
+ /* PR 17512: file: f057ec89. */
+ _bfd_error_handler (_("%B: attempt to load strings from a non-string section (number %d)"),
+ abfd, shindex);
+ return NULL;
+ }
+
+ if (bfd_elf_get_str_section (abfd, shindex) == NULL)
+ return NULL;
+ }
if (strindex >= hdr->sh_size)
{
if (shdr->contents == NULL)
{
_bfd_error_handler
- (_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ -- num_group;
+ continue;
}
memset (shdr->contents, 0, amt);
if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
|| (bfd_bread (shdr->contents, shdr->sh_size, abfd)
!= shdr->sh_size))
- return FALSE;
+ {
+ _bfd_error_handler
+ (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ bfd_set_error (bfd_error_bad_value);
+ -- num_group;
+ /* PR 17510: If the group contents are even partially
+ corrupt, do not allow any of the contents to be used. */
+ memset (shdr->contents, 0, amt);
+ continue;
+ }
/* Translate raw contents, a flag word followed by an
array of elf section indices all in target byte order,
pointers. */
src = shdr->contents + shdr->sh_size;
dest = (Elf_Internal_Group *) (shdr->contents + amt);
+
while (1)
{
unsigned int idx;
}
}
}
+
+ /* PR 17510: Corrupt binaries might contain invalid groups. */
+ if (num_group != (unsigned) elf_tdata (abfd)->num_group)
+ {
+ elf_tdata (abfd)->num_group = num_group;
+
+ /* If all groups are invalid then fail. */
+ if (num_group == 0)
+ {
+ elf_tdata (abfd)->group_sect_ptr = NULL;
+ elf_tdata (abfd)->num_group = num_group = -1;
+ (*_bfd_error_handler) (_("%B: no valid group sections found"), abfd);
+ bfd_set_error (bfd_error_bad_value);
+ }
+ }
}
}
{
(*_bfd_error_handler) (_("%B: no group info for section %A"),
abfd, newsect);
+ return FALSE;
}
return TRUE;
}
{
enum { nothing, compress, decompress } action = nothing;
char *new_name;
+ int compression_header_size;
+ bfd_boolean compressed
+ = bfd_is_section_compressed_with_header (abfd, newsect,
+ &compression_header_size);
- if (bfd_is_section_compressed (abfd, newsect))
+ if (compressed)
{
/* Compressed section. Check if we should decompress. */
if ((abfd->flags & BFD_DECOMPRESS))
action = decompress;
}
- else
+
+ /* Compress the uncompressed section or convert from/to .zdebug*
+ section. Check if we should compress. */
+ if (action == nothing)
{
- /* Normal section. Check if we should compress. */
- if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
+ if (newsect->size != 0
+ && (abfd->flags & BFD_COMPRESS)
+ && compression_header_size >= 0
+ && (!compressed
+ || ((compression_header_size > 0)
+ != ((abfd->flags & BFD_COMPRESS_GABI) != 0))))
action = compress;
+ else
+ return TRUE;
}
- new_name = NULL;
- switch (action)
+ if (action == compress)
{
- case nothing:
- break;
- case compress:
if (!bfd_init_section_compress_status (abfd, newsect))
{
(*_bfd_error_handler)
abfd, name);
return FALSE;
}
- if (name[1] != 'z')
- {
- unsigned int len = strlen (name);
-
- new_name = bfd_alloc (abfd, len + 2);
- if (new_name == NULL)
- return FALSE;
- new_name[0] = '.';
- new_name[1] = 'z';
- memcpy (new_name + 2, name + 1, len);
- }
- break;
- case decompress:
+ }
+ else
+ {
if (!bfd_init_section_decompress_status (abfd, newsect))
{
(*_bfd_error_handler)
abfd, name);
return FALSE;
}
+ }
+
+ new_name = NULL;
+ if (action == decompress
+ || (action == compress
+ && (abfd->flags & BFD_COMPRESS_GABI) != 0))
+ {
if (name[1] == 'z')
{
unsigned int len = strlen (name);
new_name[0] = '.';
memcpy (new_name + 1, name + 2, len - 1);
}
- break;
+ }
+ else if (action == compress
+ && newsect->compress_status == COMPRESS_SECTION_DONE)
+ {
+ /* PR binutils/18087: Compression does not always make a section
+ smaller. So only rename the section when compression has
+ actually taken place. */
+ if (name[1] != 'z')
+ {
+ unsigned int len = strlen (name);
+
+ new_name = bfd_alloc (abfd, len + 2);
+ if (new_name == NULL)
+ return FALSE;
+ new_name[0] = '.';
+ new_name[1] = 'z';
+ memcpy (new_name + 2, name + 1, len);
+ }
}
if (new_name != NULL)
bfd_rename_section (abfd, newsect, new_name);
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
+ /* PR 17512: file: 6f427532. */
+ if (s->size < extdynsize)
+ goto error_return;
extdynend = extdyn + s->size;
- for (; extdyn < extdynend; extdyn += extdynsize)
+ /* PR 17512: file: id:000006,sig:06,src:000000,op:flip4,pos:5664.
+ Fix range check. */
+ for (; extdyn <= (extdynend - extdynsize); extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
const char *name = "";
return FALSE;
}
+/* Get version string. */
+
+const char *
+_bfd_elf_get_symbol_version_string (bfd *abfd, asymbol *symbol,
+ bfd_boolean *hidden)
+{
+ const char *version_string = NULL;
+ if (elf_dynversym (abfd) != 0
+ && (elf_dynverdef (abfd) != 0 || elf_dynverref (abfd) != 0))
+ {
+ unsigned int vernum = ((elf_symbol_type *) symbol)->version;
+
+ *hidden = (vernum & VERSYM_HIDDEN) != 0;
+ vernum &= VERSYM_VERSION;
+
+ if (vernum == 0)
+ version_string = "";
+ else if (vernum == 1)
+ version_string = "Base";
+ else if (vernum <= elf_tdata (abfd)->cverdefs)
+ version_string =
+ elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
+ else
+ {
+ Elf_Internal_Verneed *t;
+
+ version_string = "";
+ for (t = elf_tdata (abfd)->verref;
+ t != NULL;
+ t = t->vn_nextref)
+ {
+ Elf_Internal_Vernaux *a;
+
+ for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
+ {
+ if (a->vna_other == vernum)
+ {
+ version_string = a->vna_nodename;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return version_string;
+}
+
/* Display ELF-specific fields of a symbol. */
void
const struct elf_backend_data *bed;
unsigned char st_other;
bfd_vma val;
+ const char *version_string;
+ bfd_boolean hidden;
section_name = symbol->section ? symbol->section->name : "(*none*)";
bfd_fprintf_vma (abfd, file, val);
/* If we have version information, print it. */
- if (elf_dynversym (abfd) != 0
- && (elf_dynverdef (abfd) != 0
- || elf_dynverref (abfd) != 0))
+ version_string = _bfd_elf_get_symbol_version_string (abfd,
+ symbol,
+ &hidden);
+ if (version_string)
{
- unsigned int vernum;
- const char *version_string;
-
- vernum = ((elf_symbol_type *) symbol)->version & VERSYM_VERSION;
-
- if (vernum == 0)
- version_string = "";
- else if (vernum == 1)
- version_string = "Base";
- else if (vernum <= elf_tdata (abfd)->cverdefs)
- version_string =
- elf_tdata (abfd)->verdef[vernum - 1].vd_nodename;
- else
- {
- Elf_Internal_Verneed *t;
-
- version_string = "";
- for (t = elf_tdata (abfd)->verref;
- t != NULL;
- t = t->vn_nextref)
- {
- Elf_Internal_Vernaux *a;
-
- for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
- {
- if (a->vna_other == vernum)
- {
- version_string = a->vna_nodename;
- break;
- }
- }
- }
- }
-
- if ((((elf_symbol_type *) symbol)->version & VERSYM_HIDDEN) == 0)
+ if (!hidden)
fprintf (file, " %-11s", version_string);
else
{
Elf_Internal_Ehdr *ehdr;
const struct elf_backend_data *bed;
const char *name;
+ bfd_boolean ret = TRUE;
+ static bfd_boolean * sections_being_created = NULL;
+ static bfd * sections_being_created_abfd = NULL;
+ static unsigned int nesting = 0;
if (shindex >= elf_numsections (abfd))
return FALSE;
+ if (++ nesting > 3)
+ {
+ /* PR17512: A corrupt ELF binary might contain a recursive group of
+ sections, with each the string indicies pointing to the next in the
+ loop. Detect this here, by refusing to load a section that we are
+ already in the process of loading. We only trigger this test if
+ we have nested at least three sections deep as normal ELF binaries
+ can expect to recurse at least once.
+
+ FIXME: It would be better if this array was attached to the bfd,
+ rather than being held in a static pointer. */
+
+ if (sections_being_created_abfd != abfd)
+ sections_being_created = NULL;
+ if (sections_being_created == NULL)
+ {
+ /* FIXME: It would be more efficient to attach this array to the bfd somehow. */
+ sections_being_created = (bfd_boolean *)
+ bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
+ sections_being_created_abfd = abfd;
+ }
+ if (sections_being_created [shindex])
+ {
+ (*_bfd_error_handler)
+ (_("%B: warning: loop in section dependencies detected"), abfd);
+ return FALSE;
+ }
+ sections_being_created [shindex] = TRUE;
+ }
+
hdr = elf_elfsections (abfd)[shindex];
ehdr = elf_elfheader (abfd);
name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx,
hdr->sh_name);
if (name == NULL)
- return FALSE;
+ goto fail;
bed = get_elf_backend_data (abfd);
switch (hdr->sh_type)
{
case SHT_NULL:
/* Inactive section. Throw it away. */
- return TRUE;
+ goto success;
- case SHT_PROGBITS: /* Normal section with contents. */
- case SHT_NOBITS: /* .bss section. */
- case SHT_HASH: /* .hash section. */
- case SHT_NOTE: /* .note section. */
+ case SHT_PROGBITS: /* Normal section with contents. */
+ case SHT_NOBITS: /* .bss section. */
+ case SHT_HASH: /* .hash section. */
+ case SHT_NOTE: /* .note section. */
case SHT_INIT_ARRAY: /* .init_array section. */
case SHT_FINI_ARRAY: /* .fini_array section. */
case SHT_PREINIT_ARRAY: /* .preinit_array section. */
case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
case SHT_GNU_HASH: /* .gnu.hash section. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
case SHT_DYNAMIC: /* Dynamic linking information. */
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
- return FALSE;
+ goto fail;
+
if (hdr->sh_link > elf_numsections (abfd))
{
/* PR 10478: Accept Solaris binaries with a sh_link
break;
/* Otherwise fall through. */
default:
- return FALSE;
+ goto fail;
}
}
else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
- return FALSE;
+ goto fail;
else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
{
Elf_Internal_Shdr *dynsymhdr;
}
}
}
- break;
+ goto success;
- case SHT_SYMTAB: /* A symbol table */
+ case SHT_SYMTAB: /* A symbol table. */
if (elf_onesymtab (abfd) == shindex)
- return TRUE;
+ goto success;
if (hdr->sh_entsize != bed->s->sizeof_sym)
- return FALSE;
+ goto fail;
+
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
{
if (hdr->sh_size != 0)
- return FALSE;
+ goto fail;
/* Some assemblers erroneously set sh_info to one with a
zero sh_size. ld sees this as a global symbol count
of (unsigned) -1. Fix it here. */
hdr->sh_info = 0;
- return TRUE;
+ goto success;
}
+
BFD_ASSERT (elf_onesymtab (abfd) == 0);
elf_onesymtab (abfd) = shindex;
elf_tdata (abfd)->symtab_hdr = *hdr;
&& (abfd->flags & DYNAMIC) != 0
&& ! _bfd_elf_make_section_from_shdr (abfd, hdr, name,
shindex))
- return FALSE;
+ goto fail;
/* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
can't read symbols without that section loaded as well. It
break;
}
if (i != shindex)
- return bfd_section_from_shdr (abfd, i);
+ ret = bfd_section_from_shdr (abfd, i);
}
- return TRUE;
+ goto success;
- case SHT_DYNSYM: /* A dynamic symbol table */
+ case SHT_DYNSYM: /* A dynamic symbol table. */
if (elf_dynsymtab (abfd) == shindex)
- return TRUE;
+ goto success;
if (hdr->sh_entsize != bed->s->sizeof_sym)
- return FALSE;
+ goto fail;
+
if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
{
if (hdr->sh_size != 0)
- return FALSE;
+ goto fail;
+
/* Some linkers erroneously set sh_info to one with a
zero sh_size. ld sees this as a global symbol count
of (unsigned) -1. Fix it here. */
hdr->sh_info = 0;
- return TRUE;
+ goto success;
}
+
BFD_ASSERT (elf_dynsymtab (abfd) == 0);
elf_dynsymtab (abfd) = shindex;
elf_tdata (abfd)->dynsymtab_hdr = *hdr;
/* Besides being a symbol table, we also treat this as a regular
section, so that objcopy can handle it. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
- case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */
+ case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections. */
if (elf_symtab_shndx (abfd) == shindex)
- return TRUE;
+ goto success;
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;
- return TRUE;
+ goto success;
- case SHT_STRTAB: /* A string table */
+ case SHT_STRTAB: /* A string table. */
if (hdr->bfd_section != NULL)
- return TRUE;
+ goto success;
+
if (ehdr->e_shstrndx == shindex)
{
elf_tdata (abfd)->shstrtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
- return TRUE;
+ goto success;
}
+
if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex)
{
symtab_strtab:
elf_tdata (abfd)->strtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
- return TRUE;
+ goto success;
}
+
if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex)
{
dynsymtab_strtab:
elf_elfsections (abfd)[shindex] = hdr;
/* We also treat this as a regular section, so that objcopy
can handle it. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
- shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
+ goto success;
}
/* If the string table isn't one of the above, then treat it as a
{
/* Prevent endless recursion on broken objects. */
if (i == shindex)
- return FALSE;
+ goto fail;
if (! bfd_section_from_shdr (abfd, i))
- return FALSE;
+ goto fail;
if (elf_onesymtab (abfd) == i)
goto symtab_strtab;
if (elf_dynsymtab (abfd) == i)
}
}
}
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
case SHT_REL:
case SHT_RELA:
if (hdr->sh_entsize
!= (bfd_size_type) (hdr->sh_type == SHT_REL
? bed->s->sizeof_rel : bed->s->sizeof_rela))
- return FALSE;
+ goto fail;
/* Check for a bogus link to avoid crashing. */
if (hdr->sh_link >= num_sec)
((*_bfd_error_handler)
(_("%B: invalid link %lu for reloc section %s (index %u)"),
abfd, hdr->sh_link, name, shindex));
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
- shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
+ goto success;
}
/* For some incomprehensible reason Oracle distributes
if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
|| elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM)
&& ! bfd_section_from_shdr (abfd, hdr->sh_link))
- return FALSE;
+ goto fail;
/* If this reloc section does not use the main symbol table we
don't treat it as a reloc section. BFD can't adequately
|| hdr->sh_info >= num_sec
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
|| elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
- shindex);
+ {
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
+ goto success;
+ }
if (! bfd_section_from_shdr (abfd, hdr->sh_info))
- return FALSE;
+ goto fail;
+
target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
if (target_sect == NULL)
- return FALSE;
+ goto fail;
esdt = elf_section_data (target_sect);
if (hdr->sh_type == SHT_RELA)
else
p_hdr = &esdt->rel.hdr;
- BFD_ASSERT (*p_hdr == NULL);
+ /* PR 17512: file: 0b4f81b7. */
+ if (*p_hdr != NULL)
+ goto fail;
amt = sizeof (*hdr2);
hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (hdr2 == NULL)
- return FALSE;
+ goto fail;
*hdr2 = *hdr;
*p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
target_sect->use_rela_p = 1;
}
abfd->flags |= HAS_RELOC;
- return TRUE;
+ goto success;
}
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
case SHT_GNU_versym:
if (hdr->sh_entsize != sizeof (Elf_External_Versym))
- return FALSE;
+ goto fail;
+
elf_dynversym (abfd) = shindex;
elf_tdata (abfd)->dynversym_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
case SHT_GNU_verneed:
elf_dynverref (abfd) = shindex;
elf_tdata (abfd)->dynverref_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
case SHT_SHLIB:
- return TRUE;
+ goto success;
case SHT_GROUP:
if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE))
- return FALSE;
+ goto fail;
+
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
- return FALSE;
+ goto fail;
+
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
- unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
+ unsigned int n_elt = hdr->sh_size / sizeof (* idx);
asection *s;
+ if (n_elt == 0)
+ goto fail;
if (idx->flags & GRP_COMDAT)
hdr->bfd_section->flags
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
/* We try to keep the same section order as it comes in. */
idx += n_elt;
+
while (--n_elt != 0)
{
--idx;
}
}
}
- break;
+ goto success;
default:
/* Possibly an attributes section. */
|| hdr->sh_type == bed->obj_attrs_section_type)
{
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
- return FALSE;
+ goto fail;
_bfd_elf_parse_attributes (abfd, hdr);
- return TRUE;
+ goto success;
}
/* Check for any processor-specific section types. */
if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex))
- return TRUE;
+ goto success;
if (hdr->sh_type >= SHT_LOUSER && hdr->sh_type <= SHT_HIUSER)
{
"specific section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else
- /* Allow sections reserved for applications. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
- shindex);
+ {
+ /* Allow sections reserved for applications. */
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
+ goto success;
+ }
}
else if (hdr->sh_type >= SHT_LOPROC
&& hdr->sh_type <= SHT_HIPROC)
"`%s' [0x%8x]"),
abfd, name, hdr->sh_type);
else
- /* Otherwise it should be processed. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ {
+ /* Otherwise it should be processed. */
+ ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+ goto success;
+ }
}
else
/* FIXME: We should handle this section. */
(_("%B: don't know how to handle section `%s' [0x%8x]"),
abfd, name, hdr->sh_type);
- return FALSE;
+ goto fail;
}
- return TRUE;
+ fail:
+ ret = FALSE;
+ success:
+ if (sections_being_created && sections_being_created_abfd == abfd)
+ sections_being_created [shindex] = FALSE;
+ if (-- nesting == 0)
+ {
+ sections_being_created = NULL;
+ sections_being_created_abfd = abfd;
+ }
+ return ret;
}
/* Return the local symbol specified by ABFD, R_SYMNDX. */
struct bfd_elf_section_data *esd = elf_section_data (asect);
Elf_Internal_Shdr *this_hdr;
unsigned int sh_type;
+ const char *name = asect->name;
if (arg->failed)
{
this_hdr = &esd->this_hdr;
+ /* For linking, compress DWARF debug sections with names: .debug_*. */
+ if (arg->link_info
+ && (arg->link_info->compress_debug & COMPRESS_DEBUG)
+ && (asect->flags & SEC_DEBUGGING)
+ && name[1] == 'd'
+ && name[6] == '_')
+ {
+ /* Set SEC_ELF_COMPRESS to indicate this section should be
+ compressed. */
+ asect->flags |= SEC_ELF_COMPRESS;
+
+ if (arg->link_info->compress_debug != COMPRESS_DEBUG_GABI_ZLIB)
+ {
+ /* If SHF_COMPRESSED isn't used, rename compressed DWARF
+ debug section to .zdebug_*. */
+ unsigned int len = strlen (name);
+ char *new_name = bfd_alloc (abfd, len + 2);
+ if (new_name == NULL)
+ {
+ arg->failed = TRUE;
+ return;
+ }
+ new_name[0] = '.';
+ new_name[1] = 'z';
+ memcpy (new_name + 2, name + 1, len);
+ bfd_rename_section (abfd, asect, new_name);
+ name = asect->name;
+ }
+ }
+
this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
- asect->name, FALSE);
+ name, FALSE);
if (this_hdr->sh_name == (unsigned int) -1)
{
arg->failed = TRUE;
this_hdr->sh_offset = 0;
this_hdr->sh_size = asect->size;
this_hdr->sh_link = 0;
+ /* PR 17512: file: 0eb809fe, 8b0535ee. */
+ if (asect->alignment_power >= (sizeof (bfd_vma) * 8) - 1)
+ {
+ (*_bfd_error_handler)
+ (_("%B: error: Alignment power %d of section `%A' is too big"),
+ abfd, asect, asect->alignment_power);
+ arg->failed = TRUE;
+ return;
+ }
this_hdr->sh_addralign = (bfd_vma) 1 << asect->alignment_power;
/* The sh_entsize and sh_info fields may have been set already by
copy_private_section_data. */
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
}
+/* Return the section which RELOC_SEC applies to. */
+
+asection *
+_bfd_elf_get_reloc_section (asection *reloc_sec)
+{
+ const char *name;
+ unsigned int type;
+ bfd *abfd;
+
+ if (reloc_sec == NULL)
+ return NULL;
+
+ type = elf_section_data (reloc_sec)->this_hdr.sh_type;
+ if (type != SHT_REL && type != SHT_RELA)
+ return NULL;
+
+ /* We look up the section the relocs apply to by name. */
+ name = reloc_sec->name;
+ if (type == SHT_REL)
+ name += 4;
+ else
+ name += 5;
+
+ /* If a target needs .got.plt section, relocations in rela.plt/rel.plt
+ section apply to .got.plt section. */
+ abfd = reloc_sec->owner;
+ if (get_elf_backend_data (abfd)->want_got_plt
+ && strcmp (name, ".plt") == 0)
+ {
+ /* .got.plt is a linker created input section. It may be mapped
+ to some other output section. Try two likely sections. */
+ name = ".got.plt";
+ reloc_sec = bfd_get_section_by_name (abfd, name);
+ if (reloc_sec != NULL)
+ return reloc_sec;
+ name = ".got";
+ }
+
+ reloc_sec = bfd_get_section_by_name (abfd, name);
+ return reloc_sec;
+}
+
/* Assign all ELF section numbers. The dummy first section is handled here
too. The link/info pointers for the standard section types are filled
in here too, while we're at it. */
for (sec = abfd->sections; sec; sec = sec->next)
{
asection *s;
- const char *name;
d = elf_section_data (sec);
if (s != NULL)
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
- /* We look up the section the relocs apply to by name. */
- name = sec->name;
- if (d->this_hdr.sh_type == SHT_REL)
- name += 4;
- else
- name += 5;
- s = bfd_get_section_by_name (abfd, name);
+ s = get_elf_backend_data (abfd)->get_reloc_section (sec);
if (s != NULL)
{
d->this_hdr.sh_info = elf_section_data (s)->this_idx;
last_size = 0;
phdr_index = 0;
maxpagesize = bed->maxpagesize;
+ /* PR 17512: file: c8455299.
+ Avoid divide-by-zero errors later on.
+ FIXME: Should we abort if the maxpagesize is zero ? */
+ if (maxpagesize == 0)
+ maxpagesize = 1;
writable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
if (dynsec != NULL
/* Mandated PF_R. */
m->p_flags = PF_R;
m->p_flags_valid = 1;
+ s = first_tls;
for (i = 0; i < (unsigned int) tls_count; ++i)
{
- BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
- m->sections[i] = first_tls;
- first_tls = first_tls->next;
+ if ((s->flags & SEC_THREAD_LOCAL) == 0)
+ {
+ _bfd_error_handler
+ (_("%B: TLS sections are not adjacent:"), abfd);
+ s = first_tls;
+ i = 0;
+ while (i < (unsigned int) tls_count)
+ {
+ if ((s->flags & SEC_THREAD_LOCAL) != 0)
+ {
+ _bfd_error_handler (_(" TLS: %A"), s);
+ i++;
+ }
+ else
+ _bfd_error_handler (_(" non-TLS: %A"), s);
+ s = s->next;
+ }
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ m->sections[i] = s;
+ s = s->next;
}
*pm = m;
== (SEC_LOAD | SEC_HAS_CONTENTS))
break;
- if (i == (unsigned) -1)
- continue;
-
- if (m->sections[i]->vma + m->sections[i]->size
- >= info->relro_end)
+ if (i != (unsigned) -1)
break;
}
}
static file_ptr
vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
{
+ /* PR binutils/16199: Handle an alignment of zero. */
+ if (maxpagesize == 0)
+ maxpagesize = 1;
return ((vma - off) % maxpagesize);
}
p->p_flags |= PF_W;
}
}
+
off -= off_adjust;
/* Check that all sections are in a PT_LOAD segment.
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Shdr **i_shdrpp;
- Elf_Internal_Shdr **hdrpp;
+ Elf_Internal_Shdr **hdrpp, **end_hdrpp;
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
struct elf_segment_map *m;
bfd_vma filehdr_vaddr, filehdr_paddr;
bfd_vma phdrs_vaddr, phdrs_paddr;
file_ptr off;
- unsigned int num_sec;
- unsigned int i;
unsigned int count;
i_shdrpp = elf_elfsections (abfd);
- num_sec = elf_numsections (abfd);
+ end_hdrpp = i_shdrpp + elf_numsections (abfd);
off = elf_next_file_pos (abfd);
- for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
+ for (hdrpp = i_shdrpp + 1; hdrpp < end_hdrpp; hdrpp++)
{
Elf_Internal_Shdr *hdr;
}
else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL)
+ || (hdr->bfd_section != NULL
+ && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
+ /* Compress DWARF debug sections. */
|| hdr == i_shdrpp[elf_onesymtab (abfd)]
|| hdr == i_shdrpp[elf_symtab_shndx (abfd)]
|| hdr == i_shdrpp[elf_strtab_sec (abfd)])
{
if (lp->p_type == PT_LOAD
&& lp->p_vaddr < link_info->relro_end
- && lp->p_vaddr + lp->p_filesz >= link_info->relro_end
&& lm->count != 0
&& lm->sections[0]->vma >= link_info->relro_start)
break;
}
- /* PR ld/14207. If the RELRO segment doesn't fit in the
- LOAD segment, it should be removed. */
BFD_ASSERT (lm != NULL);
}
else
}
else if (m->count != 0)
{
+ unsigned int i;
if (p->p_type != PT_LOAD
&& (p->p_type != PT_NOTE
|| bfd_get_format (abfd) != bfd_core))
{
- BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+ if (m->includes_filehdr || m->includes_phdrs)
+ {
+ /* PR 17512: file: 2195325e. */
+ (*_bfd_error_handler)
+ (_("%B: warning: non-load segment includes file header and/or program header"),
+ abfd);
+ return FALSE;
+ }
p->p_filesz = 0;
p->p_offset = m->sections[0]->filepos;
{
struct elf_obj_tdata *tdata = elf_tdata (abfd);
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
- file_ptr off;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
unsigned int num_sec = elf_numsections (abfd);
Elf_Internal_Shdr **hdrpp;
unsigned int i;
+ file_ptr off;
/* Start after the ELF header. */
off = i_ehdrp->e_ehsize;
hdr = *hdrpp;
if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
&& hdr->bfd_section == NULL)
+ || (hdr->bfd_section != NULL
+ && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
+ /* Compress DWARF debug sections. */
|| i == elf_onesymtab (abfd)
|| i == elf_symtab_shndx (abfd)
|| i == elf_strtab_sec (abfd))
else
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
}
+
+ elf_next_file_pos (abfd) = off;
}
else
{
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
return FALSE;
-
- off = elf_next_file_pos (abfd);
}
- /* Place the section headers. */
- off = align_file_position (off, 1 << bed->s->log_file_align);
- i_ehdrp->e_shoff = off;
- off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
-
- elf_next_file_pos (abfd) = off;
-
return TRUE;
}
elf_tdata (abfd)->shstrtab_hdr.sh_name =
(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)->strtab_hdr.sh_name == (unsigned int) -1
|| elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
return FALSE;
}
/* Assign file positions for all the reloc sections which are not part
- of the loadable file image. */
+ of the loadable file image, and the file position of section headers. */
-void
-_bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
+static bfd_boolean
+_bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
{
file_ptr off;
- unsigned int i, num_sec;
- Elf_Internal_Shdr **shdrpp;
+ Elf_Internal_Shdr **shdrpp, **end_shdrpp;
+ Elf_Internal_Ehdr *i_ehdrp;
+ const struct elf_backend_data *bed;
off = elf_next_file_pos (abfd);
- num_sec = elf_numsections (abfd);
- for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
+ shdrpp = elf_elfsections (abfd);
+ end_shdrpp = shdrpp + elf_numsections (abfd);
+ for (shdrpp++; shdrpp < end_shdrpp; shdrpp++)
{
Elf_Internal_Shdr *shdrp;
shdrp = *shdrpp;
- if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
- && shdrp->sh_offset == -1)
- off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
+ if (shdrp->sh_offset == -1)
+ {
+ bfd_boolean is_rel = (shdrp->sh_type == SHT_REL
+ || shdrp->sh_type == SHT_RELA);
+ if (is_rel
+ || (shdrp->bfd_section != NULL
+ && (shdrp->bfd_section->flags & SEC_ELF_COMPRESS)))
+ {
+ if (!is_rel)
+ {
+ /* Compress DWARF debug sections. */
+ if (!bfd_compress_section (abfd, shdrp->bfd_section,
+ shdrp->contents))
+ return FALSE;
+ /* Update section size and contents. */
+ shdrp->sh_size = shdrp->bfd_section->size;
+ shdrp->contents = shdrp->bfd_section->contents;
+ shdrp->bfd_section->contents = NULL;
+ }
+ off = _bfd_elf_assign_file_position_for_section (shdrp,
+ off,
+ TRUE);
+ }
+ }
}
+/* Place the section headers. */
+ i_ehdrp = elf_elfheader (abfd);
+ bed = get_elf_backend_data (abfd);
+ off = align_file_position (off, 1 << bed->s->log_file_align);
+ i_ehdrp->e_shoff = off;
+ off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
elf_next_file_pos (abfd) = off;
+
+ return TRUE;
}
bfd_boolean
if (failed)
return FALSE;
- _bfd_elf_assign_file_positions_for_relocs (abfd);
+ if (!_bfd_elf_assign_file_positions_for_non_load (abfd))
+ return FALSE;
/* After writing the headers, we need to write the sections too... */
num_sec = elf_numsections (abfd);
something. They are allowed by the ELF spec however, so only
a warning is produced. */
if (segment->p_type == PT_LOAD)
- (*_bfd_error_handler) (_("%B: warning: Empty loadable segment"
- " detected, is this intentional ?\n"),
+ (*_bfd_error_handler) (_("\
+%B: warning: Empty loadable segment detected, is this intentional ?"),
ibfd);
map->count = 0;
phdr_included = TRUE;
}
- lowest_section = first_section;
+ lowest_section = NULL;
if (section_count != 0)
{
unsigned int isec = 0;
{
bfd_vma seg_off;
- if (section->lma < lowest_section->lma)
+ if (lowest_section == NULL
+ || section->lma < lowest_section->lma)
lowest_section = section;
/* Section lmas are set up from PT_LOAD header
i++, segment++)
if (segment->p_type == PT_LOAD
&& maxpagesize < segment->p_align)
- maxpagesize = segment->p_align;
+ {
+ /* PR 17512: file: f17299af. */
+ if (segment->p_align > (bfd_vma) 1 << ((sizeof (bfd_vma) * 8) - 2))
+ (*_bfd_error_handler) (_("\
+%B: warning: segment alignment of 0x%llx is too large"),
+ ibfd, (long long) segment->p_align);
+ else
+ maxpagesize = segment->p_align;
+ }
if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
elf_next_in_group (osec) = elf_next_in_group (isec);
elf_section_data (osec)->group = elf_section_data (isec)->group;
}
+
+ /* If not decompress, preserve SHF_COMPRESSED. */
+ if ((ibfd->flags & BFD_DECOMPRESS) == 0)
+ elf_section_flags (osec) |= (elf_section_flags (isec)
+ & SHF_COMPRESSED);
}
ihdr = &elf_section_data (isec)->this_hdr;
hdr = &elf_tdata (abfd)->dynverref_hdr;
- elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
- bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
- if (elf_tdata (abfd)->verref == NULL)
- goto error_return;
-
- elf_tdata (abfd)->cverrefs = hdr->sh_info;
-
- contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
- if (contents == NULL)
+ if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verneed))
{
+error_return_bad_verref:
+ (*_bfd_error_handler)
+ (_("%B: .gnu.version_r invalid entry"), abfd);
+ bfd_set_error (bfd_error_bad_value);
error_return_verref:
elf_tdata (abfd)->verref = NULL;
elf_tdata (abfd)->cverrefs = 0;
goto error_return;
}
+
+ contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+ if (contents == NULL)
+ goto error_return_verref;
+
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
goto error_return_verref;
- if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verneed))
+ elf_tdata (abfd)->verref = (Elf_Internal_Verneed *)
+ bfd_zalloc2 (abfd, hdr->sh_info, sizeof (Elf_Internal_Verneed));
+
+ if (elf_tdata (abfd)->verref == NULL)
goto error_return_verref;
BFD_ASSERT (sizeof (Elf_External_Verneed)
bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
iverneed->vn_file);
if (iverneed->vn_filename == NULL)
- goto error_return_verref;
+ goto error_return_bad_verref;
if (iverneed->vn_cnt == 0)
iverneed->vn_auxptr = NULL;
if (iverneed->vn_aux
> (size_t) (contents_end - (bfd_byte *) everneed))
- goto error_return_verref;
+ goto error_return_bad_verref;
evernaux = ((Elf_External_Vernaux *)
((bfd_byte *) everneed + iverneed->vn_aux));
bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
ivernaux->vna_name);
if (ivernaux->vna_nodename == NULL)
- goto error_return_verref;
+ goto error_return_bad_verref;
+ if (ivernaux->vna_other > freeidx)
+ freeidx = ivernaux->vna_other;
+
+ ivernaux->vna_nextptr = NULL;
+ if (ivernaux->vna_next == 0)
+ {
+ iverneed->vn_cnt = j + 1;
+ break;
+ }
if (j + 1 < iverneed->vn_cnt)
ivernaux->vna_nextptr = ivernaux + 1;
- else
- ivernaux->vna_nextptr = NULL;
if (ivernaux->vna_next
> (size_t) (contents_end - (bfd_byte *) evernaux))
- goto error_return_verref;
+ goto error_return_bad_verref;
evernaux = ((Elf_External_Vernaux *)
((bfd_byte *) evernaux + ivernaux->vna_next));
-
- if (ivernaux->vna_other > freeidx)
- freeidx = ivernaux->vna_other;
}
+ iverneed->vn_nextref = NULL;
+ if (iverneed->vn_next == 0)
+ break;
if (i + 1 < hdr->sh_info)
iverneed->vn_nextref = iverneed + 1;
- else
- iverneed->vn_nextref = NULL;
if (iverneed->vn_next
> (size_t) (contents_end - (bfd_byte *) everneed))
- goto error_return_verref;
+ goto error_return_bad_verref;
everneed = ((Elf_External_Verneed *)
((bfd_byte *) everneed + iverneed->vn_next));
}
+ elf_tdata (abfd)->cverrefs = i;
free (contents);
contents = NULL;
hdr = &elf_tdata (abfd)->dynverdef_hdr;
+ if (hdr->sh_info == 0 || hdr->sh_size < sizeof (Elf_External_Verdef))
+ {
+ error_return_bad_verdef:
+ (*_bfd_error_handler)
+ (_("%B: .gnu.version_d invalid entry"), abfd);
+ bfd_set_error (bfd_error_bad_value);
+ error_return_verdef:
+ elf_tdata (abfd)->verdef = NULL;
+ elf_tdata (abfd)->cverdefs = 0;
+ goto error_return;
+ }
+
contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
- goto error_return;
+ goto error_return_verdef;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
- goto error_return;
-
- if (hdr->sh_info && hdr->sh_size < sizeof (Elf_External_Verdef))
- goto error_return;
+ goto error_return_verdef;
BFD_ASSERT (sizeof (Elf_External_Verdef)
>= sizeof (Elf_External_Verdaux));
{
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
+ if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) == 0)
+ goto error_return_bad_verdef;
if ((iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION)) > maxidx)
maxidx = iverdefmem.vd_ndx & ((unsigned) VERSYM_VERSION);
+ if (iverdefmem.vd_next == 0)
+ break;
+
if (iverdefmem.vd_next
> (size_t) (contents_end_def - (bfd_byte *) everdef))
- goto error_return;
+ goto error_return_bad_verdef;
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdefmem.vd_next));
else
freeidx = ++maxidx;
}
+
elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
- bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
+ bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
if (elf_tdata (abfd)->verdef == NULL)
- goto error_return;
+ goto error_return_verdef;
elf_tdata (abfd)->cverdefs = maxidx;
_bfd_elf_swap_verdef_in (abfd, everdef, &iverdefmem);
if ((iverdefmem.vd_ndx & VERSYM_VERSION) == 0)
- {
-error_return_verdef:
- elf_tdata (abfd)->verdef = NULL;
- elf_tdata (abfd)->cverdefs = 0;
- goto error_return;
- }
+ goto error_return_bad_verdef;
iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
if (iverdef->vd_aux
> (size_t) (contents_end_aux - (bfd_byte *) everdef))
- goto error_return_verdef;
+ goto error_return_bad_verdef;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdef + iverdef->vd_aux));
bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
iverdaux->vda_name);
if (iverdaux->vda_nodename == NULL)
- goto error_return_verdef;
+ goto error_return_bad_verdef;
+ iverdaux->vda_nextptr = NULL;
+ if (iverdaux->vda_next == 0)
+ {
+ iverdef->vd_cnt = j + 1;
+ break;
+ }
if (j + 1 < iverdef->vd_cnt)
iverdaux->vda_nextptr = iverdaux + 1;
- else
- iverdaux->vda_nextptr = NULL;
if (iverdaux->vda_next
> (size_t) (contents_end_aux - (bfd_byte *) everdaux))
- goto error_return_verdef;
+ goto error_return_bad_verdef;
everdaux = ((Elf_External_Verdaux *)
((bfd_byte *) everdaux + iverdaux->vda_next));
if (iverdef->vd_cnt)
iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
+ iverdef->vd_nextdef = NULL;
+ if (iverdef->vd_next == 0)
+ break;
if ((size_t) (iverdef - iverdefarr) + 1 < maxidx)
iverdef->vd_nextdef = iverdef + 1;
- else
- iverdef->vd_nextdef = NULL;
everdef = ((Elf_External_Verdef *)
((bfd_byte *) everdef + iverdef->vd_next));
if (iverdef->vd_nodename == NULL)
goto error_return_verdef;
iverdef->vd_nextdef = NULL;
- iverdef->vd_auxptr = (struct elf_internal_verdaux *)
- bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
+ iverdef->vd_auxptr = ((struct elf_internal_verdaux *)
+ bfd_zalloc (abfd, sizeof (Elf_Internal_Verdaux)));
if (iverdef->vd_auxptr == NULL)
goto error_return_verdef;
iverdaux = iverdef->vd_auxptr;
iverdaux->vda_nodename = iverdef->vd_nodename;
- iverdaux->vda_nextptr = NULL;
}
return TRUE;
_bfd_elf_make_empty_symbol (bfd *abfd)
{
elf_symbol_type *newsym;
- bfd_size_type amt = sizeof (elf_symbol_type);
- newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
+ newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof * newsym);
if (!newsym)
return NULL;
- else
- {
- newsym->symbol.the_bfd = abfd;
- return &newsym->symbol;
- }
+ newsym->symbol.the_bfd = abfd;
+ return &newsym->symbol;
}
void
if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
return TRUE;
+ /* Treat assembler generated local labels as local. */
+ if (name[0] == 'L' && name[strlen (name) - 1] < 32)
+ return TRUE;
+
return FALSE;
}
return bfd_default_set_arch_mach (abfd, arch, machine);
}
-/* Find the function to a particular section and offset,
- for error reporting. */
-
-static bfd_boolean
-elf_find_function (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr)
-{
- struct elf_find_function_cache
- {
- asection *last_section;
- asymbol *func;
- const char *filename;
- bfd_size_type func_size;
- } *cache;
-
- if (symbols == NULL)
- return FALSE;
-
- cache = elf_tdata (abfd)->elf_find_function_cache;
- if (cache == NULL)
- {
- cache = bfd_zalloc (abfd, sizeof (*cache));
- elf_tdata (abfd)->elf_find_function_cache = cache;
- if (cache == NULL)
- return FALSE;
- }
- if (cache->last_section != section
- || cache->func == NULL
- || offset < cache->func->value
- || offset >= cache->func->value + cache->func_size)
- {
- asymbol *file;
- bfd_vma low_func;
- asymbol **p;
- /* ??? Given multiple file symbols, it is impossible to reliably
- choose the right file name for global symbols. File symbols are
- local symbols, and thus all file symbols must sort before any
- global symbols. The ELF spec may be interpreted to say that a
- file symbol must sort before other local symbols, but currently
- ld -r doesn't do this. So, for ld -r output, it is possible to
- make a better choice of file name for local symbols by ignoring
- file symbols appearing after a given local symbol. */
- enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- file = NULL;
- low_func = 0;
- state = nothing_seen;
- cache->filename = NULL;
- cache->func = NULL;
- cache->func_size = 0;
- cache->last_section = section;
-
- for (p = symbols; *p != NULL; p++)
- {
- asymbol *sym = *p;
- bfd_vma code_off;
- bfd_size_type size;
-
- if ((sym->flags & BSF_FILE) != 0)
- {
- file = sym;
- if (state == symbol_seen)
- state = file_after_symbol_seen;
- continue;
- }
-
- size = bed->maybe_function_sym (sym, section, &code_off);
- if (size != 0
- && code_off <= offset
- && (code_off > low_func
- || (code_off == low_func
- && size > cache->func_size)))
- {
- cache->func = sym;
- cache->func_size = size;
- cache->filename = NULL;
- low_func = code_off;
- if (file != NULL
- && ((sym->flags & BSF_LOCAL) != 0
- || state != file_after_symbol_seen))
- cache->filename = bfd_asymbol_name (file);
- }
- if (state == nothing_seen)
- state = symbol_seen;
- }
- }
-
- if (cache->func == NULL)
- return FALSE;
-
- if (filename_ptr)
- *filename_ptr = cache->filename;
- if (functionname_ptr)
- *functionname_ptr = bfd_asymbol_name (cache->func);
-
- return TRUE;
-}
-
/* Find the nearest line to a particular section and offset,
for error reporting. */
bfd_boolean
_bfd_elf_find_nearest_line (bfd *abfd,
- asection *section,
asymbol **symbols,
+ asection *section,
bfd_vma offset,
const char **filename_ptr,
const char **functionname_ptr,
- unsigned int *line_ptr)
-{
- return _bfd_elf_find_nearest_line_discriminator (abfd, section, symbols,
- offset, filename_ptr,
- functionname_ptr,
- line_ptr,
- NULL);
-}
-
-bfd_boolean
-_bfd_elf_find_nearest_line_discriminator (bfd *abfd,
- asection *section,
- asymbol **symbols,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *line_ptr,
- unsigned int *discriminator_ptr)
+ unsigned int *line_ptr,
+ unsigned int *discriminator_ptr)
{
bfd_boolean found;
- if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
+ if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
filename_ptr, functionname_ptr,
- line_ptr))
+ line_ptr, discriminator_ptr,
+ dwarf_debug_sections, 0,
+ &elf_tdata (abfd)->dwarf2_find_line_info)
+ || _bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr))
{
if (!*functionname_ptr)
- elf_find_function (abfd, section, symbols, offset,
- *filename_ptr ? NULL : filename_ptr,
- functionname_ptr);
-
- return TRUE;
- }
-
- if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
- section, symbols, offset,
- filename_ptr, functionname_ptr,
- line_ptr, discriminator_ptr, 0,
- &elf_tdata (abfd)->dwarf2_find_line_info))
- {
- if (!*functionname_ptr)
- elf_find_function (abfd, section, symbols, offset,
- *filename_ptr ? NULL : filename_ptr,
- functionname_ptr);
-
+ _bfd_elf_find_function (abfd, symbols, section, offset,
+ *filename_ptr ? NULL : filename_ptr,
+ functionname_ptr);
return TRUE;
}
if (symbols == NULL)
return FALSE;
- if (! elf_find_function (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr))
+ if (! _bfd_elf_find_function (abfd, symbols, section, offset,
+ filename_ptr, functionname_ptr))
return FALSE;
*line_ptr = 0;
_bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol,
const char **filename_ptr, unsigned int *line_ptr)
{
- return _bfd_elf_find_line_discriminator (abfd, symbols, symbol,
- filename_ptr, line_ptr,
- NULL);
-}
-
-bfd_boolean
-_bfd_elf_find_line_discriminator (bfd *abfd, asymbol **symbols, asymbol *symbol,
- const char **filename_ptr,
- unsigned int *line_ptr,
- unsigned int *discriminator_ptr)
-{
- return _bfd_dwarf2_find_line (abfd, symbols, symbol,
- filename_ptr, line_ptr, discriminator_ptr, 0,
- &elf_tdata (abfd)->dwarf2_find_line_info);
+ return _bfd_dwarf2_find_nearest_line (abfd, symbols, symbol, NULL, 0,
+ filename_ptr, NULL, line_ptr, NULL,
+ dwarf_debug_sections, 0,
+ &elf_tdata (abfd)->dwarf2_find_line_info);
}
/* After a call to bfd_find_nearest_line, successive calls to
bfd_size_type count)
{
Elf_Internal_Shdr *hdr;
- bfd_signed_vma pos;
+ file_ptr pos;
if (! abfd->output_has_begun
&& ! _bfd_elf_compute_section_file_positions (abfd, NULL))
return FALSE;
+ if (!count)
+ return TRUE;
+
hdr = &elf_section_data (section)->this_hdr;
+ if (hdr->sh_offset == (file_ptr) -1)
+ {
+ /* We must compress this section. Write output to the buffer. */
+ unsigned char *contents = hdr->contents;
+ if ((offset + count) > hdr->sh_size
+ || (section->flags & SEC_ELF_COMPRESS) == 0
+ || contents == NULL)
+ abort ();
+ memcpy (contents + offset, location, count);
+ return TRUE;
+ }
pos = hdr->sh_offset + offset;
if (bfd_seek (abfd, pos, SEEK_SET) != 0
|| bfd_bwrite (location, count, abfd) != count)
return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note);
}
+static bfd_boolean
+elfcore_grok_s390_vxrs_low (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-low", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_vxrs_high (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-vxrs-high", note);
+}
+
static bfd_boolean
elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
{
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
return elfcore_grok_xstatereg (abfd, note);
+ else if (note->namesz == 8
+ && strcmp (note->namedata, "FreeBSD") == 0)
+ return elfcore_grok_xstatereg (abfd, note);
else
return TRUE;
else
return TRUE;
+ case NT_S390_VXRS_LOW:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_vxrs_low (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_VXRS_HIGH:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_vxrs_high (abfd, note);
+ else
+ return TRUE;
+
case NT_ARM_VFP:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
lwpstat.pr_lwpid = pid >> 16;
lwpstat.pr_cursig = cursig;
#if defined (HAVE_LWPSTATUS_T_PR_REG)
- memcpy (lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
+ memcpy (&lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
#elif defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
#if !defined(gregs)
memcpy (lwpstat.pr_context.uc_mcontext.gregs,
elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz,
const void *xfpregs, int size)
{
- char *note_name = "LINUX";
+ char *note_name;
+ if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD)
+ note_name = "FreeBSD";
+ else
+ note_name = "LINUX";
return elfcore_write_note (abfd, buf, bufsiz,
note_name, NT_X86_XSTATE, xfpregs, size);
}
note_name, NT_S390_TDB, s390_tdb, size);
}
+char *
+elfcore_write_s390_vxrs_low (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_vxrs_low,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_VXRS_LOW, s390_vxrs_low, size);
+}
+
+char *
+elfcore_write_s390_vxrs_high (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_vxrs_high,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_VXRS_HIGH,
+ s390_vxrs_high, size);
+}
+
char *
elfcore_write_arm_vfp (bfd *abfd,
char *buf,
return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-s390-tdb") == 0)
return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-vxrs-low") == 0)
+ return elfcore_write_s390_vxrs_low (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-vxrs-high") == 0)
+ return elfcore_write_s390_vxrs_high (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-arm-vfp") == 0)
return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-aarch-tls") == 0)
return TRUE;
case bfd_core:
- if (CONST_STRNEQ (in.namedata, "NetBSD-CORE"))
- {
- if (! elfcore_grok_netbsd_note (abfd, &in))
- return FALSE;
- }
- else if (CONST_STRNEQ (in.namedata, "OpenBSD"))
- {
- if (! elfcore_grok_openbsd_note (abfd, &in))
- return FALSE;
- }
- else if (CONST_STRNEQ (in.namedata, "QNX"))
+ {
+#define GROKER_ELEMENT(S,F) {S, sizeof (S) - 1, F}
+ struct
{
- if (! elfcore_grok_nto_note (abfd, &in))
- return FALSE;
+ const char * string;
+ size_t len;
+ bfd_boolean (* func)(bfd *, Elf_Internal_Note *);
}
- else if (CONST_STRNEQ (in.namedata, "SPU/"))
+ grokers[] =
{
- if (! elfcore_grok_spu_note (abfd, &in))
- return FALSE;
- }
- else
- {
- if (! elfcore_grok_note (abfd, &in))
- return FALSE;
- }
- break;
+ GROKER_ELEMENT ("", elfcore_grok_note),
+ GROKER_ELEMENT ("NetBSD-CORE", elfcore_grok_netbsd_note),
+ GROKER_ELEMENT ( "OpenBSD", elfcore_grok_openbsd_note),
+ GROKER_ELEMENT ("QNX", elfcore_grok_nto_note),
+ GROKER_ELEMENT ("SPU/", elfcore_grok_spu_note)
+ };
+#undef GROKER_ELEMENT
+ int i;
+
+ for (i = ARRAY_SIZE (grokers); i--;)
+ {
+ if (in.namesz >= grokers[i].len
+ && strncmp (in.namedata, grokers[i].string,
+ grokers[i].len) == 0)
+ {
+ if (! grokers[i].func (abfd, & in))
+ return FALSE;
+ break;
+ }
+ }
+ break;
+ }
case bfd_object:
if (in.namesz == sizeof "GNU" && strcmp (in.namedata, "GNU") == 0)
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
return FALSE;
- buf = (char *) bfd_malloc (size);
+ buf = (char *) bfd_malloc (size + 1);
if (buf == NULL)
return FALSE;
+ /* PR 17512: file: ec08f814
+ 0-termintate the buffer so that string searches will not overflow. */
+ buf[size] = 0;
+
if (bfd_bread (buf, size, abfd) != size
|| !elf_parse_notes (abfd, buf, size, offset))
{
bfd_elf_bfd_from_remote_memory
(bfd *templ,
bfd_vma ehdr_vma,
+ bfd_size_type size,
bfd_vma *loadbasep,
int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
{
return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
- (templ, ehdr_vma, loadbasep, target_read_memory);
+ (templ, ehdr_vma, size, loadbasep, target_read_memory);
}
\f
long