/* ELF executable support for BFD.
- Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003 Free Software Foundation, Inc.
+
+ Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "elf-bfd.h"
#include "libiberty.h"
-static INLINE struct elf_segment_map *make_mapping
- 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 *));
+static int elf_sort_sections (const void *, const void *);
+static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
+static bfd_boolean prep_headers (bfd *);
+static bfd_boolean swap_out_syms (bfd *, struct bfd_strtab_hash **, int) ;
+static bfd_boolean elfcore_read_notes (bfd *, file_ptr, bfd_size_type) ;
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
/* Swap in a Verdef structure. */
void
-_bfd_elf_swap_verdef_in (abfd, src, dst)
- bfd *abfd;
- const Elf_External_Verdef *src;
- Elf_Internal_Verdef *dst;
+_bfd_elf_swap_verdef_in (bfd *abfd,
+ const Elf_External_Verdef *src,
+ Elf_Internal_Verdef *dst)
{
dst->vd_version = H_GET_16 (abfd, src->vd_version);
dst->vd_flags = H_GET_16 (abfd, src->vd_flags);
/* Swap out a Verdef structure. */
void
-_bfd_elf_swap_verdef_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Verdef *src;
- Elf_External_Verdef *dst;
+_bfd_elf_swap_verdef_out (bfd *abfd,
+ const Elf_Internal_Verdef *src,
+ Elf_External_Verdef *dst)
{
H_PUT_16 (abfd, src->vd_version, dst->vd_version);
H_PUT_16 (abfd, src->vd_flags, dst->vd_flags);
/* Swap in a Verdaux structure. */
void
-_bfd_elf_swap_verdaux_in (abfd, src, dst)
- bfd *abfd;
- const Elf_External_Verdaux *src;
- Elf_Internal_Verdaux *dst;
+_bfd_elf_swap_verdaux_in (bfd *abfd,
+ const Elf_External_Verdaux *src,
+ Elf_Internal_Verdaux *dst)
{
dst->vda_name = H_GET_32 (abfd, src->vda_name);
dst->vda_next = H_GET_32 (abfd, src->vda_next);
/* Swap out a Verdaux structure. */
void
-_bfd_elf_swap_verdaux_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Verdaux *src;
- Elf_External_Verdaux *dst;
+_bfd_elf_swap_verdaux_out (bfd *abfd,
+ const Elf_Internal_Verdaux *src,
+ Elf_External_Verdaux *dst)
{
H_PUT_32 (abfd, src->vda_name, dst->vda_name);
H_PUT_32 (abfd, src->vda_next, dst->vda_next);
/* Swap in a Verneed structure. */
void
-_bfd_elf_swap_verneed_in (abfd, src, dst)
- bfd *abfd;
- const Elf_External_Verneed *src;
- Elf_Internal_Verneed *dst;
+_bfd_elf_swap_verneed_in (bfd *abfd,
+ const Elf_External_Verneed *src,
+ Elf_Internal_Verneed *dst)
{
dst->vn_version = H_GET_16 (abfd, src->vn_version);
dst->vn_cnt = H_GET_16 (abfd, src->vn_cnt);
/* Swap out a Verneed structure. */
void
-_bfd_elf_swap_verneed_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Verneed *src;
- Elf_External_Verneed *dst;
+_bfd_elf_swap_verneed_out (bfd *abfd,
+ const Elf_Internal_Verneed *src,
+ Elf_External_Verneed *dst)
{
H_PUT_16 (abfd, src->vn_version, dst->vn_version);
H_PUT_16 (abfd, src->vn_cnt, dst->vn_cnt);
/* Swap in a Vernaux structure. */
void
-_bfd_elf_swap_vernaux_in (abfd, src, dst)
- bfd *abfd;
- const Elf_External_Vernaux *src;
- Elf_Internal_Vernaux *dst;
+_bfd_elf_swap_vernaux_in (bfd *abfd,
+ const Elf_External_Vernaux *src,
+ Elf_Internal_Vernaux *dst)
{
dst->vna_hash = H_GET_32 (abfd, src->vna_hash);
dst->vna_flags = H_GET_16 (abfd, src->vna_flags);
/* Swap out a Vernaux structure. */
void
-_bfd_elf_swap_vernaux_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Vernaux *src;
- Elf_External_Vernaux *dst;
+_bfd_elf_swap_vernaux_out (bfd *abfd,
+ const Elf_Internal_Vernaux *src,
+ Elf_External_Vernaux *dst)
{
H_PUT_32 (abfd, src->vna_hash, dst->vna_hash);
H_PUT_16 (abfd, src->vna_flags, dst->vna_flags);
/* Swap in a Versym structure. */
void
-_bfd_elf_swap_versym_in (abfd, src, dst)
- bfd *abfd;
- const Elf_External_Versym *src;
- Elf_Internal_Versym *dst;
+_bfd_elf_swap_versym_in (bfd *abfd,
+ const Elf_External_Versym *src,
+ Elf_Internal_Versym *dst)
{
dst->vs_vers = H_GET_16 (abfd, src->vs_vers);
}
/* Swap out a Versym structure. */
void
-_bfd_elf_swap_versym_out (abfd, src, dst)
- bfd *abfd;
- const Elf_Internal_Versym *src;
- Elf_External_Versym *dst;
+_bfd_elf_swap_versym_out (bfd *abfd,
+ const Elf_Internal_Versym *src,
+ Elf_External_Versym *dst)
{
H_PUT_16 (abfd, src->vs_vers, dst->vs_vers);
}
cause invalid hash tables to be generated. */
unsigned long
-bfd_elf_hash (namearg)
- const char *namearg;
+bfd_elf_hash (const char *namearg)
{
const unsigned char *name = (const unsigned char *) namearg;
unsigned long h = 0;
buffer. */
static char *
-elf_read (abfd, offset, size)
- bfd *abfd;
- file_ptr offset;
- bfd_size_type size;
+elf_read (bfd *abfd, file_ptr offset, bfd_size_type size)
{
char *buf;
return NULL;
if (bfd_seek (abfd, offset, SEEK_SET) != 0)
return NULL;
- if (bfd_bread ((PTR) buf, size, abfd) != size)
+ if (bfd_bread (buf, size, abfd) != size)
{
if (bfd_get_error () != bfd_error_system_call)
bfd_set_error (bfd_error_file_truncated);
}
bfd_boolean
-bfd_elf_mkobject (abfd)
- bfd *abfd;
+bfd_elf_mkobject (bfd *abfd)
{
/* This just does initialization. */
/* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
- bfd_size_type amt = sizeof (struct elf_obj_tdata);
- elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
+ elf_tdata (abfd) = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
if (elf_tdata (abfd) == 0)
return FALSE;
/* Since everything is done at close time, do we need any
}
bfd_boolean
-bfd_elf_mkcorefile (abfd)
- bfd *abfd;
+bfd_elf_mkcorefile (bfd *abfd)
{
/* I think this can be done just like an object file. */
return bfd_elf_mkobject (abfd);
}
char *
-bfd_elf_get_str_section (abfd, shindex)
- bfd *abfd;
- unsigned int shindex;
+bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
{
Elf_Internal_Shdr **i_shdrp;
char *shstrtab = NULL;
offset = i_shdrp[shindex]->sh_offset;
shstrtabsize = i_shdrp[shindex]->sh_size;
shstrtab = elf_read (abfd, offset, shstrtabsize);
- i_shdrp[shindex]->contents = (PTR) shstrtab;
+ i_shdrp[shindex]->contents = shstrtab;
}
return shstrtab;
}
char *
-bfd_elf_string_from_elf_section (abfd, shindex, strindex)
- bfd *abfd;
- unsigned int shindex;
- unsigned int strindex;
+bfd_elf_string_from_elf_section (bfd *abfd,
+ unsigned int shindex,
+ unsigned int strindex)
{
Elf_Internal_Shdr *hdr;
if (strindex >= hdr->sh_size)
{
(*_bfd_error_handler)
- (_("%s: invalid string offset %u >= %lu for section `%s'"),
- bfd_archive_filename (abfd), strindex, (unsigned long) hdr->sh_size,
+ (_("%B: invalid string offset %u >= %lu for section `%s'"),
+ abfd, strindex, (unsigned long) hdr->sh_size,
((shindex == elf_elfheader(abfd)->e_shstrndx
&& strindex == hdr->sh_name)
? ".shstrtab"
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;
+bfd_elf_get_elf_syms (bfd *ibfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ size_t symcount,
+ size_t symoffset,
+ Elf_Internal_Sym *intsym_buf,
+ void *extsym_buf,
+ Elf_External_Sym_Shndx *extshndx_buf)
{
Elf_Internal_Shdr *shndx_hdr;
- PTR alloc_ext;
+ void *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;
+ const struct elf_backend_data *bed;
size_t extsym_size;
bfd_size_type amt;
file_ptr pos;
pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
if (extshndx_buf == NULL)
{
- alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ alloc_extshndx = bfd_malloc (amt);
extshndx_buf = alloc_extshndx;
}
if (extshndx_buf == NULL
if (intsym_buf == NULL)
{
bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
- intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt);
+ intsym_buf = bfd_malloc (amt);
if (intsym_buf == NULL)
goto out;
}
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);
+ (*bed->s->swap_symbol_in) (ibfd, esym, shndx, isym);
out:
if (alloc_ext != NULL)
/* Look up a symbol name. */
const char *
-bfd_elf_local_sym_name (abfd, isym)
- bfd *abfd;
- Elf_Internal_Sym *isym;
+bfd_elf_local_sym_name (bfd *abfd, Elf_Internal_Sym *isym)
{
unsigned int iname = isym->st_name;
unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
signature just a string? */
static const char *
-group_signature (abfd, ghdr)
- bfd *abfd;
- Elf_Internal_Shdr *ghdr;
+group_signature (bfd *abfd, Elf_Internal_Shdr *ghdr)
{
Elf_Internal_Shdr *hdr;
unsigned char esym[sizeof (Elf64_External_Sym)];
/* Set next_in_group list pointer, and group name for NEWSECT. */
static bfd_boolean
-setup_group (abfd, hdr, newsect)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- asection *newsect;
+setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
{
unsigned int num_group = elf_tdata (abfd)->num_group;
if (idx >= shnum)
{
((*_bfd_error_handler)
- (_("%s: invalid SHT_GROUP entry"),
- bfd_archive_filename (abfd)));
+ (_("%B: invalid SHT_GROUP entry"), abfd));
idx = 0;
}
dest->shdr = elf_elfsections (abfd)[idx];
if (elf_group_name (newsect) == NULL)
{
- (*_bfd_error_handler) (_("%s: no group info for section %s"),
- bfd_archive_filename (abfd), newsect->name);
+ (*_bfd_error_handler) (_("%B: no group info for section %A"),
+ abfd, newsect);
}
return TRUE;
}
bfd_boolean
-bfd_elf_discard_group (abfd, group)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *group;
+_bfd_elf_setup_group_pointers (bfd *abfd)
+{
+ unsigned int i;
+ unsigned int num_group = elf_tdata (abfd)->num_group;
+ bfd_boolean result = TRUE;
+
+ if (num_group == (unsigned) -1)
+ return result;
+
+ for (i = 0; i < num_group; i++)
+ {
+ Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
+ Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
+ unsigned int n_elt = shdr->sh_size / 4;
+
+ while (--n_elt != 0)
+ if ((++idx)->shdr->bfd_section)
+ elf_sec_group (idx->shdr->bfd_section) = shdr->bfd_section;
+ else if (idx->shdr->sh_type == SHT_RELA
+ || idx->shdr->sh_type == SHT_REL)
+ /* We won't include relocation sections in section groups in
+ output object files. We adjust the group section size here
+ so that relocatable link will work correctly when
+ relocation sections are in section group in input object
+ files. */
+ shdr->bfd_section->size -= 4;
+ else
+ {
+ /* There are some unknown sections in the group. */
+ (*_bfd_error_handler)
+ (_("%B: unknown [%d] section `%s' in group [%s]"),
+ abfd,
+ (unsigned int) idx->shdr->sh_type,
+ elf_string_from_elf_strtab (abfd, idx->shdr->sh_name),
+ shdr->bfd_section->name);
+ result = FALSE;
+ }
+ }
+ return result;
+}
+
+bfd_boolean
+bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
{
+ return elf_next_in_group (sec) != NULL;
+}
+
+bfd_boolean
+bfd_elf_discard_group (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *group ATTRIBUTE_UNUSED)
+{
+#if 0
asection *first = elf_next_in_group (group);
asection *s = first;
if (s == first)
break;
}
+#else
+ /* FIXME: Never used. Remove it! */
+ abort ();
+#endif
return TRUE;
}
BFD section in the bfd_section field of the header. */
bfd_boolean
-_bfd_elf_make_section_from_shdr (abfd, hdr, name)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- const char *name;
+_bfd_elf_make_section_from_shdr (bfd *abfd,
+ Elf_Internal_Shdr *hdr,
+ const char *name)
{
asection *newsect;
flagword flags;
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
if (hdr->bfd_section != NULL)
{
if (newsect == NULL)
return FALSE;
+ hdr->bfd_section = newsect;
+ elf_section_data (newsect)->this_hdr = *hdr;
+
+ /* Always use the real type/flags. */
+ elf_section_type (newsect) = hdr->sh_type;
+ elf_section_flags (newsect) = hdr->sh_flags;
+
newsect->filepos = hdr->sh_offset;
if (! bfd_set_section_vma (abfd, newsect, hdr->sh_addr)
}
}
- hdr->bfd_section = newsect;
- elf_section_data (newsect)->this_hdr = *hdr;
-
return TRUE;
}
*/
struct elf_internal_shdr *
-bfd_elf_find_section (abfd, name)
- bfd *abfd;
- char *name;
+bfd_elf_find_section (bfd *abfd, char *name)
{
Elf_Internal_Shdr **i_shdrp;
char *shstrtab;
relocatable output against an external symbol. */
bfd_reloc_status_type
-bfd_elf_generic_reloc (abfd,
- reloc_entry,
- symbol,
- data,
- input_section,
- output_bfd,
- error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc_entry;
- asymbol *symbol;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message ATTRIBUTE_UNUSED;
-{
- if (output_bfd != (bfd *) NULL
+bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *reloc_entry,
+ asymbol *symbol,
+ void *data ATTRIBUTE_UNUSED,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message ATTRIBUTE_UNUSED)
+{
+ if (output_bfd != NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& (! reloc_entry->howto->partial_inplace
|| reloc_entry->addend == 0))
/* Make sure sec_info_type is cleared if sec_info is cleared too. */
static void
-merge_sections_remove_hook (abfd, sec)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
+merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec)
{
BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
sec->sec_info_type = ELF_INFO_TYPE_NONE;
/* Finish SHF_MERGE section merging. */
bfd_boolean
-_bfd_elf_merge_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
{
- if (!is_elf_hash_table (info))
+ bfd *ibfd;
+ asection *sec;
+
+ if (!is_elf_hash_table (info->hash))
return FALSE;
- if (elf_hash_table (info)->merge_info)
- _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info,
+
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ if ((ibfd->flags & DYNAMIC) == 0)
+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
+ if ((sec->flags & SEC_MERGE) != 0
+ && !bfd_is_abs_section (sec->output_section))
+ {
+ struct bfd_elf_section_data *secdata;
+
+ secdata = elf_section_data (sec);
+ if (! _bfd_add_merge_section (abfd,
+ &elf_hash_table (info)->merge_info,
+ sec, &secdata->sec_info))
+ return FALSE;
+ else if (secdata->sec_info)
+ sec->sec_info_type = ELF_INFO_TYPE_MERGE;
+ }
+
+ if (elf_hash_table (info)->merge_info != NULL)
+ _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info,
merge_sections_remove_hook);
return TRUE;
}
void
-_bfd_elf_link_just_syms (sec, info)
- asection *sec;
- struct bfd_link_info *info;
+_bfd_elf_link_just_syms (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))
+ if (!is_elf_hash_table (info->hash))
return;
sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
another. */
bfd_boolean
-_bfd_elf_copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
+_bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
/* Print out the program headers. */
bfd_boolean
-_bfd_elf_print_private_bfd_data (abfd, farg)
- bfd *abfd;
- PTR farg;
+_bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
{
- FILE *f = (FILE *) farg;
+ FILE *f = farg;
Elf_Internal_Phdr *p;
asection *s;
bfd_byte *dynbuf = NULL;
case PT_TLS: pt = "TLS"; break;
case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
case PT_GNU_STACK: pt = "STACK"; break;
+ case PT_GNU_RELRO: pt = "RELRO"; break;
default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
}
fprintf (f, "%8s off 0x", pt);
unsigned long shlink;
bfd_byte *extdyn, *extdynend;
size_t extdynsize;
- void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+ void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
fprintf (f, _("\nDynamic Section:\n"));
- dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
- if (dynbuf == NULL)
- goto error_return;
- if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
- s->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
- extdynend = extdyn + s->_raw_size;
+ extdynend = extdyn + s->size;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
char ab[20];
bfd_boolean stringp;
- (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+ (*swap_dyn_in) (abfd, extdyn, &dyn);
if (dyn.d_tag == DT_NULL)
break;
/* Display ELF-specific fields of a symbol. */
void
-bfd_elf_print_symbol (abfd, filep, symbol, how)
- bfd *abfd;
- PTR filep;
- asymbol *symbol;
- bfd_print_symbol_type how;
+bfd_elf_print_symbol (bfd *abfd,
+ void *filep,
+ asymbol *symbol,
+ bfd_print_symbol_type how)
{
- FILE *file = (FILE *) filep;
+ FILE *file = filep;
switch (how)
{
case bfd_print_symbol_name:
{
const char *section_name;
const char *name = NULL;
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
unsigned char st_other;
bfd_vma val;
if (name == NULL)
{
name = symbol->name;
- bfd_print_symbol_vandf (abfd, (PTR) file, symbol);
+ bfd_print_symbol_vandf (abfd, file, symbol);
}
fprintf (file, " %s\t", section_name);
/* Create an entry in an ELF linker hash table. */
struct bfd_hash_entry *
-_bfd_elf_link_hash_newfunc (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+_bfd_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
/* Allocate the structure if it has not already been allocated by a
subclass. */
/* Set local fields. */
ret->indx = -1;
ret->dynindx = -1;
- ret->dynstr_index = 0;
- ret->elf_hash_value = 0;
- ret->weakdef = NULL;
- ret->linker_section_pointer = NULL;
- ret->verinfo.verdef = 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;
+ ret->got = ret->plt = htab->init_refcount;
+ memset (&ret->size, 0, (sizeof (struct elf_link_hash_entry)
+ - offsetof (struct elf_link_hash_entry, size)));
/* Assume that we have been called by a non-ELF symbol reader.
This flag is then reset by the code which reads an ELF input
file. This ensures that a symbol created by a non-ELF symbol
reader will have the flag set correctly. */
- ret->elf_link_hash_flags = ELF_LINK_NON_ELF;
+ ret->non_elf = 1;
}
return entry;
old indirect symbol. Also used for copying flags to a weakdef. */
void
-_bfd_elf_link_hash_copy_indirect (bed, dir, ind)
- struct elf_backend_data *bed;
- struct elf_link_hash_entry *dir, *ind;
+_bfd_elf_link_hash_copy_indirect (const struct elf_backend_data *bed,
+ struct elf_link_hash_entry *dir,
+ struct elf_link_hash_entry *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. */
- dir->elf_link_hash_flags |=
- (ind->elf_link_hash_flags
- & (ELF_LINK_HASH_REF_DYNAMIC
- | ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK
- | ELF_LINK_NON_GOT_REF));
+ dir->ref_dynamic |= ind->ref_dynamic;
+ dir->ref_regular |= ind->ref_regular;
+ dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
+ dir->non_got_ref |= ind->non_got_ref;
+ dir->needs_plt |= ind->needs_plt;
+ dir->pointer_equality_needed |= ind->pointer_equality_needed;
if (ind->root.type != bfd_link_hash_indirect)
return;
}
void
-_bfd_elf_link_hash_hide_symbol (info, h, force_local)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- bfd_boolean force_local;
+_bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ bfd_boolean force_local)
{
h->plt = elf_hash_table (info)->init_offset;
- h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 0;
if (force_local)
{
- h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+ h->forced_local = 1;
if (h->dynindx != -1)
{
h->dynindx = -1;
/* Initialize an ELF linker hash table. */
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 *));
+_bfd_elf_link_hash_table_init
+ (struct elf_link_hash_table *table,
+ bfd *abfd,
+ struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *))
{
bfd_boolean ret;
table->bucketcount = 0;
table->needed = NULL;
table->hgot = NULL;
- table->stab_info = NULL;
table->merge_info = NULL;
+ memset (&table->stab_info, 0, sizeof (table->stab_info));
memset (&table->eh_info, 0, sizeof (table->eh_info));
table->dynlocal = NULL;
table->runpath = NULL;
- table->tls_segment = NULL;
+ table->tls_sec = NULL;
+ table->tls_size = 0;
table->loaded = NULL;
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
/* Create an ELF linker hash table. */
struct bfd_link_hash_table *
-_bfd_elf_link_hash_table_create (abfd)
- bfd *abfd;
+_bfd_elf_link_hash_table_create (bfd *abfd)
{
struct elf_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_link_hash_table);
- ret = (struct elf_link_hash_table *) bfd_malloc (amt);
- if (ret == (struct elf_link_hash_table *) NULL)
+ ret = bfd_malloc (amt);
+ if (ret == NULL)
return NULL;
if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
/* This is a hook for the ELF emulation code in the generic linker to
tell the backend linker what file name to use for the DT_NEEDED
- entry for a dynamic object. The generic linker passes name as an
- empty string to indicate that no DT_NEEDED entry should be made. */
+ entry for a dynamic object. */
void
-bfd_elf_set_dt_needed_name (abfd, name)
- bfd *abfd;
- const char *name;
+bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object)
elf_dt_name (abfd) = name;
}
+int
+bfd_elf_get_dyn_lib_class (bfd *abfd)
+{
+ int lib_class;
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && bfd_get_format (abfd) == bfd_object)
+ lib_class = elf_dyn_lib_class (abfd);
+ else
+ lib_class = 0;
+ return lib_class;
+}
+
void
-bfd_elf_set_dt_needed_soname (abfd, name)
- bfd *abfd;
- const char *name;
+bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object)
- elf_dt_soname (abfd) = name;
+ elf_dyn_lib_class (abfd) = lib_class;
}
/* Get the list of DT_NEEDED entries for a link. This is a hook for
the linker ELF emulation code. */
struct bfd_link_needed_list *
-bfd_elf_get_needed_list (abfd, info)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
+bfd_elf_get_needed_list (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
{
- if (! is_elf_hash_table (info))
+ if (! is_elf_hash_table (info->hash))
return NULL;
return elf_hash_table (info)->needed;
}
hook for the linker ELF emulation code. */
struct bfd_link_needed_list *
-bfd_elf_get_runpath_list (abfd, info)
- bfd *abfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
+bfd_elf_get_runpath_list (bfd *abfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
{
- if (! is_elf_hash_table (info))
+ if (! is_elf_hash_table (info->hash))
return NULL;
return elf_hash_table (info)->runpath;
}
passed to bfd_elf_set_dt_needed_name, or it is the filename. */
const char *
-bfd_elf_get_dt_soname (abfd)
- bfd *abfd;
+bfd_elf_get_dt_soname (bfd *abfd)
{
if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object)
the ELF linker emulation code. */
bfd_boolean
-bfd_elf_get_bfd_needed_list (abfd, pneeded)
- bfd *abfd;
- struct bfd_link_needed_list **pneeded;
+bfd_elf_get_bfd_needed_list (bfd *abfd,
+ struct bfd_link_needed_list **pneeded)
{
asection *s;
bfd_byte *dynbuf = NULL;
unsigned long shlink;
bfd_byte *extdyn, *extdynend;
size_t extdynsize;
- void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+ void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
*pneeded = NULL;
return TRUE;
s = bfd_get_section_by_name (abfd, ".dynamic");
- if (s == NULL || s->_raw_size == 0)
+ if (s == NULL || s->size == 0)
return TRUE;
- dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
- if (dynbuf == NULL)
- goto error_return;
-
- if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
- s->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
goto error_return;
elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
extdyn = dynbuf;
- extdynend = extdyn + s->_raw_size;
+ extdynend = extdyn + s->size;
for (; extdyn < extdynend; extdyn += extdynsize)
{
Elf_Internal_Dyn dyn;
- (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+ (*swap_dyn_in) (abfd, extdyn, &dyn);
if (dyn.d_tag == DT_NULL)
break;
goto error_return;
amt = sizeof *l;
- l = (struct bfd_link_needed_list *) bfd_alloc (abfd, amt);
+ l = bfd_alloc (abfd, amt);
if (l == NULL)
goto error_return;
/* Allocate an ELF string table--force the first byte to be zero. */
struct bfd_strtab_hash *
-_bfd_elf_stringtab_init ()
+_bfd_elf_stringtab_init (void)
{
struct bfd_strtab_hash *ret;
/* Create a new bfd section from an ELF section header. */
bfd_boolean
-bfd_section_from_shdr (abfd, shindex)
- bfd *abfd;
- unsigned int shindex;
+bfd_section_from_shdr (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);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
const char *name;
name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
case SHT_INIT_ARRAY: /* .init_array section. */
case SHT_FINI_ARRAY: /* .fini_array section. */
case SHT_PREINIT_ARRAY: /* .preinit_array section. */
+ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
case SHT_DYNAMIC: /* Dynamic linking information. */
|| hdr->sh_link >= num_sec)
{
((*_bfd_error_handler)
- (_("%s: invalid link %lu for reloc section %s (index %u)"),
- bfd_archive_filename (abfd), hdr->sh_link, name, shindex));
+ (_("%B: invalid link %lu for reloc section %s (index %u)"),
+ abfd, hdr->sh_link, name, shindex));
return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
}
bfd_size_type amt;
BFD_ASSERT (elf_section_data (target_sect)->rel_hdr2 == NULL);
amt = sizeof (*hdr2);
- hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+ hdr2 = bfd_alloc (abfd, amt);
elf_section_data (target_sect)->rel_hdr2 = hdr2;
}
*hdr2 = *hdr;
hdr->bfd_section->flags
|= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
+ /* We try to keep the same section order as it comes in. */
+ idx += n_elt;
while (--n_elt != 0)
- if ((s = (++idx)->shdr->bfd_section) != NULL
+ if ((s = (--idx)->shdr->bfd_section) != NULL
&& elf_next_in_group (s) != NULL)
{
elf_next_in_group (hdr->bfd_section) = s;
Return SEC for sections that have no elf section, and NULL on error. */
asection *
-bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
- bfd *abfd;
- struct sym_sec_cache *cache;
- asection *sec;
- unsigned long r_symndx;
+bfd_section_from_r_symndx (bfd *abfd,
+ struct sym_sec_cache *cache,
+ asection *sec,
+ unsigned long r_symndx)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned char esym[sizeof (Elf64_External_Sym)];
}
cache->indx[ent] = r_symndx;
cache->sec[ent] = sec;
- if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
+ if ((isym.st_shndx != SHN_UNDEF && isym.st_shndx < SHN_LORESERVE)
+ || isym.st_shndx > SHN_HIRESERVE)
{
asection *s;
s = bfd_section_from_elf_index (abfd, isym.st_shndx);
section. */
asection *
-bfd_section_from_elf_index (abfd, index)
- bfd *abfd;
- unsigned int index;
+bfd_section_from_elf_index (bfd *abfd, unsigned int index)
{
if (index >= elf_numsections (abfd))
return NULL;
return elf_elfsections (abfd)[index]->bfd_section;
}
+static struct bfd_elf_special_section const special_sections[] =
+{
+ { ".bss", 4, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { ".gnu.linkonce.b",15, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { ".comment", 8, 0, SHT_PROGBITS, 0 },
+ { ".data", 5, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".data1", 6, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".debug", 6, 0, SHT_PROGBITS, 0 },
+ { ".fini", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".init", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".line", 5, 0, SHT_PROGBITS, 0 },
+ { ".rodata", 7, -2, SHT_PROGBITS, SHF_ALLOC },
+ { ".rodata1", 8, 0, SHT_PROGBITS, SHF_ALLOC },
+ { ".tbss", 5, -2, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
+ { ".tdata", 6, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_TLS },
+ { ".text", 5, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".init_array", 11, 0, SHT_INIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".fini_array", 11, 0, SHT_FINI_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".preinit_array", 14, 0, SHT_PREINIT_ARRAY, SHF_ALLOC + SHF_WRITE },
+ { ".debug_line", 11, 0, SHT_PROGBITS, 0 },
+ { ".debug_info", 11, 0, SHT_PROGBITS, 0 },
+ { ".debug_abbrev", 13, 0, SHT_PROGBITS, 0 },
+ { ".debug_aranges", 14, 0, SHT_PROGBITS, 0 },
+ { ".dynamic", 8, 0, SHT_DYNAMIC, SHF_ALLOC },
+ { ".dynstr", 7, 0, SHT_STRTAB, SHF_ALLOC },
+ { ".dynsym", 7, 0, SHT_DYNSYM, SHF_ALLOC },
+ { ".got", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".hash", 5, 0, SHT_HASH, SHF_ALLOC },
+ { ".interp", 7, 0, SHT_PROGBITS, 0 },
+ { ".plt", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".shstrtab", 9, 0, SHT_STRTAB, 0 },
+ { ".strtab", 7, 0, SHT_STRTAB, 0 },
+ { ".symtab", 7, 0, SHT_SYMTAB, 0 },
+ { ".gnu.version", 12, 0, SHT_GNU_versym, 0 },
+ { ".gnu.version_d", 14, 0, SHT_GNU_verdef, 0 },
+ { ".gnu.version_r", 14, 0, SHT_GNU_verneed, 0 },
+ { ".note.GNU-stack",15, 0, SHT_PROGBITS, 0 },
+ { ".note", 5, -1, SHT_NOTE, 0 },
+ { ".rela", 5, -1, SHT_RELA, 0 },
+ { ".rel", 4, -1, SHT_REL, 0 },
+ { ".stabstr", 5, 3, SHT_STRTAB, 0 },
+ { ".gnu.liblist", 12, 0, SHT_GNU_LIBLIST, SHF_ALLOC },
+ { ".gnu.conflict", 13, 0, SHT_RELA, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
+};
+
+static const struct bfd_elf_special_section *
+get_special_section (const char *name,
+ const struct bfd_elf_special_section *special_sections,
+ unsigned int rela)
+{
+ int i;
+ int len = strlen (name);
+
+ for (i = 0; special_sections[i].prefix != NULL; i++)
+ {
+ int suffix_len;
+ int prefix_len = special_sections[i].prefix_length;
+
+ if (len < prefix_len)
+ continue;
+ if (memcmp (name, special_sections[i].prefix, prefix_len) != 0)
+ continue;
+
+ suffix_len = special_sections[i].suffix_length;
+ if (suffix_len <= 0)
+ {
+ if (name[prefix_len] != 0)
+ {
+ if (suffix_len == 0)
+ continue;
+ if (name[prefix_len] != '.'
+ && (suffix_len == -2
+ || (rela && special_sections[i].type == SHT_REL)))
+ continue;
+ }
+ }
+ else
+ {
+ if (len < prefix_len + suffix_len)
+ continue;
+ if (memcmp (name + len - suffix_len,
+ special_sections[i].prefix + prefix_len,
+ suffix_len) != 0)
+ continue;
+ }
+ return &special_sections[i];
+ }
+
+ return NULL;
+}
+
+const struct bfd_elf_special_section *
+_bfd_elf_get_sec_type_attr (bfd *abfd, const char *name)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct bfd_elf_special_section *ssect = NULL;
+
+ /* See if this is one of the special sections. */
+ if (name)
+ {
+ unsigned int rela = bed->default_use_rela_p;
+
+ if (bed->special_sections)
+ ssect = get_special_section (name, bed->special_sections, rela);
+
+ if (! ssect)
+ ssect = get_special_section (name, special_sections, rela);
+ }
+
+ return ssect;
+}
+
bfd_boolean
-_bfd_elf_new_section_hook (abfd, sec)
- bfd *abfd;
- asection *sec;
+_bfd_elf_new_section_hook (bfd *abfd, asection *sec)
{
struct bfd_elf_section_data *sdata;
+ const struct bfd_elf_special_section *ssect;
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);
+ sdata = bfd_zalloc (abfd, sizeof (*sdata));
if (sdata == NULL)
return FALSE;
- sec->used_by_bfd = (PTR) sdata;
+ sec->used_by_bfd = sdata;
+ }
+
+ elf_section_type (sec) = SHT_NULL;
+ ssect = _bfd_elf_get_sec_type_attr (abfd, sec->name);
+ if (ssect != NULL)
+ {
+ elf_section_type (sec) = ssect->type;
+ elf_section_flags (sec) = ssect->attr;
}
/* Indicate whether or not this section should use RELA relocations. */
*/
bfd_boolean
-_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
- bfd *abfd;
- Elf_Internal_Phdr *hdr;
- int index;
- const char *typename;
+_bfd_elf_make_section_from_phdr (bfd *abfd,
+ Elf_Internal_Phdr *hdr,
+ int index,
+ const char *typename)
{
asection *newsect;
char *name;
&& (hdr->p_memsz > hdr->p_filesz));
sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
len = strlen (namebuf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
return FALSE;
newsect->vma = hdr->p_vaddr;
newsect->lma = hdr->p_paddr;
- newsect->_raw_size = hdr->p_filesz;
+ newsect->size = hdr->p_filesz;
newsect->filepos = hdr->p_offset;
newsect->flags |= SEC_HAS_CONTENTS;
+ newsect->alignment_power = bfd_log2 (hdr->p_align);
if (hdr->p_type == PT_LOAD)
{
newsect->flags |= SEC_ALLOC;
{
sprintf (namebuf, "%s%db", typename, index);
len = strlen (namebuf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (!name)
return FALSE;
memcpy (name, namebuf, len);
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->size = hdr->p_memsz - hdr->p_filesz;
if (hdr->p_type == PT_LOAD)
{
newsect->flags |= SEC_ALLOC;
}
bfd_boolean
-bfd_section_from_phdr (abfd, hdr, index)
- bfd *abfd;
- Elf_Internal_Phdr *hdr;
- int index;
+bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
{
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
switch (hdr->p_type)
{
case PT_NOTE:
if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
return FALSE;
- if (! elfcore_read_notes (abfd, (file_ptr) hdr->p_offset, hdr->p_filesz))
+ if (! elfcore_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
return FALSE;
return TRUE;
case PT_GNU_STACK:
return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+ case PT_GNU_RELRO:
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "relro");
+
default:
/* Check for any processor-specific program segment types.
If no handler for them, default to making "segment" sections. */
relocations; otherwise, we use REL relocations. */
bfd_boolean
-_bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
- bfd *abfd;
- Elf_Internal_Shdr *rel_hdr;
- asection *asect;
- bfd_boolean use_rela_p;
+_bfd_elf_init_reloc_shdr (bfd *abfd,
+ Elf_Internal_Shdr *rel_hdr,
+ asection *asect,
+ bfd_boolean use_rela_p)
{
char *name;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_size_type amt = sizeof ".rela" + strlen (asect->name);
name = bfd_alloc (abfd, amt);
/* Set up an ELF internal section header for a section. */
static void
-elf_fake_sections (abfd, asect, failedptrarg)
- bfd *abfd;
- asection *asect;
- PTR failedptrarg;
+elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_boolean *failedptr = failedptrarg;
Elf_Internal_Shdr *this_hdr;
if (*failedptr)
this_hdr->sh_addr = 0;
this_hdr->sh_offset = 0;
- this_hdr->sh_size = asect->_raw_size;
+ this_hdr->sh_size = asect->size;
this_hdr->sh_link = 0;
this_hdr->sh_addralign = 1 << asect->alignment_power;
/* The sh_entsize and sh_info fields may have been set already by
this_hdr->bfd_section = asect;
this_hdr->contents = NULL;
- /* FIXME: This should not be based on section names. */
- if (strcmp (asect->name, ".dynstr") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if (strcmp (asect->name, ".hash") == 0)
+ /* If the section type is unspecified, we set it based on
+ asect->flags. */
+ if (this_hdr->sh_type == SHT_NULL)
{
- this_hdr->sh_type = SHT_HASH;
- this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
+ if ((asect->flags & SEC_GROUP) != 0)
+ {
+ /* We also need to mark SHF_GROUP here for relocatable
+ link. */
+ struct bfd_link_order *l;
+ asection *elt;
+
+ for (l = asect->link_order_head; l != NULL; l = l->next)
+ if (l->type == bfd_indirect_link_order
+ && (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
+ do
+ {
+ /* The name is not important. Anything will do. */
+ elf_group_name (elt->output_section) = "G";
+ elf_section_flags (elt->output_section) |= SHF_GROUP;
+
+ elt = elf_next_in_group (elt);
+ /* During a relocatable link, the lists are
+ circular. */
+ }
+ while (elt != elf_next_in_group (l->u.indirect.section));
+
+ this_hdr->sh_type = SHT_GROUP;
+ }
+ else if ((asect->flags & SEC_ALLOC) != 0
+ && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ || (asect->flags & SEC_NEVER_LOAD) != 0))
+ this_hdr->sh_type = SHT_NOBITS;
+ else
+ this_hdr->sh_type = SHT_PROGBITS;
}
- else if (strcmp (asect->name, ".dynsym") == 0)
+
+ switch (this_hdr->sh_type)
{
- this_hdr->sh_type = SHT_DYNSYM;
+ default:
+ break;
+
+ case SHT_STRTAB:
+ case SHT_INIT_ARRAY:
+ case SHT_FINI_ARRAY:
+ case SHT_PREINIT_ARRAY:
+ case SHT_NOTE:
+ case SHT_NOBITS:
+ case SHT_PROGBITS:
+ break;
+
+ case SHT_HASH:
+ this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
+ break;
+
+ case SHT_DYNSYM:
this_hdr->sh_entsize = bed->s->sizeof_sym;
- }
- else if (strcmp (asect->name, ".dynamic") == 0)
- {
- this_hdr->sh_type = SHT_DYNAMIC;
+ break;
+
+ case SHT_DYNAMIC:
this_hdr->sh_entsize = bed->s->sizeof_dyn;
- }
- else if (strncmp (asect->name, ".rela", 5) == 0
- && get_elf_backend_data (abfd)->may_use_rela_p)
- {
- this_hdr->sh_type = SHT_RELA;
- this_hdr->sh_entsize = bed->s->sizeof_rela;
- }
- else if (strncmp (asect->name, ".rel", 4) == 0
- && get_elf_backend_data (abfd)->may_use_rel_p)
- {
- 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
- && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
- this_hdr->sh_type = SHT_STRTAB;
- else if (strcmp (asect->name, ".gnu.version") == 0)
- {
- this_hdr->sh_type = SHT_GNU_versym;
+ break;
+
+ case SHT_RELA:
+ if (get_elf_backend_data (abfd)->may_use_rela_p)
+ this_hdr->sh_entsize = bed->s->sizeof_rela;
+ break;
+
+ case SHT_REL:
+ if (get_elf_backend_data (abfd)->may_use_rel_p)
+ this_hdr->sh_entsize = bed->s->sizeof_rel;
+ break;
+
+ case SHT_GNU_versym:
this_hdr->sh_entsize = sizeof (Elf_External_Versym);
- }
- else if (strcmp (asect->name, ".gnu.version_d") == 0)
- {
- this_hdr->sh_type = SHT_GNU_verdef;
+ break;
+
+ case SHT_GNU_verdef:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverdefs. The linker will set cverdefs, but sh_info will be
else
BFD_ASSERT (elf_tdata (abfd)->cverdefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverdefs);
- }
- else if (strcmp (asect->name, ".gnu.version_r") == 0)
- {
- this_hdr->sh_type = SHT_GNU_verneed;
+ break;
+
+ case SHT_GNU_verneed:
this_hdr->sh_entsize = 0;
/* objcopy or strip will copy over sh_info, but may not set
cverrefs. The linker will set cverrefs, but sh_info will be
else
BFD_ASSERT (elf_tdata (abfd)->cverrefs == 0
|| this_hdr->sh_info == elf_tdata (abfd)->cverrefs);
- }
- else if ((asect->flags & SEC_GROUP) != 0)
- {
- this_hdr->sh_type = SHT_GROUP;
+ break;
+
+ case SHT_GROUP:
this_hdr->sh_entsize = 4;
+ break;
}
- else if ((asect->flags & SEC_ALLOC) != 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_ALLOC) != 0)
this_hdr->sh_flags |= SHF_ALLOC;
if ((asect->flags & SEC_THREAD_LOCAL) != 0)
{
this_hdr->sh_flags |= SHF_TLS;
- if (asect->_raw_size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
+ if (asect->size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *o;
/* Fill in the contents of a SHT_GROUP section. */
void
-bfd_elf_set_group_contents (abfd, sec, failedptrarg)
- bfd *abfd;
- asection *sec;
- PTR failedptrarg;
+bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg)
{
- bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
+ bfd_boolean *failedptr = failedptrarg;
unsigned long symindx;
asection *elt, *first;
unsigned char *loc;
if (sec->contents == NULL)
{
gas = FALSE;
- sec->contents = bfd_alloc (abfd, sec->_raw_size);
+ sec->contents = bfd_alloc (abfd, sec->size);
/* Arrange for the section to be written out. */
elf_section_data (sec)->this_hdr.contents = sec->contents;
}
}
- loc = sec->contents + sec->_raw_size;
+ loc = sec->contents + sec->size;
/* Get the pointer to the first section in the group that gas
squirreled away here. objcopy arranges for this to be set to the
}
while (elt != elf_next_in_group (l->u.indirect.section));
- /* 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);
-
- if (loc != sec->contents)
+ if ((loc -= 4) != sec->contents)
abort ();
H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
in here too, while we're at it. */
static bfd_boolean
-assign_section_numbers (abfd)
- bfd *abfd;
+assign_section_numbers (bfd *abfd)
{
struct elf_obj_tdata *t = elf_tdata (abfd);
asection *sec;
/* 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_zalloc (abfd, amt);
+ i_shdrp = bfd_zalloc (abfd, amt);
if (i_shdrp == NULL)
return FALSE;
amt = sizeof (Elf_Internal_Shdr);
- i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
+ i_shdrp[0] = bfd_zalloc (abfd, amt);
if (i_shdrp[0] == NULL)
{
bfd_release (abfd, i_shdrp);
i_shdrp[t->strtab_section] = &t->strtab_hdr;
t->symtab_hdr.sh_link = t->strtab_section;
}
+
for (sec = abfd->sections; sec; sec = sec->next)
{
struct bfd_elf_section_data *d = elf_section_data (sec);
d->rel_hdr2->sh_info = d->this_idx;
}
+ /* We need to set up sh_link for SHF_LINK_ORDER. */
+ if ((d->this_hdr.sh_flags & SHF_LINK_ORDER) != 0)
+ {
+ s = elf_linked_to_section (sec);
+ if (s)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ else
+ {
+ struct bfd_link_order *p;
+
+ /* Find out what the corresponding section in output
+ is. */
+ for (p = sec->link_order_head; p != NULL; p = p->next)
+ {
+ s = p->u.indirect.section;
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (s->owner)
+ == bfd_target_elf_flavour))
+ {
+ Elf_Internal_Shdr ** const elf_shdrp
+ = elf_elfsections (s->owner);
+ int elfsec
+ = _bfd_elf_section_from_bfd_section (s->owner, s);
+ elfsec = elf_shdrp[elfsec]->sh_link;
+ /* PR 290:
+ The Intel C compiler generates SHT_IA_64_UNWIND with
+ SHF_LINK_ORDER. But it doesn't set theh sh_link or
+ sh_info fields. Hence we could get the situation
+ where elfsec is 0. */
+ if (elfsec == 0)
+ {
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (abfd);
+ if (bed->link_order_error_handler)
+ bed->link_order_error_handler
+ (_("%B: warning: sh_link not set for section `%S'"),
+ abfd, s);
+ }
+ else
+ {
+ s = elf_shdrp[elfsec]->bfd_section->output_section;
+ BFD_ASSERT (s != NULL);
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ }
+ break;
+ }
+ }
+ }
+ }
+
switch (d->this_hdr.sh_type)
{
case SHT_REL:
char *alc;
len = strlen (sec->name);
- alc = (char *) bfd_malloc ((bfd_size_type) (len - 2));
+ alc = bfd_malloc (len - 2);
if (alc == NULL)
return FALSE;
memcpy (alc, sec->name, len - 3);
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
break;
+ case SHT_GNU_LIBLIST:
+ /* sh_link is the section header index of the prelink library
+ list
+ used for the dynamic entries, or the symbol table, or the
+ version strings. */
+ s = bfd_get_section_by_name (abfd, (sec->flags & SEC_ALLOC)
+ ? ".dynstr" : ".gnu.libstr");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ break;
+
case SHT_HASH:
case SHT_GNU_versym:
/* sh_link is the section header index of the symbol table
/* Map symbol from it's internal number to the external number, moving
all local symbols to be at the head of the list. */
-static INLINE int
-sym_is_global (abfd, sym)
- bfd *abfd;
- asymbol *sym;
+static int
+sym_is_global (bfd *abfd, asymbol *sym)
{
/* If the backend has a special mapping, use it. */
- if (get_elf_backend_data (abfd)->elf_backend_sym_is_global)
- return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
- (abfd, sym));
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ if (bed->elf_backend_sym_is_global)
+ return (*bed->elf_backend_sym_is_global) (abfd, sym);
return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
|| bfd_is_und_section (bfd_get_section (sym))
}
static bfd_boolean
-elf_map_symbols (abfd)
- bfd *abfd;
+elf_map_symbols (bfd *abfd)
{
unsigned int symcount = bfd_get_symcount (abfd);
asymbol **syms = bfd_get_outsymbols (abfd);
max_index++;
amt = max_index * sizeof (asymbol *);
- sect_syms = (asymbol **) bfd_zalloc (abfd, amt);
+ sect_syms = bfd_zalloc (abfd, amt);
if (sect_syms == NULL)
return FALSE;
elf_section_syms (abfd) = sect_syms;
/* Now sort the symbols so the local symbols are first. */
amt = (num_locals + num_globals) * sizeof (asymbol *);
- new_syms = (asymbol **) bfd_alloc (abfd, amt);
+ new_syms = bfd_alloc (abfd, amt);
if (new_syms == NULL)
return FALSE;
/* 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 (off, align)
- file_ptr off;
- int align;
+static inline file_ptr
+align_file_position (file_ptr off, int align)
{
return (off + align - 1) & ~(align - 1);
}
/* Assign a file position to a section, optionally aligning to the
required section alignment. */
-INLINE file_ptr
-_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
- Elf_Internal_Shdr *i_shdrp;
- file_ptr offset;
- bfd_boolean align;
+file_ptr
+_bfd_elf_assign_file_position_for_section (Elf_Internal_Shdr *i_shdrp,
+ file_ptr offset,
+ bfd_boolean align)
{
if (align)
{
is not NULL, this is being called by the ELF backend linker. */
bfd_boolean
-_bfd_elf_compute_section_file_positions (abfd, link_info)
- bfd *abfd;
- struct bfd_link_info *link_info;
+_bfd_elf_compute_section_file_positions (bfd *abfd,
+ struct bfd_link_info *link_info)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean failed;
struct bfd_strtab_hash *strtab;
Elf_Internal_Shdr *shstrtab_hdr;
/* sh_offset is set in assign_file_positions_except_relocs. */
shstrtab_hdr->sh_addralign = 1;
- if (!assign_file_positions_except_relocs (abfd))
+ if (!assign_file_positions_except_relocs (abfd, link_info))
return FALSE;
if (link_info == NULL && bfd_get_symcount (abfd) > 0)
/* Create a mapping from a set of sections to a program segment. */
-static INLINE struct elf_segment_map *
-make_mapping (abfd, sections, from, to, phdr)
- bfd *abfd;
- asection **sections;
- unsigned int from;
- unsigned int to;
- bfd_boolean phdr;
+static struct elf_segment_map *
+make_mapping (bfd *abfd,
+ asection **sections,
+ unsigned int from,
+ unsigned int to,
+ bfd_boolean phdr)
{
struct elf_segment_map *m;
unsigned int i;
amt = sizeof (struct elf_segment_map);
amt += (to - from - 1) * sizeof (asection *);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
return NULL;
m->next = NULL;
return m;
}
+/* Create the PT_DYNAMIC segment, which includes DYNSEC. Returns NULL
+ on failure. */
+
+struct elf_segment_map *
+_bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
+{
+ struct elf_segment_map *m;
+
+ m = bfd_zalloc (abfd, sizeof (struct elf_segment_map));
+ if (m == NULL)
+ return NULL;
+ m->next = NULL;
+ m->p_type = PT_DYNAMIC;
+ m->count = 1;
+ m->sections[0] = dynsec;
+
+ return m;
+}
+
/* Set up a mapping from BFD sections to program segments. */
static bfd_boolean
-map_sections_to_segments (abfd)
- bfd *abfd;
+map_sections_to_segments (bfd *abfd)
{
asection **sections = NULL;
asection *s;
struct elf_segment_map **pm;
struct elf_segment_map *m;
asection *last_hdr;
+ bfd_vma last_size;
unsigned int phdr_index;
bfd_vma maxpagesize;
asection **hdrpp;
/* Select the allocated sections, and sort them. */
amt = bfd_count_sections (abfd) * sizeof (asection *);
- sections = (asection **) bfd_malloc (amt);
+ sections = bfd_malloc (amt);
if (sections == NULL)
goto error_return;
if (s != NULL && (s->flags & SEC_LOAD) != 0)
{
amt = sizeof (struct elf_segment_map);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
pm = &m->next;
amt = sizeof (struct elf_segment_map);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
segment when the start of the second section can be placed within
a few bytes of the end of the first section. */
last_hdr = NULL;
+ last_size = 0;
phdr_index = 0;
maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
writable = FALSE;
segment. */
new_segment = TRUE;
}
- else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+ else if (BFD_ALIGN (last_hdr->lma + last_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;
}
- else if ((last_hdr->flags & SEC_LOAD) == 0
- && (hdr->flags & SEC_LOAD) != 0)
+ else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
+ && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
{
/* We don't want to put a loadable section after a
- nonloadable section in the same segment. */
+ nonloadable section in the same segment.
+ Consider .tbss sections as loadable for this purpose. */
new_segment = TRUE;
}
else if ((abfd->flags & D_PAGED) == 0)
}
else if (! writable
&& (hdr->flags & SEC_READONLY) == 0
- && (((last_hdr->lma + last_hdr->_raw_size - 1)
+ && (((last_hdr->lma + last_size - 1)
& ~(maxpagesize - 1))
!= (hdr->lma & ~(maxpagesize - 1))))
{
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
last_hdr = hdr;
+ /* .tbss sections effectively have zero size. */
+ if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+ last_size = hdr->size;
+ else
+ last_size = 0;
continue;
}
writable = FALSE;
last_hdr = hdr;
+ /* .tbss sections effectively have zero size. */
+ if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+ last_size = hdr->size;
+ else
+ last_size = 0;
phdr_index = i;
phdr_in_segment = FALSE;
}
/* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */
if (dynsec != NULL)
{
- amt = sizeof (struct elf_segment_map);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
if (m == NULL)
goto error_return;
- m->next = NULL;
- m->p_type = PT_DYNAMIC;
- m->count = 1;
- m->sections[0] = dynsec;
-
*pm = m;
pm = &m->next;
}
&& strncmp (s->name, ".note", 5) == 0)
{
amt = sizeof (struct elf_segment_map);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
amt = sizeof (struct elf_segment_map);
amt += (tls_count - 1) * sizeof (asection *);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = 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 = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
if (elf_tdata (abfd)->stack_flags)
{
amt = sizeof (struct elf_segment_map);
- m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+ m = bfd_zalloc (abfd, amt);
if (m == NULL)
goto error_return;
m->next = NULL;
pm = &m->next;
}
+ if (elf_tdata (abfd)->relro)
+ {
+ amt = sizeof (struct elf_segment_map);
+ m = bfd_zalloc (abfd, amt);
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_GNU_RELRO;
+ m->p_flags = PF_R;
+ m->p_flags_valid = 1;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
free (sections);
sections = NULL;
/* Sort sections by address. */
static int
-elf_sort_sections (arg1, arg2)
- const PTR arg1;
- const PTR arg2;
+elf_sort_sections (const void *arg1, const void *arg2)
{
const asection *sec1 = *(const asection **) arg1;
const asection *sec2 = *(const asection **) arg2;
/* Sort by size, to put zero sized sections
before others at the same address. */
- size1 = (sec1->flags & SEC_LOAD) ? sec1->_raw_size : 0;
- size2 = (sec2->flags & SEC_LOAD) ? sec2->_raw_size : 0;
+ size1 = (sec1->flags & SEC_LOAD) ? sec1->size : 0;
+ size2 = (sec2->flags & SEC_LOAD) ? sec2->size : 0;
if (size1 < size2)
return -1;
return sec1->target_index - sec2->target_index;
}
+/* Ian Lance Taylor writes:
+
+ We shouldn't be using % with a negative signed number. That's just
+ not good. We have to make sure either that the number is not
+ negative, or that the number has an unsigned type. When the types
+ are all the same size they wind up as unsigned. When file_ptr is a
+ larger signed type, the arithmetic winds up as signed long long,
+ which is wrong.
+
+ What we're trying to say here is something like ``increase OFF by
+ the least amount that will cause it to be equal to the VMA modulo
+ the page size.'' */
+/* In other words, something like:
+
+ vma_offset = m->sections[0]->vma % bed->maxpagesize;
+ off_offset = off % bed->maxpagesize;
+ if (vma_offset < off_offset)
+ adjustment = vma_offset + bed->maxpagesize - off_offset;
+ else
+ adjustment = vma_offset - off_offset;
+
+ which can can be collapsed into the expression below. */
+
+static file_ptr
+vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
+{
+ return ((vma - off) % maxpagesize);
+}
+
/* Assign file positions to the sections based on the mapping from
sections to segments. This function also sets up some fields in
the file header, and writes out the program headers. */
static bfd_boolean
-assign_file_positions_for_segments (abfd)
- bfd *abfd;
+assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
unsigned int count;
if (bed->elf_backend_modify_segment_map)
{
- if (! (*bed->elf_backend_modify_segment_map) (abfd))
+ if (! (*bed->elf_backend_modify_segment_map) (abfd, link_info))
return FALSE;
}
if (alloc != 0 && count > alloc)
{
((*_bfd_error_handler)
- (_("%s: Not enough room for program headers (allocated %u, need %u)"),
- bfd_get_filename (abfd), alloc, count));
+ (_("%B: Not enough room for program headers (allocated %u, need %u)"),
+ abfd, alloc, count));
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
alloc = count;
amt = alloc * sizeof (Elf_Internal_Phdr);
- phdrs = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
+ phdrs = bfd_alloc (abfd, amt);
if (phdrs == NULL)
return FALSE;
qsort (m->sections, (size_t) m->count, sizeof (asection *),
elf_sort_sections);
+ /* An ELF segment (described by Elf_Internal_Phdr) may contain a
+ number of sections with contents contributing to both p_filesz
+ and p_memsz, followed by a number of sections with no contents
+ that just contribute to p_memsz. In this loop, OFF tracks next
+ available file offset for PT_LOAD and PT_NOTE segments. VOFF is
+ an adjustment we use for segments that have no file contents
+ but need zero filled memory allocation. */
+ voff = 0;
p->p_type = m->p_type;
p->p_flags = m->p_flags;
if (p->p_type == PT_LOAD
- && m->count > 0
- && (m->sections[0]->flags & SEC_ALLOC) != 0)
+ && m->count > 0)
{
+ bfd_size_type align;
+ bfd_vma adjust;
+
if ((abfd->flags & D_PAGED) != 0)
- off += (m->sections[0]->vma - off) % bed->maxpagesize;
+ align = bed->maxpagesize;
else
{
- bfd_size_type align;
-
- align = 0;
+ unsigned int align_power = 0;
for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
{
- bfd_size_type secalign;
+ unsigned int secalign;
secalign = bfd_get_section_alignment (abfd, *secpp);
- if (secalign > align)
- align = secalign;
+ if (secalign > align_power)
+ align_power = secalign;
}
+ align = (bfd_size_type) 1 << align_power;
+ }
- off += (m->sections[0]->vma - off) % (1 << align);
+ adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
+ off += adjust;
+ if (adjust != 0
+ && !m->includes_filehdr
+ && !m->includes_phdrs
+ && (ufile_ptr) off >= align)
+ {
+ /* If the first section isn't loadable, the same holds for
+ any other sections. Since the segment won't need file
+ space, we can make p_offset overlap some prior segment.
+ However, .tbss is special. If a segment starts with
+ .tbss, we need to look at the next section to decide
+ whether the segment has any loadable sections. */
+ i = 0;
+ while ((m->sections[i]->flags & SEC_LOAD) == 0)
+ {
+ if ((m->sections[i]->flags & SEC_THREAD_LOCAL) == 0
+ || ++i >= m->count)
+ {
+ off -= adjust;
+ voff = adjust - align;
+ break;
+ }
+ }
}
}
+ /* Make sure the .dynamic section is the first section in the
+ PT_DYNAMIC segment. */
+ else if (p->p_type == PT_DYNAMIC
+ && m->count > 1
+ && strcmp (m->sections[0]->name, ".dynamic") != 0)
+ {
+ _bfd_error_handler
+ (_("%B: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
+ abfd);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
if (m->count == 0)
p->p_vaddr = 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));
+ (_("%B: Not enough room for program headers, try linking with -N"),
+ abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
|| (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core))
{
if (! m->includes_filehdr && ! m->includes_phdrs)
- p->p_offset = off;
+ p->p_offset = off + voff;
else
{
file_ptr adjust;
}
}
- voff = off;
-
for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
{
asection *sec;
flags = sec->flags;
align = 1 << bfd_get_section_alignment (abfd, sec);
- /* The section may have artificial alignment forced by a
- link script. Notice this case by the gap between the
- cumulative phdr lma and the section's lma. */
- if (p->p_paddr + p->p_memsz < sec->lma)
- {
- bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
-
- p->p_memsz += adjust;
- 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;
- }
-
- if (p->p_type == PT_LOAD)
+ if (p->p_type == PT_LOAD
+ || p->p_type == PT_TLS)
{
bfd_signed_vma adjust;
if ((flags & SEC_LOAD) != 0)
{
- adjust = sec->lma - (p->p_paddr + p->p_memsz);
+ adjust = sec->lma - (p->p_paddr + p->p_filesz);
if (adjust < 0)
- adjust = 0;
+ {
+ (*_bfd_error_handler)
+ (_("%B: section %A lma 0x%lx overlaps previous sections"),
+ abfd, sec, (unsigned long) sec->lma);
+ adjust = 0;
+ }
+ off += adjust;
+ p->p_filesz += adjust;
+ p->p_memsz += adjust;
}
- else if ((flags & SEC_ALLOC) != 0)
+ /* .tbss is special. It doesn't contribute to p_memsz of
+ normal segments. */
+ else if ((flags & SEC_THREAD_LOCAL) == 0
+ || p->p_type == PT_TLS)
{
/* The section VMA must equal the file position
- modulo the page size. FIXME: I'm not sure if
- this adjustment is really necessary. We used to
- not have the SEC_LOAD case just above, and then
- this was necessary, but now I'm not sure. */
+ modulo the page size. */
+ bfd_size_type page = align;
if ((abfd->flags & D_PAGED) != 0)
- adjust = (sec->vma - voff) % bed->maxpagesize;
- else
- adjust = (sec->vma - voff) % align;
- }
- else
- adjust = 0;
-
- if (adjust != 0)
- {
- if (i == 0)
- {
- (* _bfd_error_handler) (_("\
-Error: First section in segment (%s) starts at 0x%x whereas the segment starts at 0x%x"),
- bfd_section_name (abfd, sec),
- sec->lma,
- p->p_paddr);
- return FALSE;
- }
+ page = bed->maxpagesize;
+ adjust = vma_page_aligned_bias (sec->vma,
+ p->p_vaddr + p->p_memsz,
+ page);
p->p_memsz += adjust;
- off += adjust;
- voff += adjust;
- if ((flags & SEC_LOAD) != 0)
- p->p_filesz += adjust;
}
-
- sec->filepos = off;
-
- /* We check SEC_HAS_CONTENTS here because if NOLOAD is
- used in a linker script we may have a section with
- SEC_LOAD clear but which is supposed to have
- contents. */
- if ((flags & SEC_LOAD) != 0
- || (flags & SEC_HAS_CONTENTS) != 0)
- off += sec->_raw_size;
-
- if ((flags & SEC_ALLOC) != 0
- && ((flags & SEC_LOAD) != 0
- || (flags & SEC_THREAD_LOCAL) == 0))
- voff += sec->_raw_size;
}
if (p->p_type == PT_NOTE && bfd_get_format (abfd) == bfd_core)
{
- /* The actual "note" segment has i == 0.
- This is the one that actually contains everything. */
+ /* The section at i == 0 is the one that actually contains
+ everything. */
if (i == 0)
{
sec->filepos = off;
- p->p_filesz = sec->_raw_size;
- off += sec->_raw_size;
- voff = off;
+ off += sec->size;
+ p->p_filesz = sec->size;
+ p->p_memsz = 0;
+ p->p_align = 1;
}
else
{
- /* Fake sections -- don't need to be written. */
+ /* The rest are fake sections that shouldn't be written. */
sec->filepos = 0;
- sec->_raw_size = 0;
- flags = sec->flags = 0;
+ sec->size = 0;
+ sec->flags = 0;
+ continue;
}
- p->p_memsz = 0;
- p->p_align = 1;
}
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 (p->p_type == PT_LOAD)
+ {
+ sec->filepos = off;
+ /* FIXME: The SEC_HAS_CONTENTS test here dates back to
+ 1997, and the exact reason for it isn't clear. One
+ plausible explanation is that it is to work around
+ a problem we have with linker scripts using data
+ statements in NOLOAD sections. I don't think it
+ makes a great deal of sense to have such a section
+ assigned to a PT_LOAD segment, but apparently
+ people do this. The data statement results in a
+ bfd_data_link_order being built, and these need
+ section contents to write into. Eventually, we get
+ to _bfd_elf_write_object_contents which writes any
+ section with contents to the output. Make room
+ here for the write, so that following segments are
+ not trashed. */
+ if ((flags & SEC_LOAD) != 0
+ || (flags & SEC_HAS_CONTENTS) != 0)
+ off += sec->size;
+ }
if ((flags & SEC_LOAD) != 0)
- p->p_filesz += sec->_raw_size;
+ {
+ p->p_filesz += sec->size;
+ p->p_memsz += sec->size;
+ }
+ /* .tbss is special. It doesn't contribute to p_memsz of
+ normal segments. */
+ else if ((flags & SEC_THREAD_LOCAL) == 0
+ || p->p_type == PT_TLS)
+ p->p_memsz += sec->size;
if (p->p_type == PT_TLS
- && sec->_raw_size == 0
+ && sec->size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
{
struct bfd_link_order *o;
if (p->p_type != PT_LOAD && m->count > 0)
{
BFD_ASSERT (! m->includes_filehdr && ! m->includes_phdrs);
+ /* If the section has not yet been assigned a file position,
+ do so now. The ARM BPABI requires that .dynamic section
+ not be marked SEC_ALLOC because it is not part of any
+ PT_LOAD segment, so it will not be processed above. */
+ if (p->p_type == PT_DYNAMIC && m->sections[0]->filepos == 0)
+ {
+ unsigned int i;
+ Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
+
+ i = 1;
+ while (i_shdrpp[i]->bfd_section != m->sections[0])
+ ++i;
+ off = (_bfd_elf_assign_file_position_for_section
+ (i_shdrpp[i], off, TRUE));
+ p->p_filesz = m->sections[0]->size;
+ }
p->p_offset = m->sections[0]->filepos;
}
if (m->count == 0)
if (! m->p_paddr_valid)
p->p_paddr = phdrs_paddr;
}
+ else if (p->p_type == PT_GNU_RELRO)
+ {
+ Elf_Internal_Phdr *lp;
+
+ for (lp = phdrs; lp < phdrs + count; ++lp)
+ {
+ if (lp->p_type == PT_LOAD
+ && lp->p_vaddr <= link_info->relro_end
+ && lp->p_vaddr >= link_info->relro_start
+ && lp->p_vaddr + lp->p_filesz
+ >= link_info->relro_end)
+ break;
+ }
+
+ if (lp < phdrs + count
+ && link_info->relro_end > lp->p_vaddr)
+ {
+ p->p_vaddr = lp->p_vaddr;
+ p->p_paddr = lp->p_paddr;
+ p->p_offset = lp->p_offset;
+ p->p_filesz = link_info->relro_end - lp->p_vaddr;
+ p->p_memsz = p->p_filesz;
+ p->p_align = 1;
+ p->p_flags = (lp->p_flags & ~PF_W);
+ }
+ else
+ {
+ memset (p, 0, sizeof *p);
+ p->p_type = PT_NULL;
+ }
+ }
}
}
will be two segments. */
static bfd_size_type
-get_program_header_size (abfd)
- bfd *abfd;
+get_program_header_size (bfd *abfd)
{
size_t segs;
asection *s;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
/* We can't return a different result each time we're called. */
if (elf_tdata (abfd)->program_header_size != 0)
++segs;
}
+ if (elf_tdata (abfd)->relro)
+ {
+ /* We need a PT_GNU_RELRO segment. */
+ ++segs;
+ }
+
for (s = abfd->sections; s != NULL; s = s->next)
{
if ((s->flags & SEC_LOAD) != 0
_bfd_elf_compute_section_file_positions. All the section sizes and
VMAs must be known before this is called.
- We do not consider reloc sections at this point, unless they form
- part of the loadable image. Reloc sections are assigned file
- positions in assign_file_positions_for_relocs, which is called by
- write_object_contents and final_link.
+ Reloc sections come in two flavours: Those processed specially as
+ "side-channel" data attached to a section to which they apply, and
+ those that bfd doesn't process as relocations. The latter sort are
+ stored in a normal bfd section by bfd_section_from_shdr. We don't
+ consider the former sort here, unless they form part of the loadable
+ image. Reloc sections not assigned here will be handled later by
+ assign_file_positions_for_relocs.
We also don't set the positions of the .symtab and .strtab here. */
static bfd_boolean
-assign_file_positions_except_relocs (abfd)
- bfd *abfd;
+assign_file_positions_except_relocs (bfd *abfd,
+ struct bfd_link_info *link_info)
{
struct elf_obj_tdata * const tdata = elf_tdata (abfd);
Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
unsigned int num_sec = elf_numsections (abfd);
file_ptr off;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
&& bfd_get_format (abfd) != bfd_core)
Elf_Internal_Shdr *hdr;
hdr = *hdrpp;
- if (hdr->sh_type == SHT_REL
- || hdr->sh_type == SHT_RELA
+ if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
+ && hdr->bfd_section == NULL)
|| i == tdata->symtab_section
|| i == tdata->symtab_shndx_section
|| i == tdata->strtab_section)
/* Assign file positions for the loaded sections based on the
assignment of sections to segments. */
- if (! assign_file_positions_for_segments (abfd))
+ if (! assign_file_positions_for_segments (abfd, link_info))
return FALSE;
/* Assign file positions for the other sections. */
else if ((hdr->sh_flags & SHF_ALLOC) != 0)
{
((*_bfd_error_handler)
- (_("%s: warning: allocated section `%s' not in segment"),
- bfd_get_filename (abfd),
+ (_("%B: warning: allocated section `%s' not in segment"),
+ abfd,
(hdr->bfd_section == NULL
? "*unknown*"
: hdr->bfd_section->name)));
if ((abfd->flags & D_PAGED) != 0)
- off += (hdr->sh_addr - off) % bed->maxpagesize;
+ off += vma_page_aligned_bias (hdr->sh_addr, off,
+ bed->maxpagesize);
else
- off += (hdr->sh_addr - off) % hdr->sh_addralign;
+ off += vma_page_aligned_bias (hdr->sh_addr, off,
+ hdr->sh_addralign);
off = _bfd_elf_assign_file_position_for_section (hdr, off,
FALSE);
}
- else if (hdr->sh_type == SHT_REL
- || hdr->sh_type == SHT_RELA
+ else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
+ && hdr->bfd_section == NULL)
|| hdr == i_shdrpp[tdata->symtab_section]
|| hdr == i_shdrpp[tdata->symtab_shndx_section]
|| hdr == i_shdrpp[tdata->strtab_section])
}
static bfd_boolean
-prep_headers (abfd)
- bfd *abfd;
+prep_headers (bfd *abfd)
{
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
struct elf_strtab_hash *shstrtab;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
i_ehdrp = elf_elfheader (abfd);
i_shdrp = elf_elfsections (abfd);
Such need can generally be supplied by replacing the tests for
e_machine with the conditions used to determine it. */
default:
- if (get_elf_backend_data (abfd) != NULL)
- i_ehdrp->e_machine = get_elf_backend_data (abfd)->elf_machine_code;
- else
- i_ehdrp->e_machine = EM_NONE;
- }
+ i_ehdrp->e_machine = bed->elf_machine_code;
+ }
i_ehdrp->e_version = bed->s->ev_current;
i_ehdrp->e_ehsize = bed->s->sizeof_ehdr;
of the loadable file image. */
void
-_bfd_elf_assign_file_positions_for_relocs (abfd)
- bfd *abfd;
+_bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
{
file_ptr off;
unsigned int i, num_sec;
}
bfd_boolean
-_bfd_elf_write_object_contents (abfd)
- bfd *abfd;
+_bfd_elf_write_object_contents (bfd *abfd)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
Elf_Internal_Ehdr *i_ehdrp;
Elf_Internal_Shdr **i_shdrp;
bfd_boolean failed;
unsigned int count, num_sec;
if (! abfd->output_has_begun
- && ! _bfd_elf_compute_section_file_positions
- (abfd, (struct bfd_link_info *) NULL))
+ && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
return FALSE;
i_shdrp = elf_elfsections (abfd);
}
bfd_boolean
-_bfd_elf_write_corefile_contents (abfd)
- bfd *abfd;
+_bfd_elf_write_corefile_contents (bfd *abfd)
{
/* Hopefully this can be done just like an object file. */
return _bfd_elf_write_object_contents (abfd);
/* Given a section, search the header to find them. */
int
-_bfd_elf_section_from_bfd_section (abfd, asect)
- bfd *abfd;
- struct sec *asect;
+_bfd_elf_section_from_bfd_section (bfd *abfd, struct bfd_section *asect)
{
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
int index;
if (elf_section_data (asect) != NULL
on error. */
int
-_bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
- bfd *abfd;
- asymbol **asym_ptr_ptr;
+_bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
{
asymbol *asym_ptr = *asym_ptr_ptr;
int idx;
/* This case can occur when using --strip-symbol on a symbol
which is used in a relocation entry. */
(*_bfd_error_handler)
- (_("%s: symbol `%s' required but not present"),
- bfd_archive_filename (abfd), bfd_asymbol_name (asym_ptr));
+ (_("%B: symbol `%s' required but not present"),
+ abfd, bfd_asymbol_name (asym_ptr));
bfd_set_error (bfd_error_no_symbols);
return -1;
}
/* Copy private BFD data. This copies any program header information. */
static bfd_boolean
-copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd;
- bfd *obfd;
+copy_private_bfd_data (bfd *ibfd, bfd *obfd)
{
Elf_Internal_Ehdr *iehdr;
struct elf_segment_map *map;
bfd_vma maxpagesize;
struct elf_segment_map *phdr_adjust_seg = NULL;
unsigned int phdr_adjust_num = 0;
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
#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)
+ ? section->size : 0)
/* Returns TRUE if the given section is contained within
the given segment. VMA addresses are compared. */
&& 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 \
+ && ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
/* The complicated case when p_vaddr is 0 is to handle the Solaris
&& p->p_memsz == 0 \
&& p->p_filesz > 0 \
&& (s->flags & SEC_HAS_CONTENTS) != 0 \
- && s->_raw_size > 0 \
+ && s->size > 0 \
&& (bfd_vma) s->filepos >= p->p_offset \
- && ((bfd_vma) s->filepos + s->_raw_size \
+ && ((bfd_vma) s->filepos + s->size \
<= p->p_offset + p->p_filesz))
/* Decide if the given section should be included in the given segment.
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.
- 5. PT_TLS segment includes only SHF_TLS sections.
- 6. SHF_TLS sections are only in PT_TLS or PT_LOAD segments. */
+ 5. PT_GNU_STACK segments do not include any sections.
+ 6. PT_TLS segment includes only SHF_TLS sections.
+ 7. 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) \
&& (section->flags & SEC_ALLOC) != 0) \
|| IS_COREFILE_NOTE (segment, section)) \
&& section->output_section != NULL \
+ && segment->p_type != PT_GNU_STACK \
&& (segment->p_type != PT_TLS \
|| (section->flags & SEC_THREAD_LOCAL)) \
&& (segment->p_type == PT_LOAD \
if (IS_SOLARIS_PT_INTERP (segment, section))
{
/* Mininal change so that the normal section to segment
- assigment code will work. */
+ assignment code will work. */
segment->p_vaddr = section->vma;
break;
}
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);
+ map = bfd_alloc (obfd, amt);
if (map == NULL)
return FALSE;
a warning is produced. */
if (segment->p_type == PT_LOAD)
(*_bfd_error_handler)
- (_("%s: warning: Empty loadable segment detected, is this intentional ?\n"),
- bfd_archive_filename (ibfd));
+ (_("%B: warning: Empty loadable segment detected, is this intentional ?\n"),
+ ibfd);
map->count = 0;
*pointer_to_map = map;
/* 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);
+ sections = bfd_malloc (amt);
if (sections == NULL)
return FALSE;
/* If the gap between the end of the previous section
and the start of this section is more than
maxpagesize then we need to start a new segment. */
- if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size,
+ if ((BFD_ALIGN (prev_sec->lma + prev_sec->size,
maxpagesize)
< BFD_ALIGN (output_section->lma, maxpagesize))
- || ((prev_sec->lma + prev_sec->_raw_size)
+ || ((prev_sec->lma + prev_sec->size)
> output_section->lma))
{
if (suggested_lma == 0)
and carry on looping. */
amt = sizeof (struct elf_segment_map);
amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
- map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
+ map = bfd_alloc (obfd, amt);
if (map == NULL)
{
free (sections);
field, and sometimes the info field. */
bfd_boolean
-_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
- bfd *ibfd;
- asection *isec;
- bfd *obfd;
- asection *osec;
+_bfd_elf_copy_private_section_data (bfd *ibfd,
+ asection *isec,
+ bfd *obfd,
+ asection *osec)
{
Elf_Internal_Shdr *ihdr, *ohdr;
|| obfd->xvec->flavour != bfd_target_elf_flavour)
return TRUE;
- if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
- {
- 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;
- }
- }
-
ihdr = &elf_section_data (isec)->this_hdr;
ohdr = &elf_section_data (osec)->this_hdr;
return TRUE;
}
+/* Copy private header information. */
+
+bfd_boolean
+_bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
+{
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ /* Copy over private BFD data if it has not already been copied.
+ This must be done here, rather than in the copy_private_bfd_data
+ entry point, because the latter is called after the section
+ contents have been set, which means that the program headers have
+ already been worked out. */
+ if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* Copy private symbol information. If this symbol is in a section
which we did not map into a BFD section, try to map the section
index correctly. We use special macro definitions for the mapped
#define MAP_SYM_SHNDX (SHN_HIOS + 5)
bfd_boolean
-_bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
- bfd *ibfd;
- asymbol *isymarg;
- bfd *obfd;
- asymbol *osymarg;
+_bfd_elf_copy_private_symbol_data (bfd *ibfd,
+ asymbol *isymarg,
+ bfd *obfd,
+ asymbol *osymarg)
{
elf_symbol_type *isym, *osym;
/* Swap out the symbols. */
static bfd_boolean
-swap_out_syms (abfd, sttp, relocatable_p)
- bfd *abfd;
- struct bfd_strtab_hash **sttp;
- int relocatable_p;
+swap_out_syms (bfd *abfd,
+ struct bfd_strtab_hash **sttp,
+ int relocatable_p)
{
- struct elf_backend_data *bed;
+ const struct elf_backend_data *bed;
int symcount;
asymbol **syms;
struct bfd_strtab_hash *stt;
char *outbound_shndx;
int idx;
bfd_size_type amt;
+ bfd_boolean name_local_sections;
if (!elf_map_symbols (abfd))
return FALSE;
_bfd_stringtab_free (stt);
return FALSE;
}
- symtab_hdr->contents = (PTR) outbound_syms;
+ symtab_hdr->contents = outbound_syms;
outbound_shndx = NULL;
symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
outbound_shndx += sizeof (Elf_External_Sym_Shndx);
}
+ name_local_sections
+ = (bed->elf_backend_name_local_section_symbols
+ && bed->elf_backend_name_local_section_symbols (abfd));
+
syms = bfd_get_outsymbols (abfd);
for (idx = 0; idx < symcount; idx++)
{
flagword flags = syms[idx]->flags;
int type;
- if ((flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
+ if (!name_local_sections
+ && (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
{
/* Local section symbols have no name. */
sym.st_name = 0;
always has a dummy entry as symbol #0, so it ends up even. */
long
-_bfd_elf_get_symtab_upper_bound (abfd)
- bfd *abfd;
+_bfd_elf_get_symtab_upper_bound (bfd *abfd)
{
long symcount;
long symtab_size;
}
long
-_bfd_elf_get_dynamic_symtab_upper_bound (abfd)
- bfd *abfd;
+_bfd_elf_get_dynamic_symtab_upper_bound (bfd *abfd)
{
long symcount;
long symtab_size;
}
long
-_bfd_elf_get_reloc_upper_bound (abfd, asect)
- bfd *abfd ATTRIBUTE_UNUSED;
- sec_ptr asect;
+_bfd_elf_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED,
+ sec_ptr asect)
{
return (asect->reloc_count + 1) * sizeof (arelent *);
}
/* Canonicalize the relocs. */
long
-_bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
- bfd *abfd;
- sec_ptr section;
- arelent **relptr;
- asymbol **symbols;
+_bfd_elf_canonicalize_reloc (bfd *abfd,
+ sec_ptr section,
+ arelent **relptr,
+ asymbol **symbols)
{
arelent *tblptr;
unsigned int i;
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
return -1;
}
long
-_bfd_elf_get_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
+_bfd_elf_canonicalize_symtab (bfd *abfd, asymbol **allocation)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- long symcount = bed->s->slurp_symbol_table (abfd, alocation, FALSE);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ long symcount = bed->s->slurp_symbol_table (abfd, allocation, FALSE);
if (symcount >= 0)
bfd_get_symcount (abfd) = symcount;
}
long
-_bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
- bfd *abfd;
- asymbol **alocation;
+_bfd_elf_canonicalize_dynamic_symtab (bfd *abfd,
+ asymbol **allocation)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
- long symcount = bed->s->slurp_symbol_table (abfd, alocation, TRUE);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ long symcount = bed->s->slurp_symbol_table (abfd, allocation, TRUE);
if (symcount >= 0)
bfd_get_dynamic_symcount (abfd) = symcount;
considered to be a dynamic reloc section. */
long
-_bfd_elf_get_dynamic_reloc_upper_bound (abfd)
- bfd *abfd;
+_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
{
long ret;
asection *s;
if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
&& (elf_section_data (s)->this_hdr.sh_type == SHT_REL
|| elf_section_data (s)->this_hdr.sh_type == SHT_RELA))
- ret += ((s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize)
+ ret += ((s->size / elf_section_data (s)->this_hdr.sh_entsize)
* sizeof (arelent *));
return ret;
section. */
long
-_bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
- bfd *abfd;
- arelent **storage;
- asymbol **syms;
+_bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
+ arelent **storage,
+ asymbol **syms)
{
- bfd_boolean (*slurp_relocs)
- PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
+ bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
asection *s;
long ret;
if (! (*slurp_relocs) (abfd, s, syms, TRUE))
return -1;
- count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
+ count = s->size / elf_section_data (s)->this_hdr.sh_entsize;
p = s->relocation;
for (i = 0; i < count; i++)
*storage++ = p++;
/* Read in the version information. */
bfd_boolean
-_bfd_elf_slurp_version_tables (abfd)
- bfd *abfd;
+_bfd_elf_slurp_version_tables (bfd *abfd)
{
bfd_byte *contents = NULL;
bfd_size_type amt;
hdr = &elf_tdata (abfd)->dynverdef_hdr;
- contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+ contents = bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size)
+ || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
goto error_return;
/* We know the number of entries in the section but not the maximum
}
amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
- elf_tdata (abfd)->verdef = (Elf_Internal_Verdef *) bfd_zalloc (abfd, amt);
+ elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
iverdef->vd_bfd = abfd;
amt = (bfd_size_type) iverdef->vd_cnt * sizeof (Elf_Internal_Verdaux);
- iverdef->vd_auxptr = (Elf_Internal_Verdaux *) bfd_alloc (abfd, amt);
+ iverdef->vd_auxptr = bfd_alloc (abfd, amt);
if (iverdef->vd_auxptr == NULL)
goto error_return;
hdr = &elf_tdata (abfd)->dynverref_hdr;
amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
- elf_tdata (abfd)->verref =
- (Elf_Internal_Verneed *) bfd_zalloc (abfd, amt);
+ elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verref == NULL)
goto error_return;
elf_tdata (abfd)->cverrefs = hdr->sh_info;
- contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
+ contents = bfd_malloc (hdr->sh_size);
if (contents == NULL)
goto error_return;
if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread ((PTR) contents, hdr->sh_size, abfd) != hdr->sh_size)
+ || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
goto error_return;
everneed = (Elf_External_Verneed *) contents;
amt = iverneed->vn_cnt;
amt *= sizeof (Elf_Internal_Vernaux);
- iverneed->vn_auxptr = (Elf_Internal_Vernaux *) bfd_alloc (abfd, amt);
+ iverneed->vn_auxptr = bfd_alloc (abfd, amt);
evernaux = ((Elf_External_Vernaux *)
((bfd_byte *) everneed + iverneed->vn_aux));
}
\f
asymbol *
-_bfd_elf_make_empty_symbol (abfd)
- bfd *abfd;
+_bfd_elf_make_empty_symbol (bfd *abfd)
{
elf_symbol_type *newsym;
bfd_size_type amt = sizeof (elf_symbol_type);
- newsym = (elf_symbol_type *) bfd_zalloc (abfd, amt);
+ newsym = bfd_zalloc (abfd, amt);
if (!newsym)
return NULL;
else
}
void
-_bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
- bfd *ignore_abfd ATTRIBUTE_UNUSED;
- asymbol *symbol;
- symbol_info *ret;
+_bfd_elf_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
+ asymbol *symbol,
+ symbol_info *ret)
{
bfd_symbol_info (symbol, ret);
}
override it. */
bfd_boolean
-_bfd_elf_is_local_label_name (abfd, name)
- bfd *abfd ATTRIBUTE_UNUSED;
- const char *name;
+_bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *name)
{
/* Normal local symbols start with ``.L''. */
if (name[0] == '.' && name[1] == 'L')
}
alent *
-_bfd_elf_get_lineno (ignore_abfd, symbol)
- bfd *ignore_abfd ATTRIBUTE_UNUSED;
- asymbol *symbol ATTRIBUTE_UNUSED;
+_bfd_elf_get_lineno (bfd *abfd ATTRIBUTE_UNUSED,
+ asymbol *symbol ATTRIBUTE_UNUSED)
{
abort ();
return NULL;
}
bfd_boolean
-_bfd_elf_set_arch_mach (abfd, arch, machine)
- bfd *abfd;
- enum bfd_architecture arch;
- unsigned long machine;
+_bfd_elf_set_arch_mach (bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long machine)
{
/* If this isn't the right architecture for this backend, and this
isn't the generic backend, fail. */
for error reporting. */
static bfd_boolean
-elf_find_function (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- const char **filename_ptr;
- const char **functionname_ptr;
+elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr)
{
const char *filename;
asymbol *func;
q = (elf_symbol_type *) *p;
- if (bfd_get_section (&q->symbol) != section)
- continue;
-
switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
{
default:
break;
case STT_NOTYPE:
case STT_FUNC:
- if (q->symbol.section == section
+ if (bfd_get_section (&q->symbol) == section
&& q->symbol.value >= low_func
&& q->symbol.value <= offset)
{
for error reporting. */
bfd_boolean
-_bfd_elf_find_nearest_line (abfd, section, symbols, offset,
- filename_ptr, functionname_ptr, line_ptr)
- bfd *abfd;
- asection *section;
- asymbol **symbols;
- bfd_vma offset;
- const char **filename_ptr;
- const char **functionname_ptr;
- unsigned int *line_ptr;
+_bfd_elf_find_nearest_line (bfd *abfd,
+ asection *section,
+ asymbol **symbols,
+ bfd_vma offset,
+ const char **filename_ptr,
+ const char **functionname_ptr,
+ unsigned int *line_ptr)
{
bfd_boolean found;
}
int
-_bfd_elf_sizeof_headers (abfd, reloc)
- bfd *abfd;
- bfd_boolean reloc;
+_bfd_elf_sizeof_headers (bfd *abfd, bfd_boolean reloc)
{
int ret;
}
bfd_boolean
-_bfd_elf_set_section_contents (abfd, section, location, offset, count)
- bfd *abfd;
- sec_ptr section;
- PTR location;
- file_ptr offset;
- bfd_size_type count;
+_bfd_elf_set_section_contents (bfd *abfd,
+ sec_ptr section,
+ const void *location,
+ file_ptr offset,
+ bfd_size_type count)
{
Elf_Internal_Shdr *hdr;
bfd_signed_vma pos;
if (! abfd->output_has_begun
- && ! (_bfd_elf_compute_section_file_positions
- (abfd, (struct bfd_link_info *) NULL)))
+ && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
return FALSE;
hdr = &elf_section_data (section)->this_hdr;
}
void
-_bfd_elf_no_info_to_howto (abfd, cache_ptr, dst)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *cache_ptr ATTRIBUTE_UNUSED;
- Elf_Internal_Rela *dst ATTRIBUTE_UNUSED;
+_bfd_elf_no_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *cache_ptr ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *dst ATTRIBUTE_UNUSED)
{
abort ();
}
/* Try to convert a non-ELF reloc into an ELF one. */
bfd_boolean
-_bfd_elf_validate_reloc (abfd, areloc)
- bfd *abfd;
- arelent *areloc;
+_bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
{
/* Check whether we really have an ELF howto. */
fail:
(*_bfd_error_handler)
- (_("%s: unsupported relocation type %s"),
- bfd_archive_filename (abfd), areloc->howto->name);
+ (_("%B: unsupported relocation type %s"),
+ abfd, areloc->howto->name);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
bfd_boolean
-_bfd_elf_close_and_cleanup (abfd)
- bfd *abfd;
+_bfd_elf_close_and_cleanup (bfd *abfd)
{
if (bfd_get_format (abfd) == bfd_object)
{
this reloc. */
bfd_reloc_status_type
-_bfd_elf_rel_vtable_reloc_fn (abfd, re, symbol, data, is, obfd, errmsg)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *re ATTRIBUTE_UNUSED;
- struct symbol_cache_entry *symbol ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection *is ATTRIBUTE_UNUSED;
- bfd *obfd ATTRIBUTE_UNUSED;
- char **errmsg ATTRIBUTE_UNUSED;
+_bfd_elf_rel_vtable_reloc_fn
+ (bfd *abfd ATTRIBUTE_UNUSED, arelent *re ATTRIBUTE_UNUSED,
+ struct bfd_symbol *symbol ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED, asection *is ATTRIBUTE_UNUSED,
+ bfd *obfd ATTRIBUTE_UNUSED, char **errmsg ATTRIBUTE_UNUSED)
{
return bfd_reloc_ok;
}
/* FIXME: this is kinda wrong, but it's what gdb wants. */
static int
-elfcore_make_pid (abfd)
- bfd *abfd;
+elfcore_make_pid (bfd *abfd)
{
return ((elf_tdata (abfd)->core_lwpid << 16)
+ (elf_tdata (abfd)->core_pid));
overwrite it. */
static bfd_boolean
-elfcore_maybe_make_sect (abfd, name, sect)
- bfd *abfd;
- char *name;
- asection *sect;
+elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
{
asection *sect2;
if (sect2 == NULL)
return FALSE;
- sect2->_raw_size = sect->_raw_size;
+ sect2->size = sect->size;
sect2->filepos = sect->filepos;
sect2->flags = sect->flags;
sect2->alignment_power = sect->alignment_power;
PID is elfcore_make_pid (abfd).
Both pseudosections have identical contents. */
bfd_boolean
-_bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
- bfd *abfd;
- char *name;
- size_t size;
- ufile_ptr filepos;
+_bfd_elfcore_make_pseudosection (bfd *abfd,
+ char *name,
+ size_t size,
+ ufile_ptr filepos)
{
char buf[100];
char *threaded_name;
sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
len = strlen (buf) + 1;
- threaded_name = bfd_alloc (abfd, (bfd_size_type) len);
+ threaded_name = bfd_alloc (abfd, len);
if (threaded_name == NULL)
return FALSE;
memcpy (threaded_name, buf, len);
- sect = bfd_make_section (abfd, threaded_name);
+ sect = bfd_make_section_anyway (abfd, threaded_name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = size;
+ sect->size = size;
sect->filepos = filepos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
*/
#if defined (HAVE_PRSTATUS_T)
-static bfd_boolean elfcore_grok_prstatus
- PARAMS ((bfd *, Elf_Internal_Note *));
static bfd_boolean
-elfcore_grok_prstatus (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
{
- size_t raw_size;
+ size_t size;
int offset;
if (note->descsz == sizeof (prstatus_t))
{
prstatus_t prstat;
- raw_size = sizeof (prstat.pr_reg);
+ size = sizeof (prstat.pr_reg);
offset = offsetof (prstatus_t, pr_reg);
memcpy (&prstat, note->descdata, sizeof (prstat));
/* 64-bit host, 32-bit corefile */
prstatus32_t prstat;
- raw_size = sizeof (prstat.pr_reg);
+ size = sizeof (prstat.pr_reg);
offset = offsetof (prstatus32_t, pr_reg);
memcpy (&prstat, note->descdata, sizeof (prstat));
/* Make a ".reg/999" section and a ".reg" section. */
return _bfd_elfcore_make_pseudosection (abfd, ".reg",
- raw_size, note->descpos + offset);
+ size, note->descpos + offset);
}
#endif /* defined (HAVE_PRSTATUS_T) */
/* Create a pseudosection containing the exact contents of NOTE. */
static bfd_boolean
-elfcore_make_note_pseudosection (abfd, name, note)
- bfd *abfd;
- char *name;
- Elf_Internal_Note *note;
+elfcore_make_note_pseudosection (bfd *abfd,
+ char *name,
+ Elf_Internal_Note *note)
{
return _bfd_elfcore_make_pseudosection (abfd, name,
note->descsz, note->descpos);
data structure apart. */
static bfd_boolean
-elfcore_grok_prfpreg (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_prfpreg (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".reg2", note);
}
literally. */
static bfd_boolean
-elfcore_grok_prxfpreg (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_prxfpreg (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
}
the copy will always have a terminating '\0'. */
char *
-_bfd_elfcore_strndup (abfd, start, max)
- bfd *abfd;
- char *start;
- size_t max;
+_bfd_elfcore_strndup (bfd *abfd, char *start, size_t max)
{
char *dups;
char *end = memchr (start, '\0', max);
else
len = end - start;
- dups = bfd_alloc (abfd, (bfd_size_type) len + 1);
+ dups = bfd_alloc (abfd, len + 1);
if (dups == NULL)
return NULL;
}
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-static bfd_boolean elfcore_grok_psinfo
- PARAMS ((bfd *, Elf_Internal_Note *));
-
static bfd_boolean
-elfcore_grok_psinfo (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
{
if (note->descsz == sizeof (elfcore_psinfo_t))
{
#endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
#if defined (HAVE_PSTATUS_T)
-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;
+elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note)
{
if (note->descsz == sizeof (pstatus_t)
#if defined (HAVE_PXSTATUS_T)
#endif /* defined (HAVE_PSTATUS_T) */
#if defined (HAVE_LWPSTATUS_T)
-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;
+elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
{
lwpstatus_t lwpstat;
char buf[100];
sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
memcpy (name, buf, len);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
- sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
+ sect->size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
sect->filepos = note->descpos
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.gregs);
#endif
#if defined (HAVE_LWPSTATUS_T_PR_REG)
- sect->_raw_size = sizeof (lwpstat.pr_reg);
+ sect->size = sizeof (lwpstat.pr_reg);
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_reg);
#endif
sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
memcpy (name, buf, len);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
#if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
- sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
+ sect->size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
sect->filepos = note->descpos
+ offsetof (lwpstatus_t, pr_context.uc_mcontext.fpregs);
#endif
#if defined (HAVE_LWPSTATUS_T_PR_FPREG)
- sect->_raw_size = sizeof (lwpstat.pr_fpreg);
+ sect->size = sizeof (lwpstat.pr_fpreg);
sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_fpreg);
#endif
#if defined (HAVE_WIN32_PSTATUS_T)
static bfd_boolean
-elfcore_grok_win32pstatus (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
{
char buf[30];
char *name;
sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
memcpy (name, buf, len);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
+ sect->size = sizeof (pstatus.data.thread_info.thread_context);
sect->filepos = (note->descpos
+ offsetof (struct win32_pstatus,
data.thread_info.thread_context));
sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
len = strlen (buf) + 1;
- name = bfd_alloc (abfd, (bfd_size_type) len);
+ name = bfd_alloc (abfd, len);
if (name == NULL)
return FALSE;
memcpy (name, buf, len);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
#endif /* HAVE_WIN32_PSTATUS_T */
static bfd_boolean
-elfcore_grok_note (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
{
- struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
switch (note->type)
{
case NT_AUXV:
{
- asection *sect = bfd_make_section (abfd, ".auxv");
+ asection *sect = bfd_make_section_anyway (abfd, ".auxv");
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
}
static bfd_boolean
-elfcore_netbsd_get_lwpid (note, lwpidp)
- Elf_Internal_Note *note;
- int *lwpidp;
+elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp)
{
char *cp;
}
static bfd_boolean
-elfcore_grok_netbsd_procinfo (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
{
/* Signal number at offset 0x08. */
elf_tdata (abfd)->core_command
= _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
- return TRUE;
+ return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo",
+ note);
}
static bfd_boolean
-elfcore_grok_netbsd_note (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
{
int lwp;
}
static bfd_boolean
-elfcore_grok_nto_status (abfd, note, tid)
- bfd *abfd;
- Elf_Internal_Note *note;
- pid_t *tid;
+elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
{
void *ddata = note->descdata;
char buf[100];
/* Make a ".qnx_core_status/%d" section. */
sprintf (buf, ".qnx_core_status/%d", *tid);
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
return FALSE;
strcpy (name, buf);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
}
static bfd_boolean
-elfcore_grok_nto_gregs (abfd, note, tid)
- bfd *abfd;
- Elf_Internal_Note *note;
- pid_t tid;
+elfcore_grok_nto_gregs (bfd *abfd, Elf_Internal_Note *note, pid_t tid)
{
char buf[100];
char *name;
/* Make a ".reg/%d" section. */
sprintf (buf, ".reg/%d", tid);
- name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+ name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
return FALSE;
strcpy (name, buf);
- sect = bfd_make_section (abfd, name);
+ sect = bfd_make_section_anyway (abfd, name);
if (sect == NULL)
return FALSE;
- sect->_raw_size = note->descsz;
+ sect->size = note->descsz;
sect->filepos = note->descpos;
sect->flags = SEC_HAS_CONTENTS;
sect->alignment_power = 2;
#define BFD_QNT_CORE_FPREG 10
static bfd_boolean
-elfcore_grok_nto_note (abfd, note)
- bfd *abfd;
- Elf_Internal_Note *note;
+elfcore_grok_nto_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
End of buffer containing note. */
char *
-elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- const char *name;
- int type;
- const PTR input;
- int size;
+elfcore_write_note (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const char *name,
+ int type,
+ const void *input,
+ int size)
{
Elf_External_Note *xnp;
size_t namesz;
pad = 0;
if (name != NULL)
{
- struct elf_backend_data *bed;
+ const 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;
+ newspace = 12 + namesz + pad + size;
p = realloc (buf, *bufsiz + newspace);
dest = p + *bufsiz;
#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
char *
-elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- const char *fname;
- const char *psargs;
+elfcore_write_prpsinfo (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const char *fname,
+ const char *psargs)
{
int note_type;
char *note_name = "CORE";
#if defined (HAVE_PRSTATUS_T)
char *
-elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- long pid;
- int cursig;
- const PTR gregs;
+elfcore_write_prstatus (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ long pid,
+ int cursig,
+ const void *gregs)
{
prstatus_t prstat;
char *note_name = "CORE";
#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;
+elfcore_write_lwpstatus (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ long pid,
+ int cursig,
+ const void *gregs)
{
lwpstatus_t lwpstat;
char *note_name = "CORE";
#if defined (HAVE_PSTATUS_T)
char *
-elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- long pid;
- int cursig;
- const PTR gregs;
+elfcore_write_pstatus (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ long pid,
+ int cursig,
+ const void *gregs)
{
pstatus_t pstat;
char *note_name = "CORE";
#endif /* HAVE_PSTATUS_T */
char *
-elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- const PTR fpregs;
- int size;
+elfcore_write_prfpreg (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *fpregs,
+ int size)
{
char *note_name = "CORE";
return elfcore_write_note (abfd, buf, bufsiz,
}
char *
-elfcore_write_prxfpreg (abfd, buf, bufsiz, xfpregs, size)
- bfd *abfd;
- char *buf;
- int *bufsiz;
- const PTR xfpregs;
- int size;
+elfcore_write_prxfpreg (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const void *xfpregs,
+ int size)
{
char *note_name = "LINUX";
return elfcore_write_note (abfd, buf, bufsiz,
}
static bfd_boolean
-elfcore_read_notes (abfd, offset, size)
- bfd *abfd;
- file_ptr offset;
- bfd_size_type size;
+elfcore_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
{
char *buf;
char *p;
occurs; bfd_get_error will return an appropriate code. */
long
-bfd_get_elf_phdr_upper_bound (abfd)
- bfd *abfd;
+bfd_get_elf_phdr_upper_bound (bfd *abfd)
{
if (abfd->xvec->flavour != bfd_target_elf_flavour)
{
error occurs; bfd_get_error will return an appropriate code. */
int
-bfd_get_elf_phdrs (abfd, phdrs)
- bfd *abfd;
- void *phdrs;
+bfd_get_elf_phdrs (bfd *abfd, void *phdrs)
{
int num_phdrs;
}
void
-_bfd_elf_sprintf_vma (abfd, buf, value)
- bfd *abfd ATTRIBUTE_UNUSED;
- char *buf;
- bfd_vma value;
+_bfd_elf_sprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, char *buf, bfd_vma value)
{
#ifdef BFD64
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
}
void
-_bfd_elf_fprintf_vma (abfd, stream, value)
- bfd *abfd ATTRIBUTE_UNUSED;
- PTR stream;
- bfd_vma value;
+_bfd_elf_fprintf_vma (bfd *abfd ATTRIBUTE_UNUSED, void *stream, bfd_vma value)
{
#ifdef BFD64
Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
}
enum elf_reloc_type_class
-_bfd_elf_reloc_type_class (rela)
- const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED;
+_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
{
return reloc_class_normal;
}
relocation against a local symbol. */
bfd_vma
-_bfd_elf_rela_local_sym (abfd, sym, sec, rel)
- bfd *abfd;
- Elf_Internal_Sym *sym;
- asection *sec;
- Elf_Internal_Rela *rel;
+_bfd_elf_rela_local_sym (bfd *abfd,
+ Elf_Internal_Sym *sym,
+ asection **psec,
+ Elf_Internal_Rela *rel)
{
+ asection *sec = *psec;
bfd_vma relocation;
relocation = (sec->output_section->vma
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
- asection *msec;
-
- msec = sec;
rel->r_addend =
- _bfd_merged_section_offset (abfd, &msec,
+ _bfd_merged_section_offset (abfd, psec,
elf_section_data (sec)->sec_info,
- sym->st_value + rel->r_addend,
- (bfd_vma) 0)
- - relocation;
- rel->r_addend += msec->output_section->vma + msec->output_offset;
+ sym->st_value + rel->r_addend);
+ if (sec != *psec)
+ {
+ /* If we have changed the section, and our original section is
+ marked with SEC_EXCLUDE, it means that the original
+ SEC_MERGE section has been completely subsumed in some
+ other SEC_MERGE section. In this case, we need to leave
+ some info around for --emit-relocs. */
+ if ((sec->flags & SEC_EXCLUDE) != 0)
+ sec->kept_section = *psec;
+ sec = *psec;
+ }
+ rel->r_addend -= relocation;
+ rel->r_addend += sec->output_section->vma + sec->output_offset;
}
return relocation;
}
bfd_vma
-_bfd_elf_rel_local_sym (abfd, sym, psec, addend)
- bfd *abfd;
- Elf_Internal_Sym *sym;
- asection **psec;
- bfd_vma addend;
+_bfd_elf_rel_local_sym (bfd *abfd,
+ Elf_Internal_Sym *sym,
+ asection **psec,
+ bfd_vma addend)
{
asection *sec = *psec;
return _bfd_merged_section_offset (abfd, psec,
elf_section_data (sec)->sec_info,
- sym->st_value + addend, (bfd_vma) 0);
+ sym->st_value + addend);
}
bfd_vma
-_bfd_elf_section_offset (abfd, info, sec, offset)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- bfd_vma offset;
+_bfd_elf_section_offset (bfd *abfd,
+ struct bfd_link_info *info,
+ asection *sec,
+ bfd_vma offset)
{
- struct bfd_elf_section_data *sec_data;
-
- sec_data = elf_section_data (sec);
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 (sec, elf_section_data (sec)->sec_info,
+ offset);
case ELF_INFO_TYPE_EH_FRAME:
- return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
+ return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
default:
return offset;
}
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));
+bfd_elf_bfd_from_remote_memory
+ (bfd *templ,
+ bfd_vma ehdr_vma,
+ bfd_vma *loadbasep,
+ int (*target_read_memory) (bfd_vma, char *, int))
{
return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
(templ, ehdr_vma, loadbasep, target_read_memory);
}
+\f
+long
+_bfd_elf_get_synthetic_symtab (bfd *abfd,
+ long symcount ATTRIBUTE_UNUSED,
+ asymbol **syms ATTRIBUTE_UNUSED,
+ long dynsymcount ATTRIBUTE_UNUSED,
+ asymbol **dynsyms,
+ asymbol **ret)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ asection *relplt;
+ asymbol *s;
+ const char *relplt_name;
+ bfd_boolean (*slurp_relocs) (bfd *, asection *, asymbol **, bfd_boolean);
+ arelent *p;
+ long count, i, n;
+ size_t size;
+ Elf_Internal_Shdr *hdr;
+ char *names;
+ asection *plt;
+
+ if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
+ return 0;
+
+ *ret = NULL;
+ if (!bed->plt_sym_val)
+ return 0;
+
+ relplt_name = bed->relplt_name;
+ if (relplt_name == NULL)
+ relplt_name = bed->default_use_rela_p ? ".rela.plt" : ".rel.plt";
+ relplt = bfd_get_section_by_name (abfd, relplt_name);
+ if (relplt == NULL)
+ return 0;
+
+ hdr = &elf_section_data (relplt)->this_hdr;
+ if (hdr->sh_link != elf_dynsymtab (abfd)
+ || (hdr->sh_type != SHT_REL && hdr->sh_type != SHT_RELA))
+ return 0;
+
+ plt = bfd_get_section_by_name (abfd, ".plt");
+ if (plt == NULL)
+ return 0;
+
+ slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table;
+ if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE))
+ return -1;
+
+ count = relplt->size / hdr->sh_entsize;
+ size = count * sizeof (asymbol);
+ p = relplt->relocation;
+ for (i = 0; i < count; i++, s++, p++)
+ size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
+
+ s = *ret = bfd_malloc (size);
+ if (s == NULL)
+ return -1;
+
+ names = (char *) (s + count);
+ p = relplt->relocation;
+ n = 0;
+ for (i = 0; i < count; i++, s++, p++)
+ {
+ size_t len;
+ bfd_vma addr;
+
+ addr = bed->plt_sym_val (i, plt, p);
+ if (addr == (bfd_vma) -1)
+ continue;
+
+ *s = **p->sym_ptr_ptr;
+ s->section = plt;
+ s->value = addr - plt->vma;
+ s->name = names;
+ len = strlen ((*p->sym_ptr_ptr)->name);
+ memcpy (names, (*p->sym_ptr_ptr)->name, len);
+ names += len;
+ memcpy (names, "@plt", sizeof ("@plt"));
+ names += sizeof ("@plt");
+ ++n;
+ }
+
+ return n;
+}
+
+/* Sort symbol by binding and section. We want to put definitions
+ sorted by section at the beginning. */
+
+static int
+elf_sort_elf_symbol (const void *arg1, const void *arg2)
+{
+ const Elf_Internal_Sym *s1;
+ const Elf_Internal_Sym *s2;
+ int shndx;
+
+ /* Make sure that undefined symbols are at the end. */
+ s1 = (const Elf_Internal_Sym *) arg1;
+ if (s1->st_shndx == SHN_UNDEF)
+ return 1;
+ s2 = (const Elf_Internal_Sym *) arg2;
+ if (s2->st_shndx == SHN_UNDEF)
+ return -1;
+
+ /* Sorted by section index. */
+ shndx = s1->st_shndx - s2->st_shndx;
+ if (shndx != 0)
+ return shndx;
+
+ /* Sorted by binding. */
+ return ELF_ST_BIND (s1->st_info) - ELF_ST_BIND (s2->st_info);
+}
+
+struct elf_symbol
+{
+ Elf_Internal_Sym *sym;
+ const char *name;
+};
+
+static int
+elf_sym_name_compare (const void *arg1, const void *arg2)
+{
+ const struct elf_symbol *s1 = (const struct elf_symbol *) arg1;
+ const struct elf_symbol *s2 = (const struct elf_symbol *) arg2;
+ return strcmp (s1->name, s2->name);
+}
+
+/* Check if 2 sections define the same set of local and global
+ symbols. */
+
+bfd_boolean
+bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
+{
+ bfd *bfd1, *bfd2;
+ const struct elf_backend_data *bed1, *bed2;
+ Elf_Internal_Shdr *hdr1, *hdr2;
+ bfd_size_type symcount1, symcount2;
+ Elf_Internal_Sym *isymbuf1, *isymbuf2;
+ Elf_Internal_Sym *isymstart1 = NULL, *isymstart2 = NULL, *isym;
+ Elf_Internal_Sym *isymend;
+ struct elf_symbol *symp, *symtable1 = NULL, *symtable2 = NULL;
+ bfd_size_type count1, count2, i;
+ int shndx1, shndx2;
+ bfd_boolean result;
+
+ bfd1 = sec1->owner;
+ bfd2 = sec2->owner;
+
+ /* If both are .gnu.linkonce sections, they have to have the same
+ section name. */
+ if (strncmp (sec1->name, ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0
+ && strncmp (sec2->name, ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0)
+ return strcmp (sec1->name + sizeof ".gnu.linkonce",
+ sec2->name + sizeof ".gnu.linkonce") == 0;
+
+ /* Both sections have to be in ELF. */
+ if (bfd_get_flavour (bfd1) != bfd_target_elf_flavour
+ || bfd_get_flavour (bfd2) != bfd_target_elf_flavour)
+ return FALSE;
+
+ if (elf_section_type (sec1) != elf_section_type (sec2))
+ return FALSE;
+
+ if ((elf_section_flags (sec1) & SHF_GROUP) != 0
+ && (elf_section_flags (sec2) & SHF_GROUP) != 0)
+ {
+ /* If both are members of section groups, they have to have the
+ same group name. */
+ if (strcmp (elf_group_name (sec1), elf_group_name (sec2)) != 0)
+ return FALSE;
+ }
+
+ shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
+ shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
+ if (shndx1 == -1 || shndx2 == -1)
+ return FALSE;
+
+ bed1 = get_elf_backend_data (bfd1);
+ bed2 = get_elf_backend_data (bfd2);
+ hdr1 = &elf_tdata (bfd1)->symtab_hdr;
+ symcount1 = hdr1->sh_size / bed1->s->sizeof_sym;
+ hdr2 = &elf_tdata (bfd2)->symtab_hdr;
+ symcount2 = hdr2->sh_size / bed2->s->sizeof_sym;
+
+ if (symcount1 == 0 || symcount2 == 0)
+ return FALSE;
+
+ isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
+ NULL, NULL, NULL);
+ isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
+ NULL, NULL, NULL);
+
+ result = FALSE;
+ if (isymbuf1 == NULL || isymbuf2 == NULL)
+ goto done;
+
+ /* Sort symbols by binding and section. Global definitions are at
+ the beginning. */
+ qsort (isymbuf1, symcount1, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+ qsort (isymbuf2, symcount2, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+
+ /* Count definitions in the section. */
+ count1 = 0;
+ for (isym = isymbuf1, isymend = isym + symcount1;
+ isym < isymend; isym++)
+ {
+ if (isym->st_shndx == (unsigned int) shndx1)
+ {
+ if (count1 == 0)
+ isymstart1 = isym;
+ count1++;
+ }
+
+ if (count1 && isym->st_shndx != (unsigned int) shndx1)
+ break;
+ }
+
+ count2 = 0;
+ for (isym = isymbuf2, isymend = isym + symcount2;
+ isym < isymend; isym++)
+ {
+ if (isym->st_shndx == (unsigned int) shndx2)
+ {
+ if (count2 == 0)
+ isymstart2 = isym;
+ count2++;
+ }
+
+ if (count2 && isym->st_shndx != (unsigned int) shndx2)
+ break;
+ }
+
+ if (count1 == 0 || count2 == 0 || count1 != count2)
+ goto done;
+
+ symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+ symtable2 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+
+ if (symtable1 == NULL || symtable2 == NULL)
+ goto done;
+
+ symp = symtable1;
+ for (isym = isymstart1, isymend = isym + count1;
+ isym < isymend; isym++)
+ {
+ symp->sym = isym;
+ symp->name = bfd_elf_string_from_elf_section (bfd1,
+ hdr1->sh_link,
+ isym->st_name);
+ symp++;
+ }
+
+ symp = symtable2;
+ for (isym = isymstart2, isymend = isym + count1;
+ isym < isymend; isym++)
+ {
+ symp->sym = isym;
+ symp->name = bfd_elf_string_from_elf_section (bfd2,
+ hdr2->sh_link,
+ isym->st_name);
+ symp++;
+ }
+
+ /* Sort symbol by name. */
+ qsort (symtable1, count1, sizeof (struct elf_symbol),
+ elf_sym_name_compare);
+ qsort (symtable2, count1, sizeof (struct elf_symbol),
+ elf_sym_name_compare);
+
+ for (i = 0; i < count1; i++)
+ /* Two symbols must have the same binding, type and name. */
+ if (symtable1 [i].sym->st_info != symtable2 [i].sym->st_info
+ || symtable1 [i].sym->st_other != symtable2 [i].sym->st_other
+ || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
+ goto done;
+
+ result = TRUE;
+
+done:
+ if (symtable1)
+ free (symtable1);
+ if (symtable2)
+ free (symtable2);
+ if (isymbuf1)
+ free (isymbuf1);
+ if (isymbuf2)
+ free (isymbuf2);
+
+ return result;
+}