diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 9669fd4d47e..da5b756d445 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
 
diff --git a/bfd/elfxx-ia64.c b/bfd/elfxx-ia64.c
index 0ef08c7742d..fc9c2262e28 100644
--- a/bfd/elfxx-ia64.c
+++ b/bfd/elfxx-ia64.c
@@ -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;
 }
 
+/* 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 \