From f3b6f7c34d3b6d5024a66ab4e35d115c1c207bec Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Mon, 9 Oct 2000 23:16:30 +0000
Subject: [PATCH]         * elf64-ia64.c (elf64_ia64_unwind_entry_compare_bfd):
 New.         (elf64_ia64_unwind_entry_compare): New.        
 (elf64_ia64_final_link): Sort the .IA_64.unwind section.

---
 bfd/ChangeLog    |  6 ++++++
 bfd/elf64-ia64.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c683b4d9071..249a4bf2253 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,9 @@
+2000-10-09  Richard Henderson  <rth@cygnus.com
+
+	* elf64-ia64.c (elf64_ia64_unwind_entry_compare_bfd): New.
+	(elf64_ia64_unwind_entry_compare): New.
+	(elf64_ia64_final_link): Sort the .IA_64.unwind section.
+
 2000-10-07  Alan Modra  <alan@linuxcare.com.au>
 
 	* elflink.h (size_dynamic_sections): Don't create various tags if
diff --git a/bfd/elf64-ia64.c b/bfd/elf64-ia64.c
index cc6383894dc..03985fe9456 100644
--- a/bfd/elf64-ia64.c
+++ b/bfd/elf64-ia64.c
@@ -2973,6 +2973,25 @@ set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
   return value;
 }
 
+/* Called through qsort to sort the .IA_64.unwind section during a
+   non-relocatable link.  Set elf64_ia64_unwind_entry_compare_bfd
+   to the output bfd so we can do proper endianness frobbing.  */
+
+static bfd *elf64_ia64_unwind_entry_compare_bfd;
+
+static int
+elf64_ia64_unwind_entry_compare (a, b)
+     PTR a;
+     PTR b;
+{
+  bfd_vma av, bv;
+
+  av = bfd_get_64 (elf64_ia64_unwind_entry_compare_bfd, a);
+  bv = bfd_get_64 (elf64_ia64_unwind_entry_compare_bfd, b);
+
+  return (av < bv ? -1 : av > bv ? 1 : 0);
+}
+
 static boolean
 elf64_ia64_final_link (abfd, info)
      bfd *abfd;
@@ -3134,7 +3153,35 @@ elf64_ia64_final_link (abfd, info)
     }
 
   /* Invoke the regular ELF backend linker to do all the work.  */
-  return bfd_elf64_bfd_final_link (abfd, info);
+  if (!bfd_elf64_bfd_final_link (abfd, info))
+    return false;
+
+  /* If we're producing a final executable, we need to sort the contents
+     of the .IA_64.unwind section.  */
+  if (!info->relocateable)
+    {
+      asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
+      if (s)
+	{
+	  bfd_size_type size = s->output_section->_raw_size;
+	  char *contents = bfd_malloc (size);
+
+	  if (contents == NULL)
+	    return false;
+	  if (! bfd_get_section_contents (abfd, s->output_section,
+					  contents, (file_ptr) 0, size))
+	    return false;
+
+	  elf64_ia64_unwind_entry_compare_bfd = abfd;
+	  qsort (contents, size / 24, 24, elf64_ia64_unwind_entry_compare);
+
+	  if (! bfd_set_section_contents (abfd, s->output_section,
+					  contents, (file_ptr) 0, size))
+	    return false;
+	}
+    }
+
+  return true;
 }
 
 static boolean