+2001-02-09 David Mosberger <davidm@hpl.hp.com>
+
+ * elfxx-ia64.c (is_unwind_section_name): New function. Returns
+ true if section name is an unwind table section name.
+ (elfNN_ia64_additional_program_headers): Count each unwind section
+ separately.
+ (elfNN_ia64_modify_segment_map): Install one unwind program header
+ for each unwind separate section. Note: normally the linker
+ script merges the unwind sections that go into a single segment,
+ so this still generates at most one unwind program header per
+ segment.
+
+ * elfxx-ia64.c (elfNN_ia64_section_from_shdr): Accept any section
+ name for SHT_IA_64_UNWIND, not just .IA_64.unwind.
+ (elfNN_ia64_fake_sections): Mark sections with names that start
+ with .IA_64.unwind but not with .IA_64.unwind_info as an IA-64
+ unwind section.
+
+ * elfxx-ia64.c (elfNN_ia64_final_write_processing): New function.
+ Use it to make sh_info in unwind section point to the text section
+ it applies to.
+
2001-02-09 Martin Schwidefsky <schwidefsky@de.ibm.com>
* Makefile.am: Add linux target for S/390.
* libbfd-in.h (bfd_target_vector): Change extern array to pointer.
* libbfd.h (bfd_target_vector): Likewise.
* targets.c (bfd_target_vector): Rename to _bfd_target_vector and
- make static; create pointer reference named bfd_target_vector.
+ make static; create pointer reference named bfd_target_vector.
(_bfd_target_vector_entries): Calculate this based on the array
typed _bfd_target_vector.
/* IA-64 support for 64-bit ELF
- Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of BFD, the Binary File Descriptor library.
static boolean elfNN_ia64_relax_section
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
boolean *again));
+static boolean is_unwind_section_name
+ PARAMS ((const char *));
static boolean elfNN_ia64_section_from_shdr
PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));
static boolean elfNN_ia64_fake_sections
PARAMS ((bfd *abfd, ElfNN_Internal_Shdr *hdr, asection *sec));
+static void elfNN_ia64_final_write_processing
+ PARAMS ((bfd *abfd, boolean linker));
static boolean elfNN_ia64_add_symbol_hook
PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,
const char **namep, flagword *flagsp, asection **secp,
return false;
}
\f
+/* Return true if NAME is an unwind table section name. */
+
+static inline boolean
+is_unwind_section_name (name)
+ const char *name;
+{
+ size_t len1, len2;
+
+ len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
+ len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
+ return (strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
+ && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0);
+}
+
/* Handle an IA-64 specific section when reading an object file. This
is called when elfcode.h finds a section with an unknown type. */
switch (hdr->sh_type)
{
case SHT_IA_64_UNWIND:
- if (strcmp (name, ELF_STRING_ia64_unwind) != 0)
- return false;
break;
case SHT_IA_64_EXT:
name = bfd_get_section_name (abfd, sec);
- if (strcmp (name, ELF_STRING_ia64_unwind) == 0)
- hdr->sh_type = SHT_IA_64_UNWIND;
+ if (is_unwind_section_name (name))
+ {
+ /* We don't have the sections numbered at this point, so sh_info
+ is set later, in elfNN_ia64_final_write_processing. */
+ hdr->sh_type = SHT_IA_64_UNWIND;
+ hdr->sh_flags |= SHF_LINK_ORDER;
+ }
else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
hdr->sh_type = SHT_IA_64_EXT;
else if (strcmp (name, ".reloc") == 0)
return true;
}
+/* The final processing done just before writing out an IA-64 ELF
+ object file. */
+
+static void
+elfNN_ia64_final_write_processing (abfd, linker)
+ bfd *abfd;
+ boolean linker ATTRIBUTE_UNUSED;
+{
+ Elf_Internal_Shdr *hdr;
+ const char *sname;
+ asection *text_sect, *s;
+ size_t len;
+
+ for (s = abfd->sections; s; s = s->next)
+ {
+ hdr = &elf_section_data (s)->this_hdr;
+ switch (hdr->sh_type)
+ {
+ case SHT_IA_64_UNWIND:
+ /* See comments in gas/config/tc-ia64.c:dot_endp on why we
+ have to do this. */
+ sname = bfd_get_section_name (abfd, s);
+ len = sizeof (ELF_STRING_ia64_unwind) - 1;
+ if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
+ {
+ sname += len;
+
+ if (sname[0] == '\0')
+ /* .IA_64.unwind -> .text */
+ text_sect = bfd_get_section_by_name (abfd, ".text");
+ else
+ /* .IA_64.unwindFOO -> FOO */
+ text_sect = bfd_get_section_by_name (abfd, sname);
+ }
+ else
+ /* last resort: fall back on .text */
+ text_sect = bfd_get_section_by_name (abfd, ".text");
+
+ if (text_sect)
+ {
+ /* The IA-64 processor-specific ABI requires setting
+ sh_link to the unwind section, whereas HP-UX requires
+ sh_info to do so. For maximum compatibility, we'll
+ set both for now... */
+ hdr->sh_link = elf_section_data (text_sect)->this_idx;
+ hdr->sh_info = elf_section_data (text_sect)->this_idx;
+ }
+ break;
+ }
+ }
+}
+
/* Hook called by the linker routine which adds symbols from an object
file. We use it to put .comm items in .sbss, and not .bss. */
if (s && (s->flags & SEC_LOAD))
++ret;
- /* See if we need a PT_IA_64_UNWIND segment. */
- s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
- if (s && (s->flags & SEC_LOAD))
- ++ret;
+ /* Count how many PT_IA_64_UNWIND segments we need. */
+ for (s = abfd->sections; s; s = s->next)
+ if (is_unwind_section_name(s->name) && (s->flags & SEC_LOAD))
+ ++ret;
return ret;
}
bfd *abfd;
{
struct elf_segment_map *m, **pm;
+ Elf_Internal_Shdr *hdr;
asection *s;
/* If we need a PT_IA_64_ARCHEXT segment, it must come before
}
}
- /* Install the PT_IA_64_UNWIND segment, if needed. */
- s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
- if (s && (s->flags & SEC_LOAD))
+ /* Install PT_IA_64_UNWIND segments, if needed. */
+ for (s = abfd->sections; s; s = s->next)
{
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
- if (m->p_type == PT_IA_64_UNWIND)
- break;
- if (m == NULL)
+ hdr = &elf_section_data (s)->this_hdr;
+ if (hdr->sh_type != SHT_IA_64_UNWIND)
+ continue;
+
+ if (s && (s->flags & SEC_LOAD))
{
- m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ if (m->p_type == PT_IA_64_UNWIND && m->sections[0] == s)
+ break;
+
if (m == NULL)
- return false;
+ {
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ if (m == NULL)
+ return false;
- m->p_type = PT_IA_64_UNWIND;
- m->count = 1;
- m->sections[0] = s;
- m->next = NULL;
+ m->p_type = PT_IA_64_UNWIND;
+ m->count = 1;
+ m->sections[0] = s;
+ m->next = NULL;
- /* We want to put it last. */
- pm = &elf_tdata (abfd)->segment_map;
- while (*pm != NULL)
- pm = &(*pm)->next;
- *pm = m;
+ /* We want to put it last. */
+ pm = &elf_tdata (abfd)->segment_map;
+ while (*pm != NULL)
+ pm = &(*pm)->next;
+ *pm = m;
+ }
}
}
elfNN_ia64_section_flags
#define elf_backend_fake_sections \
elfNN_ia64_fake_sections
+#define elf_backend_final_write_processing \
+ elfNN_ia64_final_write_processing
#define elf_backend_add_symbol_hook \
elfNN_ia64_add_symbol_hook
#define elf_backend_additional_program_headers \