/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
bfd_boolean
-bfd_elf_make_generic_object (bfd *abfd)
+bfd_elf_make_object (bfd *abfd)
{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
return bfd_elf_allocate_object (abfd, sizeof (struct elf_obj_tdata),
- GENERIC_ELF_DATA);
+ bed->target_id);
}
bfd_boolean
bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
- return bfd_elf_make_generic_object (abfd);
+ return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd);
}
static char *
const struct elf_backend_data *bed;
if (hdr->bfd_section != NULL)
- {
- BFD_ASSERT (strcmp (name,
- bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
- return TRUE;
- }
+ return TRUE;
newsect = bfd_make_section_anyway (abfd, name);
if (newsect == NULL)
}
}
+ /* Compress/decompress DWARF debug sections with names: .debug_* and
+ .zdebug_*, after the section flags is set. */
+ if ((flags & SEC_DEBUGGING)
+ && ((name[1] == 'd' && name[6] == '_')
+ || (name[1] == 'z' && name[7] == '_')))
+ {
+ enum { nothing, compress, decompress } action = nothing;
+ char *new_name;
+
+ if (bfd_is_section_compressed (abfd, newsect))
+ {
+ /* Compressed section. Check if we should decompress. */
+ if ((abfd->flags & BFD_DECOMPRESS))
+ action = decompress;
+ }
+ else
+ {
+ /* Normal section. Check if we should compress. */
+ if ((abfd->flags & BFD_COMPRESS))
+ action = compress;
+ }
+
+ new_name = NULL;
+ switch (action)
+ {
+ case nothing:
+ break;
+ case compress:
+ if (!bfd_init_section_compress_status (abfd, newsect))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize commpress status for section %s"),
+ 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:
+ if (!bfd_init_section_decompress_status (abfd, newsect))
+ {
+ (*_bfd_error_handler)
+ (_("%B: unable to initialize decommpress status for section %s"),
+ abfd, name);
+ return FALSE;
+ }
+ if (name[1] == 'z')
+ {
+ unsigned int len = strlen (name);
+
+ new_name = bfd_alloc (abfd, len);
+ if (new_name == NULL)
+ return FALSE;
+ new_name[0] = '.';
+ memcpy (new_name + 1, name + 2, len - 1);
+ }
+ break;
+ }
+ if (new_name != NULL)
+ bfd_rename_section (abfd, newsect, new_name);
+ }
+
return TRUE;
}
/* *These* do a lot of work -- but build no sections! */
{
asection *target_sect;
- Elf_Internal_Shdr *hdr2;
+ Elf_Internal_Shdr *hdr2, **p_hdr;
unsigned int num_sec = elf_numsections (abfd);
+ struct bfd_elf_section_data *esdt;
+ bfd_size_type amt;
if (hdr->sh_entsize
!= (bfd_size_type) (hdr->sh_type == SHT_REL
if (target_sect == NULL)
return FALSE;
- if ((target_sect->flags & SEC_RELOC) == 0
- || target_sect->reloc_count == 0)
- hdr2 = &elf_section_data (target_sect)->rel_hdr;
+ esdt = elf_section_data (target_sect);
+ if (hdr->sh_type == SHT_RELA)
+ p_hdr = &esdt->rela.hdr;
else
- {
- bfd_size_type amt;
- BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
- amt = sizeof (*hdr2);
- hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
- if (hdr2 == NULL)
- return FALSE;
- elf_section_data (target_sect)->rel_hdr2 = hdr2;
- }
+ p_hdr = &esdt->rel.hdr;
+
+ BFD_ASSERT (*p_hdr == NULL);
+ amt = sizeof (*hdr2);
+ hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+ if (hdr2 == NULL)
+ return FALSE;
*hdr2 = *hdr;
+ *p_hdr = hdr2;
elf_elfsections (abfd)[shindex] = hdr2;
target_sect->reloc_count += NUM_SHDR_ENTRIES (hdr);
target_sect->flags |= SEC_RELOC;
/* In the section to which the relocations apply, mark whether
its relocations are of the REL or RELA variety. */
if (hdr->sh_size != 0)
- target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
+ {
+ if (hdr->sh_type == SHT_RELA)
+ target_sect->use_rela_p = 1;
+ }
abfd->flags |= HAS_RELOC;
return TRUE;
}
static const struct bfd_elf_special_section special_sections_g[] =
{
{ STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".gnu.lto_"), -1, SHT_PROGBITS, SHF_EXCLUDE },
{ STRING_COMMA_LEN (".got"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
{ STRING_COMMA_LEN (".gnu.version"), 0, SHT_GNU_versym, 0 },
{ STRING_COMMA_LEN (".gnu.version_d"), 0, SHT_GNU_verdef, 0 },
anyway. We will set ELF section type and flags for all linker
created sections. If user specifies BFD section flags, we will
set ELF section type and flags based on BFD section flags in
- elf_fake_sections. */
- if ((!sec->flags && abfd->direction != read_direction)
+ elf_fake_sections. Special handling for .init_array/.fini_array
+ output sections since they may contain .ctors/.dtors input
+ sections. We don't want _bfd_elf_init_private_section_data to
+ copy ELF section type from .ctors/.dtors input sections. */
+ if (abfd->direction != read_direction
|| (sec->flags & SEC_LINKER_CREATED) != 0)
{
ssect = (*bed->get_sec_type_attr) (abfd, sec);
- if (ssect != NULL)
+ if (ssect != NULL
+ && (!sec->flags
+ || (sec->flags & SEC_LINKER_CREATED) != 0
+ || ssect->type == SHT_INIT_ARRAY
+ || ssect->type == SHT_FINI_ARRAY))
{
elf_section_type (sec) = ssect->type;
elf_section_flags (sec) = ssect->attr;
}
}
-/* Initialize REL_HDR, the section-header for new section, containing
- relocations against ASECT. If USE_RELA_P is TRUE, we use RELA
- relocations; otherwise, we use REL relocations. */
+/* Return the REL_HDR for SEC, assuming there is only a single one, either
+ REL or RELA. */
+
+Elf_Internal_Shdr *
+_bfd_elf_single_rel_hdr (asection *sec)
+{
+ if (elf_section_data (sec)->rel.hdr)
+ {
+ BFD_ASSERT (elf_section_data (sec)->rela.hdr == NULL);
+ return elf_section_data (sec)->rel.hdr;
+ }
+ else
+ return elf_section_data (sec)->rela.hdr;
+}
+
+/* Allocate and initialize a section-header for a new reloc section,
+ containing relocations against ASECT. It is stored in RELDATA. If
+ USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL
+ relocations. */
bfd_boolean
_bfd_elf_init_reloc_shdr (bfd *abfd,
- Elf_Internal_Shdr *rel_hdr,
+ struct bfd_elf_section_reloc_data *reldata,
asection *asect,
bfd_boolean use_rela_p)
{
+ Elf_Internal_Shdr *rel_hdr;
char *name;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
+ bfd_size_type amt;
+
+ amt = sizeof (Elf_Internal_Shdr);
+ BFD_ASSERT (reldata->hdr == NULL);
+ rel_hdr = bfd_zalloc (abfd, amt);
+ reldata->hdr = rel_hdr;
+ amt = sizeof ".rela" + strlen (asect->name);
name = (char *) bfd_alloc (abfd, amt);
if (name == NULL)
return FALSE;
bfd_elf_get_default_section_type (flagword flags)
{
if ((flags & SEC_ALLOC) != 0
- && ((flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0
- || (flags & SEC_NEVER_LOAD) != 0))
+ && (flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
return SHT_NOBITS;
return SHT_PROGBITS;
}
+struct fake_section_arg
+{
+ struct bfd_link_info *link_info;
+ bfd_boolean failed;
+};
+
/* Set up an ELF internal section header for a section. */
static void
-elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
+elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
{
+ struct fake_section_arg *arg = (struct fake_section_arg *)fsarg;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
+ struct bfd_elf_section_data *esd = elf_section_data (asect);
Elf_Internal_Shdr *this_hdr;
unsigned int sh_type;
- if (*failedptr)
+ if (arg->failed)
{
/* We already failed; just get out of the bfd_map_over_sections
loop. */
return;
}
- this_hdr = &elf_section_data (asect)->this_hdr;
+ this_hdr = &esd->this_hdr;
this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
asect->name, FALSE);
if (this_hdr->sh_name == (unsigned int) -1)
{
- *failedptr = TRUE;
+ arg->failed = TRUE;
return;
}
if ((asect->flags & (SEC_GROUP | SEC_EXCLUDE)) == SEC_EXCLUDE)
this_hdr->sh_flags |= SHF_EXCLUDE;
+ /* 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
+ create the other. */
+ if ((asect->flags & SEC_RELOC) != 0)
+ {
+ /* When doing a relocatable link, create both REL and RELA sections if
+ needed. */
+ 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))
+ {
+ if (esd->rel.count && esd->rel.hdr == NULL
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE))
+ {
+ arg->failed = TRUE;
+ return;
+ }
+ if (esd->rela.count && esd->rela.hdr == NULL
+ && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE))
+ {
+ arg->failed = TRUE;
+ return;
+ }
+ }
+ else if (!_bfd_elf_init_reloc_shdr (abfd,
+ (asect->use_rela_p
+ ? &esd->rela : &esd->rel),
+ asect,
+ asect->use_rela_p))
+ arg->failed = TRUE;
+ }
+
/* 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;
+ arg->failed = TRUE;
if (sh_type == SHT_NOBITS && asect->size != 0)
{
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
- create the other. */
- if ((asect->flags & SEC_RELOC) != 0
- && !_bfd_elf_init_reloc_shdr (abfd,
- &elf_section_data (asect)->rel_hdr,
- asect,
- asect->use_rela_p))
- *failedptr = TRUE;
}
/* Fill in the contents of a SHT_GROUP section. Called from
if (d->this_hdr.sh_type != SHT_GROUP)
d->this_idx = section_number++;
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
- if ((sec->flags & SEC_RELOC) == 0)
- d->rel_idx = 0;
- else
+ if (d->rel.hdr)
{
- d->rel_idx = section_number++;
- _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr.sh_name);
+ d->rel.idx = section_number++;
+ _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name);
}
+ else
+ d->rel.idx = 0;
- if (d->rel_hdr2)
+ if (d->rela.hdr)
{
- d->rel_idx2 = section_number++;
- _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel_hdr2->sh_name);
+ d->rela.idx = section_number++;
+ _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name);
}
else
- d->rel_idx2 = 0;
+ d->rela.idx = 0;
}
t->shstrtab_section = section_number++;
d = elf_section_data (sec);
i_shdrp[d->this_idx] = &d->this_hdr;
- if (d->rel_idx != 0)
- i_shdrp[d->rel_idx] = &d->rel_hdr;
- if (d->rel_idx2 != 0)
- i_shdrp[d->rel_idx2] = d->rel_hdr2;
+ if (d->rel.idx != 0)
+ i_shdrp[d->rel.idx] = d->rel.hdr;
+ if (d->rela.idx != 0)
+ i_shdrp[d->rela.idx] = d->rela.hdr;
/* Fill in the sh_link and sh_info fields while we're at it. */
/* sh_link of a reloc section is the section index of the symbol
table. sh_info is the section index of the section to which
the relocation entries apply. */
- if (d->rel_idx != 0)
+ if (d->rel.idx != 0)
{
- d->rel_hdr.sh_link = t->symtab_section;
- d->rel_hdr.sh_info = d->this_idx;
+ d->rel.hdr->sh_link = t->symtab_section;
+ d->rel.hdr->sh_info = d->this_idx;
}
- if (d->rel_idx2 != 0)
+ if (d->rela.idx != 0)
{
- d->rel_hdr2->sh_link = t->symtab_section;
- d->rel_hdr2->sh_info = d->this_idx;
+ d->rela.hdr->sh_link = t->symtab_section;
+ d->rela.hdr->sh_info = d->this_idx;
}
/* We need to set up sh_link for SHF_LINK_ORDER. */
struct bfd_link_info *link_info)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct fake_section_arg fsargs;
bfd_boolean failed;
struct bfd_strtab_hash *strtab = NULL;
Elf_Internal_Shdr *shstrtab_hdr;
if (bed->elf_backend_post_process_headers)
(*bed->elf_backend_post_process_headers) (abfd, link_info);
- failed = FALSE;
- bfd_map_over_sections (abfd, elf_fake_sections, &failed);
- if (failed)
+ fsargs.failed = FALSE;
+ fsargs.link_info = link_info;
+ bfd_map_over_sections (abfd, elf_fake_sections, &fsargs);
+ if (fsargs.failed)
return FALSE;
if (!assign_section_numbers (abfd, link_info))
return FALSE;
}
+ failed = FALSE;
if (link_info == NULL)
{
bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
(unsigned int) m->p_type);
pt = buf;
}
+ fflush (stdout);
fprintf (stderr, "%s:", pt);
for (j = 0; j < m->count; j++)
fprintf (stderr, " %s", m->sections [j]->name);
putc ('\n',stderr);
+ fflush (stderr);
}
static bfd_boolean
header_pad = m->header_size;
}
- elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
- elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+ if (alloc)
+ {
+ elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
+ elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+ }
+ else
+ {
+ /* PR binutils/12467. */
+ elf_elfheader (abfd)->e_phoff = 0;
+ elf_elfheader (abfd)->e_phentsize = 0;
+ }
+
elf_elfheader (abfd)->e_phnum = alloc;
if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
bfd_vma s_start = sec->lma;
bfd_vma adjust = s_start - p_end;
- if (s_start < p_end
- || p_end < p_start)
+ if (adjust != 0
+ && (s_start < p_end
+ || p_end < p_start))
{
(*_bfd_error_handler)
(_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
#if DEBUG & 4
{
fprintf (stderr,
- "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n",
- (long) asym_ptr, asym_ptr->name, idx, flags,
- elf_symbol_flags (flags));
+ "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx\n",
+ (long) asym_ptr, asym_ptr->name, idx, (long) flags);
fflush (stderr);
}
#endif
bfd_size_type amt;
Elf_Internal_Shdr *this_hdr;
asection *first_section = NULL;
- asection *lowest_section = NULL;
+ asection *lowest_section;
/* Compute how many sections are in this segment. */
for (section = ibfd->sections, section_count = 0;
this_hdr = &(elf_section_data(section)->this_hdr);
if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
- if (!first_section)
- first_section = lowest_section = section;
- if (section->lma < lowest_section->lma)
- lowest_section = section;
+ if (first_section == NULL)
+ first_section = section;
section_count++;
}
}
phdr_included = TRUE;
}
- if (map->includes_filehdr && first_section)
- /* We need to keep the space used by the headers fixed. */
- map->header_size = first_section->vma - segment->p_vaddr;
-
- if (!map->includes_phdrs
- && !map->includes_filehdr
- && map->p_paddr_valid)
- /* There is some other padding before the first section. */
- map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
- - segment->p_paddr);
-
+ lowest_section = first_section;
if (section_count != 0)
{
unsigned int isec = 0;
if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
map->sections[isec++] = section->output_section;
+ if (section->lma < lowest_section->lma)
+ lowest_section = section;
+ if ((section->flags & SEC_ALLOC) != 0)
+ {
+ bfd_vma seg_off;
+
+ /* Section lmas are set up from PT_LOAD header
+ p_paddr in _bfd_elf_make_section_from_shdr.
+ If this header has a p_paddr that disagrees
+ with the section lma, flag the p_paddr as
+ invalid. */
+ if ((section->flags & SEC_LOAD) != 0)
+ seg_off = this_hdr->sh_offset - segment->p_offset;
+ else
+ seg_off = this_hdr->sh_addr - segment->p_vaddr;
+ if (section->lma - segment->p_paddr != seg_off)
+ map->p_paddr_valid = FALSE;
+ }
if (isec == section_count)
break;
}
}
}
+ if (map->includes_filehdr && lowest_section != NULL)
+ /* We need to keep the space used by the headers fixed. */
+ map->header_size = lowest_section->vma - segment->p_vaddr;
+
+ if (!map->includes_phdrs
+ && !map->includes_filehdr
+ && map->p_paddr_valid)
+ /* There is some other padding before the first section. */
+ map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
+ - segment->p_paddr);
+
map->count = section_count;
*pointer_to_map = map;
pointer_to_map = &map->next;
&& (osec->flags == isec->flags
|| (final_link
&& ((osec->flags ^ isec->flags)
- & ~ (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)) == 0)))
+ & ~(SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_RELOC)) == 0)))
elf_section_type (osec) = elf_section_type (isec);
/* FIXME: Is this correct for all OS/PROC specific flags? */