* elfxx-ia64.c (is_unwind_section_name): New function. Returns
authorRichard Henderson <rth@redhat.com>
Sat, 10 Feb 2001 01:41:06 +0000 (01:41 +0000)
committerRichard Henderson <rth@redhat.com>
Sat, 10 Feb 2001 01:41:06 +0000 (01:41 +0000)
        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.

bfd/ChangeLog
bfd/elfxx-ia64.c

index 9669fd4..da5b756 100644 (file)
@@ -1,3 +1,25 @@
+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.
@@ -66,7 +88,7 @@
        * 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.
 
index 0ef08c7..fc9c226 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -157,10 +157,14 @@ static void elfNN_ia64_info_to_howto
 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,
@@ -900,6 +904,20 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
   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.  */
 
@@ -919,8 +937,6 @@ elfNN_ia64_section_from_shdr (abfd, hdr, name)
   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:
@@ -968,8 +984,13 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
 
   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)
@@ -999,6 +1020,58 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
   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.  */
 
@@ -1052,10 +1125,10 @@ elfNN_ia64_additional_program_headers (abfd)
   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;
 }
@@ -1065,6 +1138,7 @@ elfNN_ia64_modify_segment_map (abfd)
      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
@@ -1097,29 +1171,36 @@ elfNN_ia64_modify_segment_map (abfd)
        }
     }
 
-  /* 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;
+           }
        }
     }
 
@@ -4069,6 +4150,8 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
        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 \