/* 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.
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)
{
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;
&isym, esym, &eshndx) == NULL)
return NULL;
- return bfd_elf_local_sym_name (abfd, &isym);
+ return bfd_elf_sym_name (abfd, hdr, &isym);
}
/* Set next_in_group list pointer, and group name for NEWSECT. */
(_("%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. */
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)
{
&& ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
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 */
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);
+ }
- 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;
+ 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);
case SHT_REL:
}
/* 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;
default:
/* Check for any processor-specific section types. */
- {
- if (bed->elf_backend_section_from_shdr)
- (*bed->elf_backend_section_from_shdr) (abfd, hdr, name);
- }
+ if (bed->elf_backend_section_from_shdr)
+ (*bed->elf_backend_section_from_shdr) (abfd, hdr, name);
break;
}
/* 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;
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
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))
{
}
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/%d", base, 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_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;