/* For sparc64-cross-sparc32. */
#define _SYSCALL32
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "bfdlink.h"
#include "libbfd.h"
#define ARCH_SIZE 0
bfd_size_type shstrtabsize;
i_shdrp = elf_elfsections (abfd);
- if (i_shdrp == 0 || i_shdrp[shindex] == 0)
+ if (i_shdrp == 0
+ || shindex >= elf_numsections (abfd)
+ || i_shdrp[shindex] == 0)
return NULL;
shstrtab = i_shdrp[shindex]->contents;
if (strindex == 0)
return "";
+ if (elf_elfsections (abfd) == NULL || shindex >= elf_numsections (abfd))
+ return NULL;
+
hdr = elf_elfsections (abfd)[shindex];
if (hdr->contents == NULL
section with just a flag word (ie. sh_size is 4), ignore it. */
shnum = elf_numsections (abfd);
num_group = 0;
+
+#define IS_VALID_GROUP_SECTION_HEADER(shdr) \
+ ( (shdr)->sh_type == SHT_GROUP \
+ && (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE) \
+ && (shdr)->sh_entsize == GRP_ENTRY_SIZE \
+ && ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0)
+
for (i = 0; i < shnum; i++)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
- if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8)
+
+ if (IS_VALID_GROUP_SECTION_HEADER (shdr))
num_group += 1;
}
for (i = 0; i < shnum; i++)
{
Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
- if (shdr->sh_type == SHT_GROUP && shdr->sh_size >= 8)
+
+ if (IS_VALID_GROUP_SECTION_HEADER (shdr))
{
unsigned char *src;
Elf_Internal_Group *dest;
amt = shdr->sh_size * sizeof (*dest) / 4;
shdr->contents = bfd_alloc2 (abfd, shdr->sh_size,
sizeof (*dest) / 4);
- if (shdr->contents == NULL
- || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
+ /* PR binutils/4110: Handle corrupt group headers. */
+ if (shdr->contents == NULL)
+ {
+ _bfd_error_handler
+ (_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ 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;
/* We need a BFD section for objcopy and relocatable linking,
and it's handy to have the signature available as the section
name. */
- if (hdr->sh_entsize != GRP_ENTRY_SIZE)
+ if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
return FALSE;
name = group_signature (abfd, hdr);
if (name == NULL)
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
- unsigned int n_elt = hdr->sh_size / 4;
+ unsigned int n_elt = hdr->sh_size / GRP_ENTRY_SIZE;
asection *s;
if (idx->flags & GRP_COMDAT)
/* We try to keep the same section order as it comes in. */
idx += n_elt;
while (--n_elt != 0)
- if ((s = (--idx)->shdr->bfd_section) != NULL
- && elf_next_in_group (s) != NULL)
- {
- elf_next_in_group (hdr->bfd_section) = s;
- break;
- }
+ {
+ --idx;
+
+ if (idx->shdr != NULL
+ && (s = idx->shdr->bfd_section) != NULL
+ && elf_next_in_group (s) != NULL)
+ {
+ elf_next_in_group (hdr->bfd_section) = s;
+ break;
+ }
+ }
}
break;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean *failedptr = failedptrarg;
Elf_Internal_Shdr *this_hdr;
+ unsigned int sh_type;
if (*failedptr)
{
break;
case SHT_GROUP:
- this_hdr->sh_entsize = 4;
+ this_hdr->sh_entsize = GRP_ENTRY_SIZE;
break;
case SHT_GNU_HASH:
}
/* Check for processor-specific section types. */
+ sh_type = this_hdr->sh_type;
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
*failedptr = TRUE;
+ if (sh_type == SHT_NOBITS && asect->size != 0)
+ {
+ /* Don't change the header type from NOBITS if we are being
+ called for objcopy --only-keep-debug. */
+ this_hdr->sh_type = sh_type;
+ }
+
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
this section, it is up to the processor-specific back-end to
struct elf_segment_map *m;
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
- file_ptr off, voff;
+ file_ptr off;
bfd_size_type maxpagesize;
unsigned int alloc;
- unsigned int i;
+ unsigned int i, j;
if (link_info == NULL
&& !elf_modify_segment_map (abfd, link_info))
off = bed->s->sizeof_ehdr;
off += alloc * bed->s->sizeof_phdr;
- for (m = elf_tdata (abfd)->segment_map, p = phdrs;
+ for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
m != NULL;
- m = m->next, p++)
+ m = m->next, p++, j++)
{
asection **secpp;
number of sections with contents contributing to both p_filesz
and p_memsz, followed by a number of sections with no contents
that just contribute to p_memsz. In this loop, OFF tracks next
- available file offset for PT_LOAD and PT_NOTE segments. VOFF is
- an adjustment we use for segments that have no file contents
- but need zero filled memory allocation. */
- voff = 0;
+ available file offset for PT_LOAD and PT_NOTE segments. */
p->p_type = m->p_type;
p->p_flags = m->p_flags;
align = maxpagesize;
}
+ for (i = 0; i < m->count; i++)
+ if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ /* If we aren't making room for this section, then
+ it must be SHT_NOBITS regardless of what we've
+ set via struct bfd_elf_special_section. */
+ elf_section_type (m->sections[i]) = SHT_NOBITS;
+
adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
- off += adjust;
- if (adjust != 0
- && !m->includes_filehdr
- && !m->includes_phdrs
- && (ufile_ptr) off >= align)
+ if (adjust != 0)
{
- /* If the first section isn't loadable, the same holds for
- any other sections. Since the segment won't need file
- space, we can make p_offset overlap some prior segment.
- However, .tbss is special. If a segment starts with
- .tbss, we need to look at the next section to decide
- whether the segment has any loadable sections. */
+ /* If the first section isn't loadable, the same holds
+ for any other sections. We don't need to align the
+ segment on disk since the segment doesn't need file
+ space. */
i = 0;
- while ((m->sections[i]->flags & SEC_LOAD) == 0
- && (m->sections[i]->flags & SEC_HAS_CONTENTS) == 0)
+ while (elf_section_type (m->sections[i]) == SHT_NOBITS)
{
- if ((m->sections[i]->flags & SEC_THREAD_LOCAL) == 0
+ /* If a segment starts with .tbss, we need to look
+ at the next section to decide whether the segment
+ has any loadable sections. */
+ if ((elf_section_flags (m->sections[i]) & SHF_TLS) == 0
|| ++i >= m->count)
{
- off -= adjust;
- voff = adjust - align;
+ adjust = 0;
break;
}
}
+ off += adjust;
}
}
/* Make sure the .dynamic section is the first section in the
|| (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
{
if (! m->includes_filehdr && ! m->includes_phdrs)
- p->p_offset = off + voff;
+ p->p_offset = off;
else
{
file_ptr adjust;
for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
{
asection *sec;
- flagword flags;
bfd_size_type align;
+ Elf_Internal_Shdr *this_hdr;
sec = *secpp;
- flags = sec->flags;
+ this_hdr = &elf_section_data (sec)->this_hdr;
align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
if (p->p_type == PT_LOAD
|| p->p_type == PT_TLS)
{
- bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_filesz);
+ bfd_signed_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
- if ((flags & SEC_LOAD) != 0
- || ((flags & SEC_ALLOC) != 0
- && ((flags & SEC_THREAD_LOCAL) == 0
+ if (this_hdr->sh_type != SHT_NOBITS
+ || ((this_hdr->sh_flags & SHF_ALLOC) != 0
+ && ((this_hdr->sh_flags & SHF_TLS) == 0
|| p->p_type == PT_TLS)))
{
if (adjust < 0)
}
p->p_memsz += adjust;
- if ((flags & SEC_LOAD) != 0)
+ if (this_hdr->sh_type != SHT_NOBITS)
{
off += adjust;
p->p_filesz += adjust;
everything. */
if (i == 0)
{
- sec->filepos = off;
+ this_hdr->sh_offset = sec->filepos = off;
off += sec->size;
p->p_filesz = sec->size;
p->p_memsz = 0;
{
if (p->p_type == PT_LOAD)
{
- sec->filepos = off + voff;
- /* FIXME: The SEC_HAS_CONTENTS test here dates back to
- 1997, and the exact reason for it isn't clear. One
- plausible explanation is that it is to work around
- a problem we have with linker scripts using data
- statements in NOLOAD sections. I don't think it
- makes a great deal of sense to have such a section
- assigned to a PT_LOAD segment, but apparently
- people do this. The data statement results in a
- bfd_data_link_order being built, and these need
- section contents to write into. Eventually, we get
- to _bfd_elf_write_object_contents which writes any
- section with contents to the output. Make room
- here for the write, so that following segments are
- not trashed. */
- if ((flags & SEC_LOAD) != 0
- || (flags & SEC_HAS_CONTENTS) != 0)
+ this_hdr->sh_offset = sec->filepos = off;
+ if (this_hdr->sh_type != SHT_NOBITS)
off += sec->size;
}
- if ((flags & SEC_LOAD) != 0)
+ if (this_hdr->sh_type != SHT_NOBITS)
{
p->p_filesz += sec->size;
- p->p_memsz += sec->size;
+ /* A load section without SHF_ALLOC is something like
+ a note section in a PT_NOTE segment. These take
+ file space but are not loaded into memory. */
+ if ((this_hdr->sh_flags & SHF_ALLOC) != 0)
+ p->p_memsz += sec->size;
}
/* .tbss is special. It doesn't contribute to p_memsz of
normal segments. */
- else if ((flags & SEC_ALLOC) != 0
- && ((flags & SEC_THREAD_LOCAL) == 0
+ else if ((this_hdr->sh_flags & SHF_ALLOC) != 0
+ && ((this_hdr->sh_flags & SHF_TLS) == 0
|| p->p_type == PT_TLS))
p->p_memsz += sec->size;
if (! m->p_flags_valid)
{
p->p_flags |= PF_R;
- if ((flags & SEC_CODE) != 0)
+ if ((this_hdr->sh_flags & SHF_EXECINSTR) != 0)
p->p_flags |= PF_X;
- if ((flags & SEC_READONLY) == 0)
+ if ((this_hdr->sh_flags & SHF_WRITE) != 0)
p->p_flags |= PF_W;
}
}
+
+ /* Check that all sections are in a PT_LOAD segment.
+ Don't check funky gdb generated core files. */
+ if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core)
+ for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
+ {
+ Elf_Internal_Shdr *this_hdr;
+ asection *sec;
+
+ sec = *secpp;
+ this_hdr = &(elf_section_data(sec)->this_hdr);
+ if (this_hdr->sh_size != 0
+ && !ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, p))
+ {
+ (*_bfd_error_handler)
+ (_("%B: section `%A' can't be allocated in segment %d"),
+ abfd, sec, j);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ }
}
elf_tdata (abfd)->next_file_pos = off;
&& (hdr->bfd_section->filepos != 0
|| (hdr->sh_type == SHT_NOBITS
&& hdr->contents == NULL)))
- hdr->sh_offset = hdr->bfd_section->filepos;
+ BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
if (hdr->sh_size != 0)
output BFD section flags have been set to something different.
elf_fake_sections will set ELF section type based on BFD
section flags. */
- if (osec->flags == isec->flags || !osec->flags)
- {
- BFD_ASSERT (osec->flags == isec->flags
- || (!osec->flags
- && elf_section_type (osec) == SHT_NULL));
- elf_section_type (osec) = elf_section_type (isec);
- }
+ if (elf_section_type (osec) == SHT_NULL
+ && (osec->flags == isec->flags || !osec->flags))
+ elf_section_type (osec) = elf_section_type (isec);
/* FIXME: Is this correct for all OS/PROC specific flags? */
elf_section_flags (osec) |= (elf_section_flags (isec)
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
}
+
+
+/* Return TRUE for ELF symbol types that represent functions.
+ This is the default version of this function, which is sufficient for
+ most targets. It returns true if TYPE is STT_FUNC. */
+
+bfd_boolean
+_bfd_elf_is_function_type (unsigned int type)
+{
+ return (type == STT_FUNC);
+}