/* ELF executable support for BFD.
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02110-1301, USA. */
/* SECTION
file, into a newly allocated buffer, and return a pointer to the
buffer. */
-static char *
+static bfd_byte *
elf_read (bfd *abfd, file_ptr offset, bfd_size_type size)
{
- char *buf;
+ bfd_byte *buf;
if ((buf = bfd_alloc (abfd, size)) == NULL)
return NULL;
bfd_elf_get_str_section (bfd *abfd, unsigned int shindex)
{
Elf_Internal_Shdr **i_shdrp;
- char *shstrtab = NULL;
+ bfd_byte *shstrtab = NULL;
file_ptr offset;
bfd_size_type shstrtabsize;
i_shdrp = elf_elfsections (abfd);
if (i_shdrp == 0 || i_shdrp[shindex] == 0)
- return 0;
+ return NULL;
- shstrtab = (char *) i_shdrp[shindex]->contents;
+ shstrtab = i_shdrp[shindex]->contents;
if (shstrtab == NULL)
{
/* No cached one, attempt to read, and cache what we read. */
shstrtab = elf_read (abfd, offset, shstrtabsize);
i_shdrp[shindex]->contents = shstrtab;
}
- return shstrtab;
+ return (char *) shstrtab;
}
char *
if (strindex >= hdr->sh_size)
{
+ unsigned int shstrndx = elf_elfheader(abfd)->e_shstrndx;
(*_bfd_error_handler)
(_("%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)
+ (shindex == shstrndx && strindex == hdr->sh_name
? ".shstrtab"
- : elf_string_from_elf_strtab (abfd, hdr->sh_name)));
+ : bfd_elf_string_from_elf_section (abfd, shstrndx, hdr->sh_name)));
return "";
}
/* Look up a symbol name. */
const char *
-bfd_elf_local_sym_name (bfd *abfd, Elf_Internal_Sym *isym)
+bfd_elf_sym_name (bfd *abfd,
+ Elf_Internal_Shdr *symtab_hdr,
+ Elf_Internal_Sym *isym,
+ asection *sym_sec)
{
+ const char *name;
unsigned int iname = isym->st_name;
- unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
- if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ unsigned int shindex = symtab_hdr->sh_link;
+
+ if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION
+ /* Check for a bogus st_shndx to avoid crashing. */
+ && isym->st_shndx < elf_numsections (abfd)
+ && !(isym->st_shndx >= SHN_LORESERVE && isym->st_shndx <= SHN_HIRESERVE))
{
iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
shindex = elf_elfheader (abfd)->e_shstrndx;
}
- return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+ name = bfd_elf_string_from_elf_section (abfd, shindex, iname);
+ if (name == NULL)
+ name = "(null)";
+ else if (sym_sec && *name == '\0')
+ name = bfd_section_name (abfd, sym_sec);
+
+ return name;
}
/* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
&isym, esym, &eshndx) == NULL)
return NULL;
- return bfd_elf_local_sym_name (abfd, &isym);
+ return bfd_elf_sym_name (abfd, hdr, &isym, NULL);
}
/* Set next_in_group list pointer, and group name for NEWSECT. */
}
if (num_group == 0)
- num_group = (unsigned) -1;
- elf_tdata (abfd)->num_group = num_group;
-
- if (num_group > 0)
+ {
+ num_group = (unsigned) -1;
+ elf_tdata (abfd)->num_group = num_group;
+ }
+ else
{
/* We keep a list of elf section headers for group sections,
so we can find them quickly. */
- bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *);
+ bfd_size_type amt;
+
+ elf_tdata (abfd)->num_group = num_group;
+ amt = num_group * sizeof (Elf_Internal_Shdr *);
elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
if (elf_tdata (abfd)->group_sect_ptr == NULL)
return FALSE;
(_("%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),
+ bfd_elf_string_from_elf_section (abfd,
+ (elf_elfheader (abfd)
+ ->e_shstrndx),
+ idx->shdr->sh_name),
shdr->bfd_section->name);
result = FALSE;
}
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;
-
- while (s != NULL)
- {
- s->output_section = bfd_abs_section_ptr;
- s = elf_next_in_group (s);
- /* These lists are circular. */
- if (s == first)
- break;
- }
-#else
- /* FIXME: Never used. Remove it! */
- abort ();
-#endif
- return TRUE;
-}
-
/* Make a BFD section from an ELF section. We store a pointer to the
BFD section in the bfd_section field of the header. */
bfd_boolean
_bfd_elf_make_section_from_shdr (bfd *abfd,
Elf_Internal_Shdr *hdr,
- const char *name)
+ const char *name,
+ int shindex)
{
asection *newsect;
flagword flags;
hdr->bfd_section = newsect;
elf_section_data (newsect)->this_hdr = *hdr;
+ elf_section_data (newsect)->this_idx = shindex;
/* Always use the real type/flags. */
elf_section_type (newsect) = hdr->sh_type;
if ((elf_dynverdef (abfd) != 0 && elf_tdata (abfd)->verdef == NULL)
|| (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
{
- if (! _bfd_elf_slurp_version_tables (abfd))
+ if (! _bfd_elf_slurp_version_tables (abfd, FALSE))
return FALSE;
}
/* Set local fields. */
ret->indx = -1;
ret->dynindx = -1;
- ret->dynstr_index = 0;
- ret->elf_hash_value = 0;
- ret->weakdef = 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;
/* 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
- | ELF_LINK_HASH_NEEDS_PLT
- | ELF_LINK_POINTER_EQUALITY_NEEDED);
+ 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;
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;
table->tls_sec = NULL;
table->tls_size = 0;
table->loaded = NULL;
+ table->is_relocatable_executable = FALSE;
ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
table->root.type = bfd_link_elf_hash_table;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
const char *name;
- name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
+ name = bfd_elf_string_from_elf_section (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ hdr->sh_name);
switch (hdr->sh_type)
{
case SHT_INIT_ARRAY: /* .init_array section. */
case SHT_FINI_ARRAY: /* .fini_array section. */
case SHT_PREINIT_ARRAY: /* .preinit_array section. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ case SHT_GNU_LIBLIST: /* .gnu.liblist section. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_DYNAMIC: /* Dynamic linking information. */
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
{
linker. */
if ((hdr->sh_flags & SHF_ALLOC) != 0
&& (abfd->flags & DYNAMIC) != 0
- && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex))
return FALSE;
+ /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
+ can't read symbols without that section loaded as well. It
+ is most likely specified by the next section header. */
+ if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex)
+ {
+ unsigned int i, num_sec;
+
+ num_sec = elf_numsections (abfd);
+ for (i = shindex + 1; i < num_sec; i++)
+ {
+ Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+ if (hdr2->sh_type == SHT_SYMTAB_SHNDX
+ && hdr2->sh_link == shindex)
+ break;
+ }
+ if (i == num_sec)
+ for (i = 1; i < shindex; i++)
+ {
+ Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+ if (hdr2->sh_type == SHT_SYMTAB_SHNDX
+ && hdr2->sh_link == shindex)
+ break;
+ }
+ if (i != shindex)
+ return bfd_section_from_shdr (abfd, i);
+ }
return TRUE;
case SHT_DYNSYM: /* A dynamic symbol table */
/* Besides being a symbol table, we also treat this as a regular
section, so that objcopy can handle it. */
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_SYMTAB_SHNDX: /* Symbol section indices when >64k sections */
if (elf_symtab_shndx (abfd) == shindex)
return TRUE;
- /* Get the associated symbol table. */
- if (! bfd_section_from_shdr (abfd, hdr->sh_link)
- || hdr->sh_link != elf_onesymtab (abfd))
- return FALSE;
-
+ BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
elf_symtab_shndx (abfd) = shindex;
elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
return TRUE;
}
- {
- unsigned int i, num_sec;
+ if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex)
+ {
+ symtab_strtab:
+ elf_tdata (abfd)->strtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
+ return TRUE;
+ }
+ if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex)
+ {
+ dynsymtab_strtab:
+ elf_tdata (abfd)->dynstrtab_hdr = *hdr;
+ hdr = &elf_tdata (abfd)->dynstrtab_hdr;
+ elf_elfsections (abfd)[shindex] = hdr;
+ /* We also treat this as a regular section, so that objcopy
+ can handle it. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
+ }
- num_sec = elf_numsections (abfd);
- for (i = 1; i < num_sec; i++)
- {
- Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
- if (hdr2->sh_link == shindex)
- {
- if (! bfd_section_from_shdr (abfd, i))
- return FALSE;
- if (elf_onesymtab (abfd) == i)
- {
- elf_tdata (abfd)->strtab_hdr = *hdr;
- elf_elfsections (abfd)[shindex] =
- &elf_tdata (abfd)->strtab_hdr;
- return TRUE;
- }
- if (elf_dynsymtab (abfd) == i)
- {
- elf_tdata (abfd)->dynstrtab_hdr = *hdr;
- elf_elfsections (abfd)[shindex] = hdr =
- &elf_tdata (abfd)->dynstrtab_hdr;
- /* We also treat this as a regular section, so
- that objcopy can handle it. */
- break;
- }
-#if 0 /* Not handling other string tables specially right now. */
- hdr2 = elf_elfsections (abfd)[i]; /* in case it moved */
- /* We have a strtab for some random other section. */
- newsect = (asection *) hdr2->bfd_section;
- if (!newsect)
- break;
- hdr->bfd_section = newsect;
- hdr2 = &elf_section_data (newsect)->str_hdr;
- *hdr2 = *hdr;
- elf_elfsections (abfd)[shindex] = hdr2;
-#endif
- }
- }
- }
+ /* If the string table isn't one of the above, then treat it as a
+ regular section. We need to scan all the headers to be sure,
+ just in case this strtab section appeared before the above. */
+ if (elf_onesymtab (abfd) == 0 || elf_dynsymtab (abfd) == 0)
+ {
+ unsigned int i, num_sec;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ num_sec = elf_numsections (abfd);
+ for (i = 1; i < num_sec; i++)
+ {
+ Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+ if (hdr2->sh_link == shindex)
+ {
+ if (! bfd_section_from_shdr (abfd, i))
+ return FALSE;
+ if (elf_onesymtab (abfd) == i)
+ goto symtab_strtab;
+ if (elf_dynsymtab (abfd) == i)
+ goto dynsymtab_strtab;
+ }
+ }
+ }
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
case SHT_REL:
case SHT_RELA:
((*_bfd_error_handler)
(_("%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);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
}
/* For some incomprehensible reason Oracle distributes
}
/* Get the symbol table. */
- if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
+ if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
+ || elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM)
&& ! bfd_section_from_shdr (abfd, hdr->sh_link))
return FALSE;
can't use it as a reloc section if it points to the null
section. */
if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF)
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+ shindex);
if (! bfd_section_from_shdr (abfd, hdr->sh_info))
return FALSE;
case SHT_GNU_verdef:
elf_dynverdef (abfd) = shindex;
elf_tdata (abfd)->dynverdef_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
break;
case SHT_GNU_versym:
elf_dynversym (abfd) = shindex;
elf_tdata (abfd)->dynversym_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
break;
case SHT_GNU_verneed:
elf_dynverref (abfd) = shindex;
elf_tdata (abfd)->dynverref_hdr = *hdr;
- return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
break;
case SHT_SHLIB:
name = group_signature (abfd, hdr);
if (name == NULL)
return FALSE;
- if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
if (hdr->contents != NULL)
{
default:
/* Check for any processor-specific section types. */
- {
- if (bed->elf_backend_section_from_shdr)
- (*bed->elf_backend_section_from_shdr) (abfd, hdr, name);
- }
- break;
+ return bed->elf_backend_section_from_shdr (abfd, hdr, name,
+ shindex);
}
return TRUE;
{ ".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 }
};
sec->used_by_bfd = sdata;
}
- elf_section_type (sec) = SHT_NULL;
- ssect = _bfd_elf_get_sec_type_attr (abfd, sec->name);
- if (ssect != NULL)
+ /* When we read a file, we don't need section type and flags.
+ They will be overridden in _bfd_elf_make_section_from_shdr
+ anyway. */
+ if (abfd->direction != read_direction)
{
- elf_section_type (sec) = ssect->type;
- elf_section_flags (sec) = ssect->attr;
+ 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. */
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. */
+ /* Check for any processor-specific program segment types. */
bed = get_elf_backend_data (abfd);
- if (bed->elf_backend_section_from_phdr)
- return (*bed->elf_backend_section_from_phdr) (abfd, hdr, index);
- else
- return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "segment");
+ return bed->elf_backend_section_from_phdr (abfd, hdr, index, "proc");
}
}
struct bfd_link_order *l;
asection *elt;
- for (l = asect->link_order_head; l != NULL; l = l->next)
+ for (l = asect->map_head.link_order; l != NULL; l = l->next)
if (l->type == bfd_indirect_link_order
&& (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
do
struct bfd_link_order *o;
this_hdr->sh_size = 0;
- for (o = asect->link_order_head; o != NULL; o = o->next)
+ for (o = asect->map_head.link_order; o != NULL; o = o->next)
if (this_hdr->sh_size < o->offset + o->size)
this_hdr->sh_size = o->offset + o->size;
if (this_hdr->sh_size)
struct bfd_link_order *l;
bfd_boolean gas;
- if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
+ /* Ignore linker created group section. See elfNN_ia64_object_p in
+ elfxx-ia64.c. */
+ if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
|| *failedptr)
return;
/* If this is a relocatable link, then the above did nothing because
SEC is the output section. Look through the input sections
instead. */
- for (l = sec->link_order_head; l != NULL; l = l->next)
+ for (l = sec->map_head.link_order; l != NULL; l = l->next)
if (l->type == bfd_indirect_link_order
&& (elt = elf_next_in_group (l->u.indirect.section)) != NULL)
do
in here too, while we're at it. */
static bfd_boolean
-assign_section_numbers (bfd *abfd)
+assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
{
struct elf_obj_tdata *t = elf_tdata (abfd);
asection *sec;
unsigned int section_number, secn;
Elf_Internal_Shdr **i_shdrp;
bfd_size_type amt;
+ struct bfd_elf_section_data *d;
section_number = 1;
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
+ /* SHT_GROUP sections are in relocatable files only. */
+ if (link_info == NULL || link_info->relocatable)
+ {
+ /* Put SHT_GROUP sections first. */
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ d = elf_section_data (sec);
+
+ if (d->this_hdr.sh_type == SHT_GROUP)
+ {
+ if (sec->flags & SEC_LINKER_CREATED)
+ {
+ /* Remove the linker created SHT_GROUP sections. */
+ bfd_section_list_remove (abfd, sec);
+ abfd->section_count--;
+ }
+ else
+ {
+ if (section_number == SHN_LORESERVE)
+ section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+ d->this_idx = section_number++;
+ }
+ }
+ }
+ }
+
for (sec = abfd->sections; sec; sec = sec->next)
{
- struct bfd_elf_section_data *d = elf_section_data (sec);
+ d = elf_section_data (sec);
- if (section_number == SHN_LORESERVE)
- section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
- d->this_idx = section_number++;
+ if (d->this_hdr.sh_type != SHT_GROUP)
+ {
+ if (section_number == SHN_LORESERVE)
+ section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
+ d->this_idx = section_number++;
+ }
_bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
if ((sec->flags & SEC_RELOC) == 0)
d->rel_idx = 0;
/* Find out what the corresponding section in output
is. */
- for (p = sec->link_order_head; p != NULL; p = p->next)
+ for (p = sec->map_head.link_order; p != NULL; p = p->next)
{
s = p->u.indirect.section;
if (p->type == bfd_indirect_link_order
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
+ SHF_LINK_ORDER. But it doesn't set the sh_link or
sh_info fields. Hence we could get the situation
where elfsec is 0. */
if (elfsec == 0)
= 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'"),
+ (_("%B: warning: sh_link not set for section `%A'"),
abfd, s);
}
else
{
- s = elf_shdrp[elfsec]->bfd_section->output_section;
+ s = elf_shdrp[elfsec]->bfd_section;
+ if (elf_discarded_section (s))
+ {
+ asection *kept;
+ (*_bfd_error_handler)
+ (_("%B: sh_link of section `%A' points to discarded section `%A' of `%B'"),
+ abfd, d->this_hdr.bfd_section,
+ s, s->owner);
+ /* Point to the kept section if it has
+ the same size as the discarded
+ one. */
+ kept = _bfd_elf_check_kept_section (s);
+ if (kept == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+ s = kept;
+ }
+ s = s->output_section;
BFD_ASSERT (s != NULL);
d->this_hdr.sh_link = elf_section_data (s)->this_idx;
}
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
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
bfd_boolean failed;
- struct bfd_strtab_hash *strtab;
+ struct bfd_strtab_hash *strtab = NULL;
Elf_Internal_Shdr *shstrtab_hdr;
if (abfd->output_has_begun)
if (failed)
return FALSE;
- if (!assign_section_numbers (abfd))
+ if (!assign_section_numbers (abfd, link_info))
return FALSE;
/* The backend linker builds symbol table information itself. */
elf_elfheader (abfd)->e_phnum = count;
if (count == 0)
- return TRUE;
+ {
+ elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
+ return TRUE;
+ }
/* If we already counted the number of program segments, make sure
that we allocated enough space. This happens when SIZEOF_HEADERS
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;
}
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 += vma_page_aligned_bias (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 += vma_page_aligned_bias (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
&& strcmp (m->sections[0]->name, ".dynamic") != 0)
{
_bfd_error_handler
- (_("%s: The first section in the PT_DYNAMIC segment is not the .dynamic section"),
- bfd_get_filename (abfd));
+ (_("%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 (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 = vma_page_aligned_bias (sec->vma, voff,
- bed->maxpagesize);
- else
- adjust = vma_page_aligned_bias (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->size;
-
- if ((flags & SEC_ALLOC) != 0
- && ((flags & SEC_LOAD) != 0
- || (flags & SEC_THREAD_LOCAL) == 0))
- voff += sec->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->size;
off += sec->size;
- voff = off;
+ 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->size = 0;
- flags = sec->flags = 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->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->size;
+ p->p_memsz += sec->size;
+ }
+ /* PR ld/594: Sections in note segments which are not loaded
+ contribute to the file size but not the in-memory size. */
+ else if (p->p_type == PT_NOTE
+ && (flags & SEC_HAS_CONTENTS) != 0)
p->p_filesz += 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->size == 0
&& (sec->flags & SEC_HAS_CONTENTS) == 0)
struct bfd_link_order *o;
bfd_vma tbss_size = 0;
- for (o = sec->link_order_head; o != NULL; o = o->next)
+ for (o = sec->map_head.link_order; o != NULL; o = o->next)
if (tbss_size < o->offset + o->size)
tbss_size = o->offset + o->size;
_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. */
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)
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)));
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])
/* If we're building an executable, we'll need a program header table. */
if (abfd->flags & EXEC_P)
- {
- /* It all happens later. */
-#if 0
- i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
-
- /* elf_build_phdrs() returns a (NULL-terminated) array of
- Elf_Internal_Phdrs. */
- i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum);
- i_ehdrp->e_phoff = outbase;
- outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum;
-#endif
- }
+ /* It all happens later. */
+ ;
else
{
i_ehdrp->e_phentsize = 0;
else if (bfd_is_und_section (asect))
index = SHN_UNDEF;
else
- {
- Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
- int maxindex = elf_numsections (abfd);
-
- for (index = 1; index < maxindex; index++)
- {
- Elf_Internal_Shdr *hdr = i_shdrp[index];
-
- if (hdr != NULL && hdr->bfd_section == asect)
- return index;
- }
- index = -1;
- }
+ index = -1;
bed = get_elf_backend_data (abfd);
if (bed->elf_backend_section_from_bfd_section)
4. The section has not already been allocated to a previous segment.
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. */
+ 7. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.
+ 8. PT_DYNAMIC should not contain empty sections at the beginning
+ (with the possible exception of .dynamic). */
#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed) \
((((segment->p_paddr \
? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr) \
&& (segment->p_type == PT_LOAD \
|| segment->p_type == PT_TLS \
|| (section->flags & SEC_THREAD_LOCAL) == 0) \
+ && (segment->p_type != PT_DYNAMIC \
+ || SECTION_SIZE (section, segment) > 0 \
+ || (segment->p_paddr \
+ ? segment->p_paddr != section->lma \
+ : segment->p_vaddr != section->vma) \
+ || (strcmp (bfd_get_section_name (ibfd, section), ".dynamic") \
+ == 0)) \
&& ! section->segment_mark)
/* Returns TRUE iff seg1 starts after the end of seg2. */
-= (count - phdr_adjust_num) * iehdr->e_phentsize;
}
-#if 0
- /* Final Step: Sort the segments into ascending order of physical
- address. */
- if (map_first != NULL)
- {
- struct elf_segment_map *prev;
-
- prev = map_first;
- for (map = map_first->next; map != NULL; prev = map, map = map->next)
- {
- /* Yes I know - its a bubble sort.... */
- if (map->next != NULL && (map->next->p_paddr < map->p_paddr))
- {
- /* Swap map and map->next. */
- prev->next = map->next;
- map->next = map->next->next;
- prev->next->next = map;
-
- /* Restart loop. */
- map = map_first;
- }
- }
- }
-#endif
-
#undef SEGMENT_END
#undef SECTION_SIZE
#undef IS_CONTAINED_BY_VMA
/* Set things up for objcopy. The output SHT_GROUP section will
have its elf_next_in_group pointing back to the input group
- members. */
- elf_next_in_group (osec) = elf_next_in_group (isec);
- elf_group_name (osec) = elf_group_name (isec);
+ members. Ignore linker created group section. See
+ elfNN_ia64_object_p in elfxx-ia64.c. */
+ if (elf_sec_group (isec) == NULL
+ || (elf_sec_group (isec)->flags & SEC_LINKER_CREATED) == 0)
+ {
+ elf_next_in_group (osec) = elf_next_in_group (isec);
+ elf_group_name (osec) = elf_group_name (isec);
+ }
osec->use_rela_p = isec->use_rela_p;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Shdr *symtab_shndx_hdr;
Elf_Internal_Shdr *symstrtab_hdr;
- char *outbound_syms;
- char *outbound_shndx;
+ bfd_byte *outbound_syms;
+ bfd_byte *outbound_shndx;
int idx;
bfd_size_type amt;
bfd_boolean name_local_sections;
return symcount;
}
-/* Return the size required for the dynamic reloc entries. Any
- section that was actually installed in the BFD, and has type
- SHT_REL or SHT_RELA, and uses the dynamic symbol table, is
- considered to be a dynamic reloc section. */
+/* Return the size required for the dynamic reloc entries. Any loadable
+ section that was actually installed in the BFD, and has type SHT_REL
+ or SHT_RELA, and uses the dynamic symbol table, is considered to be a
+ dynamic reloc section. */
long
_bfd_elf_get_dynamic_reloc_upper_bound (bfd *abfd)
ret = sizeof (arelent *);
for (s = abfd->sections; s != NULL; s = s->next)
- if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+ if ((s->flags & SEC_LOAD) != 0
+ && 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->size / elf_section_data (s)->this_hdr.sh_entsize)
return ret;
}
-/* Canonicalize the dynamic relocation entries. Note that we return
- the dynamic relocations as a single block, although they are
- actually associated with particular sections; the interface, which
- was designed for SunOS style shared libraries, expects that there
- is only one set of dynamic relocs. Any section that was actually
- installed in the BFD, and has type SHT_REL or SHT_RELA, and uses
- the dynamic symbol table, is considered to be a dynamic reloc
- section. */
+/* Canonicalize the dynamic relocation entries. Note that we return the
+ dynamic relocations as a single block, although they are actually
+ associated with particular sections; the interface, which was
+ designed for SunOS style shared libraries, expects that there is only
+ one set of dynamic relocs. Any loadable section that was actually
+ installed in the BFD, and has type SHT_REL or SHT_RELA, and uses the
+ dynamic symbol table, is considered to be a dynamic reloc section. */
long
_bfd_elf_canonicalize_dynamic_reloc (bfd *abfd,
ret = 0;
for (s = abfd->sections; s != NULL; s = s->next)
{
- if (elf_section_data (s)->this_hdr.sh_link == elf_dynsymtab (abfd)
+ if ((s->flags & SEC_LOAD) != 0
+ && 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))
{
/* Read in the version information. */
bfd_boolean
-_bfd_elf_slurp_version_tables (bfd *abfd)
+_bfd_elf_slurp_version_tables (bfd *abfd, bfd_boolean default_imported_symver)
{
bfd_byte *contents = NULL;
bfd_size_type amt;
+ unsigned int freeidx = 0;
+
+ if (elf_dynverref (abfd) != 0)
+ {
+ Elf_Internal_Shdr *hdr;
+ Elf_External_Verneed *everneed;
+ Elf_Internal_Verneed *iverneed;
+ unsigned int i;
+
+ hdr = &elf_tdata (abfd)->dynverref_hdr;
+
+ amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
+ 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_malloc (hdr->sh_size);
+ if (contents == NULL)
+ goto error_return;
+ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
+ goto error_return;
+
+ everneed = (Elf_External_Verneed *) contents;
+ iverneed = elf_tdata (abfd)->verref;
+ for (i = 0; i < hdr->sh_info; i++, iverneed++)
+ {
+ Elf_External_Vernaux *evernaux;
+ Elf_Internal_Vernaux *ivernaux;
+ unsigned int j;
+
+ _bfd_elf_swap_verneed_in (abfd, everneed, iverneed);
+
+ iverneed->vn_bfd = abfd;
+
+ iverneed->vn_filename =
+ bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+ iverneed->vn_file);
+ if (iverneed->vn_filename == NULL)
+ goto error_return;
+
+ amt = iverneed->vn_cnt;
+ amt *= sizeof (Elf_Internal_Vernaux);
+ iverneed->vn_auxptr = bfd_alloc (abfd, amt);
+
+ evernaux = ((Elf_External_Vernaux *)
+ ((bfd_byte *) everneed + iverneed->vn_aux));
+ ivernaux = iverneed->vn_auxptr;
+ for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++)
+ {
+ _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
+
+ ivernaux->vna_nodename =
+ bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
+ ivernaux->vna_name);
+ if (ivernaux->vna_nodename == NULL)
+ goto error_return;
+
+ if (j + 1 < iverneed->vn_cnt)
+ ivernaux->vna_nextptr = ivernaux + 1;
+ else
+ ivernaux->vna_nextptr = NULL;
+
+ evernaux = ((Elf_External_Vernaux *)
+ ((bfd_byte *) evernaux + ivernaux->vna_next));
+
+ if (ivernaux->vna_other > freeidx)
+ freeidx = ivernaux->vna_other;
+ }
+
+ if (i + 1 < hdr->sh_info)
+ iverneed->vn_nextref = iverneed + 1;
+ else
+ iverneed->vn_nextref = NULL;
+
+ everneed = ((Elf_External_Verneed *)
+ ((bfd_byte *) everneed + iverneed->vn_next));
+ }
+
+ free (contents);
+ contents = NULL;
+ }
if (elf_dynverdef (abfd) != 0)
{
((bfd_byte *) everdef + iverdefmem.vd_next));
}
+ if (default_imported_symver)
+ {
+ if (freeidx > maxidx)
+ maxidx = ++freeidx;
+ else
+ freeidx = ++maxidx;
+ }
amt = (bfd_size_type) maxidx * sizeof (Elf_Internal_Verdef);
elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
if (elf_tdata (abfd)->verdef == NULL)
free (contents);
contents = NULL;
}
-
- if (elf_dynverref (abfd) != 0)
+ else if (default_imported_symver)
{
- Elf_Internal_Shdr *hdr;
- Elf_External_Verneed *everneed;
- Elf_Internal_Verneed *iverneed;
- unsigned int i;
-
- hdr = &elf_tdata (abfd)->dynverref_hdr;
-
- amt = (bfd_size_type) hdr->sh_info * sizeof (Elf_Internal_Verneed);
- elf_tdata (abfd)->verref = bfd_zalloc (abfd, amt);
- if (elf_tdata (abfd)->verref == NULL)
- goto error_return;
-
- elf_tdata (abfd)->cverrefs = hdr->sh_info;
+ if (freeidx < 3)
+ freeidx = 3;
+ else
+ freeidx++;
- contents = bfd_malloc (hdr->sh_size);
- if (contents == NULL)
- goto error_return;
- if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread (contents, hdr->sh_size, abfd) != hdr->sh_size)
+ amt = (bfd_size_type) freeidx * sizeof (Elf_Internal_Verdef);
+ elf_tdata (abfd)->verdef = bfd_zalloc (abfd, amt);
+ if (elf_tdata (abfd)->verdef == NULL)
goto error_return;
- everneed = (Elf_External_Verneed *) contents;
- iverneed = elf_tdata (abfd)->verref;
- for (i = 0; i < hdr->sh_info; i++, iverneed++)
- {
- Elf_External_Vernaux *evernaux;
- Elf_Internal_Vernaux *ivernaux;
- unsigned int j;
-
- _bfd_elf_swap_verneed_in (abfd, everneed, iverneed);
-
- iverneed->vn_bfd = abfd;
-
- iverneed->vn_filename =
- bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
- iverneed->vn_file);
- if (iverneed->vn_filename == NULL)
- goto error_return;
-
- amt = iverneed->vn_cnt;
- amt *= sizeof (Elf_Internal_Vernaux);
- iverneed->vn_auxptr = bfd_alloc (abfd, amt);
-
- evernaux = ((Elf_External_Vernaux *)
- ((bfd_byte *) everneed + iverneed->vn_aux));
- ivernaux = iverneed->vn_auxptr;
- for (j = 0; j < iverneed->vn_cnt; j++, ivernaux++)
- {
- _bfd_elf_swap_vernaux_in (abfd, evernaux, ivernaux);
+ elf_tdata (abfd)->cverdefs = freeidx;
+ }
- ivernaux->vna_nodename =
- bfd_elf_string_from_elf_section (abfd, hdr->sh_link,
- ivernaux->vna_name);
- if (ivernaux->vna_nodename == NULL)
- goto error_return;
+ /* Create a default version based on the soname. */
+ if (default_imported_symver)
+ {
+ Elf_Internal_Verdef *iverdef;
+ Elf_Internal_Verdaux *iverdaux;
- if (j + 1 < iverneed->vn_cnt)
- ivernaux->vna_nextptr = ivernaux + 1;
- else
- ivernaux->vna_nextptr = NULL;
+ iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];;
- evernaux = ((Elf_External_Vernaux *)
- ((bfd_byte *) evernaux + ivernaux->vna_next));
- }
+ iverdef->vd_version = VER_DEF_CURRENT;
+ iverdef->vd_flags = 0;
+ iverdef->vd_ndx = freeidx;
+ iverdef->vd_cnt = 1;
- if (i + 1 < hdr->sh_info)
- iverneed->vn_nextref = iverneed + 1;
- else
- iverneed->vn_nextref = NULL;
+ iverdef->vd_bfd = abfd;
- everneed = ((Elf_External_Verneed *)
- ((bfd_byte *) everneed + iverneed->vn_next));
- }
+ iverdef->vd_nodename = bfd_elf_get_dt_soname (abfd);
+ if (iverdef->vd_nodename == NULL)
+ goto error_return;
+ iverdef->vd_nextdef = NULL;
+ amt = (bfd_size_type) sizeof (Elf_Internal_Verdaux);
+ iverdef->vd_auxptr = bfd_alloc (abfd, amt);
- free (contents);
- contents = NULL;
+ iverdaux = iverdef->vd_auxptr;
+ iverdaux->vda_nodename = iverdef->vd_nodename;
+ iverdaux->vda_nextptr = NULL;
}
return TRUE;
const char **functionname_ptr)
{
const char *filename;
- asymbol *func;
+ asymbol *func, *file;
bfd_vma low_func;
asymbol **p;
+ /* ??? Given multiple file symbols, it is impossible to reliably
+ choose the right file name for global symbols. File symbols are
+ local symbols, and thus all file symbols must sort before any
+ global symbols. The ELF spec may be interpreted to say that a
+ file symbol must sort before other local symbols, but currently
+ ld -r doesn't do this. So, for ld -r output, it is possible to
+ make a better choice of file name for local symbols by ignoring
+ file symbols appearing after a given local symbol. */
+ enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
filename = NULL;
func = NULL;
+ file = NULL;
low_func = 0;
+ state = nothing_seen;
for (p = symbols; *p != NULL; p++)
{
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_FILE:
- filename = bfd_asymbol_name (&q->symbol);
- break;
+ file = &q->symbol;
+ if (state == symbol_seen)
+ state = file_after_symbol_seen;
+ continue;
+ case STT_SECTION:
+ continue;
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)
{
func = (asymbol *) q;
low_func = q->symbol.value;
+ if (file == NULL)
+ filename = NULL;
+ else if (ELF_ST_BIND (q->internal_elf_sym.st_info) != STB_LOCAL
+ && state == file_after_symbol_seen)
+ filename = NULL;
+ else
+ filename = bfd_asymbol_name (file);
}
break;
}
+ if (state == nothing_seen)
+ state = symbol_seen;
}
if (func == NULL)
case NOTE_INFO_THREAD:
/* Make a ".reg/999" section. */
- sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
+ sprintf (buf, ".reg/%ld", (long) pstatus.data.thread_info.tid);
len = strlen (buf) + 1;
name = bfd_alloc (abfd, len);
case NOTE_INFO_MODULE:
/* Make a ".module/xxxxxxxx" section. */
- sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
+ sprintf (buf, ".module/%08lx",
+ (long) pstatus.data.module_info.base_address);
len = strlen (buf) + 1;
name = bfd_alloc (abfd, len);
elf_tdata (abfd)->core_lwpid = *tid;
/* Make a ".qnx_core_status/%d" section. */
- sprintf (buf, ".qnx_core_status/%d", *tid);
+ sprintf (buf, ".qnx_core_status/%ld", (long) *tid);
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
}
static bfd_boolean
-elfcore_grok_nto_gregs (bfd *abfd, Elf_Internal_Note *note, pid_t tid)
+elfcore_grok_nto_regs (bfd *abfd,
+ Elf_Internal_Note *note,
+ pid_t tid,
+ char *base)
{
char buf[100];
char *name;
asection *sect;
- /* Make a ".reg/%d" section. */
- sprintf (buf, ".reg/%d", tid);
+ /* Make a "(base)/%d" section. */
+ sprintf (buf, "%s/%ld", base, (long) tid);
name = bfd_alloc (abfd, strlen (buf) + 1);
if (name == NULL)
/* This is the current thread. */
if (elf_tdata (abfd)->core_lwpid == tid)
- return elfcore_maybe_make_sect (abfd, ".reg", sect);
+ return elfcore_maybe_make_sect (abfd, base, sect);
return TRUE;
}
switch (note->type)
{
- case BFD_QNT_CORE_INFO: return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
- case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid);
- case BFD_QNT_CORE_GREG: return elfcore_grok_nto_gregs (abfd, note, tid);
- case BFD_QNT_CORE_FPREG: return elfcore_grok_prfpreg (abfd, note);
- default: return TRUE;
+ case BFD_QNT_CORE_INFO:
+ return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+ case BFD_QNT_CORE_STATUS:
+ return elfcore_grok_nto_status (abfd, note, &tid);
+ case BFD_QNT_CORE_GREG:
+ return elfcore_grok_nto_regs (abfd, note, tid, ".reg");
+ case BFD_QNT_CORE_FPREG:
+ return elfcore_grok_nto_regs (abfd, note, tid, ".reg2");
+ default:
+ return TRUE;
}
}
bfd_vma
_bfd_elf_section_offset (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info,
asection *sec,
bfd_vma 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;
}
(bfd *templ,
bfd_vma ehdr_vma,
bfd_vma *loadbasep,
- int (*target_read_memory) (bfd_vma, char *, int))
+ int (*target_read_memory) (bfd_vma, bfd_byte *, int))
{
return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
(templ, ehdr_vma, loadbasep, target_read_memory);
_bfd_elf_get_synthetic_symtab (bfd *abfd,
long symcount ATTRIBUTE_UNUSED,
asymbol **syms ATTRIBUTE_UNUSED,
- long dynsymcount ATTRIBUTE_UNUSED,
+ long dynsymcount,
asymbol **dynsyms,
asymbol **ret)
{
char *names;
asection *plt;
+ *ret = NULL;
+
if ((abfd->flags & (DYNAMIC | EXEC_P)) == 0)
return 0;
- *ret = NULL;
+ if (dynsymcount <= 0)
+ return 0;
+
if (!bed->plt_sym_val)
return 0;