/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "libiberty.h"
#include "safe-ctype.h"
+#ifdef CORE_HEADER
+#include CORE_HEADER
+#endif
+
static int elf_sort_sections (const void *, const void *);
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
static bfd_boolean prep_headers (bfd *);
bfd_boolean
bfd_elf_allocate_object (bfd *abfd,
size_t object_size,
- enum elf_object_id object_id)
+ enum elf_target_id object_id)
{
BFD_ASSERT (object_size >= sizeof (struct elf_obj_tdata));
abfd->tdata.any = bfd_zalloc (abfd, object_size);
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_TDATA);
+ 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 *
/* 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_alloc (abfd, shstrtabsize + 1)) == NULL
+ || (shstrtab = (bfd_byte *) bfd_alloc (abfd, shstrtabsize + 1)) == NULL
|| bfd_seek (abfd, offset, SEEK_SET) != 0)
shstrtab = NULL;
else if (bfd_bread (shstrtab, shstrtabsize, abfd) != shstrtabsize)
(shindex == shstrndx && strindex == hdr->sh_name
? ".shstrtab"
: bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
- return "";
+ return NULL;
}
return ((char *) hdr->contents) + strindex;
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
if (extshndx_buf == NULL)
{
- alloc_extshndx = bfd_malloc2 (symcount,
- sizeof (Elf_External_Sym_Shndx));
+ alloc_extshndx = (Elf_External_Sym_Shndx *)
+ bfd_malloc2 (symcount, sizeof (Elf_External_Sym_Shndx));
extshndx_buf = alloc_extshndx;
}
if (extshndx_buf == NULL
if (intsym_buf == NULL)
{
- alloc_intsym = bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
+ alloc_intsym = (Elf_Internal_Sym *)
+ bfd_malloc2 (symcount, sizeof (Elf_Internal_Sym));
intsym_buf = alloc_intsym;
if (intsym_buf == NULL)
goto out;
/* Convert the symbols to internal form. */
isymend = intsym_buf + symcount;
- for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
+ for (esym = (const bfd_byte *) extsym_buf, isym = intsym_buf,
+ shndx = extshndx_buf;
isym < isymend;
esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
if (!(*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym))
bfd_size_type amt;
elf_tdata (abfd)->num_group = num_group;
- elf_tdata (abfd)->group_sect_ptr
- = bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
+ elf_tdata (abfd)->group_sect_ptr = (Elf_Internal_Shdr **)
+ bfd_alloc2 (abfd, num_group, sizeof (Elf_Internal_Shdr *));
if (elf_tdata (abfd)->group_sect_ptr == NULL)
return FALSE;
/* Read the raw contents. */
BFD_ASSERT (sizeof (*dest) >= 4);
amt = shdr->sh_size * sizeof (*dest) / 4;
- shdr->contents = bfd_alloc2 (abfd, shdr->sh_size,
- sizeof (*dest) / 4);
+ shdr->contents = (unsigned char *)
+ bfd_alloc2 (abfd, shdr->sh_size, sizeof (*dest) / 4);
/* PR binutils/4110: Handle corrupt group headers. */
if (shdr->contents == NULL)
{
}
else
{
- asection *link = NULL;
+ asection *linksec = NULL;
if (elfsec < elf_numsections (abfd))
{
this_hdr = elf_elfsections (abfd)[elfsec];
- link = this_hdr->bfd_section;
+ linksec = this_hdr->bfd_section;
}
/* PR 1991, 2008:
Some strip/objcopy may leave an incorrect value in
sh_link. We don't want to proceed. */
- if (link == NULL)
+ if (linksec == NULL)
{
(*_bfd_error_handler)
(_("%B: sh_link [%d] in section `%A' is incorrect"),
result = FALSE;
}
- elf_linked_to_section (s) = link;
+ elf_linked_to_section (s) = linksec;
}
}
}
return FALSE;
if ((hdr->sh_flags & SHF_TLS) != 0)
flags |= SEC_THREAD_LOCAL;
+ if ((hdr->sh_flags & SHF_EXCLUDE) != 0)
+ flags |= SEC_EXCLUDE;
if ((flags & SEC_ALLOC) == 0)
{
phdr = elf_tdata (abfd)->phdr;
for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
{
- /* This section is part of this segment if its file
- offset plus size lies within the segment's memory
- span and, if the section is loaded, the extent of the
- loaded data lies within the extent of the segment.
-
- Note - we used to check the p_paddr field as well, and
- refuse to set the LMA if it was 0. This is wrong
- though, as a perfectly valid initialised segment can
- have a p_paddr of zero. Some architectures, eg ARM,
- place special significance on the address 0 and
- executables need to be able to have a segment which
- covers this address. */
if (phdr->p_type == PT_LOAD
- && (bfd_vma) hdr->sh_offset >= phdr->p_offset
- && (hdr->sh_offset + hdr->sh_size
- <= phdr->p_offset + phdr->p_memsz)
- && ((flags & SEC_LOAD) == 0
- || (hdr->sh_offset + hdr->sh_size
- <= phdr->p_offset + phdr->p_filesz)))
+ && ELF_SECTION_IN_SEGMENT (hdr, phdr))
{
if ((flags & SEC_LOAD) == 0)
newsect->lma = (phdr->p_paddr
/* Copy object attributes. */
_bfd_elf_copy_obj_attributes (ibfd, obfd);
-
return TRUE;
}
bfd_boolean
_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
{
- FILE *f = farg;
+ FILE *f = (FILE *) farg;
Elf_Internal_Phdr *p;
asection *s;
bfd_byte *dynbuf = NULL;
asymbol *symbol,
bfd_print_symbol_type how)
{
- FILE *file = filep;
+ FILE *file = (FILE *) filep;
switch (how)
{
case bfd_print_symbol_name:
case SHT_DYNAMIC: /* Dynamic linking information. */
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
- if (hdr->sh_link > elf_numsections (abfd)
- || elf_elfsections (abfd)[hdr->sh_link] == NULL)
+ if (hdr->sh_link > elf_numsections (abfd))
+ {
+ /* PR 10478: Accept Solaris binaries with a sh_link
+ field set to SHN_BEFORE or SHN_AFTER. */
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_i386:
+ case bfd_arch_sparc:
+ if (hdr->sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
+ || hdr->sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
+ break;
+ /* Otherwise fall through. */
+ default:
+ return FALSE;
+ }
+ }
+ else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
return FALSE;
- if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
+ else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
{
Elf_Internal_Shdr *dynsymhdr;
/* *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 = 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;
}
section. */
asection *
-bfd_section_from_elf_index (bfd *abfd, unsigned int index)
+bfd_section_from_elf_index (bfd *abfd, unsigned int sec_index)
{
- if (index >= elf_numsections (abfd))
+ if (sec_index >= elf_numsections (abfd))
return NULL;
- return elf_elfsections (abfd)[index]->bfd_section;
+ return elf_elfsections (abfd)[sec_index]->bfd_section;
}
static const struct bfd_elf_special_section special_sections_b[] =
sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
if (sdata == NULL)
{
- sdata = bfd_zalloc (abfd, sizeof (*sdata));
+ sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd,
+ sizeof (*sdata));
if (sdata == NULL)
return FALSE;
sec->used_by_bfd = sdata;
bfd_boolean
_bfd_elf_make_section_from_phdr (bfd *abfd,
Elf_Internal_Phdr *hdr,
- int index,
- const char *typename)
+ int hdr_index,
+ const char *type_name)
{
asection *newsect;
char *name;
if (hdr->p_filesz > 0)
{
- sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
+ sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "a" : "");
len = strlen (namebuf) + 1;
- name = bfd_alloc (abfd, len);
+ name = (char *) bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
{
bfd_vma align;
- sprintf (namebuf, "%s%d%s", typename, index, split ? "b" : "");
+ sprintf (namebuf, "%s%d%s", type_name, hdr_index, split ? "b" : "");
len = strlen (namebuf) + 1;
- name = bfd_alloc (abfd, len);
+ name = (char *) bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
}
bfd_boolean
-bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
+bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int hdr_index)
{
const struct elf_backend_data *bed;
switch (hdr->p_type)
{
case PT_NULL:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "null");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "null");
case PT_LOAD:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "load");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "load");
case PT_DYNAMIC:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "dynamic");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "dynamic");
case PT_INTERP:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "interp");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "interp");
case PT_NOTE:
- if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
+ if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note"))
return FALSE;
if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
return FALSE;
return TRUE;
case PT_SHLIB:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "shlib");
case PT_PHDR:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "phdr");
case PT_GNU_EH_FRAME:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index,
"eh_frame_hdr");
case PT_GNU_STACK:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "stack");
case PT_GNU_RELRO:
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "relro");
default:
/* Check for any processor-specific program segment types. */
bed = get_elf_backend_data (abfd);
- return bed->elf_backend_section_from_phdr (abfd, hdr, index, "proc");
+ return bed->elf_backend_section_from_phdr (abfd, hdr, hdr_index, "proc");
}
}
-/* 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;
- name = bfd_alloc (abfd, amt);
+ amt = sizeof ".rela" + strlen (asect->name);
+ name = (char *) bfd_alloc (abfd, amt);
if (name == NULL)
return FALSE;
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
return TRUE;
}
+/* Return the default section type based on the passed in section flags. */
+
+int
+bfd_elf_get_default_section_type (flagword flags)
+{
+ if ((flags & SEC_ALLOC) != 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 = 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;
}
asect->flags. */
if ((asect->flags & SEC_GROUP) != 0)
sh_type = SHT_GROUP;
- else if ((asect->flags & SEC_ALLOC) != 0
- && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
- || (asect->flags & SEC_NEVER_LOAD) != 0))
- sh_type = SHT_NOBITS;
else
- sh_type = SHT_PROGBITS;
+ sh_type = bfd_elf_get_default_section_type (asect->flags);
if (this_hdr->sh_type == SHT_NULL)
this_hdr->sh_type = sh_type;
}
}
}
+ 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
void
bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
{
- bfd_boolean *failedptr = failedptrarg;
+ bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
asection *elt, *first;
unsigned char *loc;
bfd_boolean gas;
if (sec->contents == NULL)
{
gas = FALSE;
- sec->contents = bfd_alloc (abfd, sec->size);
+ sec->contents = (unsigned char *) bfd_alloc (abfd, sec->size);
/* Arrange for the section to be written out. */
elf_section_data (sec)->this_hdr.contents = sec->contents;
while (elt != NULL)
{
asection *s;
- unsigned int idx;
s = elt;
- if (! elf_discarded_section (s))
+ if (!gas)
+ s = s->output_section;
+ if (s != NULL
+ && !bfd_is_abs_section (s))
{
+ unsigned int idx = elf_section_data (s)->this_idx;
+
loc -= 4;
- if (!gas)
- s = s->output_section;
- idx = 0;
- if (s != NULL)
- idx = elf_section_data (s)->this_idx;
H_PUT_32 (abfd, idx, loc);
}
elt = elf_next_in_group (elt);
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++;
/* Set up the list of section header pointers, in agreement with the
indices. */
- i_shdrp = bfd_zalloc2 (abfd, section_number, sizeof (Elf_Internal_Shdr *));
+ i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc2 (abfd, section_number,
+ sizeof (Elf_Internal_Shdr *));
if (i_shdrp == NULL)
return FALSE;
- i_shdrp[0] = bfd_zalloc (abfd, sizeof (Elf_Internal_Shdr));
+ i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd,
+ sizeof (Elf_Internal_Shdr));
if (i_shdrp[0] == NULL)
{
bfd_release (abfd, i_shdrp);
for (sec = abfd->sections; sec; sec = sec->next)
{
- struct bfd_elf_section_data *d = elf_section_data (sec);
asection *s;
const char *name;
+ 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. */
char *alc;
len = strlen (sec->name);
- alc = bfd_malloc (len - 2);
+ alc = (char *) bfd_malloc (len - 2);
if (alc == NULL)
return FALSE;
memcpy (alc, sec->name, len - 3);
if (bed->elf_backend_sym_is_global)
return (*bed->elf_backend_sym_is_global) (abfd, sym);
- return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ return ((sym->flags & (BSF_GLOBAL | BSF_WEAK | BSF_GNU_UNIQUE)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
|| bfd_is_com_section (bfd_get_section (sym)));
}
}
max_index++;
- sect_syms = bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
+ sect_syms = (asymbol **) bfd_zalloc2 (abfd, max_index, sizeof (asymbol *));
if (sect_syms == NULL)
return FALSE;
elf_section_syms (abfd) = sect_syms;
}
/* Now sort the symbols so the local symbols are first. */
- new_syms = bfd_alloc2 (abfd, num_locals + num_globals, sizeof (asymbol *));
+ new_syms = (asymbol **) bfd_alloc2 (abfd, num_locals + num_globals,
+ sizeof (asymbol *));
if (new_syms == NULL)
return FALSE;
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);
amt = sizeof (struct elf_segment_map);
amt += (to - from - 1) * sizeof (asection *);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
return NULL;
m->next = NULL;
{
struct elf_segment_map *m;
- m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+ m = (struct elf_segment_map *) bfd_zalloc (abfd,
+ sizeof (struct elf_segment_map));
if (m == NULL)
return NULL;
m->next = NULL;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
+ bfd_vma addr_mask, wrap_to = 0;
/* Select the allocated sections, and sort them. */
- sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
+ sections = (asection **) bfd_malloc2 (bfd_count_sections (abfd),
+ sizeof (asection *));
if (sections == NULL)
goto error_return;
+ /* Calculate top address, avoiding undefined behaviour of shift
+ left operator when shift count is equal to size of type
+ being shifted. */
+ addr_mask = ((bfd_vma) 1 << (bfd_arch_bits_per_address (abfd) - 1)) - 1;
+ addr_mask = (addr_mask << 1) + 1;
+
i = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
{
sections[i] = s;
++i;
+ /* A wrapping section potentially clashes with header. */
+ if (((s->lma + s->size) & addr_mask) < (s->lma & addr_mask))
+ wrap_to = (s->lma + s->size) & addr_mask;
}
}
BFD_ASSERT (i <= bfd_count_sections (abfd));
if (s != NULL && (s->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
pm = &m->next;
amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
if (phdr_size == (bfd_size_type) -1)
phdr_size = get_program_header_size (abfd, info);
if ((abfd->flags & D_PAGED) == 0
- || sections[0]->lma < phdr_size
- || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
+ || (sections[0]->lma & addr_mask) < phdr_size
+ || ((sections[0]->lma & addr_mask) % maxpagesize
+ < phdr_size % maxpagesize)
+ || (sections[0]->lma & addr_mask & -maxpagesize) < wrap_to)
phdr_in_segment = FALSE;
}
segment. */
new_segment = TRUE;
}
+ else if (hdr->lma < last_hdr->lma + last_size
+ || last_hdr->lma + last_size < last_hdr->lma)
+ {
+ /* If this section has a load address that makes it overlap
+ the previous section, then we need a new segment. */
+ new_segment = TRUE;
+ }
/* In the next test we have to be careful when last_hdr->lma is close
to the end of the address space. If the aligned address wraps
around to the start of the address space, then there are no more
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
- && (((last_hdr->lma + last_size - 1)
- & ~(maxpagesize - 1))
- != (hdr->lma & ~(maxpagesize - 1))))
+ && (((last_hdr->lma + last_size - 1) & -maxpagesize)
+ != (hdr->lma & -maxpagesize)))
{
/* We don't want to put a writable section in a read only
segment, unless they are on the same page in memory
&& CONST_STRNEQ (s->name, ".note"))
{
asection *s2;
- unsigned count = 1;
+
+ count = 1;
amt = sizeof (struct elf_segment_map);
if (s->alignment_power == 2)
for (s2 = s; s2->next != NULL; s2 = s2->next)
if (s2->next->alignment_power == 2
&& (s2->next->flags & SEC_LOAD) != 0
&& CONST_STRNEQ (s2->next->name, ".note")
- && align_power (s2->vma + s2->size, 2)
- == s2->next->vma)
+ && align_power (s2->lma + s2->size, 2)
+ == s2->next->lma)
count++;
else
break;
}
amt += (count - 1) * sizeof (asection *);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
/* If there are any SHF_TLS output sections, add PT_TLS segment. */
if (tls_count > 0)
{
- int i;
-
amt = sizeof (struct elf_segment_map);
amt += (tls_count - 1) * sizeof (asection *);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
/* Mandated PF_R. */
m->p_flags = PF_R;
m->p_flags_valid = 1;
- for (i = 0; i < tls_count; ++i)
+ for (i = 0; i < (unsigned int) tls_count; ++i)
{
BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
m->sections[i] = first_tls;
&& (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
if (elf_tdata (abfd)->stack_flags)
{
amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
if (m != NULL)
{
amt = sizeof (struct elf_segment_map);
- m = bfd_zalloc (abfd, amt);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
putc ('\n',stderr);
}
+static bfd_boolean
+write_zeros (bfd *abfd, file_ptr pos, bfd_size_type len)
+{
+ void *buf;
+ bfd_boolean ret;
+
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+ return FALSE;
+ buf = bfd_zmalloc (len);
+ if (buf == NULL)
+ return FALSE;
+ ret = bfd_bwrite (buf, len, abfd) == len;
+ free (buf);
+ return ret;
+}
+
/* Assign file positions to the sections based on the mapping from
sections to segments. This function also sets up some fields in
the file header. */
last iterations for the testcase ld-elf/header. */
BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
== 0);
- phdrs = bfd_zalloc2 (abfd,
- (elf_tdata (abfd)->program_header_size
- / bed->s->sizeof_phdr),
- sizeof (Elf_Internal_Phdr));
+ phdrs = (Elf_Internal_Phdr *)
+ bfd_zalloc2 (abfd,
+ (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr),
+ sizeof (Elf_Internal_Phdr));
elf_tdata (abfd)->phdr = phdrs;
if (phdrs == NULL)
return FALSE;
break;
}
- off_adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
+ off_adjust = vma_page_aligned_bias (p->p_vaddr, off, align);
off += off_adjust;
if (no_contents)
{
&& ((this_hdr->sh_flags & SHF_TLS) == 0
|| p->p_type == PT_TLS))))
{
- bfd_signed_vma adjust = sec->vma - (p->p_vaddr + p->p_memsz);
-
- if (adjust < 0)
+ bfd_vma p_start = p->p_paddr;
+ bfd_vma p_end = p_start + p->p_memsz;
+ bfd_vma s_start = sec->lma;
+ bfd_vma adjust = s_start - p_end;
+
+ if (adjust != 0
+ && (s_start < p_end
+ || p_end < p_start))
{
(*_bfd_error_handler)
- (_("%B: section %A vma 0x%lx overlaps previous sections"),
- abfd, sec, (unsigned long) sec->vma);
+ (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec,
+ (unsigned long) s_start, (unsigned long) p_end);
adjust = 0;
+ sec->lma = p_end;
}
p->p_memsz += adjust;
if (this_hdr->sh_type != SHT_NOBITS)
{
+ if (p->p_filesz + adjust < p->p_memsz)
+ {
+ /* We have a PROGBITS section following NOBITS ones.
+ Allocate file space for the NOBITS section(s) and
+ zero it. */
+ adjust = p->p_memsz - p->p_filesz;
+ if (!write_zeros (abfd, off, adjust))
+ return FALSE;
+ }
off += adjust;
p->p_filesz += adjust;
}
/* 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_boolean check_vma = TRUE;
+
+ for (i = 1; i < m->count; i++)
+ if (m->sections[i]->vma == m->sections[i - 1]->vma
+ && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i])
+ ->this_hdr), p) != 0
+ && ELF_SECTION_SIZE (&(elf_section_data (m->sections[i - 1])
+ ->this_hdr), p) != 0)
{
- (*_bfd_error_handler)
- (_("%B: section `%A' can't be allocated in segment %d"),
- abfd, sec, j);
- print_segment_map (m);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ /* Looks like we have overlays packed into the segment. */
+ check_vma = FALSE;
+ break;
}
- }
+
+ for (i = 0; i < m->count; i++)
+ {
+ Elf_Internal_Shdr *this_hdr;
+ asection *sec;
+
+ sec = m->sections[i];
+ this_hdr = &(elf_section_data(sec)->this_hdr);
+ if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0))
+ {
+ (*_bfd_error_handler)
+ (_("%B: section `%A' can't be allocated in segment %d"),
+ abfd, sec, j);
+ print_segment_map (m);
+ }
+ }
+ }
}
elf_tdata (abfd)->next_file_pos = off;
BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
- if (hdr->sh_size != 0)
- ((*_bfd_error_handler)
- (_("%B: warning: allocated section `%s' not in segment"),
- abfd,
- (hdr->bfd_section == NULL
- ? "*unknown*"
- : hdr->bfd_section->name)));
+ (*_bfd_error_handler)
+ (_("%B: warning: allocated section `%s' not in segment"),
+ abfd,
+ (hdr->bfd_section == NULL
+ ? "*unknown*"
+ : hdr->bfd_section->name));
/* We don't need to page align empty sections. */
if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
off += vma_page_aligned_bias (hdr->sh_addr, off,
static bfd_boolean
prep_headers (bfd *abfd)
{
- Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
- Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form. */
struct elf_strtab_hash *shstrtab;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
else
{
i_ehdrp->e_phentsize = 0;
- i_phdrp = 0;
i_ehdrp->e_phoff = 0;
}
_bfd_elf_write_object_contents (bfd *abfd)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Shdr **i_shdrp;
bfd_boolean failed;
unsigned int count, num_sec;
return FALSE;
i_shdrp = elf_elfsections (abfd);
- i_ehdrp = elf_elfheader (abfd);
failed = FALSE;
bfd_map_over_sections (abfd, bed->s->write_relocs, &failed);
_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
{
const struct elf_backend_data *bed;
- unsigned int index;
+ unsigned int sec_index;
if (elf_section_data (asect) != NULL
&& elf_section_data (asect)->this_idx != 0)
return elf_section_data (asect)->this_idx;
if (bfd_is_abs_section (asect))
- index = SHN_ABS;
+ sec_index = SHN_ABS;
else if (bfd_is_com_section (asect))
- index = SHN_COMMON;
+ sec_index = SHN_COMMON;
else if (bfd_is_und_section (asect))
- index = SHN_UNDEF;
+ sec_index = SHN_UNDEF;
else
- index = SHN_BAD;
+ sec_index = SHN_BAD;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_from_bfd_section)
{
- int retval = index;
+ int retval = sec_index;
if ((*bed->elf_backend_section_from_bfd_section) (abfd, asect, &retval))
return retval;
}
- if (index == SHN_BAD)
+ if (sec_index == SHN_BAD)
bfd_set_error (bfd_error_nonrepresentable_section);
- return index;
+ return sec_index;
}
/* Given a BFD symbol, return the index in the ELF symbol table, or -1
#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
all of the sections we have selected. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = bfd_zalloc (obfd, amt);
+ map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
pointers that we are interested in. As these sections get assigned
to a segment, they are removed from this array. */
- sections = bfd_malloc2 (section_count, sizeof (asection *));
+ sections = (asection **) bfd_malloc2 (section_count, sizeof (asection *));
if (sections == NULL)
return FALSE;
and carry on looping. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = bfd_alloc (obfd, amt);
+ map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
if (map == NULL)
{
free (sections);
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;
section = section->next)
{
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ 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++;
}
}
amt = sizeof (struct elf_segment_map);
if (section_count != 0)
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = bfd_zalloc (obfd, amt);
+ map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
if (map == NULL)
return FALSE;
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;
section = section->next)
{
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ 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;
/* Check if this section is covered by the segment. */
this_hdr = &(elf_section_data(section)->this_hdr);
- if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
{
/* FIXME: Check if its output section is changed or
removed. What else do we need to check? */
{
Elf_Internal_Shdr *ihdr, *ohdr;
- bfd_boolean need_group = link_info == NULL || link_info->relocatable;
+ bfd_boolean final_link = link_info != NULL && !link_info->relocatable;
if (ibfd->xvec->flavour != bfd_target_elf_flavour
|| obfd->xvec->flavour != bfd_target_elf_flavour)
return TRUE;
- /* Don't copy the output ELF section type from input if the
- output BFD section flags have been set to something different.
- elf_fake_sections will set ELF section type based on BFD
- section flags. */
+ /* For objcopy and relocatable link, don't copy the output ELF
+ section type from input if the output BFD section flags have been
+ set to something different. For a final link allow some flags
+ that the linker clears to differ. */
if (elf_section_type (osec) == SHT_NULL
- && (osec->flags == isec->flags || !osec->flags))
+ && (osec->flags == isec->flags
+ || (final_link
+ && ((osec->flags ^ isec->flags)
+ & ~(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? */
SHT_GROUP section will have its elf_next_in_group pointing back
to the input group members. Ignore linker created group section.
See elfNN_ia64_object_p in elfxx-ia64.c. */
- if (need_group)
+ if (!final_link)
{
if (elf_sec_group (isec) == NULL
|| (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
NULL);
}
-/* Copy private header information. */
+/* Look at all the SHT_GROUP sections in IBFD, making any adjustments
+ necessary if we are removing either the SHT_GROUP section or any of
+ the group member sections. DISCARDED is the value that a section's
+ output_section has if the section will be discarded, NULL when this
+ function is called from objcopy, bfd_abs_section_ptr when called
+ from the linker. */
bfd_boolean
-_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
+_bfd_elf_fixup_group_sections (bfd *ibfd, asection *discarded)
{
asection *isec;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- /* Copy over private BFD data if it has not already been copied.
- This must be done here, rather than in the copy_private_bfd_data
- entry point, because the latter is called after the section
- contents have been set, which means that the program headers have
- already been worked out. */
- if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
- {
- if (! copy_private_bfd_data (ibfd, obfd))
- return FALSE;
- }
-
- /* _bfd_elf_copy_private_section_data copied over the SHF_GROUP flag
- but this might be wrong if we deleted the group section. */
for (isec = ibfd->sections; isec != NULL; isec = isec->next)
- if (elf_section_type (isec) == SHT_GROUP
- && isec->output_section == NULL)
+ if (elf_section_type (isec) == SHT_GROUP)
{
asection *first = elf_next_in_group (isec);
asection *s = first;
+ bfd_size_type removed = 0;
+
while (s != NULL)
{
- if (s->output_section != NULL)
+ /* If this member section is being output but the
+ SHT_GROUP section is not, then clear the group info
+ set up by _bfd_elf_copy_private_section_data. */
+ if (s->output_section != discarded
+ && isec->output_section == discarded)
{
elf_section_flags (s->output_section) &= ~SHF_GROUP;
elf_group_name (s->output_section) = NULL;
}
+ /* Conversely, if the member section is not being output
+ but the SHT_GROUP section is, then adjust its size. */
+ else if (s->output_section == discarded
+ && isec->output_section != discarded)
+ removed += 4;
s = elf_next_in_group (s);
if (s == first)
break;
}
+ if (removed != 0)
+ {
+ if (discarded != NULL)
+ {
+ /* If we've been called for ld -r, then we need to
+ adjust the input section size. This function may
+ be called multiple times, so save the original
+ size. */
+ if (isec->rawsize == 0)
+ isec->rawsize = isec->size;
+ isec->size = isec->rawsize - removed;
+ }
+ else
+ {
+ /* Adjust the output section size when called from
+ objcopy. */
+ isec->output_section->size -= removed;
+ }
+ }
}
return TRUE;
}
+/* Copy private header information. */
+
+bfd_boolean
+_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
+{
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* Copy over private BFD data if it has not already been copied.
+ This must be done here, rather than in the copy_private_bfd_data
+ entry point, because the latter is called after the section
+ contents have been set, which means that the program headers have
+ already been worked out. */
+ if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+ }
+
+ return _bfd_elf_fixup_group_sections (ibfd, NULL);
+}
+
/* Copy private symbol information. If this symbol is in a section
which we did not map into a BFD section, try to map the section
index correctly. We use special macro definitions for the mapped
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
symstrtab_hdr->sh_type = SHT_STRTAB;
- outbound_syms = bfd_alloc2 (abfd, 1 + symcount, bed->s->sizeof_sym);
+ outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
+ bed->s->sizeof_sym);
if (outbound_syms == NULL)
{
_bfd_stringtab_free (stt);
if (symtab_shndx_hdr->sh_name != 0)
{
amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
- outbound_shndx = bfd_zalloc2 (abfd, 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)
{
_bfd_stringtab_free (stt);
if (flags & BSF_LOCAL)
bind = STB_LOCAL;
+ else if (flags & BSF_GNU_UNIQUE)
+ bind = STB_GNU_UNIQUE;
else if (flags & BSF_WEAK)
bind = STB_WEAK;
else if (flags & BSF_GLOBAL)
hdr = &elf_tdata (abfd)->dynverref_hdr;
- elf_tdata (abfd)->verref = bfd_zalloc2 (abfd, hdr->sh_info,
- sizeof (Elf_Internal_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;
elf_tdata (abfd)->cverrefs = hdr->sh_info;
- contents = bfd_malloc (hdr->sh_size);
+ contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
{
error_return_verref:
iverneed->vn_auxptr = NULL;
else
{
- iverneed->vn_auxptr = bfd_alloc2 (abfd, iverneed->vn_cnt,
- sizeof (Elf_Internal_Vernaux));
+ iverneed->vn_auxptr = (struct elf_internal_vernaux *)
+ bfd_alloc2 (abfd, iverneed->vn_cnt,
+ sizeof (Elf_Internal_Vernaux));
if (iverneed->vn_auxptr == NULL)
goto error_return_verref;
}
hdr = &elf_tdata (abfd)->dynverdef_hdr;
- contents = bfd_malloc (hdr->sh_size);
+ contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
else
freeidx = ++maxidx;
}
- elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, maxidx,
- sizeof (Elf_Internal_Verdef));
+ elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
+ bfd_zalloc2 (abfd, maxidx, sizeof (Elf_Internal_Verdef));
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
iverdef->vd_auxptr = NULL;
else
{
- iverdef->vd_auxptr = bfd_alloc2 (abfd, iverdef->vd_cnt,
- sizeof (Elf_Internal_Verdaux));
+ iverdef->vd_auxptr = (struct elf_internal_verdaux *)
+ bfd_alloc2 (abfd, iverdef->vd_cnt,
+ sizeof (Elf_Internal_Verdaux));
if (iverdef->vd_auxptr == NULL)
goto error_return_verdef;
}
else
freeidx++;
- elf_tdata (abfd)->verdef = bfd_zalloc2 (abfd, freeidx,
- sizeof (Elf_Internal_Verdef));
+ elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *)
+ bfd_zalloc2 (abfd, freeidx, sizeof (Elf_Internal_Verdef));
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
if (iverdef->vd_nodename == NULL)
goto error_return_verdef;
iverdef->vd_nextdef = NULL;
- iverdef->vd_auxptr = bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
+ iverdef->vd_auxptr = (struct elf_internal_verdaux *)
+ bfd_alloc (abfd, sizeof (Elf_Internal_Verdaux));
if (iverdef->vd_auxptr == NULL)
goto error_return_verdef;
elf_symbol_type *newsym;
bfd_size_type amt = sizeof (elf_symbol_type);
- newsym = bfd_zalloc (abfd, amt);
+ newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
if (!newsym)
return NULL;
else
out details about the corefile. */
#ifdef HAVE_SYS_PROCFS_H
+/* Needed for new procfs interface on sparc-solaris. */
+# define _STRUCTURED_PROC 1
# include <sys/procfs.h>
#endif
-/* FIXME: this is kinda wrong, but it's what gdb wants. */
+/* Return a PID that identifies a "thread" for threaded cores, or the
+ PID of the main process for non-threaded cores. */
static int
elfcore_make_pid (bfd *abfd)
{
- return ((elf_tdata (abfd)->core_lwpid << 16)
- + (elf_tdata (abfd)->core_pid));
+ int pid;
+
+ pid = elf_tdata (abfd)->core_lwpid;
+ if (pid == 0)
+ pid = elf_tdata (abfd)->core_pid;
+
+ return pid;
}
/* If there isn't a section called NAME, make one, using
sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
len = strlen (buf) + 1;
- threaded_name = bfd_alloc (abfd, len);
+ threaded_name = (char *) bfd_alloc (abfd, len);
if (threaded_name == NULL)
return FALSE;
memcpy (threaded_name, buf, len);
has already been set by another thread. */
if (elf_tdata (abfd)->core_signal == 0)
elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core_pid == 0)
+ elf_tdata (abfd)->core_pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
*/
#if defined (HAVE_PRSTATUS_T_PR_WHO)
elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+#else
+ elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
#endif
}
#if defined (HAVE_PRSTATUS32_T)
has already been set by another thread. */
if (elf_tdata (abfd)->core_signal == 0)
elf_tdata (abfd)->core_signal = prstat.pr_cursig;
- elf_tdata (abfd)->core_pid = prstat.pr_pid;
+ if (elf_tdata (abfd)->core_pid == 0)
+ elf_tdata (abfd)->core_pid = prstat.pr_pid;
/* pr_who exists on:
solaris 2.5+
*/
#if defined (HAVE_PRSTATUS32_T_PR_WHO)
elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+#else
+ elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
#endif
}
#endif /* HAVE_PRSTATUS32_T */
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
}
+/* Linux dumps the Intel XSAVE extended state in a note named "LINUX"
+ with a note type of NT_X86_XSTATE. Just include the whole note's
+ contents literally. */
+
+static bfd_boolean
+elfcore_grok_xstatereg (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-xstate", note);
+}
+
static bfd_boolean
elfcore_grok_ppc_vmx (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".reg-ppc-vsx", note);
}
+static bfd_boolean
+elfcore_grok_s390_high_gprs (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-high-gprs", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_timer (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-timer", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_todcmp (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-todcmp", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_todpreg (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-todpreg", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_ctrs (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-ctrs", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_prefix (bfd *abfd, Elf_Internal_Note *note)
+{
+ return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note);
+}
+
#if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
_bfd_elfcore_strndup (bfd *abfd, char *start, size_t max)
{
char *dups;
- char *end = memchr (start, '\0', max);
+ char *end = (char *) memchr (start, '\0', max);
size_t len;
if (end == NULL)
else
len = end - start;
- dups = bfd_alloc (abfd, len + 1);
+ dups = (char *) bfd_alloc (abfd, len + 1);
if (dups == NULL)
return NULL;
memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid;
- elf_tdata (abfd)->core_signal = lwpstat.pr_cursig;
+ /* Do not overwrite the core signal if it has already been set by
+ another thread. */
+ if (elf_tdata (abfd)->core_signal == 0)
+ elf_tdata (abfd)->core_signal = lwpstat.pr_cursig;
/* Make a ".reg/999" section. */
sprintf (buf, ".reg/%ld", (long) bfd_get_32 (abfd, note->descdata + 8));
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, len);
+ name = (char *) bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
sprintf (buf, ".module/%08lx", (unsigned long) base_addr);
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, len);
+ name = (char *) bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
else
return TRUE;
+ case NT_X86_XSTATE: /* Linux XSAVE extension */
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_xstatereg (abfd, note);
+ else
+ return TRUE;
+
case NT_PPC_VMX:
if (note->namesz == 6
&& strcmp (note->namedata, "LINUX") == 0)
else
return TRUE;
+ case NT_S390_HIGH_GPRS:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_high_gprs (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_TIMER:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_timer (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_TODCMP:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_todcmp (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_TODPREG:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_todpreg (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_CTRS:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_ctrs (abfd, note);
+ else
+ return TRUE;
+
+ case NT_S390_PREFIX:
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
+ return elfcore_grok_s390_prefix (abfd, note);
+ else
+ return TRUE;
+
case NT_PRPSINFO:
case NT_PSINFO:
if (bed->elf_backend_grok_psinfo)
elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
{
elf_tdata (abfd)->build_id_size = note->descsz;
- elf_tdata (abfd)->build_id = bfd_alloc (abfd, note->descsz);
+ elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz);
if (elf_tdata (abfd)->build_id == NULL)
return FALSE;
/* Make a ".qnx_core_status/%d" section. */
sprintf (buf, ".qnx_core_status/%ld", *tid);
- name = bfd_alloc (abfd, strlen (buf) + 1);
+ name = (char *) bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
return FALSE;
strcpy (name, buf);
/* Make a "(base)/%d" section. */
sprintf (buf, "%s/%ld", base, tid);
- name = bfd_alloc (abfd, strlen (buf) + 1);
+ name = (char *) bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
return FALSE;
strcpy (name, buf);
/* Use note name as section name. */
len = note->namesz;
- name = bfd_alloc (abfd, len);
+ name = (char *) bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
memcpy (name, note->namedata, len);
newspace = 12 + ((namesz + 3) & -4) + ((size + 3) & -4);
- buf = realloc (buf, *bufsiz + newspace);
+ buf = (char *) realloc (buf, *bufsiz + newspace);
if (buf == NULL)
return buf;
dest = buf + *bufsiz;
}
char *
+elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz,
+ const void *xfpregs, int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_X86_XSTATE, xfpregs, size);
+}
+
+char *
elfcore_write_ppc_vmx (bfd *abfd,
char *buf,
int *bufsiz,
note_name, NT_PPC_VSX, ppc_vsx, size);
}
+static char *
+elfcore_write_s390_high_gprs (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_high_gprs,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_HIGH_GPRS,
+ s390_high_gprs, size);
+}
+
+char *
+elfcore_write_s390_timer (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_timer,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_TIMER, s390_timer, size);
+}
+
+char *
+elfcore_write_s390_todcmp (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_todcmp,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_TODCMP, s390_todcmp, size);
+}
+
+char *
+elfcore_write_s390_todpreg (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_todpreg,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_TODPREG, s390_todpreg, size);
+}
+
+char *
+elfcore_write_s390_ctrs (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_ctrs,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_CTRS, s390_ctrs, size);
+}
+
+char *
+elfcore_write_s390_prefix (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *s390_prefix,
+ int size)
+{
+ char *note_name = "LINUX";
+ return elfcore_write_note (abfd, buf, bufsiz,
+ note_name, NT_S390_PREFIX, s390_prefix, size);
+}
+
char *
elfcore_write_register_note (bfd *abfd,
char *buf,
return elfcore_write_prfpreg (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-xfp") == 0)
return elfcore_write_prxfpreg (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-xstate") == 0)
+ return elfcore_write_xstatereg (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-ppc-vmx") == 0)
return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
if (strcmp (section, ".reg-ppc-vsx") == 0)
return elfcore_write_ppc_vsx (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-high-gprs") == 0)
+ return elfcore_write_s390_high_gprs (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-timer") == 0)
+ return elfcore_write_s390_timer (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-todcmp") == 0)
+ return elfcore_write_s390_todcmp (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-todpreg") == 0)
+ return elfcore_write_s390_todpreg (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-ctrs") == 0)
+ return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-s390-prefix") == 0)
+ return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size);
return NULL;
}
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
return FALSE;
- buf = bfd_malloc (size);
+ buf = (char *) bfd_malloc (size);
if (buf == NULL)
return FALSE;
size = count * sizeof (asymbol);
p = relplt->relocation;
for (i = 0; i < count; i++, p += bed->s->int_rels_per_ext_rel)
- size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+ {
+ size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+ if (p->addend != 0)
+ {
+#ifdef BFD64
+ size += sizeof ("+0x") - 1 + 8 + 8 * (bed->s->elfclass == ELFCLASS64);
+#else
+ size += sizeof ("+0x") - 1 + 8;
+#endif
+ }
+ }
- s = *ret = bfd_malloc (size);
+ s = *ret = (asymbol *) bfd_malloc (size);
if (s == NULL)
return -1;
len = strlen ((*p->sym_ptr_ptr)->name);
memcpy (names, (*p->sym_ptr_ptr)->name, len);
names += len;
+ if (p->addend != 0)
+ {
+ char buf[30], *a;
+
+ memcpy (names, "+0x", sizeof ("+0x") - 1);
+ names += sizeof ("+0x") - 1;
+ bfd_sprintf_vma (abfd, buf, p->addend);
+ for (a = buf; *a == '0'; ++a)
+ ;
+ len = strlen (a);
+ memcpy (names, a, len);
+ names += len;
+ }
memcpy (names, "@plt", sizeof ("@plt"));
names += sizeof ("@plt");
++s, ++n;