/* ELF executable support for BFD.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Fred Fish @ Cygnus Support, from information published
const void *pshn,
Elf_Internal_Sym *dst)
{
- const Elf_External_Sym *src = psrc;
- const Elf_External_Sym_Shndx *shndx = pshn;
+ const Elf_External_Sym *src = (const Elf_External_Sym *) psrc;
+ const Elf_External_Sym_Shndx *shndx = (const Elf_External_Sym_Shndx *) pshn;
int signed_vma = get_elf_backend_data (abfd)->sign_extend_vma;
dst->st_name = H_GET_32 (abfd, src->st_name);
dst->st_info = H_GET_8 (abfd, src->st_info);
dst->st_other = H_GET_8 (abfd, src->st_other);
dst->st_shndx = H_GET_16 (abfd, src->st_shndx);
- if (dst->st_shndx == SHN_XINDEX)
+ if (dst->st_shndx == (SHN_XINDEX & 0xffff))
{
if (shndx == NULL)
return FALSE;
dst->st_shndx = H_GET_32 (abfd, shndx->est_shndx);
}
+ else if (dst->st_shndx >= (SHN_LORESERVE & 0xffff))
+ dst->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
return TRUE;
}
void *shndx)
{
unsigned int tmp;
- Elf_External_Sym *dst = cdst;
+ Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
H_PUT_32 (abfd, src->st_name, dst->st_name);
H_PUT_WORD (abfd, src->st_value, dst->st_value);
H_PUT_WORD (abfd, src->st_size, dst->st_size);
H_PUT_8 (abfd, src->st_info, dst->st_info);
H_PUT_8 (abfd, src->st_other, dst->st_other);
tmp = src->st_shndx;
- if (tmp > SHN_HIRESERVE)
+ if (tmp >= (SHN_LORESERVE & 0xffff) && tmp < SHN_LORESERVE)
{
if (shndx == NULL)
abort ();
H_PUT_32 (abfd, tmp, shndx);
- tmp = SHN_XINDEX;
+ tmp = SHN_XINDEX & 0xffff;
}
H_PUT_16 (abfd, tmp, dst->st_shndx);
}
H_PUT_32 (abfd, src->e_flags, dst->e_flags);
H_PUT_16 (abfd, src->e_ehsize, dst->e_ehsize);
H_PUT_16 (abfd, src->e_phentsize, dst->e_phentsize);
- H_PUT_16 (abfd, src->e_phnum, dst->e_phnum);
+ tmp = src->e_phnum;
+ if (tmp > PN_XNUM)
+ tmp = PN_XNUM;
+ H_PUT_16 (abfd, tmp, dst->e_phnum);
H_PUT_16 (abfd, src->e_shentsize, dst->e_shentsize);
tmp = src->e_shnum;
- if (tmp >= SHN_LORESERVE)
+ if (tmp >= (SHN_LORESERVE & 0xffff))
tmp = SHN_UNDEF;
H_PUT_16 (abfd, tmp, dst->e_shnum);
tmp = src->e_shstrndx;
- if (tmp >= SHN_LORESERVE)
- tmp = SHN_XINDEX;
+ if (tmp >= (SHN_LORESERVE & 0xffff))
+ tmp = SHN_XINDEX & 0xffff;
H_PUT_16 (abfd, tmp, dst->e_shstrndx);
}
const Elf_Internal_Phdr *src,
Elf_External_Phdr *dst)
{
+ const struct elf_backend_data *bed;
+ bfd_vma p_paddr;
+
+ bed = get_elf_backend_data (abfd);
+ p_paddr = bed->want_p_paddr_set_to_zero ? 0 : src->p_paddr;
+
/* note that all elements of dst are *arrays of unsigned char* already... */
H_PUT_32 (abfd, src->p_type, dst->p_type);
H_PUT_WORD (abfd, src->p_offset, dst->p_offset);
H_PUT_WORD (abfd, src->p_vaddr, dst->p_vaddr);
- H_PUT_WORD (abfd, src->p_paddr, dst->p_paddr);
+ H_PUT_WORD (abfd, p_paddr, dst->p_paddr);
H_PUT_WORD (abfd, src->p_filesz, dst->p_filesz);
H_PUT_WORD (abfd, src->p_memsz, dst->p_memsz);
H_PUT_32 (abfd, src->p_flags, dst->p_flags);
const void *p,
Elf_Internal_Dyn *dst)
{
- const Elf_External_Dyn *src = p;
+ const Elf_External_Dyn *src = (const Elf_External_Dyn *) p;
dst->d_tag = H_GET_WORD (abfd, src->d_tag);
dst->d_un.d_val = H_GET_WORD (abfd, src->d_un.d_val);
const Elf_Internal_Dyn *src,
void *p)
{
- Elf_External_Dyn *dst = p;
+ Elf_External_Dyn *dst = (Elf_External_Dyn *) p;
H_PUT_WORD (abfd, src->d_tag, dst->d_tag);
H_PUT_WORD (abfd, src->d_un.d_val, dst->d_un.d_val);
&& (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
}
-/* Determines if a given section index is valid. */
-
-static inline bfd_boolean
-valid_section_index_p (unsigned index, unsigned num_sections)
-{
- /* Note: We allow SHN_UNDEF as a valid section index. */
- if (index < SHN_LORESERVE || index > SHN_HIRESERVE)
- return index < num_sections;
-
- /* We disallow the use of reserved indcies, except for those
- with OS or Application specific meaning. The test make use
- of the knowledge that:
- SHN_LORESERVE == SHN_LOPROC
- and
- SHN_HIPROC == SHN_LOOS - 1 */
- /* XXX - Should we allow SHN_XINDEX as a valid index here ? */
- return (index >= SHN_LOPROC && index <= SHN_HIOS);
-}
-
/* Check to see if the file associated with ABFD matches the target vector
that ABFD points to.
goto got_wrong_format_error;
ebd = get_elf_backend_data (abfd);
+ if (ebd->s->arch_size != ARCH_SIZE)
+ goto got_wrong_format_error;
/* Check that the ELF e_machine field matches what this particular
BFD format expects. */
if ((*target_ptr)->flavour != bfd_target_elf_flavour)
continue;
back = xvec_get_elf_backend_data (*target_ptr);
+ if (back->s->arch_size != ARCH_SIZE)
+ continue;
if (back->elf_machine_code == i_ehdrp->e_machine
|| (back->elf_machine_alt1 != 0
&& back->elf_machine_alt1 == i_ehdrp->e_machine)
}
/* And similarly for the string table index. */
- if (i_ehdrp->e_shstrndx == SHN_XINDEX)
+ if (i_ehdrp->e_shstrndx == (SHN_XINDEX & 0xffff))
{
i_ehdrp->e_shstrndx = i_shdr.sh_link;
if (i_ehdrp->e_shstrndx != i_shdr.sh_link)
goto got_wrong_format_error;
}
+ /* And program headers. */
+ if (i_ehdrp->e_phnum == PN_XNUM && i_shdr.sh_info != 0)
+ {
+ i_ehdrp->e_phnum = i_shdr.sh_info;
+ if (i_ehdrp->e_phnum != i_shdr.sh_info)
+ goto got_wrong_format_error;
+ }
+
/* Sanity check that we can read all of the section headers.
It ought to be good enough to just read the last one. */
if (i_ehdrp->e_shnum != 1)
unsigned int num_sec;
amt = sizeof (*i_shdrp) * i_ehdrp->e_shnum;
- i_shdrp = bfd_alloc (abfd, amt);
+ i_shdrp = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
if (!i_shdrp)
goto got_no_match;
num_sec = i_ehdrp->e_shnum;
- if (num_sec > SHN_LORESERVE)
- num_sec += SHN_HIRESERVE + 1 - SHN_LORESERVE;
elf_numsections (abfd) = num_sec;
amt = sizeof (i_shdrp) * num_sec;
- elf_elfsections (abfd) = bfd_alloc (abfd, amt);
+ elf_elfsections (abfd) = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
if (!elf_elfsections (abfd))
goto got_no_match;
memcpy (i_shdrp, &i_shdr, sizeof (*i_shdrp));
- shdrp = i_shdrp;
- shindex = 0;
- if (num_sec > SHN_LORESERVE)
- {
- for ( ; shindex < SHN_LORESERVE; shindex++)
- elf_elfsections (abfd)[shindex] = shdrp++;
- for ( ; shindex < SHN_HIRESERVE + 1; shindex++)
- elf_elfsections (abfd)[shindex] = i_shdrp;
- }
- for ( ; shindex < num_sec; shindex++)
+ for (shdrp = i_shdrp, shindex = 0; shindex < num_sec; shindex++)
elf_elfsections (abfd)[shindex] = shdrp++;
/* Read in the rest of the section header table and convert it
elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
/* Sanity check sh_link and sh_info. */
- if (! valid_section_index_p (i_shdrp[shindex].sh_link, num_sec))
- goto got_wrong_format_error;
+ if (i_shdrp[shindex].sh_link >= num_sec)
+ {
+ /* PR 10478: Accept Solaris binaries with a sh_link
+ field set to SHN_BEFORE or SHN_AFTER. */
+ switch (ebd->elf_machine_code)
+ {
+ case EM_386:
+ case EM_486:
+ case EM_X86_64:
+ case EM_OLD_SPARCV9:
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ case EM_SPARC:
+ if (i_shdrp[shindex].sh_link == (SHN_LORESERVE & 0xffff) /* SHN_BEFORE */
+ || i_shdrp[shindex].sh_link == ((SHN_LORESERVE + 1) & 0xffff) /* SHN_AFTER */)
+ break;
+ /* Otherwise fall through. */
+ default:
+ goto got_wrong_format_error;
+ }
+ }
if (((i_shdrp[shindex].sh_flags & SHF_INFO_LINK)
|| i_shdrp[shindex].sh_type == SHT_RELA
|| i_shdrp[shindex].sh_type == SHT_REL)
- && ! valid_section_index_p (i_shdrp[shindex].sh_info, num_sec))
+ && i_shdrp[shindex].sh_info >= num_sec)
goto got_wrong_format_error;
/* If the section is loaded, but not page aligned, clear
/* A further sanity check. */
if (i_ehdrp->e_shnum != 0)
{
- if (! valid_section_index_p (i_ehdrp->e_shstrndx, elf_numsections (abfd)))
+ if (i_ehdrp->e_shstrndx >= elf_numsections (abfd))
{
/* PR 2257:
We used to just goto got_wrong_format_error here
unsigned int i;
amt = i_ehdrp->e_phnum * sizeof (Elf_Internal_Phdr);
- elf_tdata (abfd)->phdr = bfd_alloc (abfd, amt);
+ elf_tdata (abfd)->phdr = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
if (elf_tdata (abfd)->phdr == NULL)
goto got_no_match;
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
a dummy placeholder entry, so we ignore it. */
num_sec = elf_numsections (abfd);
for (shindex = 1; shindex < num_sec; shindex++)
- {
- if (! bfd_section_from_shdr (abfd, shindex))
- goto got_no_match;
- if (shindex == SHN_LORESERVE - 1)
- shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
- }
+ if (!bfd_section_from_shdr (abfd, shindex))
+ goto got_no_match;
/* Set up ELF sections for SHF_GROUP and SHF_LINK_ORDER. */
if (! _bfd_elf_setup_sections (abfd))
void
elf_write_relocs (bfd *abfd, asection *sec, void *data)
{
- bfd_boolean *failedp = data;
+ bfd_boolean *failedp = (bfd_boolean *) data;
Elf_Internal_Shdr *rela_hdr;
bfd_vma addr_offset;
void (*swap_out) (bfd *, const Elf_Internal_Rela *, bfd_byte *);
rela_hdr = &elf_section_data (sec)->rel_hdr;
rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
- rela_hdr->contents = bfd_alloc (abfd, rela_hdr->sh_size);
+ rela_hdr->contents = (unsigned char *) bfd_alloc (abfd, rela_hdr->sh_size);
if (rela_hdr->contents == NULL)
{
*failedp = TRUE;
/* Some fields in the first section header handle overflow of ehdr
fields. */
- if (i_ehdrp->e_shnum >= SHN_LORESERVE)
+ if (i_ehdrp->e_phnum >= PN_XNUM)
+ i_shdrp[0]->sh_info = i_ehdrp->e_phnum;
+ if (i_ehdrp->e_shnum >= (SHN_LORESERVE & 0xffff))
i_shdrp[0]->sh_size = i_ehdrp->e_shnum;
- if (i_ehdrp->e_shstrndx >= SHN_LORESERVE)
+ if (i_ehdrp->e_shstrndx >= (SHN_LORESERVE & 0xffff))
i_shdrp[0]->sh_link = i_ehdrp->e_shstrndx;
/* at this point we've concocted all the ELF sections... */
amt = i_ehdrp->e_shnum;
amt *= sizeof (*x_shdrp);
- x_shdrp = bfd_alloc (abfd, amt);
+ x_shdrp = (Elf_External_Shdr *) bfd_alloc (abfd, amt);
if (!x_shdrp)
return FALSE;
elf_debug_section (count, *i_shdrp);
#endif
elf_swap_shdr_out (abfd, *i_shdrp, x_shdrp + count);
-
- if (count == SHN_LORESERVE - 1)
- i_shdrp += SHN_HIRESERVE + 1 - SHN_LORESERVE;
}
if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
|| bfd_bwrite (x_shdrp, amt, abfd) != amt)
amt = symcount;
amt *= sizeof (elf_symbol_type);
- symbase = bfd_zalloc (abfd, amt);
+ symbase = (elf_symbol_type *) bfd_zalloc (abfd, amt);
if (symbase == (elf_symbol_type *) NULL)
goto error_return;
if (bfd_seek (abfd, verhdr->sh_offset, SEEK_SET) != 0)
goto error_return;
- xverbuf = bfd_malloc (verhdr->sh_size);
+ xverbuf = (Elf_External_Versym *) bfd_malloc (verhdr->sh_size);
if (xverbuf == NULL && verhdr->sh_size != 0)
goto error_return;
{
sym->symbol.section = bfd_und_section_ptr;
}
- else if (isym->st_shndx < SHN_LORESERVE
- || isym->st_shndx > SHN_HIRESERVE)
- {
- sym->symbol.section = bfd_section_from_elf_index (abfd,
- isym->st_shndx);
- if (sym->symbol.section == NULL)
- {
- /* This symbol is in a section for which we did not
- create a BFD section. Just use bfd_abs_section,
- although it is wrong. FIXME. */
- sym->symbol.section = bfd_abs_section_ptr;
- }
- }
else if (isym->st_shndx == SHN_ABS)
{
sym->symbol.section = bfd_abs_section_ptr;
sym->symbol.value = isym->st_size;
}
else
- sym->symbol.section = bfd_abs_section_ptr;
+ {
+ sym->symbol.section
+ = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ if (sym->symbol.section == NULL)
+ {
+ /* This symbol is in a section for which we did not
+ create a BFD section. Just use bfd_abs_section,
+ although it is wrong. FIXME. */
+ sym->symbol.section = bfd_abs_section_ptr;
+ }
+ }
/* If this is a relocatable file, then the symbol value is
already section relative. */
case STB_WEAK:
sym->symbol.flags |= BSF_WEAK;
break;
+ case STB_GNU_UNIQUE:
+ sym->symbol.flags |= BSF_GNU_UNIQUE;
+ break;
}
switch (ELF_ST_TYPE (isym->st_info))
case STT_FUNC:
sym->symbol.flags |= BSF_FUNCTION;
break;
+ case STT_COMMON:
+ /* FIXME: Do we have to put the size field into the value field
+ as we do with symbols in SHN_COMMON sections (see above) ? */
+ /* Fall through. */
case STT_OBJECT:
sym->symbol.flags |= BSF_OBJECT;
break;
case STT_SRELC:
sym->symbol.flags |= BSF_SRELC;
break;
+ case STT_GNU_IFUNC:
+ sym->symbol.flags |= BSF_GNU_INDIRECT_FUNCTION;
+ break;
}
if (dynamic)
!= rel_hdr->sh_size))
goto error_return;
- native_relocs = allocated;
+ native_relocs = (bfd_byte *) allocated;
entsize = rel_hdr->sh_entsize;
BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
}
amt = (reloc_count + reloc_count2) * sizeof (arelent);
- relents = bfd_alloc (abfd, amt);
+ relents = (arelent *) bfd_alloc (abfd, amt);
if (relents == NULL)
return FALSE;
return NULL;
}
- x_phdrs = bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
+ x_phdrs = (Elf_External_Phdr *)
+ bfd_malloc (i_ehdr.e_phnum * (sizeof *x_phdrs + sizeof *i_phdrs));
if (x_phdrs == NULL)
{
bfd_set_error (bfd_error_no_memory);
contents_size = last_phdr->p_offset + last_phdr->p_filesz;
/* Now we know the size of the whole image we want read in. */
- contents = bfd_zmalloc (contents_size);
+ contents = (bfd_byte *) bfd_zmalloc (contents_size);
if (contents == NULL)
{
free (x_phdrs);
memcpy (contents, &x_ehdr, sizeof x_ehdr);
/* Now we have a memory image of the ELF file contents. Make a BFD. */
- bim = bfd_malloc (sizeof (struct bfd_in_memory));
+ bim = (struct bfd_in_memory *) bfd_malloc (sizeof (struct bfd_in_memory));
if (bim == NULL)
{
free (contents);
bim->buffer = contents;
nbfd->iostream = bim;
nbfd->flags = BFD_IN_MEMORY;
+ nbfd->iovec = &_bfd_memory_iovec;
+ nbfd->origin = 0;
nbfd->direction = read_direction;
nbfd->mtime = time (NULL);
nbfd->mtime_set = TRUE;