/* ELF executable support for BFD.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
- Free Software Foundation, Inc.
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003 Free Software Foundation, Inc.
-This file is part of BFD, the Binary File Descriptor library.
+ This file is part of BFD, the Binary File Descriptor library.
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-/*
+/* SECTION
-SECTION
ELF backends
BFD support for ELF formats is being worked on.
Documentation of the internals of the support code still needs
to be written. The code is changing quickly enough that we
- haven't bothered yet.
- */
+ haven't bothered yet. */
/* For sparc64-cross-sparc32. */
#define _SYSCALL32
#include "libiberty.h"
static INLINE struct elf_segment_map *make_mapping
- PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
-static boolean map_sections_to_segments PARAMS ((bfd *));
-static int elf_sort_sections PARAMS ((const PTR, const PTR));
-static boolean assign_file_positions_for_segments PARAMS ((bfd *));
-static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
-static boolean prep_headers PARAMS ((bfd *));
-static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int));
-static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
-static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
-static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
-static void merge_sections_remove_hook PARAMS ((bfd *, asection *));
-static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
-static void set_group_contents PARAMS ((bfd *, asection *, PTR));
-static boolean assign_section_numbers PARAMS ((bfd *));
-static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean elf_map_symbols PARAMS ((bfd *));
-static bfd_size_type get_program_header_size PARAMS ((bfd *));
-static boolean elfcore_read_notes PARAMS ((bfd *, file_ptr, bfd_size_type));
-static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **,
- bfd_vma, const char **,
- const char **));
-static int elfcore_make_pid PARAMS ((bfd *));
-static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *));
-static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *,
- Elf_Internal_Note *));
-static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean elfcore_netbsd_get_lwpid PARAMS ((Elf_Internal_Note *, int *));
-static boolean elfcore_grok_netbsd_procinfo PARAMS ((bfd *,
- Elf_Internal_Note *));
-static boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *));
+ PARAMS ((bfd *, asection **, unsigned int, unsigned int, bfd_boolean));
+static bfd_boolean map_sections_to_segments
+ PARAMS ((bfd *));
+static int elf_sort_sections
+ PARAMS ((const PTR, const PTR));
+static bfd_boolean assign_file_positions_for_segments
+ PARAMS ((bfd *));
+static bfd_boolean assign_file_positions_except_relocs
+ PARAMS ((bfd *));
+static bfd_boolean prep_headers
+ PARAMS ((bfd *));
+static bfd_boolean swap_out_syms
+ PARAMS ((bfd *, struct bfd_strtab_hash **, int));
+static bfd_boolean copy_private_bfd_data
+ PARAMS ((bfd *, bfd *));
+static char *elf_read
+ PARAMS ((bfd *, file_ptr, bfd_size_type));
+static const char *group_signature
+ PARAMS ((bfd *, Elf_Internal_Shdr *));
+static bfd_boolean setup_group
+ PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
+static void merge_sections_remove_hook
+ PARAMS ((bfd *, asection *));
+static void elf_fake_sections
+ PARAMS ((bfd *, asection *, PTR));
+static bfd_boolean assign_section_numbers
+ PARAMS ((bfd *));
+static INLINE int sym_is_global
+ PARAMS ((bfd *, asymbol *));
+static bfd_boolean elf_map_symbols
+ PARAMS ((bfd *));
+static bfd_size_type get_program_header_size
+ PARAMS ((bfd *));
+static bfd_boolean elfcore_read_notes
+ PARAMS ((bfd *, file_ptr, bfd_size_type));
+static bfd_boolean elf_find_function
+ PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
+ const char **));
+static int elfcore_make_pid
+ PARAMS ((bfd *));
+static bfd_boolean elfcore_maybe_make_sect
+ PARAMS ((bfd *, char *, asection *));
+static bfd_boolean elfcore_make_note_pseudosection
+ PARAMS ((bfd *, char *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prfpreg
+ PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prxfpreg
+ PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_note
+ PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_netbsd_get_lwpid
+ PARAMS ((Elf_Internal_Note *, int *));
+static bfd_boolean elfcore_grok_netbsd_procinfo
+ PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_netbsd_note
+ PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_nto_gregs
+ PARAMS ((bfd *, Elf_Internal_Note *, pid_t));
+static bfd_boolean elfcore_grok_nto_status
+ PARAMS ((bfd *, Elf_Internal_Note *, pid_t *));
+static bfd_boolean elfcore_grok_nto_note
+ PARAMS ((bfd *, Elf_Internal_Note *));
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
h ^= g;
}
}
- return h;
+ return h & 0xffffffff;
}
/* Read a specified number of bytes at a specified offset in an ELF
return buf;
}
-boolean
+bfd_boolean
bfd_elf_mkobject (abfd)
bfd *abfd;
{
bfd_size_type amt = sizeof (struct elf_obj_tdata);
elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
if (elf_tdata (abfd) == 0)
- return false;
+ return FALSE;
/* Since everything is done at close time, do we need any
initialization? */
- return true;
+ return TRUE;
}
-boolean
+bfd_boolean
bfd_elf_mkcorefile (abfd)
bfd *abfd;
{
return ((char *) hdr->contents) + strindex;
}
+/* Read and convert symbols to internal format.
+ SYMCOUNT specifies the number of symbols to read, starting from
+ symbol SYMOFFSET. If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
+ are non-NULL, they are used to store the internal symbols, external
+ symbols, and symbol section index extensions, respectively. */
+
+Elf_Internal_Sym *
+bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
+ intsym_buf, extsym_buf, extshndx_buf)
+ bfd *ibfd;
+ Elf_Internal_Shdr *symtab_hdr;
+ size_t symcount;
+ size_t symoffset;
+ Elf_Internal_Sym *intsym_buf;
+ PTR extsym_buf;
+ Elf_External_Sym_Shndx *extshndx_buf;
+{
+ Elf_Internal_Shdr *shndx_hdr;
+ PTR alloc_ext;
+ const bfd_byte *esym;
+ Elf_External_Sym_Shndx *alloc_extshndx;
+ Elf_External_Sym_Shndx *shndx;
+ Elf_Internal_Sym *isym;
+ Elf_Internal_Sym *isymend;
+ struct elf_backend_data *bed;
+ size_t extsym_size;
+ bfd_size_type amt;
+ file_ptr pos;
+
+ if (symcount == 0)
+ return intsym_buf;
+
+ /* Normal syms might have section extension entries. */
+ shndx_hdr = NULL;
+ if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
+ shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+
+ /* Read the symbols. */
+ alloc_ext = NULL;
+ alloc_extshndx = NULL;
+ bed = get_elf_backend_data (ibfd);
+ extsym_size = bed->s->sizeof_sym;
+ amt = symcount * extsym_size;
+ pos = symtab_hdr->sh_offset + symoffset * extsym_size;
+ if (extsym_buf == NULL)
+ {
+ alloc_ext = bfd_malloc (amt);
+ extsym_buf = alloc_ext;
+ }
+ if (extsym_buf == NULL
+ || bfd_seek (ibfd, pos, SEEK_SET) != 0
+ || bfd_bread (extsym_buf, amt, ibfd) != amt)
+ {
+ intsym_buf = NULL;
+ goto out;
+ }
+
+ if (shndx_hdr == NULL || shndx_hdr->sh_size == 0)
+ extshndx_buf = NULL;
+ else
+ {
+ amt = symcount * sizeof (Elf_External_Sym_Shndx);
+ pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
+ if (extshndx_buf == NULL)
+ {
+ alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ extshndx_buf = alloc_extshndx;
+ }
+ if (extshndx_buf == NULL
+ || bfd_seek (ibfd, pos, SEEK_SET) != 0
+ || bfd_bread (extshndx_buf, amt, ibfd) != amt)
+ {
+ intsym_buf = NULL;
+ goto out;
+ }
+ }
+
+ if (intsym_buf == NULL)
+ {
+ bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
+ intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt);
+ 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;
+ isym < isymend;
+ esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
+ (*bed->s->swap_symbol_in) (ibfd, esym, (const PTR) shndx, isym);
+
+ out:
+ if (alloc_ext != NULL)
+ free (alloc_ext);
+ if (alloc_extshndx != NULL)
+ free (alloc_extshndx);
+
+ return intsym_buf;
+}
+
+/* Look up a symbol name. */
+const char *
+bfd_elf_local_sym_name (abfd, isym)
+ bfd *abfd;
+ Elf_Internal_Sym *isym;
+{
+ unsigned int iname = isym->st_name;
+ unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
+ if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ {
+ iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
+ shindex = elf_elfheader (abfd)->e_shstrndx;
+ }
+
+ return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+}
+
/* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
sections. The first element is the flags, the rest are section
pointers. */
unsigned int flags;
} Elf_Internal_Group;
+/* Return the name of the group signature symbol. Why isn't the
+ signature just a string? */
+
+static const char *
+group_signature (abfd, ghdr)
+ bfd *abfd;
+ Elf_Internal_Shdr *ghdr;
+{
+ Elf_Internal_Shdr *hdr;
+ unsigned char esym[sizeof (Elf64_External_Sym)];
+ Elf_External_Sym_Shndx eshndx;
+ Elf_Internal_Sym isym;
+
+ /* First we need to ensure the symbol table is available. */
+ if (! bfd_section_from_shdr (abfd, ghdr->sh_link))
+ return NULL;
+
+ /* Go read the symbol. */
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info,
+ &isym, esym, &eshndx) == NULL)
+ return NULL;
+
+ return bfd_elf_local_sym_name (abfd, &isym);
+}
+
/* Set next_in_group list pointer, and group name for NEWSECT. */
-static boolean
+static bfd_boolean
setup_group (abfd, hdr, newsect)
bfd *abfd;
Elf_Internal_Shdr *hdr;
bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *);
elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
if (elf_tdata (abfd)->group_sect_ptr == NULL)
- return false;
+ return FALSE;
num_group = 0;
for (i = 0; i < shnum; i++)
|| bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
|| (bfd_bread (shdr->contents, shdr->sh_size, abfd)
!= shdr->sh_size))
- return false;
+ return FALSE;
/* Translate raw contents, a flag word followed by an
array of elf section indices all in target byte order,
if (src == shdr->contents)
{
dest->flags = idx;
+ if (shdr->bfd_section != NULL && (idx & GRP_COMDAT))
+ shdr->bfd_section->flags
+ |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
break;
}
if (idx >= shnum)
}
else
{
- struct elf_backend_data *bed;
- file_ptr pos;
- unsigned char ename[4];
- unsigned long iname;
const char *gname;
- /* Humbug. Get the name from the group signature
- symbol. Why isn't the signature just a string?
- Fortunately, the name index is at the same
- place in the external symbol for both 32 and 64
- bit ELF. */
- bed = get_elf_backend_data (abfd);
- pos = elf_tdata (abfd)->symtab_hdr.sh_offset;
- pos += shdr->sh_info * bed->s->sizeof_sym;
- if (bfd_seek (abfd, pos, SEEK_SET) != 0
- || bfd_bread (ename, (bfd_size_type) 4, abfd) != 4)
- return false;
- iname = H_GET_32 (abfd, ename);
- gname = elf_string_from_elf_strtab (abfd, iname);
+ gname = group_signature (abfd, shdr);
+ if (gname == NULL)
+ return FALSE;
elf_group_name (newsect) = gname;
/* Start a circular list with one element. */
elf_next_in_group (newsect) = newsect;
}
+
+ /* If the group section has been created, point to the
+ new member. */
if (shdr->bfd_section != NULL)
elf_next_in_group (shdr->bfd_section) = newsect;
+
i = num_group - 1;
break;
}
(*_bfd_error_handler) (_("%s: no group info for section %s"),
bfd_archive_filename (abfd), newsect->name);
}
- return true;
+ return TRUE;
+}
+
+bfd_boolean
+bfd_elf_discard_group (abfd, group)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ asection *group;
+{
+ asection *first = elf_next_in_group (group);
+ asection *s = first;
+
+ while (s != NULL)
+ {
+ s->output_section = bfd_abs_section_ptr;
+ s = elf_next_in_group (s);
+ /* These lists are circular. */
+ if (s == first)
+ break;
+ }
+ return TRUE;
}
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
-boolean
+bfd_boolean
_bfd_elf_make_section_from_shdr (abfd, hdr, name)
bfd *abfd;
Elf_Internal_Shdr *hdr;
{
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)
- return false;
+ return FALSE;
newsect->filepos = hdr->sh_offset;
|| ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
|| ! bfd_set_section_alignment (abfd, newsect,
bfd_log2 ((bfd_vma) hdr->sh_addralign)))
- return false;
+ return FALSE;
flags = SEC_NO_FLAGS;
if (hdr->sh_type != SHT_NOBITS)
}
if (hdr->sh_flags & SHF_GROUP)
if (!setup_group (abfd, hdr, newsect))
- return false;
+ return FALSE;
+ if ((hdr->sh_flags & SHF_TLS) != 0)
+ flags |= SEC_THREAD_LOCAL;
/* The debugging sections appear to be recognized only by name, not
any sort of flag. */
The symbols will be defined as weak, so that multiple definitions
are permitted. The GNU linker extension is to actually discard
all but one of the sections. */
- if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
+ if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0
+ && elf_next_in_group (newsect) == NULL)
flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_flags)
if (! bed->elf_backend_section_flags (&flags, hdr))
- return false;
+ return FALSE;
if (! bfd_set_section_flags (abfd, newsect, flags))
- return false;
+ return FALSE;
if ((flags & SEC_ALLOC) != 0)
{
/* 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.
- If the p_paddr field is not set, we don't alter the
- LMA. */
+ 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
- && phdr->p_paddr
&& (bfd_vma) hdr->sh_offset >= phdr->p_offset
&& (hdr->sh_offset + hdr->sh_size
<= phdr->p_offset + phdr->p_memsz)
&& ((flags & SEC_LOAD) == 0
- || (phdr->p_offset + phdr->p_filesz
- >= hdr->sh_offset + hdr->sh_size)))
+ || (hdr->sh_offset + hdr->sh_size
+ <= phdr->p_offset + phdr->p_filesz)))
{
- /* We used to do a relative adjustment here, but
- that doesn't work if the segment is packed with
- code from multiple VMAs. Instead we calculate
- the LMA absoultely, based on the LMA of the
- segment (it is assumed that the segment will
- contain sections with contiguous LMAs, even if
- the VMAs are not). */
- newsect->lma = phdr->p_paddr
- + hdr->sh_offset - phdr->p_offset;
- break;
+ if ((flags & SEC_LOAD) == 0)
+ newsect->lma = (phdr->p_paddr
+ + hdr->sh_addr - phdr->p_vaddr);
+ else
+ /* We used to use the same adjustment for SEC_LOAD
+ sections, but that doesn't work if the segment
+ is packed with code from multiple VMAs.
+ Instead we calculate the section LMA based on
+ the segment LMA. It is assumed that the
+ segment will contain sections with contiguous
+ LMAs, even if the VMAs are not. */
+ newsect->lma = (phdr->p_paddr
+ + hdr->sh_offset - phdr->p_offset);
+
+ /* With contiguous segments, we can't tell from file
+ offsets whether a section with zero size should
+ be placed at the end of one segment or the
+ beginning of the next. Decide based on vaddr. */
+ if (hdr->sh_addr >= phdr->p_vaddr
+ && (hdr->sh_addr + hdr->sh_size
+ <= phdr->p_vaddr + phdr->p_memsz))
+ break;
}
}
}
hdr->bfd_section = newsect;
elf_section_data (newsect)->this_hdr = *hdr;
- return true;
+ return TRUE;
}
/*
"SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
};
-/* ELF relocs are against symbols. If we are producing relocateable
+/* ELF relocs are against symbols. If we are producing relocatable
output, and the reloc is against an external symbol, and nothing
has given us any additional addend, the resulting reloc will also
be against the same symbol. In such a case, we don't want to
all be done at final link time. Rather than put special case code
into bfd_perform_relocation, all the reloc types use this howto
function. It just short circuits the reloc if producing
- relocateable output against an external symbol. */
+ relocatable output against an external symbol. */
bfd_reloc_status_type
bfd_elf_generic_reloc (abfd,
bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
{
- struct bfd_elf_section_data *sec_data;
-
- sec_data = elf_section_data (sec);
- BFD_ASSERT (sec_data->sec_info_type == ELF_INFO_TYPE_MERGE);
- sec_data->sec_info_type = ELF_INFO_TYPE_NONE;
+ BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
+ sec->sec_info_type = ELF_INFO_TYPE_NONE;
}
/* Finish SHF_MERGE section merging. */
-boolean
+bfd_boolean
_bfd_elf_merge_sections (abfd, info)
bfd *abfd;
struct bfd_link_info *info;
{
if (!is_elf_hash_table (info))
- return false;
+ return FALSE;
if (elf_hash_table (info)->merge_info)
_bfd_merge_sections (abfd, elf_hash_table (info)->merge_info,
merge_sections_remove_hook);
- return true;
+ return TRUE;
+}
+
+void
+_bfd_elf_link_just_syms (sec, info)
+ asection *sec;
+ struct bfd_link_info *info;
+{
+ sec->output_section = bfd_abs_section_ptr;
+ sec->output_offset = sec->vma;
+ if (!is_elf_hash_table (info))
+ return;
+
+ sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
}
\f
/* Copy the program header and other data from one object module to
another. */
-boolean
+bfd_boolean
_bfd_elf_copy_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
+ return TRUE;
BFD_ASSERT (!elf_flags_init (obfd)
|| (elf_elfheader (obfd)->e_flags
elf_gp (obfd) = elf_gp (ibfd);
elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = true;
- return true;
+ elf_flags_init (obfd) = TRUE;
+ return TRUE;
}
/* Print out the program headers. */
-boolean
+bfd_boolean
_bfd_elf_print_private_bfd_data (abfd, farg)
bfd *abfd;
PTR farg;
case PT_NOTE: pt = "NOTE"; break;
case PT_SHLIB: pt = "SHLIB"; break;
case PT_PHDR: pt = "PHDR"; break;
+ case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
+ case PT_GNU_STACK: pt = "STACK"; break;
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
}
fprintf (f, "%8s off 0x", pt);
Elf_Internal_Dyn dyn;
const char *name;
char ab[20];
- boolean stringp;
+ bfd_boolean stringp;
(*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
if (dyn.d_tag == DT_NULL)
break;
- stringp = false;
+ stringp = FALSE;
switch (dyn.d_tag)
{
default:
name = ab;
break;
- case DT_NEEDED: name = "NEEDED"; stringp = true; break;
+ case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
case DT_PLTRELSZ: name = "PLTRELSZ"; break;
case DT_PLTGOT: name = "PLTGOT"; break;
case DT_HASH: name = "HASH"; break;
case DT_SYMENT: name = "SYMENT"; break;
case DT_INIT: name = "INIT"; break;
case DT_FINI: name = "FINI"; break;
- case DT_SONAME: name = "SONAME"; stringp = true; break;
- case DT_RPATH: name = "RPATH"; stringp = true; break;
+ case DT_SONAME: name = "SONAME"; stringp = TRUE; break;
+ case DT_RPATH: name = "RPATH"; stringp = TRUE; break;
case DT_SYMBOLIC: name = "SYMBOLIC"; break;
case DT_REL: name = "REL"; break;
case DT_RELSZ: name = "RELSZ"; break;
case DT_FINI_ARRAY: name = "FINI_ARRAY"; break;
case DT_INIT_ARRAYSZ: name = "INIT_ARRAYSZ"; break;
case DT_FINI_ARRAYSZ: name = "FINI_ARRAYSZ"; break;
- case DT_RUNPATH: name = "RUNPATH"; stringp = true; break;
+ case DT_RUNPATH: name = "RUNPATH"; stringp = TRUE; break;
case DT_FLAGS: name = "FLAGS"; break;
case DT_PREINIT_ARRAY: name = "PREINIT_ARRAY"; break;
case DT_PREINIT_ARRAYSZ: name = "PREINIT_ARRAYSZ"; break;
case DT_POSFLAG_1: name = "POSFLAG_1"; break;
case DT_SYMINSZ: name = "SYMINSZ"; break;
case DT_SYMINENT: name = "SYMINENT"; break;
- case DT_CONFIG: name = "CONFIG"; stringp = true; break;
- case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = true; break;
- case DT_AUDIT: name = "AUDIT"; stringp = true; break;
+ case DT_CONFIG: name = "CONFIG"; stringp = TRUE; break;
+ case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = TRUE; break;
+ case DT_AUDIT: name = "AUDIT"; stringp = TRUE; break;
case DT_PLTPAD: name = "PLTPAD"; break;
case DT_MOVETAB: name = "MOVETAB"; break;
case DT_SYMINFO: name = "SYMINFO"; break;
case DT_VERDEFNUM: name = "VERDEFNUM"; break;
case DT_VERNEED: name = "VERNEED"; break;
case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
- case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+ case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
case DT_USED: name = "USED"; break;
- case DT_FILTER: name = "FILTER"; stringp = true; break;
+ case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
}
fprintf (f, " %-11s ", name);
|| (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
{
if (! _bfd_elf_slurp_version_tables (abfd))
- return false;
+ return FALSE;
}
if (elf_dynverdef (abfd) != 0)
}
}
- return true;
+ return TRUE;
error_return:
if (dynbuf != NULL)
free (dynbuf);
- return false;
+ return FALSE;
}
/* Display ELF-specific fields of a symbol. */
/* Set local fields. */
ret->indx = -1;
- ret->size = 0;
ret->dynindx = -1;
ret->dynstr_index = 0;
+ ret->elf_hash_value = 0;
ret->weakdef = NULL;
- ret->got.refcount = htab->init_refcount;
- ret->plt.refcount = htab->init_refcount;
ret->linker_section_pointer = NULL;
ret->verinfo.verdef = NULL;
- ret->vtable_entries_used = NULL;
ret->vtable_entries_size = 0;
+ ret->vtable_entries_used = NULL;
ret->vtable_parent = NULL;
+ ret->got = htab->init_refcount;
+ ret->plt = htab->init_refcount;
+ ret->size = 0;
ret->type = STT_NOTYPE;
ret->other = 0;
/* Assume that we have been called by a non-ELF symbol reader.
old indirect symbol. Also used for copying flags to a weakdef. */
void
-_bfd_elf_link_hash_copy_indirect (dir, ind)
+_bfd_elf_link_hash_copy_indirect (bed, dir, ind)
+ struct elf_backend_data *bed;
struct elf_link_hash_entry *dir, *ind;
{
bfd_signed_vma tmp;
+ bfd_signed_vma lowest_valid = bed->can_refcount;
/* Copy down any references that we may have already seen to the
symbol which just became indirect. */
/* Copy over the global and procedure linkage table refcount entries.
These may have been already set up by a check_relocs routine. */
tmp = dir->got.refcount;
- if (tmp <= 0)
+ if (tmp < lowest_valid)
{
dir->got.refcount = ind->got.refcount;
ind->got.refcount = tmp;
}
else
- BFD_ASSERT (ind->got.refcount <= 0);
+ BFD_ASSERT (ind->got.refcount < lowest_valid);
tmp = dir->plt.refcount;
- if (tmp <= 0)
+ if (tmp < lowest_valid)
{
dir->plt.refcount = ind->plt.refcount;
ind->plt.refcount = tmp;
}
else
- BFD_ASSERT (ind->plt.refcount <= 0);
+ BFD_ASSERT (ind->plt.refcount < lowest_valid);
if (dir->dynindx == -1)
{
_bfd_elf_link_hash_hide_symbol (info, h, force_local)
struct bfd_link_info *info;
struct elf_link_hash_entry *h;
- boolean force_local;
+ bfd_boolean force_local;
{
- h->plt.offset = (bfd_vma) -1;
+ h->plt = elf_hash_table (info)->init_offset;
h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
if (force_local)
{
/* Initialize an ELF linker hash table. */
-boolean
+bfd_boolean
_bfd_elf_link_hash_table_init (table, abfd, newfunc)
struct elf_link_hash_table *table;
bfd *abfd;
- struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
- struct bfd_hash_table *,
- const char *));
+ struct bfd_hash_entry *(*newfunc)
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
{
- boolean ret;
+ bfd_boolean ret;
- table->dynamic_sections_created = false;
+ table->dynamic_sections_created = FALSE;
table->dynobj = NULL;
- table->init_refcount = get_elf_backend_data (abfd)->can_refcount - 1;
+ /* Make sure can_refcount is extended to the width and signedness of
+ init_refcount before we subtract one from it. */
+ table->init_refcount.refcount = get_elf_backend_data (abfd)->can_refcount;
+ table->init_refcount.refcount -= 1;
+ table->init_offset.offset = -(bfd_vma) 1;
/* The first dynamic symbol is a dummy. */
table->dynsymcount = 1;
table->dynstr = NULL;
table->bucketcount = 0;
table->needed = NULL;
- table->runpath = NULL;
table->hgot = NULL;
table->stab_info = NULL;
table->merge_info = NULL;
+ memset (&table->eh_info, 0, sizeof (table->eh_info));
table->dynlocal = NULL;
- ret = _bfd_link_hash_table_init (& table->root, abfd, newfunc);
+ table->runpath = NULL;
+ table->tls_segment = NULL;
+ table->loaded = NULL;
+
+ ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
table->root.type = bfd_link_elf_hash_table;
return ret;
struct elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_link_hash_table);
- ret = (struct elf_link_hash_table *) bfd_alloc (abfd, amt);
+ ret = (struct elf_link_hash_table *) bfd_malloc (amt);
if (ret == (struct elf_link_hash_table *) NULL)
return NULL;
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
{
- bfd_release (abfd, ret);
+ free (ret);
return NULL;
}
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
- if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ if (! is_elf_hash_table (info))
return NULL;
return elf_hash_table (info)->needed;
}
bfd *abfd ATTRIBUTE_UNUSED;
struct bfd_link_info *info;
{
- if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ if (! is_elf_hash_table (info))
return NULL;
return elf_hash_table (info)->runpath;
}
/* Get the list of DT_NEEDED entries from a BFD. This is a hook for
the ELF linker emulation code. */
-boolean
+bfd_boolean
bfd_elf_get_bfd_needed_list (abfd, pneeded)
bfd *abfd;
struct bfd_link_needed_list **pneeded;
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
|| bfd_get_format (abfd) != bfd_object)
- return true;
+ return TRUE;
s = bfd_get_section_by_name (abfd, ".dynamic");
if (s == NULL || s->_raw_size == 0)
- return true;
+ return TRUE;
dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
if (dynbuf == NULL)
free (dynbuf);
- return true;
+ return TRUE;
error_return:
if (dynbuf != NULL)
free (dynbuf);
- return false;
+ return FALSE;
}
\f
/* Allocate an ELF string table--force the first byte to be zero. */
{
bfd_size_type loc;
- loc = _bfd_stringtab_add (ret, "", true, false);
+ loc = _bfd_stringtab_add (ret, "", TRUE, FALSE);
BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
if (loc == (bfd_size_type) -1)
{
/* Create a new bfd section from an ELF section header. */
-boolean
+bfd_boolean
bfd_section_from_shdr (abfd, shindex)
bfd *abfd;
unsigned int shindex;
Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- char *name;
+ const char *name;
name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
{
case SHT_NULL:
/* Inactive section. Throw it away. */
- return true;
+ return TRUE;
case SHT_PROGBITS: /* Normal section with contents. */
- case SHT_DYNAMIC: /* Dynamic linking information. */
case SHT_NOBITS: /* .bss section. */
case SHT_HASH: /* .hash section. */
case SHT_NOTE: /* .note section. */
+ case SHT_INIT_ARRAY: /* .init_array section. */
+ case SHT_FINI_ARRAY: /* .fini_array section. */
+ case SHT_PREINIT_ARRAY: /* .preinit_array section. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ case SHT_DYNAMIC: /* Dynamic linking information. */
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ return FALSE;
+ if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
+ {
+ Elf_Internal_Shdr *dynsymhdr;
+
+ /* The shared libraries distributed with hpux11 have a bogus
+ sh_link field for the ".dynamic" section. Find the
+ string table for the ".dynsym" section instead. */
+ if (elf_dynsymtab (abfd) != 0)
+ {
+ dynsymhdr = elf_elfsections (abfd)[elf_dynsymtab (abfd)];
+ hdr->sh_link = dynsymhdr->sh_link;
+ }
+ else
+ {
+ unsigned int i, num_sec;
+
+ num_sec = elf_numsections (abfd);
+ for (i = 1; i < num_sec; i++)
+ {
+ dynsymhdr = elf_elfsections (abfd)[i];
+ if (dynsymhdr->sh_type == SHT_DYNSYM)
+ {
+ hdr->sh_link = dynsymhdr->sh_link;
+ break;
+ }
+ }
+ }
+ }
+ break;
+
case SHT_SYMTAB: /* A symbol table */
if (elf_onesymtab (abfd) == shindex)
- return true;
+ return TRUE;
BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
BFD_ASSERT (elf_onesymtab (abfd) == 0);
SHF_ALLOC is set, and this is a shared object, then we also
treat this section as a BFD section. We can not base the
decision purely on SHF_ALLOC, because that flag is sometimes
- set in a relocateable object file, which would confuse the
+ set in a relocatable object file, which would confuse the
linker. */
if ((hdr->sh_flags & SHF_ALLOC) != 0
&& (abfd->flags & DYNAMIC) != 0
&& ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
- return false;
+ return FALSE;
- return true;
+ return TRUE;
case SHT_DYNSYM: /* A dynamic symbol table */
if (elf_dynsymtab (abfd) == shindex)
- return true;
+ return TRUE;
BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
BFD_ASSERT (elf_dynsymtab (abfd) == 0);
case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */
if (elf_symtab_shndx (abfd) == shindex)
- return true;
+ return TRUE;
/* Get the associated symbol table. */
if (! bfd_section_from_shdr (abfd, hdr->sh_link)
|| hdr->sh_link != elf_onesymtab (abfd))
- return false;
+ return FALSE;
elf_symtab_shndx (abfd) = shindex;
elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
- return true;
+ return TRUE;
case SHT_STRTAB: /* A string table */
if (hdr->bfd_section != NULL)
- return true;
+ return TRUE;
if (ehdr->e_shstrndx == shindex)
{
elf_tdata (abfd)->shstrtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
- return true;
+ return TRUE;
}
{
unsigned int i, num_sec;
if (hdr2->sh_link == shindex)
{
if (! bfd_section_from_shdr (abfd, i))
- return false;
+ return FALSE;
if (elf_onesymtab (abfd) == i)
{
elf_tdata (abfd)->strtab_hdr = *hdr;
elf_elfsections (abfd)[shindex] =
&elf_tdata (abfd)->strtab_hdr;
- return true;
+ return TRUE;
}
if (elf_dynsymtab (abfd) == i)
{
/* Get the symbol table. */
if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
&& ! bfd_section_from_shdr (abfd, hdr->sh_link))
- return false;
+ return FALSE;
/* If this reloc section does not use the main symbol table we
don't treat it as a reloc section. BFD can't adequately
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
if (! bfd_section_from_shdr (abfd, hdr->sh_info))
- return false;
+ return FALSE;
target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
if (target_sect == NULL)
- return false;
+ return FALSE;
if ((target_sect->flags & SEC_RELOC) == 0
|| target_sect->reloc_count == 0)
/* In the section to which the relocations apply, mark whether
its relocations are of the REL or RELA variety. */
if (hdr->sh_size != 0)
- elf_section_data (target_sect)->use_rela_p
- = (hdr->sh_type == SHT_RELA);
+ target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
abfd->flags |= HAS_RELOC;
- return true;
+ return TRUE;
}
break;
break;
case SHT_SHLIB:
- return true;
+ return TRUE;
case SHT_GROUP:
- /* Make a section for objcopy and relocatable links. */
+ /* We need a BFD section for objcopy and relocatable linking,
+ and it's handy to have the signature available as the section
+ name. */
+ name = group_signature (abfd, hdr);
+ if (name == NULL)
+ return FALSE;
if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
- return false;
+ return FALSE;
if (hdr->contents != NULL)
{
Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
unsigned int n_elt = hdr->sh_size / 4;
asection *s;
+ if (idx->flags & GRP_COMDAT)
+ hdr->bfd_section->flags
+ |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
+
while (--n_elt != 0)
if ((s = (++idx)->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
break;
}
- return true;
+ return TRUE;
}
/* Return the section for the local symbol specified by ABFD, R_SYMNDX.
asection *sec;
unsigned long r_symndx;
{
- unsigned char esym_shndx[4];
- unsigned int isym_shndx;
Elf_Internal_Shdr *symtab_hdr;
- file_ptr pos;
- bfd_size_type amt;
+ unsigned char esym[sizeof (Elf64_External_Sym)];
+ Elf_External_Sym_Shndx eshndx;
+ Elf_Internal_Sym isym;
unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
return cache->sec[ent];
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
- pos = symtab_hdr->sh_offset;
- if (get_elf_backend_data (abfd)->s->sizeof_sym
- == sizeof (Elf64_External_Sym))
- {
- pos += r_symndx * sizeof (Elf64_External_Sym);
- pos += offsetof (Elf64_External_Sym, st_shndx);
- amt = sizeof (((Elf64_External_Sym *) 0)->st_shndx);
- }
- else
- {
- pos += r_symndx * sizeof (Elf32_External_Sym);
- pos += offsetof (Elf32_External_Sym, st_shndx);
- amt = sizeof (((Elf32_External_Sym *) 0)->st_shndx);
- }
- if (bfd_seek (abfd, pos, SEEK_SET) != 0
- || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+ if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
+ &isym, esym, &eshndx) == NULL)
return NULL;
- isym_shndx = H_GET_16 (abfd, esym_shndx);
-
- if (isym_shndx == SHN_XINDEX)
- {
- Elf_Internal_Shdr *shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (shndx_hdr->sh_size != 0)
- {
- pos = shndx_hdr->sh_offset;
- pos += r_symndx * sizeof (Elf_External_Sym_Shndx);
- amt = sizeof (Elf_External_Sym_Shndx);
- if (bfd_seek (abfd, pos, SEEK_SET) != 0
- || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
- return NULL;
- isym_shndx = H_GET_32 (abfd, esym_shndx);
- }
- }
if (cache->abfd != abfd)
{
}
cache->indx[ent] = r_symndx;
cache->sec[ent] = sec;
- if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE)
+ if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
{
asection *s;
- s = bfd_section_from_elf_index (abfd, isym_shndx);
+ s = bfd_section_from_elf_index (abfd, isym.st_shndx);
if (s != NULL)
cache->sec[ent] = s;
}
return elf_elfsections (abfd)[index]->bfd_section;
}
-boolean
+bfd_boolean
_bfd_elf_new_section_hook (abfd, sec)
bfd *abfd;
asection *sec;
{
struct bfd_elf_section_data *sdata;
- bfd_size_type amt = sizeof (*sdata);
- sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
- if (!sdata)
- return false;
- sec->used_by_bfd = (PTR) sdata;
+ sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
+ if (sdata == NULL)
+ {
+ bfd_size_type amt = sizeof (*sdata);
+ sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
+ if (sdata == NULL)
+ return FALSE;
+ sec->used_by_bfd = (PTR) sdata;
+ }
/* Indicate whether or not this section should use RELA relocations. */
- sdata->use_rela_p
- = get_elf_backend_data (abfd)->default_use_rela_p;
+ sec->use_rela_p = get_elf_backend_data (abfd)->default_use_rela_p;
- return true;
+ return TRUE;
}
/* Create a new bfd section from an ELF program header.
*/
-boolean
+bfd_boolean
_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
bfd *abfd;
Elf_Internal_Phdr *hdr;
asection *newsect;
char *name;
char namebuf[64];
+ size_t len;
int split;
split = ((hdr->p_memsz > 0)
&& (hdr->p_filesz > 0)
&& (hdr->p_memsz > hdr->p_filesz));
sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
- name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
+ len = strlen (namebuf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (!name)
- return false;
- strcpy (name, namebuf);
+ return FALSE;
+ memcpy (name, namebuf, len);
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
- return false;
+ return FALSE;
newsect->vma = hdr->p_vaddr;
newsect->lma = hdr->p_paddr;
newsect->_raw_size = hdr->p_filesz;
if (split)
{
sprintf (namebuf, "%s%db", typename, index);
- name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
+ len = strlen (namebuf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (!name)
- return false;
- strcpy (name, namebuf);
+ return FALSE;
+ memcpy (name, namebuf, len);
newsect = bfd_make_section (abfd, name);
if (newsect == NULL)
- return false;
+ return FALSE;
newsect->vma = hdr->p_vaddr + hdr->p_filesz;
newsect->lma = hdr->p_paddr + hdr->p_filesz;
newsect->_raw_size = hdr->p_memsz - hdr->p_filesz;
newsect->flags |= SEC_READONLY;
}
- return true;
+ return TRUE;
}
-boolean
+bfd_boolean
bfd_section_from_phdr (abfd, hdr, index)
bfd *abfd;
Elf_Internal_Phdr *hdr;
case PT_NOTE:
if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
- return false;
+ return FALSE;
if (! elfcore_read_notes (abfd, (file_ptr) hdr->p_offset, hdr->p_filesz))
- return false;
- return true;
+ return FALSE;
+ return TRUE;
case PT_SHLIB:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib");
case PT_PHDR:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
+ case PT_GNU_EH_FRAME:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+ "eh_frame_hdr");
+
+ case PT_GNU_STACK:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+
default:
/* Check for any processor-specific program segment types.
If no handler for them, default to making "segment" sections. */
}
/* Initialize REL_HDR, the section-header for new section, containing
- relocations against ASECT. If USE_RELA_P is true, we use RELA
+ relocations against ASECT. If USE_RELA_P is TRUE, we use RELA
relocations; otherwise, we use REL relocations. */
-boolean
+bfd_boolean
_bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
bfd *abfd;
Elf_Internal_Shdr *rel_hdr;
asection *asect;
- boolean use_rela_p;
+ bfd_boolean use_rela_p;
{
char *name;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
name = bfd_alloc (abfd, amt);
if (name == NULL)
- return false;
+ return FALSE;
sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
rel_hdr->sh_name =
(unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
- false);
+ FALSE);
if (rel_hdr->sh_name == (unsigned int) -1)
- return false;
+ return FALSE;
rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
rel_hdr->sh_entsize = (use_rela_p
? bed->s->sizeof_rela
: bed->s->sizeof_rel);
- rel_hdr->sh_addralign = bed->s->file_align;
+ rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
rel_hdr->sh_flags = 0;
rel_hdr->sh_addr = 0;
rel_hdr->sh_size = 0;
rel_hdr->sh_offset = 0;
- return true;
+ return TRUE;
}
/* Set up an ELF internal section header for a section. */
PTR failedptrarg;
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- boolean *failedptr = (boolean *) failedptrarg;
+ bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
Elf_Internal_Shdr *this_hdr;
if (*failedptr)
this_hdr = &elf_section_data (asect)->this_hdr;
- this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd),
- asect->name, false);
- if (this_hdr->sh_name == (unsigned long) -1)
+ 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;
+ *failedptr = TRUE;
return;
}
this_hdr->sh_type = SHT_REL;
this_hdr->sh_entsize = bed->s->sizeof_rel;
}
+ else if (strcmp (asect->name, ".init_array") == 0)
+ this_hdr->sh_type = SHT_INIT_ARRAY;
+ else if (strcmp (asect->name, ".fini_array") == 0)
+ this_hdr->sh_type = SHT_FINI_ARRAY;
+ else if (strcmp (asect->name, ".preinit_array") == 0)
+ this_hdr->sh_type = SHT_PREINIT_ARRAY;
else if (strncmp (asect->name, ".note", 5) == 0)
this_hdr->sh_type = SHT_NOTE;
else if (strncmp (asect->name, ".stab", 5) == 0
this_hdr->sh_entsize = 4;
}
else if ((asect->flags & SEC_ALLOC) != 0
- && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0))
+ && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ || (asect->flags & SEC_NEVER_LOAD) != 0))
this_hdr->sh_type = SHT_NOBITS;
else
this_hdr->sh_type = SHT_PROGBITS;
if ((asect->flags & SEC_STRINGS) != 0)
this_hdr->sh_flags |= SHF_STRINGS;
}
- if (elf_group_name (asect) != NULL)
+ if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
this_hdr->sh_flags |= SHF_GROUP;
+ if ((asect->flags & SEC_THREAD_LOCAL) != 0)
+ {
+ this_hdr->sh_flags |= SHF_TLS;
+ if (asect->_raw_size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ struct bfd_link_order *o;
+
+ this_hdr->sh_size = 0;
+ for (o = asect->link_order_head; o != NULL; o = o->next)
+ if (this_hdr->sh_size < o->offset + o->size)
+ this_hdr->sh_size = o->offset + o->size;
+ if (this_hdr->sh_size)
+ this_hdr->sh_type = SHT_NOBITS;
+ }
+ }
/* Check for processor-specific section types. */
if (bed->elf_backend_fake_sections
&& !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
- *failedptr = true;
+ *failedptr = TRUE;
/* If the section has relocs, set up a section header for the
SHT_REL[A] section. If two relocation sections are required for
&& !_bfd_elf_init_reloc_shdr (abfd,
&elf_section_data (asect)->rel_hdr,
asect,
- elf_section_data (asect)->use_rela_p))
- *failedptr = true;
+ asect->use_rela_p))
+ *failedptr = TRUE;
}
/* Fill in the contents of a SHT_GROUP section. */
-static void
-set_group_contents (abfd, sec, failedptrarg)
+void
+bfd_elf_set_group_contents (abfd, sec, failedptrarg)
bfd *abfd;
asection *sec;
- PTR failedptrarg ATTRIBUTE_UNUSED;
+ PTR failedptrarg;
{
- boolean *failedptr = (boolean *) failedptrarg;
+ bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
unsigned long symindx;
- asection *elt;
+ asection *elt, *first;
unsigned char *loc;
struct bfd_link_order *l;
+ bfd_boolean gas;
if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
|| *failedptr)
return;
- /* If called from the assembler, swap_out_syms will have set up
- elf_section_syms; If called for "ld -r", the symbols won't yet
- be mapped, so emulate elf_bfd_final_link. */
- if (elf_section_syms (abfd) != NULL)
- symindx = elf_section_syms (abfd)[sec->index]->udata.i;
- else
- symindx = elf_section_data (sec)->this_idx;
+ symindx = 0;
+ if (elf_group_id (sec) != NULL)
+ symindx = elf_group_id (sec)->udata.i;
+
+ if (symindx == 0)
+ {
+ /* If called from the assembler, swap_out_syms will have set up
+ elf_section_syms; If called for "ld -r", use target_index. */
+ if (elf_section_syms (abfd) != NULL)
+ symindx = elf_section_syms (abfd)[sec->index]->udata.i;
+ else
+ symindx = sec->target_index;
+ }
elf_section_data (sec)->this_hdr.sh_info = symindx;
- /* Nor will the contents be allocated for "ld -r". */
+ /* The contents won't be allocated for "ld -r" or objcopy. */
+ gas = TRUE;
if (sec->contents == NULL)
{
+ gas = FALSE;
sec->contents = bfd_alloc (abfd, sec->_raw_size);
+
+ /* Arrange for the section to be written out. */
+ elf_section_data (sec)->this_hdr.contents = sec->contents;
if (sec->contents == NULL)
{
- *failedptr = true;
+ *failedptr = TRUE;
return;
}
}
loc = sec->contents + sec->_raw_size;
- /* Get the pointer to the first section in the group that we
- squirreled away here. */
- elt = elf_next_in_group (sec);
+ /* Get the pointer to the first section in the group that gas
+ squirreled away here. objcopy arranges for this to be set to the
+ start of the input section group. */
+ first = elt = elf_next_in_group (sec);
/* First element is a flag word. Rest of section is elf section
indices for all the sections of the group. Write them backwards
directives, not that it matters. */
while (elt != NULL)
{
+ asection *s;
+ unsigned int idx;
+
loc -= 4;
- H_PUT_32 (abfd, elf_section_data (elt)->this_idx, loc);
+ s = elt;
+ 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 (elt == first)
+ break;
}
/* If this is a relocatable link, then the above did nothing because
}
while (elt != elf_next_in_group (l->u.indirect.section));
- loc -= 4;
- H_PUT_32 (abfd, 0, loc);
+ /* With ld -r, merging SHT_GROUP sections results in wasted space
+ due to allowing for the flag word on each input. We may well
+ duplicate entries too. */
+ while ((loc -= 4) > sec->contents)
+ H_PUT_32 (abfd, 0, loc);
- BFD_ASSERT (loc == sec->contents);
+ if (loc != sec->contents)
+ abort ();
+
+ H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
}
/* Assign all ELF section numbers. The dummy first section is handled here
too. The link/info pointers for the standard section types are filled
in here too, while we're at it. */
-static boolean
+static bfd_boolean
assign_section_numbers (abfd)
bfd *abfd;
{
t->symtab_shndx_section = section_number++;
t->symtab_shndx_hdr.sh_name
= (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
- ".symtab_shndx", false);
+ ".symtab_shndx", FALSE);
if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
- return false;
+ return FALSE;
}
if (section_number == SHN_LORESERVE)
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
/* Set up the list of section header pointers, in agreement with the
indices. */
amt = section_number * sizeof (Elf_Internal_Shdr *);
- i_shdrp = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
+ i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc (abfd, amt);
if (i_shdrp == NULL)
- return false;
+ return FALSE;
amt = sizeof (Elf_Internal_Shdr);
- i_shdrp[0] = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+ i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
if (i_shdrp[0] == NULL)
{
bfd_release (abfd, i_shdrp);
- return false;
+ return FALSE;
}
- memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
elf_elfsections (abfd) = i_shdrp;
char *alc;
len = strlen (sec->name);
- alc = (char *) bfd_malloc ((bfd_size_type) len - 2);
+ alc = (char *) bfd_malloc ((bfd_size_type) (len - 2));
if (alc == NULL)
- return false;
- strncpy (alc, sec->name, len - 3);
+ return FALSE;
+ memcpy (alc, sec->name, len - 3);
alc[len - 3] = '\0';
s = bfd_get_section_by_name (abfd, alc);
free (alc);
elf_section_data (s)->this_hdr.sh_link = d->this_idx;
/* This is a .stab section. */
- elf_section_data (s)->this_hdr.sh_entsize =
- 4 + 2 * bfd_get_arch_size (abfd) / 8;
+ if (elf_section_data (s)->this_hdr.sh_entsize == 0)
+ elf_section_data (s)->this_hdr.sh_entsize
+ = 4 + 2 * bfd_get_arch_size (abfd) / 8;
}
}
break;
else
i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
i_shdrp[secn]->sh_name);
- return true;
+ return TRUE;
}
/* Map symbol from it's internal number to the external number, moving
|| bfd_is_com_section (bfd_get_section (sym)));
}
-static boolean
+static bfd_boolean
elf_map_symbols (abfd)
bfd *abfd;
{
amt = max_index * sizeof (asymbol *);
sect_syms = (asymbol **) bfd_zalloc (abfd, amt);
if (sect_syms == NULL)
- return false;
+ return FALSE;
elf_section_syms (abfd) = sect_syms;
elf_num_section_syms (abfd) = max_index;
new_syms = (asymbol **) bfd_alloc (abfd, amt);
if (new_syms == NULL)
- return false;
+ return FALSE;
for (idx = 0; idx < symcount; idx++)
{
elf_num_locals (abfd) = num_locals;
elf_num_globals (abfd) = num_globals;
- return true;
+ return TRUE;
}
/* Align to the maximum file alignment that could be required for any
ELF data structure. */
-static INLINE file_ptr align_file_position PARAMS ((file_ptr, int));
+static INLINE file_ptr align_file_position
+ PARAMS ((file_ptr, int));
static INLINE file_ptr
align_file_position (off, align)
file_ptr off;
_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
Elf_Internal_Shdr *i_shdrp;
file_ptr offset;
- boolean align;
+ bfd_boolean align;
{
if (align)
{
otherwise prepare to begin writing out the ELF file. If LINK_INFO
is not NULL, this is being called by the ELF backend linker. */
-boolean
+bfd_boolean
_bfd_elf_compute_section_file_positions (abfd, link_info)
bfd *abfd;
struct bfd_link_info *link_info;
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- boolean failed;
+ bfd_boolean failed;
struct bfd_strtab_hash *strtab;
Elf_Internal_Shdr *shstrtab_hdr;
if (abfd->output_has_begun)
- return true;
+ return TRUE;
/* Do any elf backend specific processing first. */
if (bed->elf_backend_begin_write_processing)
(*bed->elf_backend_begin_write_processing) (abfd, link_info);
if (! prep_headers (abfd))
- return false;
+ return FALSE;
/* Post process the headers if necessary. */
if (bed->elf_backend_post_process_headers)
(*bed->elf_backend_post_process_headers) (abfd, link_info);
- failed = false;
+ failed = FALSE;
bfd_map_over_sections (abfd, elf_fake_sections, &failed);
if (failed)
- return false;
+ return FALSE;
if (!assign_section_numbers (abfd))
- return false;
+ return FALSE;
/* The backend linker builds symbol table information itself. */
if (link_info == NULL && bfd_get_symcount (abfd) > 0)
int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
if (! swap_out_syms (abfd, &strtab, relocatable_p))
- return false;
+ return FALSE;
}
- if (link_info == NULL || link_info->relocateable)
+ if (link_info == NULL)
{
- bfd_map_over_sections (abfd, set_group_contents, &failed);
+ bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
if (failed)
- return false;
+ return FALSE;
}
shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
shstrtab_hdr->sh_addralign = 1;
if (!assign_file_positions_except_relocs (abfd))
- return false;
+ return FALSE;
if (link_info == NULL && bfd_get_symcount (abfd) > 0)
{
off = elf_tdata (abfd)->next_file_pos;
hdr = &elf_tdata (abfd)->symtab_hdr;
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
if (hdr->sh_size != 0)
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
hdr = &elf_tdata (abfd)->strtab_hdr;
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
elf_tdata (abfd)->next_file_pos = off;
out. */
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
|| ! _bfd_stringtab_emit (abfd, strtab))
- return false;
+ return FALSE;
_bfd_stringtab_free (strtab);
}
- abfd->output_has_begun = true;
+ abfd->output_has_begun = TRUE;
- return true;
+ return TRUE;
}
/* Create a mapping from a set of sections to a program segment. */
asection **sections;
unsigned int from;
unsigned int to;
- boolean phdr;
+ bfd_boolean phdr;
{
struct elf_segment_map *m;
unsigned int i;
/* Set up a mapping from BFD sections to program segments. */
-static boolean
+static bfd_boolean
map_sections_to_segments (abfd)
bfd *abfd;
{
unsigned int phdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
- boolean phdr_in_segment = true;
- boolean writable;
+ bfd_boolean phdr_in_segment = TRUE;
+ bfd_boolean writable;
+ int tls_count = 0;
+ asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
bfd_size_type amt;
if (elf_tdata (abfd)->segment_map != NULL)
- return true;
+ return TRUE;
if (bfd_count_sections (abfd) == 0)
- return true;
+ return TRUE;
/* Select the allocated sections, and sort them. */
last_hdr = NULL;
phdr_index = 0;
maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
- writable = false;
+ writable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
if (dynsec != NULL
&& (dynsec->flags & SEC_LOAD) == 0)
if ((abfd->flags & D_PAGED) == 0
|| sections[0]->lma < phdr_size
|| sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
- phdr_in_segment = false;
+ phdr_in_segment = FALSE;
}
for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
{
asection *hdr;
- boolean new_segment;
+ bfd_boolean new_segment;
hdr = *hdrpp;
{
/* If we don't have a segment yet, then we don't need a new
one (we build the last one after this loop). */
- new_segment = false;
+ new_segment = FALSE;
}
else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
{
/* If this section has a different relation between the
virtual address and the load address, then we need a new
segment. */
- new_segment = true;
+ new_segment = TRUE;
}
else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
< BFD_ALIGN (hdr->lma, maxpagesize))
{
/* If putting this section in this segment would force us to
skip a page in the segment, then we need a new segment. */
- new_segment = true;
+ new_segment = TRUE;
}
else if ((last_hdr->flags & SEC_LOAD) == 0
&& (hdr->flags & SEC_LOAD) != 0)
{
/* We don't want to put a loadable section after a
nonloadable section in the same segment. */
- new_segment = true;
+ new_segment = TRUE;
}
else if ((abfd->flags & D_PAGED) == 0)
{
/* If the file is not demand paged, which means that we
don't require the sections to be correctly aligned in the
file, then there is no other reason for a new segment. */
- new_segment = false;
+ new_segment = FALSE;
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
- && (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
- == hdr->lma))
+ && (((last_hdr->lma + last_hdr->_raw_size - 1)
+ & ~(maxpagesize - 1))
+ != (hdr->lma & ~(maxpagesize - 1))))
{
/* We don't want to put a writable section in a read only
segment, unless they are on the same page in memory
only case in which the new section is not on the same
page as the previous section is when the previous section
ends precisely on a page boundary. */
- new_segment = true;
+ new_segment = TRUE;
}
else
{
/* Otherwise, we can use the same segment. */
- new_segment = false;
+ new_segment = FALSE;
}
if (! new_segment)
{
if ((hdr->flags & SEC_READONLY) == 0)
- writable = true;
+ writable = TRUE;
last_hdr = hdr;
continue;
}
pm = &m->next;
if ((hdr->flags & SEC_READONLY) == 0)
- writable = true;
+ writable = TRUE;
else
- writable = false;
+ writable = FALSE;
last_hdr = hdr;
phdr_index = i;
- phdr_in_segment = false;
+ phdr_in_segment = FALSE;
}
/* Create a final PT_LOAD program segment. */
*pm = m;
pm = &m->next;
}
+ if (s->flags & SEC_THREAD_LOCAL)
+ {
+ if (! tls_count)
+ first_tls = s;
+ tls_count++;
+ }
+ }
+
+ /* 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 = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_TLS;
+ m->count = tls_count;
+ /* Mandated PF_R. */
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+ for (i = 0; i < tls_count; ++i)
+ {
+ BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
+ m->sections[i] = first_tls;
+ first_tls = first_tls->next;
+ }
+
+ *pm = m;
+ pm = &m->next;
}
/* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
segment. */
- eh_frame_hdr = NULL;
- if (elf_tdata (abfd)->eh_frame_hdr)
- eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
- if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
+ eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
+ if (eh_frame_hdr != NULL
+ && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
m->next = NULL;
m->p_type = PT_GNU_EH_FRAME;
m->count = 1;
- m->sections[0] = eh_frame_hdr;
+ m->sections[0] = eh_frame_hdr->output_section;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ amt = sizeof (struct elf_segment_map);
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_STACK;
+ m->p_flags = elf_tdata (abfd)->stack_flags;
+ m->p_flags_valid = 1;
*pm = m;
pm = &m->next;
sections = NULL;
elf_tdata (abfd)->segment_map = mfirst;
- return true;
+ return TRUE;
error_return:
if (sections != NULL)
free (sections);
- return false;
+ return FALSE;
}
/* Sort sections by address. */
{
const asection *sec1 = *(const asection **) arg1;
const asection *sec2 = *(const asection **) arg2;
+ bfd_size_type size1, size2;
/* Sort by LMA first, since this is the address used to
place the section into a segment. */
/* Put !SEC_LOAD sections after SEC_LOAD ones. */
-#define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
if (TOEND (sec1))
{
/* Sort by size, to put zero sized sections
before others at the same address. */
- if (sec1->_raw_size < sec2->_raw_size)
+ size1 = (sec1->flags & SEC_LOAD) ? sec1->_raw_size : 0;
+ size2 = (sec2->flags & SEC_LOAD) ? sec2->_raw_size : 0;
+
+ if (size1 < size2)
return -1;
- if (sec1->_raw_size > sec2->_raw_size)
+ if (size1 > size2)
return 1;
return sec1->target_index - sec2->target_index;
sections to segments. This function also sets up some fields in
the file header, and writes out the program headers. */
-static boolean
+static bfd_boolean
assign_file_positions_for_segments (abfd)
bfd *abfd;
{
if (elf_tdata (abfd)->segment_map == NULL)
{
if (! map_sections_to_segments (abfd))
- return false;
+ return FALSE;
+ }
+ else
+ {
+ /* The placement algorithm assumes that non allocated sections are
+ not in PT_LOAD segments. We ensure this here by removing such
+ sections from the segment map. */
+ for (m = elf_tdata (abfd)->segment_map;
+ m != NULL;
+ m = m->next)
+ {
+ unsigned int new_count;
+ unsigned int i;
+
+ if (m->p_type != PT_LOAD)
+ continue;
+
+ new_count = 0;
+ for (i = 0; i < m->count; i ++)
+ {
+ if ((m->sections[i]->flags & SEC_ALLOC) != 0)
+ {
+ if (i != new_count)
+ m->sections[new_count] = m->sections[i];
+
+ new_count ++;
+ }
+ }
+
+ if (new_count != m->count)
+ m->count = new_count;
+ }
}
if (bed->elf_backend_modify_segment_map)
{
if (! (*bed->elf_backend_modify_segment_map) (abfd))
- return false;
+ return FALSE;
}
count = 0;
elf_elfheader (abfd)->e_phnum = count;
if (count == 0)
- return true;
+ return TRUE;
/* If we already counted the number of program segments, make sure
that we allocated enough space. This happens when SIZEOF_HEADERS
(_("%s: Not enough room for program headers (allocated %u, need %u)"),
bfd_get_filename (abfd), alloc, count));
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
if (alloc == 0)
amt = alloc * sizeof (Elf_Internal_Phdr);
phdrs = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
if (phdrs == NULL)
- return false;
+ return FALSE;
off = bed->s->sizeof_ehdr;
off += alloc * bed->s->sizeof_phdr;
asection **secpp;
/* If elf_segment_map is not from map_sections_to_segments, the
- sections may not be correctly ordered. NOTE: sorting should
+ sections may not be correctly ordered. NOTE: sorting should
not be done to the PT_NOTE section of a corefile, which may
contain several pseudo-sections artificially created by bfd.
Sorting these pseudo-sections breaks things badly. */
- if (m->count > 1
- && !(elf_elfheader (abfd)->e_type == ET_CORE
+ if (m->count > 1
+ && !(elf_elfheader (abfd)->e_type == ET_CORE
&& m->p_type == PT_NOTE))
qsort (m->sections, (size_t) m->count, sizeof (asection *),
elf_sort_sections);
&& (abfd->flags & D_PAGED) != 0)
p->p_align = bed->maxpagesize;
else if (m->count == 0)
- p->p_align = bed->s->file_align;
+ p->p_align = 1 << bed->s->log_file_align;
else
p->p_align = 0;
if (p->p_vaddr < (bfd_vma) off)
{
- _bfd_error_handler (_("%s: Not enough room for program headers, try linking with -N"),
- bfd_get_filename (abfd));
+ (*_bfd_error_handler)
+ (_("%s: Not enough room for program headers, try linking with -N"),
+ bfd_get_filename (abfd));
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
p->p_vaddr -= off;
bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
p->p_memsz += adjust;
- off += adjust;
- voff += adjust;
- if ((flags & SEC_LOAD) != 0)
+ if (p->p_type == PT_LOAD
+ || (p->p_type == PT_NOTE
+ && bfd_get_format (abfd) == bfd_core))
+ {
+ off += adjust;
+ voff += adjust;
+ }
+ if ((flags & SEC_LOAD) != 0
+ || (flags & SEC_THREAD_LOCAL) != 0)
p->p_filesz += adjust;
}
bfd_section_name (abfd, sec),
sec->lma,
p->p_paddr);
- return false;
+ return FALSE;
}
p->p_memsz += adjust;
off += adjust;
|| (flags & SEC_HAS_CONTENTS) != 0)
off += sec->_raw_size;
- if ((flags & SEC_ALLOC) != 0)
+ if ((flags & SEC_ALLOC) != 0
+ && ((flags & SEC_LOAD) != 0
+ || (flags & SEC_THREAD_LOCAL) == 0))
voff += sec->_raw_size;
}
}
else
{
+ if ((sec->flags & SEC_LOAD) != 0
+ || (sec->flags & SEC_THREAD_LOCAL) == 0
+ || p->p_type == PT_TLS)
p->p_memsz += sec->_raw_size;
if ((flags & SEC_LOAD) != 0)
p->p_filesz += sec->_raw_size;
+ if (p->p_type == PT_TLS
+ && sec->_raw_size == 0
+ && (sec->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ struct bfd_link_order *o;
+ bfd_vma tbss_size = 0;
+
+ for (o = sec->link_order_head; o != NULL; o = o->next)
+ if (tbss_size < o->offset + o->size)
+ tbss_size = o->offset + o->size;
+
+ p->p_memsz += tbss_size;
+ }
+
if (align > p->p_align
&& (p->p_type != PT_LOAD || (abfd->flags & D_PAGED) == 0))
p->p_align = align;
/* Write out the program headers. */
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0)
- return false;
+ return FALSE;
- return true;
+ return TRUE;
}
/* Get the size of the program header.
++segs;
}
- if (elf_tdata (abfd)->eh_frame_hdr
- && bfd_get_section_by_name (abfd, ".eh_frame_hdr") != NULL)
+ if (elf_tdata (abfd)->eh_frame_hdr)
{
/* We need a PT_GNU_EH_FRAME segment. */
++segs;
}
+ if (elf_tdata (abfd)->stack_flags)
+ {
+ /* We need a PT_GNU_STACK segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
}
}
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if (s->flags & SEC_THREAD_LOCAL)
+ {
+ /* We need a PT_TLS segment. */
+ ++segs;
+ break;
+ }
+ }
+
/* Let the backend count up any program headers it might need. */
if (bed->elf_backend_additional_program_headers)
{
We also don't set the positions of the .symtab and .strtab here. */
-static boolean
+static bfd_boolean
assign_file_positions_except_relocs (abfd)
bfd *abfd;
{
hdr->sh_offset = -1;
}
else
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
if (i == SHN_LORESERVE - 1)
{
/* Assign file positions for the loaded sections based on the
assignment of sections to segments. */
if (! assign_file_positions_for_segments (abfd))
- return false;
+ return FALSE;
/* Assign file positions for the other sections. */
else
off += (hdr->sh_addr - off) % hdr->sh_addralign;
off = _bfd_elf_assign_file_position_for_section (hdr, off,
- false);
+ FALSE);
}
else if (hdr->sh_type == SHT_REL
|| hdr->sh_type == SHT_RELA
|| hdr == i_shdrpp[tdata->strtab_section])
hdr->sh_offset = -1;
else
- off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
if (i == SHN_LORESERVE - 1)
{
}
/* Place the section headers. */
- off = align_file_position (off, bed->s->file_align);
+ off = align_file_position (off, 1 << bed->s->log_file_align);
i_ehdrp->e_shoff = off;
off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
elf_tdata (abfd)->next_file_pos = off;
- return true;
+ return TRUE;
}
-static boolean
+static bfd_boolean
prep_headers (abfd)
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_Shdr **i_shdrp; /* Section header table, internal form */
- int count;
struct elf_strtab_hash *shstrtab;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
shstrtab = _bfd_elf_strtab_init ();
if (shstrtab == NULL)
- return false;
+ return FALSE;
elf_shstrtab (abfd) = shstrtab;
bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NONE;
- i_ehdrp->e_ident[EI_ABIVERSION] = 0;
-
- for (count = EI_PAD; count < EI_NIDENT; count++)
- i_ehdrp->e_ident[count] = 0;
-
if ((abfd->flags & DYNAMIC) != 0)
i_ehdrp->e_type = ET_DYN;
else if ((abfd->flags & EXEC_P) != 0)
}
elf_tdata (abfd)->symtab_hdr.sh_name =
- (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", false);
+ (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE);
elf_tdata (abfd)->strtab_hdr.sh_name =
- (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", false);
+ (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", FALSE);
elf_tdata (abfd)->shstrtab_hdr.sh_name =
- (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", false);
+ (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", FALSE);
if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
|| elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
|| elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
- return false;
+ return FALSE;
- return true;
+ return TRUE;
}
/* Assign file positions for all the reloc sections which are not part
shdrp = *shdrpp;
if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
&& shdrp->sh_offset == -1)
- off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+ off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
}
elf_tdata (abfd)->next_file_pos = off;
}
-boolean
+bfd_boolean
_bfd_elf_write_object_contents (abfd)
bfd *abfd;
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Shdr **i_shdrp;
- boolean failed;
+ bfd_boolean failed;
unsigned int count, num_sec;
if (! abfd->output_has_begun
&& ! _bfd_elf_compute_section_file_positions
(abfd, (struct bfd_link_info *) NULL))
- return false;
+ return FALSE;
i_shdrp = elf_elfsections (abfd);
i_ehdrp = elf_elfheader (abfd);
- failed = false;
+ failed = FALSE;
bfd_map_over_sections (abfd, bed->s->write_relocs, &failed);
if (failed)
- return false;
+ return FALSE;
_bfd_elf_assign_file_positions_for_relocs (abfd);
if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
|| bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
- return false;
+ return FALSE;
}
if (count == SHN_LORESERVE - 1)
count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
/* Write out the section header names. */
if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
|| ! _bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))
- return false;
+ return FALSE;
if (bed->elf_backend_final_write_processing)
(*bed->elf_backend_final_write_processing) (abfd,
return bed->s->write_shdrs_and_ehdr (abfd);
}
-boolean
+bfd_boolean
_bfd_elf_write_corefile_contents (abfd)
bfd *abfd;
{
#if DEBUG & 4
{
fprintf (stderr,
- _("elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n"),
+ "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));
fflush (stderr);
/* Copy private BFD data. This copies any program header information. */
-static boolean
+static bfd_boolean
copy_private_bfd_data (ibfd, obfd)
bfd *ibfd;
bfd *obfd;
{
- Elf_Internal_Ehdr * iehdr;
- struct elf_segment_map * map;
- struct elf_segment_map * map_first;
- struct elf_segment_map ** pointer_to_map;
- Elf_Internal_Phdr * segment;
- asection * section;
- unsigned int i;
- unsigned int num_segments;
- boolean phdr_included = false;
- bfd_vma maxpagesize;
- struct elf_segment_map * phdr_adjust_seg = NULL;
- unsigned int phdr_adjust_num = 0;
+ Elf_Internal_Ehdr *iehdr;
+ struct elf_segment_map *map;
+ struct elf_segment_map *map_first;
+ struct elf_segment_map **pointer_to_map;
+ Elf_Internal_Phdr *segment;
+ asection *section;
+ unsigned int i;
+ unsigned int num_segments;
+ bfd_boolean phdr_included = FALSE;
+ bfd_vma maxpagesize;
+ struct elf_segment_map *phdr_adjust_seg = NULL;
+ unsigned int phdr_adjust_num = 0;
+ struct elf_backend_data *bed;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
+ return TRUE;
if (elf_tdata (ibfd)->phdr == NULL)
- return true;
+ return TRUE;
+ bed = get_elf_backend_data (ibfd);
iehdr = elf_elfheader (ibfd);
map_first = NULL;
maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
/* Returns the end address of the segment + 1. */
-#define SEGMENT_END(segment, start) \
- (start + (segment->p_memsz > segment->p_filesz \
- ? segment->p_memsz : segment->p_filesz))
+#define SEGMENT_END(segment, start) \
+ (start + (segment->p_memsz > segment->p_filesz \
+ ? segment->p_memsz : segment->p_filesz))
- /* Returns true if the given section is contained within
+#define SECTION_SIZE(section, segment) \
+ (((section->flags & (SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) \
+ != SEC_THREAD_LOCAL || segment->p_type == PT_TLS) \
+ ? section->_raw_size : 0)
+
+ /* Returns TRUE if the given section is contained within
the given segment. VMA addresses are compared. */
-#define IS_CONTAINED_BY_VMA(section, segment) \
- (section->vma >= segment->p_vaddr \
- && (section->vma + section->_raw_size) \
- <= (SEGMENT_END (segment, segment->p_vaddr)))
+#define IS_CONTAINED_BY_VMA(section, segment) \
+ (section->vma >= segment->p_vaddr \
+ && (section->vma + SECTION_SIZE (section, segment) \
+ <= (SEGMENT_END (segment, segment->p_vaddr))))
- /* Returns true if the given section is contained within
+ /* Returns TRUE if the given section is contained within
the given segment. LMA addresses are compared. */
-#define IS_CONTAINED_BY_LMA(section, segment, base) \
- (section->lma >= base \
- && (section->lma + section->_raw_size) \
- <= SEGMENT_END (segment, base))
+#define IS_CONTAINED_BY_LMA(section, segment, base) \
+ (section->lma >= base \
+ && (section->lma + SECTION_SIZE (section, segment) \
+ <= SEGMENT_END (segment, base)))
/* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
-#define IS_COREFILE_NOTE(p, s) \
- (p->p_type == PT_NOTE \
- && bfd_get_format (ibfd) == bfd_core \
- && s->vma == 0 && s->lma == 0 \
- && (bfd_vma) s->filepos >= p->p_offset \
- && (bfd_vma) s->filepos + s->_raw_size \
- <= p->p_offset + p->p_filesz)
+#define IS_COREFILE_NOTE(p, s) \
+ (p->p_type == PT_NOTE \
+ && bfd_get_format (ibfd) == bfd_core \
+ && s->vma == 0 && s->lma == 0 \
+ && (bfd_vma) s->filepos >= p->p_offset \
+ && ((bfd_vma) s->filepos + s->_raw_size \
+ <= p->p_offset + p->p_filesz))
/* The complicated case when p_vaddr is 0 is to handle the Solaris
linker, which generates a PT_INTERP section with p_vaddr and
p_memsz set to 0. */
-#define IS_SOLARIS_PT_INTERP(p, s) \
- ( p->p_vaddr == 0 \
- && p->p_filesz > 0 \
- && (s->flags & SEC_HAS_CONTENTS) != 0 \
- && s->_raw_size > 0 \
- && (bfd_vma) s->filepos >= p->p_offset \
- && ((bfd_vma) s->filepos + s->_raw_size \
- <= p->p_offset + p->p_filesz))
+#define IS_SOLARIS_PT_INTERP(p, s) \
+ (p->p_vaddr == 0 \
+ && p->p_paddr == 0 \
+ && p->p_memsz == 0 \
+ && p->p_filesz > 0 \
+ && (s->flags & SEC_HAS_CONTENTS) != 0 \
+ && s->_raw_size > 0 \
+ && (bfd_vma) s->filepos >= p->p_offset \
+ && ((bfd_vma) s->filepos + s->_raw_size \
+ <= p->p_offset + p->p_filesz))
/* Decide if the given section should be included in the given segment.
A section will be included if:
if that is set for the segment and the VMA otherwise,
2. It is an allocated segment,
3. There is an output section associated with it,
- 4. The section has not already been allocated to a previous segment. */
-#define INCLUDE_SECTION_IN_SEGMENT(section, segment) \
- (((((segment->p_paddr \
- ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
- : IS_CONTAINED_BY_VMA (section, segment)) \
- || IS_SOLARIS_PT_INTERP (segment, section)) \
+ 4. The section has not already been allocated to a previous segment.
+ 5. PT_TLS segment includes only SHF_TLS sections.
+ 6. SHF_TLS sections are only in PT_TLS or PT_LOAD segments. */
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \
+ ((((segment->p_paddr \
+ ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
+ : IS_CONTAINED_BY_VMA (section, segment)) \
&& (section->flags & SEC_ALLOC) != 0) \
|| IS_COREFILE_NOTE (segment, section)) \
&& section->output_section != NULL \
- && section->segment_mark == false)
-
- /* Returns true iff seg1 starts after the end of seg2. */
-#define SEGMENT_AFTER_SEGMENT(seg1, seg2) \
- (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr))
-
- /* Returns true iff seg1 and seg2 overlap. */
-#define SEGMENT_OVERLAPS(seg1, seg2) \
- (!(SEGMENT_AFTER_SEGMENT (seg1, seg2) || SEGMENT_AFTER_SEGMENT (seg2, seg1)))
+ && (segment->p_type != PT_TLS \
+ || (section->flags & SEC_THREAD_LOCAL)) \
+ && (segment->p_type == PT_LOAD \
+ || segment->p_type == PT_TLS \
+ || (section->flags & SEC_THREAD_LOCAL) == 0) \
+ && ! section->segment_mark)
+
+ /* Returns TRUE iff seg1 starts after the end of seg2. */
+#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field) \
+ (seg1->field >= SEGMENT_END (seg2, seg2->field))
+
+ /* Returns TRUE iff seg1 and seg2 overlap. Segments overlap iff both
+ their VMA address ranges and their LMA address ranges overlap.
+ It is possible to have overlapping VMA ranges without overlapping LMA
+ ranges. RedBoot images for example can have both .data and .bss mapped
+ to the same VMA range, but with the .data section mapped to a different
+ LMA. */
+#define SEGMENT_OVERLAPS(seg1, seg2) \
+ ( !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_vaddr) \
+ || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_vaddr)) \
+ && !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_paddr) \
+ || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_paddr)))
/* Initialise the segment mark field. */
for (section = ibfd->sections; section != NULL; section = section->next)
- section->segment_mark = false;
+ section->segment_mark = FALSE;
/* Scan through the segments specified in the program header
of the input BFD. For this first scan we look for overlaps
in the loadable segments. These can be created by weird
- parameters to objcopy. */
+ parameters to objcopy. Also, fix some solaris weirdness. */
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
i++, segment++)
unsigned int j;
Elf_Internal_Phdr *segment2;
+ if (segment->p_type == PT_INTERP)
+ for (section = ibfd->sections; section; section = section->next)
+ if (IS_SOLARIS_PT_INTERP (segment, section))
+ {
+ /* Mininal change so that the normal section to segment
+ assigment code will work. */
+ segment->p_vaddr = section->vma;
+ break;
+ }
+
if (segment->p_type != PT_LOAD)
continue;
continue;
/* Compute how many sections might be placed into this segment. */
- section_count = 0;
- for (section = ibfd->sections; section != NULL; section = section->next)
- if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
+ for (section = ibfd->sections, section_count = 0;
+ section != NULL;
+ section = section->next)
+ if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
++section_count;
- /* Allocate a segment map big enough to contain all of the
- sections we have selected. */
+ /* Allocate a segment map big enough to contain
+ all of the sections we have selected. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
if (map == NULL)
- return false;
+ return FALSE;
/* Initialise the fields of the segment map. Default to
using the physical address of the segment in the input BFD. */
+ iehdr->e_phnum * iehdr->e_phentsize)));
if (segment->p_type == PT_LOAD && map->includes_phdrs)
- phdr_included = true;
+ phdr_included = TRUE;
}
if (section_count == 0)
{
/* Special segments, such as the PT_PHDR segment, may contain
no sections, but ordinary, loadable segments should contain
- something. */
+ something. They are allowed by the ELF spec however, so only
+ a warning is produced. */
if (segment->p_type == PT_LOAD)
- _bfd_error_handler
- (_("%s: warning: Empty loadable segment detected\n"),
- bfd_archive_filename (ibfd));
+ (*_bfd_error_handler)
+ (_("%s: warning: Empty loadable segment detected, is this intentional ?\n"),
+ bfd_archive_filename (ibfd));
map->count = 0;
*pointer_to_map = map;
and possibly its LMA changed, and a new segment or segments will
have to be created to contain the other sections.
- 4. The sections have been moved, but not be the same amount.
+ 4. The sections have been moved, but not by the same amount.
In this case we can change the segment's LMA to match the LMA
of the first section and we will have to create a new segment
or segments to contain the other sections.
pointers that we are interested in. As these sections get assigned
to a segment, they are removed from this array. */
- amt = (bfd_size_type) section_count * sizeof (asection *);
+ /* Gcc 2.96 miscompiles this code on mips. Don't do casting here
+ to work around this long long bug. */
+ amt = section_count * sizeof (asection *);
sections = (asection **) bfd_malloc (amt);
if (sections == NULL)
- return false;
+ return FALSE;
/* Step One: Scan for segment vs section LMA conflicts.
Also add the sections to the section array allocated above.
section != NULL;
section = section->next)
{
- if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
+ if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
{
output_section = section->output_section;
/* The Solaris native linker always sets p_paddr to 0.
We try to catch that case here, and set it to the
- correct value. */
+ correct value. Note - some backends require that
+ p_paddr be left as zero. */
if (segment->p_paddr == 0
&& segment->p_vaddr != 0
+ && (! bed->want_p_paddr_set_to_zero)
&& isec == 0
&& output_section->lma != 0
&& (output_section->vma == (segment->p_vaddr
/* Match up the physical address of the segment with the
LMA address of the output section. */
if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
- || IS_COREFILE_NOTE (segment, section))
+ || IS_COREFILE_NOTE (segment, section)
+ || (bed->want_p_paddr_set_to_zero &&
+ IS_CONTAINED_BY_VMA (output_section, segment))
+ )
{
if (matching_lma == 0)
matching_lma = output_section->lma;
}
/* Step Three: Loop over the sections again, this time assigning
- those that fit to the current segment and remvoing them from the
+ those that fit to the current segment and removing them from the
sections array; but making sure not to leave large gaps. Once all
possible sections have been assigned to the current segment it is
added to the list of built segments and if sections still remain
maxpagesize then we need to start a new segment. */
if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size,
maxpagesize)
- < BFD_ALIGN (output_section->lma, maxpagesize))
+ < BFD_ALIGN (output_section->lma, maxpagesize))
|| ((prev_sec->lma + prev_sec->_raw_size)
> output_section->lma))
{
map->sections[map->count++] = output_section;
++isec;
sections[j] = NULL;
- section->segment_mark = true;
+ section->segment_mark = TRUE;
}
else if (suggested_lma == 0)
suggested_lma = output_section->lma;
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
if (map == NULL)
- return false;
+ {
+ free (sections);
+ return FALSE;
+ }
/* Initialise the fields of the segment map. Set the physical
physical address to the LMA of the first section that has
if (map->p_paddr != 0)
break;
if (map == NULL)
- {
- for (map = map_first; map != NULL; map = map->next)
- map->p_paddr_valid = 0;
- }
+ for (map = map_first; map != NULL; map = map->next)
+ map->p_paddr_valid = 0;
elf_tdata (obfd)->segment_map = map_first;
#endif
#undef SEGMENT_END
+#undef SECTION_SIZE
#undef IS_CONTAINED_BY_VMA
#undef IS_CONTAINED_BY_LMA
#undef IS_COREFILE_NOTE
#undef INCLUDE_SECTION_IN_SEGMENT
#undef SEGMENT_AFTER_SEGMENT
#undef SEGMENT_OVERLAPS
- return true;
+ return TRUE;
}
/* Copy private section information. This copies over the entsize
field, and sometimes the info field. */
-boolean
+bfd_boolean
_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
bfd *ibfd;
asection *isec;
if (ibfd->xvec->flavour != bfd_target_elf_flavour
|| obfd->xvec->flavour != bfd_target_elf_flavour)
- return true;
+ 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 (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
{
- asection *s;
+ asection *s;
- /* Only set up the segments if there are no more SEC_ALLOC
- sections. FIXME: This won't do the right thing if objcopy is
- used to remove the last SEC_ALLOC section, since objcopy
- won't call this routine in that case. */
- for (s = isec->next; s != NULL; s = s->next)
- if ((s->flags & SEC_ALLOC) != 0)
- break;
- if (s == NULL)
- {
- if (! copy_private_bfd_data (ibfd, obfd))
- return false;
- }
+ /* Only set up the segments if there are no more SEC_ALLOC
+ sections. FIXME: This won't do the right thing if objcopy is
+ used to remove the last SEC_ALLOC section, since objcopy
+ won't call this routine in that case. */
+ for (s = isec->next; s != NULL; s = s->next)
+ if ((s->flags & SEC_ALLOC) != 0)
+ break;
+ if (s == NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+ }
}
ihdr = &elf_section_data (isec)->this_hdr;
|| ihdr->sh_type == SHT_GNU_verdef)
ohdr->sh_info = ihdr->sh_info;
- elf_section_data (osec)->use_rela_p
- = elf_section_data (isec)->use_rela_p;
+ /* Set things up for objcopy. The output SHT_GROUP section will
+ have its elf_next_in_group pointing back to the input group
+ members. */
+ elf_next_in_group (osec) = elf_next_in_group (isec);
+ elf_group_name (osec) = elf_group_name (isec);
+
+ osec->use_rela_p = isec->use_rela_p;
- return true;
+ return TRUE;
}
/* Copy private symbol information. If this symbol is in a section
#define MAP_SHSTRTAB (SHN_HIOS + 4)
#define MAP_SYM_SHNDX (SHN_HIOS + 5)
-boolean
+bfd_boolean
_bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
bfd *ibfd;
asymbol *isymarg;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
+ return TRUE;
isym = elf_symbol_from (ibfd, isymarg);
osym = elf_symbol_from (obfd, osymarg);
osym->internal_elf_sym.st_shndx = shndx;
}
- return true;
+ return TRUE;
}
/* Swap out the symbols. */
-static boolean
+static bfd_boolean
swap_out_syms (abfd, sttp, relocatable_p)
bfd *abfd;
struct bfd_strtab_hash **sttp;
bfd_size_type amt;
if (!elf_map_symbols (abfd))
- return false;
+ return FALSE;
/* Dump out the symtabs. */
stt = _bfd_elf_stringtab_init ();
if (stt == NULL)
- return false;
+ return FALSE;
bed = get_elf_backend_data (abfd);
symcount = bfd_get_symcount (abfd);
symtab_hdr->sh_entsize = bed->s->sizeof_sym;
symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
- symtab_hdr->sh_addralign = bed->s->file_align;
+ symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
symstrtab_hdr->sh_type = SHT_STRTAB;
amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym;
outbound_syms = bfd_alloc (abfd, amt);
if (outbound_syms == NULL)
- return false;
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
symtab_hdr->contents = (PTR) outbound_syms;
outbound_shndx = NULL;
if (symtab_shndx_hdr->sh_name != 0)
{
amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
- outbound_shndx = bfd_alloc (abfd, amt);
+ outbound_shndx = bfd_zalloc (abfd, amt);
if (outbound_shndx == NULL)
- return false;
- memset (outbound_shndx, 0, (unsigned long) amt);
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
+
symtab_shndx_hdr->contents = outbound_shndx;
symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
symtab_shndx_hdr->sh_size = amt;
symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
}
- /* now generate the data (for "contents") */
+ /* Now generate the data (for "contents"). */
{
/* Fill in zeroth symbol and swap it out. */
Elf_Internal_Sym sym;
{
sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
syms[idx]->name,
- true, false);
+ TRUE, FALSE);
if (sym.st_name == (unsigned long) -1)
- return false;
+ {
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
}
type_ptr = elf_symbol_from (abfd, syms[idx]);
value += sec->output_offset;
sec = sec->output_section;
}
+
/* Don't add in the section vma for relocatable output. */
if (! relocatable_p)
value += sec->vma;
section of a symbol to be a section that is
actually in the output file. */
sec2 = bfd_get_section_by_name (abfd, sec->name);
- BFD_ASSERT (sec2 != 0);
+ if (sec2 == NULL)
+ {
+ _bfd_error_handler (_("\
+Unable to find equivalent output section for symbol '%s' from section '%s'"),
+ syms[idx]->name ? syms[idx]->name : "<Local sym>",
+ sec->name);
+ bfd_set_error (bfd_error_invalid_operation);
+ _bfd_stringtab_free (stt);
+ return FALSE;
+ }
+
shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
BFD_ASSERT (shndx != -1);
}
sym.st_shndx = shndx;
}
- if ((flags & BSF_FUNCTION) != 0)
+ if ((flags & BSF_THREAD_LOCAL) != 0)
+ type = STT_TLS;
+ else if ((flags & BSF_FUNCTION) != 0)
type = STT_FUNC;
else if ((flags & BSF_OBJECT) != 0)
type = STT_OBJECT;
else
type = STT_NOTYPE;
- /* Processor-specific types */
+ if (syms[idx]->section->flags & SEC_THREAD_LOCAL)
+ type = STT_TLS;
+
+ /* Processor-specific types. */
if (type_ptr != NULL
&& bed->elf_backend_get_symbol_type)
type = ((*bed->elf_backend_get_symbol_type)
symstrtab_hdr->sh_info = 0;
symstrtab_hdr->sh_addralign = 1;
- return true;
+ return TRUE;
}
/* Return the number of bytes required to hold the symtab vector.
Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+ symtab_size = (symcount + 1) * (sizeof (asymbol *));
+ if (symcount > 0)
+ symtab_size -= sizeof (asymbol *);
return symtab_size;
}
}
symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
- symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+ symtab_size = (symcount + 1) * (sizeof (asymbol *));
+ if (symcount > 0)
+ symtab_size -= sizeof (asymbol *);
return symtab_size;
}
unsigned int i;
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- if (! bed->s->slurp_reloc_table (abfd, section, symbols, false))
+ if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
return -1;
tblptr = section->relocation;
asymbol **alocation;
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- long symcount = bed->s->slurp_symbol_table (abfd, alocation, false);
+ long symcount = bed->s->slurp_symbol_table (abfd, alocation, FALSE);
if (symcount >= 0)
bfd_get_symcount (abfd) = symcount;
asymbol **alocation;
{
struct elf_backend_data *bed = get_elf_backend_data (abfd);
- return bed->s->slurp_symbol_table (abfd, alocation, true);
+ long symcount = bed->s->slurp_symbol_table (abfd, alocation, TRUE);
+
+ if (symcount >= 0)
+ bfd_get_dynamic_symcount (abfd) = symcount;
+ return symcount;
}
/* Return the size required for the dynamic reloc entries. Any
arelent **storage;
asymbol **syms;
{
- boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+ bfd_boolean (*slurp_relocs)
+ PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
asection *s;
long ret;
arelent *p;
long count, i;
- if (! (*slurp_relocs) (abfd, s, syms, true))
+ if (! (*slurp_relocs) (abfd, s, syms, TRUE))
return -1;
count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
p = s->relocation;
\f
/* Read in the version information. */
-boolean
+bfd_boolean
_bfd_elf_slurp_version_tables (abfd)
bfd *abfd;
{
contents = NULL;
}
- return true;
+ return TRUE;
error_return:
- if (contents == NULL)
+ if (contents != NULL)
free (contents);
- return false;
+ return FALSE;
}
\f
asymbol *
use this function for the is_local_label_name entry point, but some
override it. */
-boolean
+bfd_boolean
_bfd_elf_is_local_label_name (abfd, name)
bfd *abfd ATTRIBUTE_UNUSED;
const char *name;
{
/* Normal local symbols start with ``.L''. */
if (name[0] == '.' && name[1] == 'L')
- return true;
+ return TRUE;
/* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
DWARF debugging symbols starting with ``..''. */
if (name[0] == '.' && name[1] == '.')
- return true;
+ return TRUE;
/* gcc will sometimes generate symbols beginning with ``_.L_'' when
emitting DWARF debugging output. I suspect this is actually a
underscore to be emitted on some ELF targets). For ease of use,
we treat such symbols as local. */
if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
- return true;
+ return TRUE;
- return false;
+ return FALSE;
}
alent *
return NULL;
}
-boolean
+bfd_boolean
_bfd_elf_set_arch_mach (abfd, arch, machine)
bfd *abfd;
enum bfd_architecture arch;
if (arch != get_elf_backend_data (abfd)->arch
&& arch != bfd_arch_unknown
&& get_elf_backend_data (abfd)->arch != bfd_arch_unknown)
- return false;
+ return FALSE;
return bfd_default_set_arch_mach (abfd, arch, machine);
}
/* Find the function to a particular section and offset,
for error reporting. */
-static boolean
+static bfd_boolean
elf_find_function (abfd, section, symbols, offset,
filename_ptr, functionname_ptr)
bfd *abfd ATTRIBUTE_UNUSED;
}
if (func == NULL)
- return false;
+ return FALSE;
if (filename_ptr)
*filename_ptr = filename;
if (functionname_ptr)
*functionname_ptr = bfd_asymbol_name (func);
- return true;
+ return TRUE;
}
/* Find the nearest line to a particular section and offset,
for error reporting. */
-boolean
+bfd_boolean
_bfd_elf_find_nearest_line (abfd, section, symbols, offset,
filename_ptr, functionname_ptr, line_ptr)
bfd *abfd;
const char **functionname_ptr;
unsigned int *line_ptr;
{
- boolean found;
+ bfd_boolean found;
if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
filename_ptr, functionname_ptr,
*filename_ptr ? NULL : filename_ptr,
functionname_ptr);
- return true;
+ return TRUE;
}
if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
*filename_ptr ? NULL : filename_ptr,
functionname_ptr);
- return true;
+ return TRUE;
}
if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
&found, filename_ptr,
functionname_ptr, line_ptr,
&elf_tdata (abfd)->line_info))
- return false;
- if (found)
- return true;
+ return FALSE;
+ if (found && (*functionname_ptr || *line_ptr))
+ return TRUE;
if (symbols == NULL)
- return false;
+ return FALSE;
if (! elf_find_function (abfd, section, symbols, offset,
filename_ptr, functionname_ptr))
- return false;
+ return FALSE;
*line_ptr = 0;
- return true;
+ return TRUE;
}
int
_bfd_elf_sizeof_headers (abfd, reloc)
bfd *abfd;
- boolean reloc;
+ bfd_boolean reloc;
{
int ret;
return ret;
}
-boolean
+bfd_boolean
_bfd_elf_set_section_contents (abfd, section, location, offset, count)
bfd *abfd;
sec_ptr section;
bfd_signed_vma pos;
if (! abfd->output_has_begun
- && ! _bfd_elf_compute_section_file_positions
- (abfd, (struct bfd_link_info *) NULL))
- return false;
+ && ! (_bfd_elf_compute_section_file_positions
+ (abfd, (struct bfd_link_info *) NULL)))
+ return FALSE;
hdr = &elf_section_data (section)->this_hdr;
pos = hdr->sh_offset + offset;
if (bfd_seek (abfd, pos, SEEK_SET) != 0
|| bfd_bwrite (location, count, abfd) != count)
- return false;
+ return FALSE;
- return true;
+ return TRUE;
}
void
abort ();
}
-#if 0
-void
-_bfd_elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
- bfd *abfd;
- arelent *cache_ptr;
- Elf_Internal_Rel *dst;
-{
- abort ();
-}
-#endif
-
/* Try to convert a non-ELF reloc into an ELF one. */
-boolean
+bfd_boolean
_bfd_elf_validate_reloc (abfd, areloc)
bfd *abfd;
arelent *areloc;
goto fail;
}
- return true;
+ return TRUE;
fail:
(*_bfd_error_handler)
(_("%s: unsupported relocation type %s"),
bfd_archive_filename (abfd), areloc->howto->name);
bfd_set_error (bfd_error_bad_value);
- return false;
+ return FALSE;
}
-boolean
+bfd_boolean
_bfd_elf_close_and_cleanup (abfd)
bfd *abfd;
{
reference to NAME, so you shouldn't deallocate or
overwrite it. */
-static boolean
+static bfd_boolean
elfcore_maybe_make_sect (abfd, name, sect)
bfd *abfd;
char *name;
asection *sect2;
if (bfd_get_section_by_name (abfd, name) != NULL)
- return true;
+ return TRUE;
sect2 = bfd_make_section (abfd, name);
if (sect2 == NULL)
- return false;
+ return FALSE;
sect2->_raw_size = sect->_raw_size;
sect2->filepos = sect->filepos;
sect2->flags = sect->flags;
sect2->alignment_power = sect->alignment_power;
- return true;
+ return TRUE;
}
/* Create a pseudosection containing SIZE bytes at FILEPOS. This
- For the multi-threaded case, a section named "NAME/PID", where
PID is elfcore_make_pid (abfd).
Both pseudosections have identical contents. */
-boolean
+bfd_boolean
_bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
bfd *abfd;
char *name;
{
char buf[100];
char *threaded_name;
+ size_t len;
asection *sect;
/* Build the section name. */
sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
- threaded_name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ len = strlen (buf) + 1;
+ threaded_name = bfd_alloc (abfd, (bfd_size_type) len);
if (threaded_name == NULL)
- return false;
- strcpy (threaded_name, buf);
+ return FALSE;
+ memcpy (threaded_name, buf, len);
sect = bfd_make_section (abfd, threaded_name);
if (sect == NULL)
- return false;
+ return FALSE;
sect->_raw_size = size;
sect->filepos = filepos;
sect->flags = SEC_HAS_CONTENTS;
*/
#if defined (HAVE_PRSTATUS_T)
-static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prstatus
+ PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean
+static bfd_boolean
elfcore_grok_prstatus (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
{
/* Fail - we don't know how to handle any other
note size (ie. data object type). */
- return true;
+ return TRUE;
}
/* Make a ".reg/999" section and a ".reg" section. */
#endif /* defined (HAVE_PRSTATUS_T) */
/* Create a pseudosection containing the exact contents of NOTE. */
-static boolean
+static bfd_boolean
elfcore_make_note_pseudosection (abfd, name, note)
bfd *abfd;
char *name;
but it doesn't matter, because we don't have to pick this
data structure apart. */
-static boolean
+static bfd_boolean
elfcore_grok_prfpreg (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
type of 5 (NT_PRXFPREG). Just include the whole note's contents
literally. */
-static boolean
+static bfd_boolean
elfcore_grok_prxfpreg (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
}
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_psinfo
+ PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean
+static bfd_boolean
elfcore_grok_psinfo (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
{
/* Fail - we don't know how to handle any other
note size (ie. data object type). */
- return true;
+ return TRUE;
}
/* Note that for some reason, a spurious space is tacked
command[n - 1] = '\0';
}
- return true;
+ return TRUE;
}
#endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
#if defined (HAVE_PSTATUS_T)
-static boolean
+static bfd_boolean elfcore_grok_pstatus
+ PARAMS ((bfd *, Elf_Internal_Note *));
+
+static bfd_boolean
elfcore_grok_pstatus (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
lwpstatus_t in pstat.pr_lwp, but we'll catch it all in an
NT_LWPSTATUS note, presumably. */
- return true;
+ return TRUE;
}
#endif /* defined (HAVE_PSTATUS_T) */
#if defined (HAVE_LWPSTATUS_T)
-static boolean
+static bfd_boolean elfcore_grok_lwpstatus
+ PARAMS ((bfd *, Elf_Internal_Note *));
+
+static bfd_boolean
elfcore_grok_lwpstatus (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
lwpstatus_t lwpstat;
char buf[100];
char *name;
+ size_t len;
asection *sect;
if (note->descsz != sizeof (lwpstat)
&& note->descsz != sizeof (lwpxstatus_t)
#endif
)
- return true;
+ return TRUE;
memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
/* Make a ".reg/999" section. */
sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ len = strlen (buf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (name == NULL)
- return false;
- strcpy (name, buf);
+ return FALSE;
+ memcpy (name, buf, len);
sect = bfd_make_section (abfd, name);
if (sect == NULL)
- return false;
+ return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
sect->alignment_power = 2;
if (!elfcore_maybe_make_sect (abfd, ".reg", sect))
- return false;
+ return FALSE;
/* Make a ".reg2/999" section */
sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ len = strlen (buf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (name == NULL)
- return false;
- strcpy (name, buf);
+ return FALSE;
+ memcpy (name, buf, len);
sect = bfd_make_section (abfd, name);
if (sect == NULL)
- return false;
+ return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
#endif /* defined (HAVE_LWPSTATUS_T) */
#if defined (HAVE_WIN32_PSTATUS_T)
-static boolean
+static bfd_boolean
elfcore_grok_win32pstatus (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
{
char buf[30];
char *name;
+ size_t len;
asection *sect;
win32_pstatus_t pstatus;
if (note->descsz < sizeof (pstatus))
- return true;
+ return TRUE;
- memcpy (&pstatus, note->descdata, note->descsz);
+ memcpy (&pstatus, note->descdata, sizeof (pstatus));
switch (pstatus.data_type)
{
/* Make a ".reg/999" section. */
sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ len = strlen (buf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (name == NULL)
- return false;
+ return FALSE;
- strcpy (name, buf);
+ memcpy (name, buf, len);
sect = bfd_make_section (abfd, name);
if (sect == NULL)
- return false;
+ return FALSE;
sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
sect->filepos = (note->descpos
if (pstatus.data.thread_info.is_active_thread)
if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
- return false;
+ return FALSE;
break;
case NOTE_INFO_MODULE:
/* Make a ".module/xxxxxxxx" section. */
sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ len = strlen (buf) + 1;
+ name = bfd_alloc (abfd, (bfd_size_type) len);
if (name == NULL)
- return false;
+ return FALSE;
- strcpy (name, buf);
+ memcpy (name, buf, len);
sect = bfd_make_section (abfd, name);
if (sect == NULL)
- return false;
+ return FALSE;
sect->_raw_size = note->descsz;
sect->filepos = note->descpos;
break;
default:
- return true;
+ return TRUE;
}
- return true;
+ return TRUE;
}
#endif /* HAVE_WIN32_PSTATUS_T */
-static boolean
+static bfd_boolean
elfcore_grok_note (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
switch (note->type)
{
default:
- return true;
+ return TRUE;
case NT_PRSTATUS:
if (bed->elf_backend_grok_prstatus)
if ((*bed->elf_backend_grok_prstatus) (abfd, note))
- return true;
+ return TRUE;
#if defined (HAVE_PRSTATUS_T)
return elfcore_grok_prstatus (abfd, note);
#else
- return true;
+ return TRUE;
#endif
#if defined (HAVE_PSTATUS_T)
#endif
case NT_PRXFPREG: /* Linux SSE extension */
- if (note->namesz == 5
- && ! strcmp (note->namedata, "LINUX"))
+ if (note->namesz == 6
+ && strcmp (note->namedata, "LINUX") == 0)
return elfcore_grok_prxfpreg (abfd, note);
else
- return true;
+ return TRUE;
case NT_PRPSINFO:
case NT_PSINFO:
if (bed->elf_backend_grok_psinfo)
if ((*bed->elf_backend_grok_psinfo) (abfd, note))
- return true;
+ return TRUE;
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
return elfcore_grok_psinfo (abfd, note);
#else
- return true;
+ return TRUE;
#endif
+
+ case NT_AUXV:
+ {
+ asection *sect = bfd_make_section (abfd, ".auxv");
+
+ if (sect == NULL)
+ return FALSE;
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+ return TRUE;
+ }
}
}
-static boolean
+static bfd_boolean
elfcore_netbsd_get_lwpid (note, lwpidp)
Elf_Internal_Note *note;
int *lwpidp;
cp = strchr (note->namedata, '@');
if (cp != NULL)
{
- *lwpidp = atoi(cp);
- return true;
+ *lwpidp = atoi(cp + 1);
+ return TRUE;
}
- return false;
+ return FALSE;
}
-static boolean
+static bfd_boolean
elfcore_grok_netbsd_procinfo (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
elf_tdata (abfd)->core_command
= _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
- return true;
+ return TRUE;
}
-static boolean
+static bfd_boolean
elfcore_grok_netbsd_note (abfd, note)
bfd *abfd;
Elf_Internal_Note *note;
find this note before any of the others, which is fine,
since the kernel writes this note out first when it
creates a core file. */
-
+
return elfcore_grok_netbsd_procinfo (abfd, note);
}
defined for NetBSD core files. If the note type is less
than the start of the machine-dependent note types, we don't
understand it. */
-
+
if (note->type < NT_NETBSDCORE_FIRSTMACH)
- return true;
+ return TRUE;
switch (bfd_get_arch (abfd))
return elfcore_make_note_pseudosection (abfd, ".reg2", note);
default:
- return true;
+ return TRUE;
}
/* On all other arch's, PT_GETREGS == mach+1 and
return elfcore_make_note_pseudosection (abfd, ".reg2", note);
default:
- return true;
+ return TRUE;
}
}
/* NOTREACHED */
}
+static bfd_boolean
+elfcore_grok_nto_status (abfd, note, tid)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+ pid_t *tid;
+{
+ void *ddata = note->descdata;
+ char buf[100];
+ char *name;
+ asection *sect;
+ short sig;
+ unsigned flags;
+
+ /* nto_procfs_status 'pid' field is at offset 0. */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
+
+ /* nto_procfs_status 'tid' field is at offset 4. Pass it back. */
+ *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4);
+
+ /* nto_procfs_status 'flags' field is at offset 8. */
+ flags = bfd_get_32 (abfd, (bfd_byte *) ddata + 8);
+
+ /* nto_procfs_status 'what' field is at offset 14. */
+ if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0)
+ {
+ elf_tdata (abfd)->core_signal = sig;
+ elf_tdata (abfd)->core_lwpid = *tid;
+ }
+
+ /* _DEBUG_FLAG_CURTID (current thread) is 0x80. Some cores
+ do not come from signals so we make sure we set the current
+ thread just in case. */
+ if (flags & 0x00000080)
+ elf_tdata (abfd)->core_lwpid = *tid;
+
+ /* Make a ".qnx_core_status/%d" section. */
+ sprintf (buf, ".qnx_core_status/%d", *tid);
+
+ name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ if (name == NULL)
+ return FALSE;
+ strcpy (name, buf);
+
+ sect = bfd_make_section (abfd, name);
+ if (sect == NULL)
+ return FALSE;
+
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 2;
+
+ return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
+}
+
+static bfd_boolean
+elfcore_grok_nto_gregs (abfd, note, tid)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+ pid_t tid;
+{
+ char buf[100];
+ char *name;
+ asection *sect;
+
+ /* Make a ".reg/%d" section. */
+ sprintf (buf, ".reg/%d", tid);
+
+ name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ if (name == NULL)
+ return FALSE;
+ strcpy (name, buf);
+
+ sect = bfd_make_section (abfd, name);
+ if (sect == NULL)
+ return FALSE;
+
+ sect->_raw_size = note->descsz;
+ sect->filepos = note->descpos;
+ sect->flags = SEC_HAS_CONTENTS;
+ sect->alignment_power = 2;
+
+ /* This is the current thread. */
+ if (elf_tdata (abfd)->core_lwpid == tid)
+ return elfcore_maybe_make_sect (abfd, ".reg", sect);
+
+ return TRUE;
+}
+
+#define BFD_QNT_CORE_INFO 7
+#define BFD_QNT_CORE_STATUS 8
+#define BFD_QNT_CORE_GREG 9
+#define BFD_QNT_CORE_FPREG 10
+
+static bfd_boolean
+elfcore_grok_nto_note (abfd, note)
+ bfd *abfd;
+ Elf_Internal_Note *note;
+{
+ /* Every GREG section has a STATUS section before it. Store the
+ tid from the previous call to pass down to the next gregs
+ function. */
+ static pid_t tid = 1;
+
+ switch (note->type)
+ {
+ case BFD_QNT_CORE_INFO: return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+ case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid);
+ case BFD_QNT_CORE_GREG: return elfcore_grok_nto_gregs (abfd, note, tid);
+ case BFD_QNT_CORE_FPREG: return elfcore_grok_prfpreg (abfd, note);
+ default: return TRUE;
+ }
+}
+
/* Function: elfcore_write_note
- Inputs:
+ Inputs:
buffer to hold note
name of note
type of note
bfd *abfd;
char *buf;
int *bufsiz;
- char *name;
+ const char *name;
int type;
- void *input;
+ const PTR input;
int size;
{
Elf_External_Note *xnp;
- int namesz = strlen (name);
- int newspace = BFD_ALIGN (sizeof (Elf_External_Note) + size + namesz - 1, 4);
+ size_t namesz;
+ size_t pad;
+ size_t newspace;
char *p, *dest;
+ namesz = 0;
+ pad = 0;
+ if (name != NULL)
+ {
+ struct elf_backend_data *bed;
+
+ namesz = strlen (name) + 1;
+ bed = get_elf_backend_data (abfd);
+ pad = -namesz & ((1 << bed->s->log_file_align) - 1);
+ }
+
+ newspace = sizeof (Elf_External_Note) - 1 + namesz + pad + size;
+
p = realloc (buf, *bufsiz + newspace);
dest = p + *bufsiz;
*bufsiz += newspace;
H_PUT_32 (abfd, namesz, xnp->namesz);
H_PUT_32 (abfd, size, xnp->descsz);
H_PUT_32 (abfd, type, xnp->type);
- strcpy (xnp->name, name);
- memcpy (xnp->name + BFD_ALIGN (namesz, 4), input, size);
+ dest = xnp->name;
+ if (name != NULL)
+ {
+ memcpy (dest, name, namesz);
+ dest += namesz;
+ while (pad != 0)
+ {
+ *dest++ = '\0';
+ --pad;
+ }
+ }
+ memcpy (dest, input, size);
return p;
}
bfd *abfd;
char *buf;
int *bufsiz;
- char *fname;
- char *psargs;
+ const char *fname;
+ const char *psargs;
{
int note_type;
char *note_name = "CORE";
memset (&data, 0, sizeof (data));
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
- return elfcore_write_note (abfd, buf, bufsiz,
+ return elfcore_write_note (abfd, buf, bufsiz,
note_name, note_type, &data, sizeof (data));
}
#endif /* PSINFO_T or PRPSINFO_T */
int *bufsiz;
long pid;
int cursig;
- void *gregs;
+ const PTR gregs;
{
prstatus_t prstat;
char *note_name = "CORE";
prstat.pr_pid = pid;
prstat.pr_cursig = cursig;
memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
- return elfcore_write_note (abfd, buf, bufsiz,
+ return elfcore_write_note (abfd, buf, bufsiz,
note_name, NT_PRSTATUS, &prstat, sizeof (prstat));
}
#endif /* HAVE_PRSTATUS_T */
+#if defined (HAVE_LWPSTATUS_T)
+char *
+elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
+ bfd *abfd;
+ char *buf;
+ int *bufsiz;
+ long pid;
+ int cursig;
+ const PTR gregs;
+{
+ lwpstatus_t lwpstat;
+ char *note_name = "CORE";
+
+ memset (&lwpstat, 0, sizeof (lwpstat));
+ lwpstat.pr_lwpid = pid >> 16;
+ lwpstat.pr_cursig = cursig;
+#if defined (HAVE_LWPSTATUS_T_PR_REG)
+ memcpy (lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
+#elif defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
+#if !defined(gregs)
+ memcpy (lwpstat.pr_context.uc_mcontext.gregs,
+ gregs, sizeof (lwpstat.pr_context.uc_mcontext.gregs));
+#else
+ memcpy (lwpstat.pr_context.uc_mcontext.__gregs,
+ gregs, sizeof (lwpstat.pr_context.uc_mcontext.__gregs));
+#endif
+#endif
+ return elfcore_write_note (abfd, buf, bufsiz, note_name,
+ NT_LWPSTATUS, &lwpstat, sizeof (lwpstat));
+}
+#endif /* HAVE_LWPSTATUS_T */
+
#if defined (HAVE_PSTATUS_T)
char *
elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
int *bufsiz;
long pid;
int cursig;
- void *gregs;
+ const PTR gregs;
{
pstatus_t pstat;
char *note_name = "CORE";
- memset (&pstat, 0, sizeof (prstat));
- pstat.pr_pid = pid;
- memcpy (pstat.pr_reg, gregs, sizeof (pstat.pr_reg));
- return elfcore_write_note (abfd, buf, bufsiz,
- note_name, NT_PSTATUS, &pstat, sizeof (pstat));
+ memset (&pstat, 0, sizeof (pstat));
+ pstat.pr_pid = pid & 0xffff;
+ buf = elfcore_write_note (abfd, buf, bufsiz, note_name,
+ NT_PSTATUS, &pstat, sizeof (pstat));
+ return buf;
}
#endif /* HAVE_PSTATUS_T */
bfd *abfd;
char *buf;
int *bufsiz;
- void *fpregs;
+ const PTR fpregs;
int size;
{
char *note_name = "CORE";
- return elfcore_write_note (abfd, buf, bufsiz,
+ return elfcore_write_note (abfd, buf, bufsiz,
note_name, NT_FPREGSET, fpregs, size);
}
bfd *abfd;
char *buf;
int *bufsiz;
- void *xfpregs;
+ const PTR xfpregs;
int size;
{
char *note_name = "LINUX";
- return elfcore_write_note (abfd, buf, bufsiz,
+ return elfcore_write_note (abfd, buf, bufsiz,
note_name, NT_PRXFPREG, xfpregs, size);
}
-static boolean
+static bfd_boolean
elfcore_read_notes (abfd, offset, size)
bfd *abfd;
file_ptr offset;
char *p;
if (size <= 0)
- return true;
+ return TRUE;
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
- return false;
+ return FALSE;
buf = bfd_malloc (size);
if (buf == NULL)
- return false;
+ return FALSE;
if (bfd_bread (buf, size, abfd) != size)
{
error:
free (buf);
- return false;
+ return FALSE;
}
p = buf;
if (! elfcore_grok_netbsd_note (abfd, &in))
goto error;
}
+ else if (strncmp (in.namedata, "QNX", 3) == 0)
+ {
+ if (! elfcore_grok_nto_note (abfd, &in))
+ goto error;
+ }
else
{
if (! elfcore_grok_note (abfd, &in))
}
free (buf);
- return true;
+ return TRUE;
}
\f
/* Providing external access to the ELF program header table. */
return reloc_class_normal;
}
-/* For RELA architectures, return what the relocation value for
+/* For RELA architectures, return the relocation value for a
relocation against a local symbol. */
bfd_vma
+ sym->st_value);
if ((sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
- && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
+ && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
asection *msec;
Elf_Internal_Sym *sym;
asection **psec;
bfd_vma addend;
-{
+{
asection *sec = *psec;
- if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
+ if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
return sym->st_value + addend;
return _bfd_merged_section_offset (abfd, psec,
struct bfd_elf_section_data *sec_data;
sec_data = elf_section_data (sec);
- switch (sec_data->sec_info_type)
+ switch (sec->sec_info_type)
{
case ELF_INFO_TYPE_STABS:
- return _bfd_stab_section_offset
- (abfd, &elf_hash_table (info)->merge_info, sec, &sec_data->sec_info,
- offset);
+ return _bfd_stab_section_offset (abfd,
+ &elf_hash_table (info)->merge_info,
+ sec, &sec_data->sec_info, offset);
case ELF_INFO_TYPE_EH_FRAME:
return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
default:
return offset;
}
}
+\f
+/* Create a new BFD as if by bfd_openr. Rather than opening a file,
+ reconstruct an ELF file by reading the segments out of remote memory
+ based on the ELF file header at EHDR_VMA and the ELF program headers it
+ points to. If not null, *LOADBASEP is filled in with the difference
+ between the VMAs from which the segments were read, and the VMAs the
+ file headers (and hence BFD's idea of each section's VMA) put them at.
+
+ The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+ remote memory at target address VMA into the local buffer at MYADDR; it
+ should return zero on success or an `errno' code on failure. TEMPL must
+ be a BFD for an ELF target with the word size and byte order found in
+ the remote memory. */
+
+bfd *
+bfd_elf_bfd_from_remote_memory (templ, ehdr_vma, loadbasep, target_read_memory)
+ bfd *templ;
+ bfd_vma ehdr_vma;
+ bfd_vma *loadbasep;
+ int (*target_read_memory) PARAMS ((bfd_vma vma, char *myaddr, int len));
+{
+ return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
+ (templ, ehdr_vma, loadbasep, target_read_memory);
+}