This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

IA-64 unwind dump support for "readelf"


Please consider the attached patch for inclusion in binutils.  The
patch is relative to the Jan 31st version of the binutils CVS tree and
adds IA-64 unwind info dump support to the "readelf" program.  Being
able to easily read the unwind information often proves valuable when
working with IA-64, particularly when learning the unwind format and
when debugging unwind-related problems.  Here is a sample output:

        $ readelf -u init/main.o

        Unwind section '.IA_64.unwind' at offset 0x20a00 contains 16 entries:
                :
        <profile_setup>: [0x0-0xa0), info at +0x18
          v1, flags=0x0 ( ), len=16 bytes
            R2:prologue_gr(mask=[rp,ar.pfs],grsave=r34,rlen=5)
                P7:pfs_when(t=0)
                P7:mem_stack_f(t=1,size=16)
                P7:rp_when(t=4)
            R1:body(rlen=25)
                B2:epilogue(t=2,ecount=0)
                :

More features:

        - the dump works even when there are relocation present in the
	  unwind section; this makes it possible to do dump the unwind
	  info of an object file (not just an executable)

        - support both 64-bit and 32-bit ELF files

The only limitation that I know of is that "readelf -u" is currently
unable to process programs with more than one segment containing text
sections, but no normal UNIX/Linux program does that, so this
shouldn't be much of a real issue.

I should say that I would have preferred to put the entire IA-64
specific unwind dump support in separate object files, but that would
have required restructuring "readelf", so I refrained from doing so.
The FSF should have my copyright assignments on file, so I hope this
can be merged without too much trouble.

Thanks!

        --david


diff -urN binutils-cvs-010131/binutils/ChangeLog binutils-cvs-010131-lia/binutils/ChangeLog
--- binutils-cvs-010131/binutils/ChangeLog	Wed Jan 31 14:50:53 2001
+++ binutils-cvs-010131-lia/binutils/ChangeLog	Sat Feb  3 00:52:25 2001
@@ -1,3 +1,16 @@
+2001-02-03  David Mosberger  <davidm@hpl.hp.com>
+
+	* readelf.c (process_unwind): New function.
+	(slurp_ia64_unwind_table): Ditto.
+	(dump_ia64_unwind): Ditto.
+	(find_symbol_for_address): Ditto.
+	(slurp_rela_relocs): New function (split off from dump_relocations()).
+	(slurp_rel_relocs): Ditto.
+	(parse_args): Handle '-u' option.
+
+	* unwind-ia64-reader.c: New file.
+	* unwind-ia64.c: Ditto.
+
 2001-01-31  Steve deRosier  <sderosier@vari-lite.com>
 
 	* ieee.c (ieee_add_bb11): Don't check for backslashes
diff -urN binutils-cvs-010131/binutils/readelf.c binutils-cvs-010131-lia/binutils/readelf.c
--- binutils-cvs-010131/binutils/readelf.c	Tue Jan 23 05:49:37 2001
+++ binutils-cvs-010131-lia/binutils/readelf.c	Sat Feb  3 00:46:03 2001
@@ -104,6 +104,7 @@
 int 			do_reloc;
 int 			do_sections;
 int 			do_segments;
+int			do_unwind;
 int 			do_using_dynamic;
 int 			do_header;
 int 			do_dump;
@@ -150,6 +151,8 @@
 static const char *       get_sparc64_dynamic_type    PARAMS ((unsigned long));
 static const char *       get_parisc_dynamic_type     PARAMS ((unsigned long));
 static const char *       get_dynamic_type            PARAMS ((unsigned long));
+static int		  slurp_rela_relocs 	      PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rela **, unsigned long *));
+static int		  slurp_rel_relocs 	      PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Rel **, unsigned long *));
 static int                dump_relocations            PARAMS ((FILE *, unsigned long, unsigned long, Elf_Internal_Sym *, unsigned long, char *, int));
 static char *             get_file_type               PARAMS ((unsigned));
 static char *             get_machine_name            PARAMS ((unsigned));
@@ -157,9 +160,11 @@
 static char *             get_machine_flags           PARAMS ((unsigned, unsigned));
 static const char *       get_mips_segment_type       PARAMS ((unsigned long));
 static const char *       get_parisc_segment_type     PARAMS ((unsigned long));
+static const char *       get_ia64_segment_type       PARAMS ((unsigned long));
 static const char *       get_segment_type            PARAMS ((unsigned long));
 static const char *       get_mips_section_type_name  PARAMS ((unsigned int));
 static const char *       get_parisc_section_type_name PARAMS ((unsigned int));
+static const char *       get_ia64_section_type_name  PARAMS ((unsigned int));
 static const char *       get_section_type_name       PARAMS ((unsigned int));
 static const char *       get_symbol_binding          PARAMS ((unsigned int));
 static const char *       get_symbol_type             PARAMS ((unsigned int));
@@ -171,6 +176,7 @@
 static int                process_file_header         PARAMS ((void));
 static int                process_program_headers     PARAMS ((FILE *));
 static int                process_section_headers     PARAMS ((FILE *));
+static int		  process_unwind	      PARAMS ((FILE *));
 static void               dynamic_segment_mips_val    PARAMS ((Elf_Internal_Dyn *));
 static void               dynamic_segment_parisc_val  PARAMS ((Elf_Internal_Dyn *));
 static int                process_dynamic_segment     PARAMS ((FILE *));
@@ -187,6 +193,7 @@
 static int                get_file_header             PARAMS ((FILE *));
 static Elf_Internal_Sym * get_32bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
 static Elf_Internal_Sym * get_64bit_elf_symbols       PARAMS ((FILE *, unsigned long, unsigned long));
+static const char *	  get_elf_section_flags	      PARAMS ((bfd_vma));
 static int *              get_dynamic_data            PARAMS ((FILE *, unsigned int));
 static int                get_32bit_dynamic_segment   PARAMS ((FILE *));
 static int                get_64bit_dynamic_segment   PARAMS ((FILE *));
@@ -244,7 +251,7 @@
 /* If we can support a 64 bit data type then BFD64 should be defined
    and sizeof (bfd_vma) == 8.  In this case when translating from an
    external 8 byte field to an internal field, we can assume that the
-   internal field is also 8 bytes wide and so we can extact all the data.
+   internal field is also 8 bytes wide and so we can extract all the data.
    If, however, BFD64 is not defined, then we must assume that the
    internal data structure only has 4 byte wide fields that are the
    equivalent of the 8 byte wide external counterparts, and so we must
@@ -602,144 +609,172 @@
     }
 }
 
-/* Display the contents of the relocation data found at the specified offset.  */
 static int
-dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
-     FILE *             file;
-     unsigned long      rel_offset;
-     unsigned long      rel_size;
-     Elf_Internal_Sym * symtab;
-     unsigned long      nsyms;
-     char *             strtab;
-     int                is_rela;
+slurp_rela_relocs (file, rel_offset, rel_size, relasp, nrelasp)
+     FILE *file;
+     unsigned long rel_offset;
+     unsigned long rel_size;
+     Elf_Internal_Rela **relasp;
+     unsigned long *nrelasp;
 {
-  unsigned int        i;
-  Elf_Internal_Rel *  rels;
-  Elf_Internal_Rela * relas;
+  Elf_Internal_Rela *relas;
+  unsigned long nrelas;
+  unsigned int i;
 
+  if (is_32bit_elf)
+    {
+      Elf32_External_Rela * erelas;
 
-  if (is_rela == UNKNOWN)
-    is_rela = guess_is_rela (elf_header.e_machine);
+      GET_DATA_ALLOC (rel_offset, rel_size, erelas,
+		      Elf32_External_Rela *, "relocs");
 
-  if (is_rela)
-    {
-      if (is_32bit_elf)
-	{
-	  Elf32_External_Rela * erelas;
+      nrelas = rel_size / sizeof (Elf32_External_Rela);
 
-	  GET_DATA_ALLOC (rel_offset, rel_size, erelas,
-			  Elf32_External_Rela *, "relocs");
+      relas = (Elf_Internal_Rela *)
+	malloc (nrelas * sizeof (Elf_Internal_Rela));
 
-	  rel_size = rel_size / sizeof (Elf32_External_Rela);
+      if (relas == NULL)
+	{
+	  error(_("out of memory parsing relocs"));
+	  return 0;
+	}
 
-	  relas = (Elf_Internal_Rela *)
-	    malloc (rel_size * sizeof (Elf_Internal_Rela));
+      for (i = 0; i < nrelas; i++)
+	{
+	  relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
+	  relas[i].r_info   = BYTE_GET (erelas[i].r_info);
+	  relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
+	}
 
-	  if (relas == NULL)
-	    {
-	      error(_("out of memory parsing relocs"));
-	      return 0;
-	    }
+      free (erelas);
+    }
+  else
+    {
+      Elf64_External_Rela * erelas;
 
-	  for (i = 0; i < rel_size; i++)
-	    {
-	      relas[i].r_offset = BYTE_GET (erelas[i].r_offset);
-	      relas[i].r_info   = BYTE_GET (erelas[i].r_info);
-	      relas[i].r_addend = BYTE_GET (erelas[i].r_addend);
-	    }
+      GET_DATA_ALLOC (rel_offset, rel_size, erelas,
+		      Elf64_External_Rela *, "relocs");
+
+      nrelas = rel_size / sizeof (Elf64_External_Rela);
 
-	  free (erelas);
+      relas = (Elf_Internal_Rela *)
+	malloc (nrelas * sizeof (Elf_Internal_Rela));
 
-	  rels = (Elf_Internal_Rel *) relas;
+      if (relas == NULL)
+	{
+	  error(_("out of memory parsing relocs"));
+	  return 0;
 	}
-      else
+
+      for (i = 0; i < nrelas; i++)
 	{
-	  Elf64_External_Rela * erelas;
+	  relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset);
+	  relas[i].r_info   = BYTE_GET8 (erelas[i].r_info);
+	  relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend);
+	}
 
-	  GET_DATA_ALLOC (rel_offset, rel_size, erelas,
-			  Elf64_External_Rela *, "relocs");
+      free (erelas);
+    }
+  *relasp = relas;
+  *nrelasp = nrelas;
+  return 1;
+}
 
-	  rel_size = rel_size / sizeof (Elf64_External_Rela);
+static int
+slurp_rel_relocs (file, rel_offset, rel_size, relsp, nrelsp)
+     FILE *file;
+     unsigned long rel_offset;
+     unsigned long rel_size;
+     Elf_Internal_Rel **relsp;
+     unsigned long *nrelsp;
+{
+  Elf_Internal_Rel *rels;
+  unsigned long nrels;
+  unsigned int i;
 
-	  relas = (Elf_Internal_Rela *)
-	    malloc (rel_size * sizeof (Elf_Internal_Rela));
+  if (is_32bit_elf)
+    {
+      Elf32_External_Rel * erels;
 
-	  if (relas == NULL)
-	    {
-	      error(_("out of memory parsing relocs"));
-	      return 0;
-	    }
+      GET_DATA_ALLOC (rel_offset, rel_size, erels,
+		      Elf32_External_Rel *, "relocs");
 
-	  for (i = 0; i < rel_size; i++)
-	    {
-	      relas[i].r_offset = BYTE_GET8 (erelas[i].r_offset);
-	      relas[i].r_info   = BYTE_GET8 (erelas[i].r_info);
-	      relas[i].r_addend = BYTE_GET8 (erelas[i].r_addend);
-	    }
+      nrels = rel_size / sizeof (Elf32_External_Rel);
 
-	  free (erelas);
+      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
+
+      if (rels == NULL)
+	{
+	  error(_("out of memory parsing relocs"));
+	  return 0;
+	}
 
-	  rels = (Elf_Internal_Rel *) relas;
+      for (i = 0; i < nrels; i++)
+	{
+	  rels[i].r_offset = BYTE_GET (erels[i].r_offset);
+	  rels[i].r_info   = BYTE_GET (erels[i].r_info);
 	}
+
+      free (erels);
     }
   else
     {
-      if (is_32bit_elf)
-	{
-	  Elf32_External_Rel * erels;
+      Elf64_External_Rel * erels;
 
-	  GET_DATA_ALLOC (rel_offset, rel_size, erels,
-			  Elf32_External_Rel *, "relocs");
+      GET_DATA_ALLOC (rel_offset, rel_size, erels,
+		      Elf64_External_Rel *, "relocs");
 
-	  rel_size = rel_size / sizeof (Elf32_External_Rel);
+      nrels = rel_size / sizeof (Elf64_External_Rel);
 
-	  rels = (Elf_Internal_Rel *)
-	    malloc (rel_size * sizeof (Elf_Internal_Rel));
-
-	  if (rels == NULL)
-	    {
-	      error(_("out of memory parsing relocs"));
-	      return 0;
-	    }
+      rels = (Elf_Internal_Rel *) malloc (nrels * sizeof (Elf_Internal_Rel));
 
-	  for (i = 0; i < rel_size; i++)
-	    {
-	      rels[i].r_offset = BYTE_GET (erels[i].r_offset);
-	      rels[i].r_info   = BYTE_GET (erels[i].r_info);
-	    }
-
-	  free (erels);
-
-	  relas = (Elf_Internal_Rela *) rels;
-	}
-      else
+      if (rels == NULL)
 	{
-	  Elf64_External_Rel * erels;
-
-	  GET_DATA_ALLOC (rel_offset, rel_size, erels,
-			  Elf64_External_Rel *, "relocs");
+	  error(_("out of memory parsing relocs"));
+	  return 0;
+	}
 
-	  rel_size = rel_size / sizeof (Elf64_External_Rel);
+      for (i = 0; i < nrels; i++)
+	{
+	  rels[i].r_offset = BYTE_GET8 (erels[i].r_offset);
+	  rels[i].r_info   = BYTE_GET8 (erels[i].r_info);
+	}
 
-	  rels = (Elf_Internal_Rel *)
-	    malloc (rel_size * sizeof (Elf_Internal_Rel));
+      free (erels);
+    }
+  *relsp = rels;
+  *nrelsp = nrels;
+  return 1;
+}
 
-	  if (rels == NULL)
-	    {
-	      error(_("out of memory parsing relocs"));
-	      return 0;
-	    }
+/* Display the contents of the relocation data found at the specified offset.  */
+static int
+dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
+     FILE *             file;
+     unsigned long      rel_offset;
+     unsigned long      rel_size;
+     Elf_Internal_Sym * symtab;
+     unsigned long      nsyms;
+     char *             strtab;
+     int                is_rela;
+{
+  unsigned int        i;
+  Elf_Internal_Rel *  rels;
+  Elf_Internal_Rela * relas;
 
-	  for (i = 0; i < rel_size; i++)
-	    {
-	      rels[i].r_offset = BYTE_GET8 (erels[i].r_offset);
-	      rels[i].r_info   = BYTE_GET8 (erels[i].r_info);
-	    }
 
-	  free (erels);
+  if (is_rela == UNKNOWN)
+    is_rela = guess_is_rela (elf_header.e_machine);
 
-	  relas = (Elf_Internal_Rela *) rels;
-	}
+  if (is_rela)
+    {
+      if (!slurp_rela_relocs (file, rel_offset, rel_size, &relas, &rel_size))
+	return 0;
+    }
+  else
+    {
+      if (!slurp_rel_relocs (file, rel_offset, rel_size, &rels, &rel_size))
+	return 0;
     }
 
   if (is_rela)
@@ -1565,6 +1600,21 @@
 	  if ((e_flags & EF_PICOJAVA_GNUCALLS) == EF_PICOJAVA_GNUCALLS)
 	    strcat (buf, ", gnu calling convention");
 	  break;
+
+	case EM_IA_64:
+	  if ((e_flags & EF_IA_64_ABI64))
+	    strcat (buf, ", 64-bit");
+	  else
+	    strcat (buf, ", 32-bit");
+	  if ((e_flags & EF_IA_64_REDUCEDFP))
+	    strcat (buf, ", reduced fp model");
+	  if ((e_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
+	    strcat (buf, ", no function descriptors, constant gp");
+	  else if ((e_flags & EF_IA_64_CONS_GP))
+	    strcat (buf, ", constant gp");
+	  if ((e_flags & EF_IA_64_ABSOLUTE))
+	    strcat (buf, ", absolute");
+	  break;
 	}
     }
 
@@ -1618,6 +1668,21 @@
 }
 
 static const char *
+get_ia64_segment_type (type)
+     unsigned long type;
+{
+  switch (type)
+    {
+    case PT_IA_64_ARCHEXT:	return "IA_64_ARCHEXT";
+    case PT_IA_64_UNWIND:	return "IA_64_UNWIND";
+    default:
+      break;
+    }
+
+  return NULL;
+}
+
+static const char *
 get_segment_type (p_type)
      unsigned long p_type;
 {
@@ -1647,6 +1712,9 @@
 	    case EM_PARISC:
 	      result = get_parisc_segment_type (p_type);
 	      break;
+	    case EM_IA_64:
+	      result = get_ia64_segment_type (p_type);
+	      break;
 	    default:
 	      result = NULL;
 	      break;
@@ -1750,6 +1818,20 @@
 }
 
 static const char *
+get_ia64_section_type_name (sh_type)
+     unsigned int sh_type;
+{
+  switch (sh_type)
+    {
+    case SHT_IA_64_EXT:		return "IA_64_EXT";
+    case SHT_IA_64_UNWIND:	return "IA_64_UNWIND";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+static const char *
 get_section_type_name (sh_type)
      unsigned int sh_type;
 {
@@ -1796,6 +1878,9 @@
 	    case EM_PARISC:
 	      result = get_parisc_section_type_name (sh_type);
 	      break;
+	    case EM_IA_64:
+	      result = get_ia64_section_type_name (sh_type);
+	      break;
 	    default:
 	      result = NULL;
 	      break;
@@ -1837,6 +1922,7 @@
   {"use-dynamic",      no_argument, 0, 'D'},
   {"hex-dump",         required_argument, 0, 'x'},
   {"debug-dump",       optional_argument, 0, 'w'},
+  {"unwind",	       no_argument, 0, 'u'},
 #ifdef SUPPORT_DISASSEMBLY
   {"instruction-dump", required_argument, 0, 'i'},
 #endif
@@ -1861,6 +1947,7 @@
   fprintf (stdout, _("  -s or --syms or --symbols Display the symbol table\n"));
   fprintf (stdout, _("  -n or --notes             Display the core notes (if present)\n"));
   fprintf (stdout, _("  -r or --relocs            Display the relocations (if present)\n"));
+  fprintf (stdout, _("  -u or --unwind            Display the unwind info (if present)\n"));
   fprintf (stdout, _("  -d or --dynamic           Display the dynamic segment (if present)\n"));
   fprintf (stdout, _("  -V or --version-info      Display the version sections (if present)\n"));
   fprintf (stdout, _("  -A or --arch-specific     Display architecture specific information (if any).\n"));
@@ -1923,7 +2010,7 @@
     usage ();
 
   while ((c = getopt_long
-	  (argc, argv, "ersahnldSDAIw::x:i:vV", options, NULL)) != EOF)
+	  (argc, argv, "ersuahnldSDAIw::x:i:vV", options, NULL)) != EOF)
     {
       char *    cp;
       int	section;
@@ -1940,6 +2027,7 @@
 	case 'a':
 	  do_syms ++;
 	  do_reloc ++;
+	  do_unwind ++;
 	  do_dynamic ++;
 	  do_header ++;
 	  do_sections ++;
@@ -1963,6 +2051,9 @@
 	case 'r':
 	  do_reloc ++;
 	  break;
+	case 'u':
+	  do_unwind ++;
+	  break;
 	case 'h':
 	  do_header ++;
 	  break;
@@ -2065,7 +2156,7 @@
 	}
     }
 
-  if (!do_dynamic && !do_syms && !do_reloc && !do_sections
+  if (!do_dynamic && !do_syms && !do_reloc && !do_unwind && !do_sections
       && !do_segments && !do_header && !do_dump && !do_version
       && !do_histogram && !do_debugging && !do_arch && !do_notes)
     usage ();
@@ -2976,6 +3067,349 @@
   return 1;
 }
 
+#include "unwind-ia64.c"
+
+/* An absolute address consists of a section and an offset.  If the
+   section is NULL, the offset itself is the address, otherwise, the
+   address equals to LOAD_ADDRESS(section) + offset.  */
+
+struct absaddr
+  {
+    unsigned short section;
+    bfd_vma offset;
+  };
+
+struct unw_aux_info
+  {
+    struct unw_table_entry
+      {
+	struct absaddr start;
+	struct absaddr end;
+	struct absaddr info;
+      }
+    *table;				/* unwind table */
+    unsigned long table_len;		/* length of unwind table */
+    const unsigned char *info;		/* unwind info */
+    unsigned long info_size;		/* size of unwind info */
+    bfd_vma info_addr;			/* starting address of unwind info */
+    bfd_vma seg_base;			/* starting address of segment */
+
+    Elf_Internal_Sym *symtab;		/* the symbol table */
+    unsigned long nsyms;		/* number of symbols */
+    const char *strtab;			/* the string table */
+    unsigned long strtab_size;		/* size of string table */
+  };
+
+static void find_symbol_for_address PARAMS ((struct unw_aux_info *,
+					     struct absaddr, const char **,
+					     bfd_vma *));
+static void dump_ia64_unwind PARAMS ((struct unw_aux_info *));
+static int slurp_ia64_unwind_table PARAMS ((FILE *file, struct unw_aux_info *,
+					    Elf32_Internal_Shdr *));
+
+static void
+find_symbol_for_address (aux, addr, symname, offset)
+     struct unw_aux_info *aux;
+     struct absaddr addr;
+     const char **symname;
+     bfd_vma *offset;
+{
+  bfd_vma dist = (bfd_vma) 0x100000;
+  Elf_Internal_Sym *sym, *best = NULL;
+  unsigned long i;
+
+  for (i = 0, sym = aux->symtab; i < aux->nsyms; ++i, ++sym)
+    {
+      if (ELF_ST_TYPE (sym->st_info) == STT_FUNC
+	  && sym->st_name != 0
+	  && (addr.section == SHN_UNDEF || addr.section == sym->st_shndx)
+	  && addr.offset >= sym->st_value
+	  && addr.offset - sym->st_value < dist)
+	{
+	  best = sym;
+	  dist = addr.offset - sym->st_value;
+	  if (!dist)
+	    break;
+	}
+    }
+  if (best)
+    {
+      *symname = (best->st_name >= aux->strtab_size
+		  ? "<corrupt>" : aux->strtab + best->st_name);
+      *offset = dist;
+      return;
+    }
+  *symname = NULL;
+  *offset = addr.offset;
+}
+
+static void
+dump_ia64_unwind (aux)
+     struct unw_aux_info *aux;
+{
+  bfd_vma stamp, addr_size, offset;
+  const unsigned char *dp, *head;
+  struct unw_table_entry *tp;
+  const char *procname;
+  int in_body;
+
+  addr_size = is_32bit_elf ? 4 : 8;
+
+  for (tp = aux->table; tp < aux->table + aux->table_len; ++tp)
+    {
+      find_symbol_for_address (aux, tp->start, &procname, &offset);
+
+      fputs ("\n<", stdout);
+      if (procname)
+	{
+	  fputs (procname, stdout);
+	  if (offset)
+	    printf ("+%lx", (unsigned long) offset);
+	}
+      fputs (">: [", stdout);
+      print_vma (tp->start.offset, PREFIX_HEX);
+      fputc ('-', stdout);
+      print_vma (tp->end.offset, PREFIX_HEX);
+      printf ("), info at +0x%lx\n",
+	      (unsigned long) tp->info.offset - aux->seg_base);
+
+      head = aux->info + (tp->info.offset - aux->info_addr);
+      stamp = BYTE_GET8 ((unsigned char *) head);
+
+      printf ("  v%u, flags=0x%lx (%s%s ), len=%lu bytes\n",
+	      (unsigned) UNW_VER (stamp),
+	      (unsigned long) ((stamp & UNW_FLAG_MASK) >> 32),
+	      UNW_FLAG_EHANDLER (stamp) ? " ehandler" : "",
+	      UNW_FLAG_UHANDLER (stamp) ? " uhandler" : "",
+	      addr_size*(unsigned long)UNW_LENGTH (stamp));
+
+      if (UNW_VER (stamp) != 1)
+	{
+	  printf ("\tUnknown version.\n");
+	  continue;
+	}
+
+      in_body = 0;
+      for (dp = head + 8; dp < head + 8 + addr_size*UNW_LENGTH (stamp);)
+	dp = unw_decode (dp, in_body, &in_body);
+    }
+}
+
+static int
+slurp_ia64_unwind_table (file, aux, sec)
+     FILE *file;
+     struct unw_aux_info *aux;
+     Elf32_Internal_Shdr *sec;
+{
+  unsigned long size, addr_size, nrelas, i;
+  Elf_Internal_Phdr *prog_hdrs, *seg;
+  struct unw_table_entry *tep;
+  Elf32_Internal_Shdr *relsec;
+  Elf_Internal_Rela *rela, *rp;
+  unsigned char *table, *tp;
+  Elf_Internal_Sym *sym;
+  const char *relname;
+  int result;
+
+  addr_size = is_32bit_elf ? 4 : 8;
+
+  /* First, find the starting address of the segment that includes
+     this section: */
+
+  if (elf_header.e_phnum)
+    {
+      prog_hdrs = (Elf_Internal_Phdr *)
+	xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+      if (is_32bit_elf)
+	result = get_32bit_program_headers (file, prog_hdrs);
+      else
+	result = get_64bit_program_headers (file, prog_hdrs);
+      if (!result)
+	{
+	  free (prog_hdrs);
+	  return 0;
+	}
+      for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg)
+	{
+	  if (seg->p_type != PT_LOAD)
+	    continue;
+	  if (sec->sh_addr >= seg->p_vaddr
+	      && (sec->sh_addr + sec->sh_size <= seg->p_vaddr + seg->p_memsz))
+	    {
+	      aux->seg_base = seg->p_vaddr;
+	      break;
+	    }
+	}
+      free (prog_hdrs);
+    }
+
+  /* Second, build the unwind table from the contents of the unwind section: */
+
+  size = sec->sh_size;
+  GET_DATA_ALLOC (sec->sh_offset, size, table, char *, "unwind table");
+
+  tep = aux->table = xmalloc (size/(3*addr_size)*sizeof(aux->table[0]));
+  for (tp = table; tp < table + size; tp += 3*addr_size, ++tep)
+    {
+      tep->start.section = SHN_UNDEF;
+      tep->end.section = SHN_UNDEF;
+      tep->info.section = SHN_UNDEF;
+      if (is_32bit_elf)
+	{
+	  tep->start.offset = byte_get ((unsigned char *) tp + 0, 4);
+	  tep->end.offset   = byte_get ((unsigned char *) tp + 4, 4);
+	  tep->info.offset  = byte_get ((unsigned char *) tp + 8, 4);
+	}
+      else
+	{
+	  tep->start.offset = BYTE_GET8 ((unsigned char *) tp +  0);
+	  tep->end.offset   = BYTE_GET8 ((unsigned char *) tp +  8);
+	  tep->info.offset  = BYTE_GET8 ((unsigned char *) tp + 16);
+	}
+      tep->start.offset += aux->seg_base;
+      tep->end.offset   += aux->seg_base;
+      tep->info.offset  += aux->seg_base;
+    }
+  free (table);
+
+  /* Third, apply any relocations to the unwind table: */
+
+  for (relsec = section_headers;
+       relsec < section_headers + elf_header.e_shnum;
+       ++relsec)
+    {
+      if (relsec->sh_type != SHT_RELA
+	  || section_headers + relsec->sh_info != sec)
+	continue;
+
+      if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
+			      &rela, &nrelas))
+	return 0;
+
+      for (rp = rela; rp < rela + nrelas; ++rp)
+	{
+	  if (is_32bit_elf)
+	    {
+	      relname = elf_ia64_reloc_type (ELF32_R_TYPE (rp->r_info));
+	      sym = aux->symtab + ELF32_R_SYM (rp->r_info);
+	      if (ELF32_ST_TYPE (sym->st_info) != STT_SECTION)
+		{
+		  warn (_("Skipping unexpected symbol type %u"),
+			ELF32_ST_TYPE (sym->st_info));
+		  continue;
+		}
+	    }
+	  else
+	    {
+	      relname = elf_ia64_reloc_type (ELF64_R_TYPE (rp->r_info));
+	      sym = aux->symtab + ELF64_R_SYM (rp->r_info);
+	      if (ELF64_ST_TYPE (sym->st_info) != STT_SECTION)
+		{
+		  warn (_("Skipping unexpected symbol type %u"),
+			ELF64_ST_TYPE (sym->st_info));
+		  continue;
+		}
+	    }
+	  if (strncmp (relname, "R_IA64_SEGREL", 13) != 0)
+	    {
+	      warn (_("Skipping unexpected relocation type %s"), relname);
+	      continue;
+	    }
+
+	  i = rp->r_offset/(3*addr_size);
+	  switch (rp->r_offset/addr_size % 3)
+	    {
+	    case 0:
+	      aux->table[i].start.section = sym->st_shndx;
+	      aux->table[i].start.offset += rp->r_addend;
+	      break;
+	    case 1:
+	      aux->table[i].end.section   = sym->st_shndx;
+	      aux->table[i].end.offset   += rp->r_addend;
+	      break;
+	    case 2:
+	      aux->table[i].info.section  = sym->st_shndx;
+	      aux->table[i].info.offset  += rp->r_addend;
+	      break;
+	    }
+	}
+
+      free (rela);
+    }
+
+  aux->table_len = size / (3*addr_size);
+  return 1;
+}
+
+static int
+process_unwind (file)
+     FILE * file;
+{
+  Elf32_Internal_Shdr *sec, *unwsec = NULL, *strsec;
+  unsigned long i, addr_size;
+  struct unw_aux_info aux;
+
+  memset (&aux, 0, sizeof (aux));
+
+  addr_size = is_32bit_elf ? 4 : 8;
+
+  if (!do_unwind)
+    return 1;
+
+  for (i = 0, sec = section_headers; i < elf_header.e_shnum; ++i, ++sec)
+    {
+      if (sec->sh_type == SHT_SYMTAB)
+	{
+	  aux.nsyms = sec->sh_size / sec->sh_entsize;
+	  aux.symtab = GET_ELF_SYMBOLS (file, sec->sh_offset, aux.nsyms);
+
+	  strsec = section_headers + sec->sh_link;
+	  aux.strtab_size = strsec->sh_size;
+	  GET_DATA_ALLOC (strsec->sh_offset, aux.strtab_size,
+			  (char *) aux.strtab, char *, "string table");
+	}
+      else if (sec->sh_type == SHT_IA_64_UNWIND)
+	unwsec = sec;
+      else if (strcmp (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info) == 0)
+	{
+	  aux.info_size = sec->sh_size;
+	  aux.info_addr = sec->sh_addr;
+	  GET_DATA_ALLOC (sec->sh_offset, aux.info_size, (char *) aux.info,
+			  char *, "unwind info");
+	}
+    }
+
+  if (unwsec)
+    {
+      printf (_("\nUnwind section "));
+
+      if (string_table == NULL)
+	printf ("%d", unwsec->sh_name);
+      else
+	printf ("'%s'", SECTION_NAME (unwsec));
+
+      printf (_(" at offset 0x%lx contains %lu entries:\n"),
+	      unwsec->sh_offset, unwsec->sh_size/(3*addr_size));
+
+      slurp_ia64_unwind_table (file, &aux, unwsec);
+
+      if (aux.table_len > 0)
+	dump_ia64_unwind (&aux);
+    }
+  else
+    printf (_("\nThere are no unwind sections in this file.\n"));
+
+  if (aux.table)
+    free ((char *) aux.table);
+  if (aux.info)
+    free ((char *) aux.info);
+  if (aux.symtab)
+    free (aux.symtab);
+  if (aux.strtab)
+    free ((char *) aux.strtab);
+  return 1;
+}
+
 
 static void
 dynamic_segment_mips_val (entry)
@@ -7895,6 +8329,8 @@
   process_dynamic_segment (file);
 
   process_relocs (file);
+
+  process_unwind (file);
 
   process_symbol_table (file);
 
diff -urN binutils-cvs-010131/binutils/unwind-ia64-reader.c binutils-cvs-010131-lia/binutils/unwind-ia64-reader.c
--- binutils-cvs-010131/binutils/unwind-ia64-reader.c	Wed Dec 31 16:00:00 1969
+++ binutils-cvs-010131-lia/binutils/unwind-ia64-reader.c	Sat Feb  3 00:44:06 2001
@@ -0,0 +1,665 @@
+/* unwind_decoder.c -- decoder for IA-64 unwind info.
+   Copyright (c) 2000-2001 Free Software Foundation, Inc.
+	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/*
+ * Generic IA-64 unwind info decoder.
+ *
+ * This file is used both by the Linux kernel and objdump.  Please
+ * keep the two copies of this file in sync (modulo differences in the
+ * prototypes...).
+ *
+ * You need to customize the decoder by defining the following
+ * macros/constants before including this file:
+ *
+ *  Types:
+ *	unw_word	Unsigned integer type with at least 64 bits 
+ *
+ *  Register names:
+ *	UNW_REG_BSP
+ *	UNW_REG_BSPSTORE
+ *	UNW_REG_FPSR
+ *	UNW_REG_LC
+ *	UNW_REG_PFS
+ *	UNW_REG_PR
+ *	UNW_REG_RNAT
+ *	UNW_REG_PSP
+ *	UNW_REG_RP
+ *	UNW_REG_UNAT
+ *
+ *  Decoder action macros:
+ *	UNW_DEC_BAD_CODE(code)
+ *	UNW_DEC_ABI(fmt,abi,context,arg)
+ *	UNW_DEC_BR_GR(fmt,brmask,gr,arg)
+ *	UNW_DEC_BR_MEM(fmt,brmask,arg)
+ *	UNW_DEC_COPY_STATE(fmt,label,arg)
+ *	UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
+ *	UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
+ *	UNW_DEC_FR_MEM(fmt,frmask,arg)
+ *	UNW_DEC_GR_GR(fmt,grmask,gr,arg)
+ *	UNW_DEC_GR_MEM(fmt,grmask,arg)
+ *	UNW_DEC_LABEL_STATE(fmt,label,arg)
+ *	UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
+ *	UNW_DEC_MEM_STACK_V(fmt,t,arg)
+ *	UNW_DEC_PRIUNAT_GR(fmt,r,arg)
+ *	UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
+ *	UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
+ *	UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
+ *	UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
+ *	UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
+ *	UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
+ *	UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
+ *	UNW_DEC_REG_REG(fmt,src,dst,arg)
+ *	UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
+ *	UNW_DEC_REG_WHEN(fmt,reg,t,arg)
+ *	UNW_DEC_RESTORE(fmt,t,abreg,arg)
+ *	UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
+ *	UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
+ *	UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
+ *	UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
+ *	UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ *	UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
+ *	UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
+ *	UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
+ *	UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
+ */
+
+static unw_word unw_decode_uleb128 PARAMS ((const unsigned char **));
+static const unsigned char *unw_decode_x1 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_x2 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_x3 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_x4 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_r1 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_r2 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_r3 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_p1 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_p2_p5 PARAMS ((const unsigned char *,
+						      unsigned char, void *));
+static const unsigned char *unw_decode_p6 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_p7_p10 PARAMS ((const unsigned char *,
+						       unsigned char, void *));
+static const unsigned char *unw_decode_b1 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_b2 PARAMS ((const unsigned char *,
+						   unsigned char, void *));
+static const unsigned char *unw_decode_b3_x4 PARAMS ((const unsigned char *,
+						      unsigned char, void *));
+static const unsigned char *unw_decode PARAMS ((const unsigned char *, int,
+						void *));
+
+static unw_word
+unw_decode_uleb128 (dpp)
+     const unsigned char **dpp;
+{
+  unsigned shift = 0;
+  unw_word byte, result = 0;
+  const unsigned char *bp = *dpp;
+
+  while (1)
+    {
+      byte = *bp++;
+      result |= (byte & 0x7f) << shift;
+      if ((byte & 0x80) == 0)
+	break;
+      shift += 7;
+    }
+  *dpp = bp;
+  return result;
+}
+
+static const unsigned char *
+unw_decode_x1 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code __attribute__((unused));
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char byte1, abreg;
+  unw_word t, off;
+
+  byte1 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  off = unw_decode_uleb128 (&dp);
+  abreg = (byte1 & 0x7f);
+  if (byte1 & 0x80)
+    UNW_DEC_SPILL_SPREL (X1, t, abreg, off, arg);
+  else
+    UNW_DEC_SPILL_PSPREL (X1, t, abreg, off, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_x2 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char byte1, byte2, abreg, x, ytreg;
+  unw_word t;
+
+  byte1 = *dp++;
+  byte2 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  abreg = (byte1 & 0x7f);
+  ytreg = byte2;
+  x = (byte1 >> 7) & 1;
+  if ((byte1 & 0x80) == 0 && ytreg == 0)
+    UNW_DEC_RESTORE (X2, t, abreg, arg);
+  else
+    UNW_DEC_SPILL_REG (X2, t, abreg, x, ytreg, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_x3 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char byte1, byte2, abreg, qp;
+  unw_word t, off;
+
+  byte1 = *dp++;
+  byte2 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+  off = unw_decode_uleb128 (&dp);
+
+  qp = (byte1 & 0x3f);
+  abreg = (byte2 & 0x7f);
+
+  if (byte1 & 0x80)
+    UNW_DEC_SPILL_SPREL_P (X3, qp, t, abreg, off, arg);
+  else
+    UNW_DEC_SPILL_PSPREL_P (X3, qp, t, abreg, off, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_x4 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
+  unw_word t;
+
+  byte1 = *dp++;
+  byte2 = *dp++;
+  byte3 = *dp++;
+  t = unw_decode_uleb128 (&dp);
+
+  qp = (byte1 & 0x3f);
+  abreg = (byte2 & 0x7f);
+  x = (byte2 >> 7) & 1;
+  ytreg = byte3;
+
+  if ((byte2 & 0x80) == 0 && byte3 == 0)
+    UNW_DEC_RESTORE_P (X4, qp, t, abreg, arg);
+  else
+    UNW_DEC_SPILL_REG_P (X4, qp, t, abreg, x, ytreg, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_r1 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  int body = (code & 0x20) != 0;
+  unw_word rlen;
+
+  rlen = (code & 0x1f);
+  UNW_DEC_PROLOGUE (R1, body, rlen, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_r2 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char byte1, mask, grsave;
+  unw_word rlen;
+
+  byte1 = *dp++;
+
+  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+  grsave = (byte1 & 0x7f);
+  rlen = unw_decode_uleb128 (&dp);
+  UNW_DEC_PROLOGUE_GR (R2, rlen, mask, grsave, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_r3 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unw_word rlen;
+
+  rlen = unw_decode_uleb128 (&dp);
+  UNW_DEC_PROLOGUE (R3, ((code & 0x3) == 1), rlen, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_p1 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char brmask = (code & 0x1f);
+
+  UNW_DEC_BR_MEM (P1, brmask, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_p2_p5 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  if ((code & 0x10) == 0)
+    {
+      unsigned char byte1 = *dp++;
+
+      UNW_DEC_BR_GR (P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
+		     (byte1 & 0x7f), arg);
+    }
+  else if ((code & 0x08) == 0)
+    {
+      unsigned char byte1 = *dp++, r, dst;
+
+      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
+      dst = (byte1 & 0x7f);
+      switch (r)
+	{
+	case 0:
+	  UNW_DEC_REG_GR (P3, UNW_REG_PSP, dst, arg);
+	  break;
+	case 1:
+	  UNW_DEC_REG_GR (P3, UNW_REG_RP, dst, arg);
+	  break;
+	case 2:
+	  UNW_DEC_REG_GR (P3, UNW_REG_PFS, dst, arg);
+	  break;
+	case 3:
+	  UNW_DEC_REG_GR (P3, UNW_REG_PR, dst, arg);
+	  break;
+	case 4:
+	  UNW_DEC_REG_GR (P3, UNW_REG_UNAT, dst, arg);
+	  break;
+	case 5:
+	  UNW_DEC_REG_GR (P3, UNW_REG_LC, dst, arg);
+	  break;
+	case 6:
+	  UNW_DEC_RP_BR (P3, dst, arg);
+	  break;
+	case 7:
+	  UNW_DEC_REG_GR (P3, UNW_REG_RNAT, dst, arg);
+	  break;
+	case 8:
+	  UNW_DEC_REG_GR (P3, UNW_REG_BSP, dst, arg);
+	  break;
+	case 9:
+	  UNW_DEC_REG_GR (P3, UNW_REG_BSPSTORE, dst, arg);
+	  break;
+	case 10:
+	  UNW_DEC_REG_GR (P3, UNW_REG_FPSR, dst, arg);
+	  break;
+	case 11:
+	  UNW_DEC_PRIUNAT_GR (P3, dst, arg);
+	  break;
+	default:
+	  UNW_DEC_BAD_CODE (r);
+	  break;
+	}
+    }
+  else if ((code & 0x7) == 0)
+    UNW_DEC_SPILL_MASK (P4, dp, arg);
+  else if ((code & 0x7) == 1)
+    {
+      unw_word grmask, frmask, byte1, byte2, byte3;
+
+      byte1 = *dp++;
+      byte2 = *dp++;
+      byte3 = *dp++;
+      grmask = ((byte1 >> 4) & 0xf);
+      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
+      UNW_DEC_FRGR_MEM (P5, grmask, frmask, arg);
+    }
+  else
+    UNW_DEC_BAD_CODE (code);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_p6 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  int gregs = (code & 0x10) != 0;
+  unsigned char mask = (code & 0x0f);
+
+  if (gregs)
+    UNW_DEC_GR_MEM (P6, mask, arg);
+  else
+    UNW_DEC_FR_MEM (P6, mask, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_p7_p10 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unsigned char r, byte1, byte2;
+  unw_word t, size;
+
+  if ((code & 0x10) == 0)
+    {
+      r = (code & 0xf);
+      t = unw_decode_uleb128 (&dp);
+      switch (r)
+	{
+	case 0:
+	  size = unw_decode_uleb128 (&dp);
+	  UNW_DEC_MEM_STACK_F (P7, t, size, arg);
+	  break;
+
+	case 1:
+	  UNW_DEC_MEM_STACK_V (P7, t, arg);
+	  break;
+	case 2:
+	  UNW_DEC_SPILL_BASE (P7, t, arg);
+	  break;
+	case 3:
+	  UNW_DEC_REG_SPREL (P7, UNW_REG_PSP, t, arg);
+	  break;
+	case 4:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_RP, t, arg);
+	  break;
+	case 5:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_RP, t, arg);
+	  break;
+	case 6:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_PFS, t, arg);
+	  break;
+	case 7:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_PFS, t, arg);
+	  break;
+	case 8:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_PR, t, arg);
+	  break;
+	case 9:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_PR, t, arg);
+	  break;
+	case 10:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_LC, t, arg);
+	  break;
+	case 11:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_LC, t, arg);
+	  break;
+	case 12:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_UNAT, t, arg);
+	  break;
+	case 13:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_UNAT, t, arg);
+	  break;
+	case 14:
+	  UNW_DEC_REG_WHEN (P7, UNW_REG_FPSR, t, arg);
+	  break;
+	case 15:
+	  UNW_DEC_REG_PSPREL (P7, UNW_REG_FPSR, t, arg);
+	  break;
+	default:
+	  UNW_DEC_BAD_CODE (r);
+	  break;
+	}
+    }
+  else
+    {
+      switch (code & 0xf)
+	{
+	case 0x0:		/* p8 */
+	  {
+	    r = *dp++;
+	    t = unw_decode_uleb128 (&dp);
+	    switch (r)
+	      {
+	      case 1:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_RP, t, arg);
+		break;
+	      case 2:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_PFS, t, arg);
+		break;
+	      case 3:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_PR, t, arg);
+		break;
+	      case 4:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_LC, t, arg);
+		break;
+	      case 5:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_UNAT, t, arg);
+		break;
+	      case 6:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_FPSR, t, arg);
+		break;
+	      case 7:
+		UNW_DEC_REG_WHEN (P8, UNW_REG_BSP, t, arg);
+		break;
+	      case 8:
+		UNW_DEC_REG_PSPREL (P8, UNW_REG_BSP, t, arg);
+		break;
+	      case 9:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_BSP, t, arg);
+		break;
+	      case 10:
+		UNW_DEC_REG_WHEN (P8, UNW_REG_BSPSTORE, t, arg);
+		break;
+	      case 11:
+		UNW_DEC_REG_PSPREL (P8, UNW_REG_BSPSTORE, t, arg);
+		break;
+	      case 12:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_BSPSTORE, t, arg);
+		break;
+	      case 13:
+		UNW_DEC_REG_WHEN (P8, UNW_REG_RNAT, t, arg);
+		break;
+	      case 14:
+		UNW_DEC_REG_PSPREL (P8, UNW_REG_RNAT, t, arg);
+		break;
+	      case 15:
+		UNW_DEC_REG_SPREL (P8, UNW_REG_RNAT, t, arg);
+		break;
+	      case 16:
+		UNW_DEC_PRIUNAT_WHEN_GR (P8, t, arg);
+		break;
+	      case 17:
+		UNW_DEC_PRIUNAT_PSPREL (P8, t, arg);
+		break;
+	      case 18:
+		UNW_DEC_PRIUNAT_SPREL (P8, t, arg);
+		break;
+	      case 19:
+		UNW_DEC_PRIUNAT_WHEN_MEM (P8, t, arg);
+		break;
+	      default:
+		UNW_DEC_BAD_CODE (r);
+		break;
+	      }
+	  }
+	  break;
+
+	case 0x1:
+	  byte1 = *dp++;
+	  byte2 = *dp++;
+	  UNW_DEC_GR_GR (P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
+	  break;
+
+	case 0xf:		/* p10 */
+	  byte1 = *dp++;
+	  byte2 = *dp++;
+	  UNW_DEC_ABI (P10, byte1, byte2, arg);
+	  break;
+
+	case 0x9:
+	  return unw_decode_x1 (dp, code, arg);
+
+	case 0xa:
+	  return unw_decode_x2 (dp, code, arg);
+
+	case 0xb:
+	  return unw_decode_x3 (dp, code, arg);
+
+	case 0xc:
+	  return unw_decode_x4 (dp, code, arg);
+
+	default:
+	  UNW_DEC_BAD_CODE (code);
+	  break;
+	}
+    }
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_b1 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unw_word label = (code & 0x1f);
+
+  if ((code & 0x20) != 0)
+    UNW_DEC_COPY_STATE (B1, label, arg);
+  else
+    UNW_DEC_LABEL_STATE (B1, label, arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_b2 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unw_word t;
+
+  t = unw_decode_uleb128 (&dp);
+  UNW_DEC_EPILOGUE (B2, t, (code & 0x1f), arg);
+  return dp;
+}
+
+static const unsigned char *
+unw_decode_b3_x4 (dp, code, arg)
+     const unsigned char *dp;
+     unsigned char code ATTRIBUTE_UNUSED;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unw_word t, ecount, label;
+
+  if ((code & 0x10) == 0)
+    {
+      t = unw_decode_uleb128 (&dp);
+      ecount = unw_decode_uleb128 (&dp);
+      UNW_DEC_EPILOGUE (B3, t, ecount, arg);
+    }
+  else if ((code & 0x07) == 0)
+    {
+      label = unw_decode_uleb128 (&dp);
+      if ((code & 0x08) != 0)
+	UNW_DEC_COPY_STATE (B4, label, arg);
+      else
+	UNW_DEC_LABEL_STATE (B4, label, arg);
+    }
+  else
+    switch (code & 0x7)
+      {
+      case 1:
+	return unw_decode_x1 (dp, code, arg);
+      case 2:
+	return unw_decode_x2 (dp, code, arg);
+      case 3:
+	return unw_decode_x3 (dp, code, arg);
+      case 4:
+	return unw_decode_x4 (dp, code, arg);
+      default:
+	UNW_DEC_BAD_CODE (code);
+	break;
+      }
+  return dp;
+}
+
+typedef const unsigned char *(*unw_decoder) PARAMS((const unsigned char *, unsigned char,
+					      void *));
+
+static unw_decoder unw_decode_table[2][8] = {
+  /* prologue table: */
+  {
+   unw_decode_r1,		/* 0 */
+   unw_decode_r1,
+   unw_decode_r2,
+   unw_decode_r3,
+   unw_decode_p1,		/* 4 */
+   unw_decode_p2_p5,
+   unw_decode_p6,
+   unw_decode_p7_p10},
+  {
+   unw_decode_r1,		/* 0 */
+   unw_decode_r1,
+   unw_decode_r2,
+   unw_decode_r3,
+   unw_decode_b1,		/* 4 */
+   unw_decode_b1,
+   unw_decode_b2,
+   unw_decode_b3_x4}
+};
+
+/*
+ * Decode one descriptor and return address of next descriptor.
+ */
+static inline const unsigned char *
+unw_decode (dp, inside_body, arg)
+     const unsigned char *dp;
+     int inside_body;
+     void *arg ATTRIBUTE_UNUSED;
+{
+  unw_decoder decoder;
+  unsigned char code;
+
+  code = *dp++;
+  decoder = unw_decode_table[inside_body][code >> 5];
+  dp = (*decoder) (dp, code, arg);
+  return dp;
+}
diff -urN binutils-cvs-010131/binutils/unwind-ia64.c binutils-cvs-010131-lia/binutils/unwind-ia64.c
--- binutils-cvs-010131/binutils/unwind-ia64.c	Wed Dec 31 16:00:00 1969
+++ binutils-cvs-010131-lia/binutils/unwind-ia64.c	Sat Feb  3 00:41:52 2001
@@ -0,0 +1,413 @@
+/* readelf-unwind-ia64.c -- dump IA-64 unwind info.
+   Copyright (c) 2000-2001 Free Software Foundation, Inc.
+	Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#include <elf/ia64.h>
+
+#define UNW_VER(x)		((x) >> 48)
+#define UNW_FLAG_MASK		0x0000ffff00000000
+#define UNW_FLAG_OSMASK		0x0000f00000000000
+#define UNW_FLAG_EHANDLER(x)	((x) & 0x0000000100000000L)
+#define UNW_FLAG_UHANDLER(x)	((x) & 0x0000000200000000L)
+#define UNW_LENGTH(x)		((x) & 0x00000000ffffffffL)
+
+static bfd_vma unw_rlen = 0;
+
+static void
+unw_print_brmask (char *cp, unsigned char mask)
+{
+  char *sep = "";
+  int i;
+
+  for (i = 0; mask && (i < 5); ++i)
+    {
+      if (mask & 1)
+	{
+	  cp += sprintf (cp, "%sb%u", sep, i + 1);
+	  sep = ",";
+	}
+      mask >>= 1;
+    }
+  *cp = '\0';
+}
+
+static void
+unw_print_grmask (char *cp, unsigned char mask)
+{
+  char *sep = "";
+  int i;
+
+  *cp = '\0';
+  for (i = 0; i < 4; ++i)
+    {
+      if (mask & 1)
+	{
+	  cp += sprintf (cp, "%sr%u", sep, i + 4);
+	  sep = ",";
+	}
+      mask >>= 1;
+    }
+}
+
+static void
+unw_print_frmask (char *cp, unsigned long mask)
+{
+  char *sep = "";
+  int i;
+
+  *cp = '\0';
+  for (i = 0; i < 20; ++i)
+    {
+      if (mask & 1)
+	{
+	  cp += sprintf (cp, "%sf%u", sep, (i < 4) ? (i + 2) : (i + 12));
+	  sep = ",";
+	}
+      mask >>= 1;
+    }
+}
+
+static void
+unw_print_abreg (char *cp, unsigned char abreg)
+{
+  static const char *special_reg[16] =
+  {
+    "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
+    "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
+    "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
+  };
+
+  switch ((abreg >> 5) & 0x3)
+    {
+    case 0: /* gr */
+      sprintf (cp, "r%u", (abreg & 0x1f));
+      break;
+
+    case 1: /* fr */
+      sprintf (cp, "f%u", (abreg & 0x1f));
+      break;
+
+    case 2: /* br */
+      sprintf (cp, "b%u", (abreg & 0x1f));
+      break;
+
+    case 3: /* special */
+      strcpy (cp, special_reg[abreg & 0xf]);
+      break;
+    }
+}
+
+static void
+unw_print_xyreg (char *cp, unsigned char x, unsigned char ytreg)
+{
+  switch ((x << 1) | ((ytreg >> 7) & 1))
+    {
+    case 0: /* gr */
+      sprintf (cp, "r%u", (ytreg & 0x1f));
+      break;
+
+    case 1: /* fr */
+      sprintf (cp, "f%u", (ytreg & 0x1f));
+      break;
+
+    case 2: /* br */
+      sprintf (cp, "b%u", (ytreg & 0x1f));
+      break;
+    }
+}
+
+#define UNW_REG_BSP		"bsp"
+#define UNW_REG_BSPSTORE	"bspstore"
+#define UNW_REG_FPSR		"fpsr"
+#define UNW_REG_LC		"lc"
+#define UNW_REG_PFS		"pfs"
+#define UNW_REG_PR		"pr"
+#define UNW_REG_PSP		"psp"
+#define UNW_REG_RNAT		"rnat"
+#define UNW_REG_RP		"rp"
+#define UNW_REG_UNAT		"unat"
+
+typedef bfd_vma unw_word;
+
+#define STR(x)	#x
+
+#define UNW_DEC_BAD_CODE(code)			\
+    printf ("Unknown code 0x%02x\n", code)
+
+#define UNW_DEC_PROLOGUE(fmt, body, rlen, arg)			\
+do {								\
+  unw_rlen = rlen;						\
+  *(int *)arg = body;						\
+  printf ("    "STR(fmt)":%s(rlen=%lu)\n",			\
+	  body ? "body" : "prologue", (unsigned long) rlen);	\
+} while (0)
+
+#define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg)		\
+do {									\
+  char regname[16], maskstr[64], *sep;					\
+									\
+  unw_rlen = rlen;							\
+  *(int *)arg = 0;							\
+									\
+  maskstr[0] = '\0';							\
+  sep = "";								\
+  if (mask & 0x8)							\
+    {									\
+      strcat (maskstr, "rp");						\
+      sep = ",";							\
+    }									\
+  if (mask & 0x4)							\
+    {									\
+      strcat (maskstr, sep);						\
+      strcat (maskstr, "ar.pfs");					\
+      sep = ",";							\
+    }									\
+  if (mask & 0x2)							\
+    {									\
+      strcat (maskstr, sep);						\
+      strcat (maskstr, "psp");						\
+      sep = ",";							\
+    }									\
+  if (mask & 0x1)							\
+    {									\
+      strcat (maskstr, sep);						\
+      strcat (maskstr, "pr");						\
+    }									\
+  sprintf (regname, "r%u", grsave);					\
+  printf ("    "STR(fmt)":prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n",	\
+	  maskstr, regname, (unsigned long) rlen);			\
+} while (0)
+
+#define UNW_DEC_FR_MEM(fmt, frmask, arg)		\
+do {							\
+  char frstr[200];					\
+							\
+  unw_print_frmask (frstr, frmask);			\
+  printf ("\t"STR(fmt)":fr_mem(frmask=[%s])\n", frstr);	\
+} while (0)
+
+#define UNW_DEC_GR_MEM(fmt, grmask, arg)		\
+do {							\
+  char grstr[200];					\
+							\
+  unw_print_grmask (grstr, grmask);			\
+  printf ("\t"STR(fmt)":gr_mem(grmask=[%s])\n", grstr);	\
+} while (0)
+
+#define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg)			     \
+do {									     \
+  char frstr[200], grstr[20];						     \
+									     \
+  unw_print_grmask (grstr, grmask);					     \
+  unw_print_frmask (frstr, frmask);					     \
+  printf ("\t"STR(fmt)":frgr_mem(grmask=[%s],frmask=[%s])\n", grstr, frstr); \
+} while (0)
+
+#define UNW_DEC_BR_MEM(fmt, brmask, arg)		\
+do {							\
+  char brstr[20];					\
+							\
+  unw_print_brmask (brstr, brmask);			\
+  printf ("\t"STR(fmt)":br_mem(brmask=[%s])\n", brstr);	\
+} while (0)
+
+#define UNW_DEC_BR_GR(fmt, brmask, gr, arg)				\
+do {									\
+  char brstr[20];							\
+									\
+  unw_print_brmask (brstr, brmask);					\
+  printf ("\t"STR(fmt)":br_gr(brmask=[%s],gr=r%u)\n", brstr, gr);	\
+} while (0)
+
+#define UNW_DEC_REG_GR(fmt, src, dst, arg)		\
+  printf ("\t"STR(fmt)":%s_gr(reg=r%u)\n", src, dst)
+
+#define UNW_DEC_RP_BR(fmt, dst, arg)		\
+  printf ("\t"STR(fmt)":rp_br(reg=b%u)\n", dst)
+
+#define UNW_DEC_REG_WHEN(fmt, reg, t, arg)				\
+  printf ("\t"STR(fmt)":%s_when(t=%lu)\n", reg, (unsigned long) t)
+
+#define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg)		\
+  printf ("\t"STR(fmt)":%s_sprel(spoff=0x%lx)\n",	\
+	  reg, 4*(unsigned long)spoff)
+
+#define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg)		\
+  printf ("\t"STR(fmt)":%s_psprel(pspoff=0x10-0x%lx)\n",	\
+	  reg, 4*(unsigned long)pspoff)
+
+#define UNW_DEC_GR_GR(fmt, grmask, gr, arg)			\
+do {								\
+  char grstr[20];						\
+								\
+  unw_print_grmask (grstr, grmask);				\
+  printf ("\t"STR(fmt)":gr_gr(grmask=[%s],r%u)\n", grstr, gr);	\
+} while (0)
+
+#define UNW_DEC_ABI(fmt, abi, context, arg)			\
+do {								\
+  static const char *abiname[] =				\
+  {								\
+    "@svr4", "@hpux", "@nt"					\
+  };								\
+  char buf[20];							\
+  const char *abistr = buf;					\
+								\
+  if (abi < 3)							\
+    abistr = abiname[abi];					\
+  else								\
+    sprintf (buf, "0x%x", abi);					\
+  printf ("\t"STR(fmt)":unwabi(abi=%s,context=0x%02x)\n",	\
+	  abistr, context);					\
+} while (0)
+
+#define UNW_DEC_PRIUNAT_GR(fmt, r, arg)		\
+  printf ("\t"STR(fmt)":priunat_gr(reg=r%u)\n", r)
+
+#define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg)				\
+  printf ("\t"STR(fmt)":priunat_when_gr(t=%lu)\n", (unsigned long) t)
+
+#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg)				\
+  printf ("\t"STR(fmt)":priunat_when_mem(t=%lu)\n", (unsigned long) t)
+
+#define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg)		\
+  printf ("\t"STR(fmt)":priunat_psprel(pspoff=0x10-0x%lx)\n",	\
+	  4*(unsigned long)pspoff)
+
+#define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg)		\
+  printf ("\t"STR(fmt)":priunat_sprel(spoff=0x%lx)\n",	\
+	  4*(unsigned long)spoff)
+
+#define UNW_DEC_MEM_STACK_F(fmt, t, size, arg)		\
+  printf ("\t"STR(fmt)":mem_stack_f(t=%lu,size=%lu)\n",	\
+	  (unsigned long) t, 16*(unsigned long)size)
+
+#define UNW_DEC_MEM_STACK_V(fmt, t, arg)				\
+  printf ("\t"STR(fmt)":mem_stack_v(t=%lu)\n", (unsigned long) t)
+
+#define UNW_DEC_SPILL_BASE(fmt, pspoff, arg)			\
+  printf ("\t"STR(fmt)":spill_base(pspoff=0x10-0x%lx)\n",	\
+	  4*(unsigned long)pspoff)
+
+#define UNW_DEC_SPILL_MASK(fmt, dp, arg)				\
+do {									\
+  static const char *spill_type = "-frb";				\
+  unsigned const char *imaskp = dp;					\
+  unsigned char mask = 0;						\
+  bfd_vma insn = 0;							\
+									\
+  printf ("\t"STR(fmt)":spill_mask(imask=[");				\
+  for (insn = 0; insn < unw_rlen; ++insn)				\
+    {									\
+      if ((insn % 4) == 0)						\
+	mask = *imaskp++;						\
+      if (insn > 0 && (insn % 3) == 0)					\
+	putchar (',');							\
+      putchar (spill_type[(mask >> (2*(3-(insn & 0x3)))) & 0x3]);	\
+    }									\
+  printf ("])\n");							\
+  dp = imaskp;								\
+} while (0)
+
+#define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg)			\
+do {									\
+  char regname[10];							\
+									\
+  unw_print_abreg (regname, abreg);					\
+  printf ("\t"STR(fmt)":spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n",	\
+	  regname, (unsigned long) t, 4*(unsigned long)off);		\
+} while (0)
+
+#define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg)		 \
+do {									 \
+  char regname[10];							 \
+									 \
+  unw_print_abreg (regname, abreg);					 \
+  printf ("\t"STR(fmt)":spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
+	  regname, (unsigned long) t, 4*(unsigned long)pspoff);		 \
+} while (0)
+
+#define UNW_DEC_RESTORE(fmt, t, abreg, arg)		\
+do {							\
+  char regname[10];					\
+							\
+  unw_print_abreg (regname, abreg);			\
+  printf ("\t"STR(fmt)":restore(t=%lu,reg=%s)\n",	\
+	  (unsigned long) t, regname);			\
+} while (0)
+
+#define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg)		\
+do {								\
+  char abregname[10], tregname[10];				\
+								\
+  unw_print_abreg (abregname, abreg);				\
+  unw_print_xyreg (tregname, x, ytreg);				\
+  printf ("\t"STR(fmt)":spill_reg(t=%lu,reg=%s,treg=%s)\n",	\
+	  (unsigned long) t, abregname, tregname);		\
+} while (0)
+
+#define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg)		   \
+do {									   \
+  char regname[20];							   \
+									   \
+  unw_print_abreg (regname, abreg);					   \
+  printf ("\t"STR(fmt)":spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
+	  qp, (unsigned long) t, regname, 4*(unsigned long)spoff);	   \
+} while (0)
+
+#define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg)		\
+do {									\
+  char regname[20];							\
+									\
+  unw_print_abreg (regname, abreg);					\
+  printf ("\t"STR(fmt)							\
+	  ":spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",	\
+	  qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);	\
+} while (0)
+
+#define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg)		\
+do {								\
+  char regname[20];						\
+								\
+  unw_print_abreg (regname, abreg);				\
+  printf ("\t"STR(fmt)":restore_p(qp=p%u,t=%lu,reg=%s)\n",	\
+	  qp, (unsigned long) t, regname);			\
+} while (0)
+
+#define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg)		\
+do {									\
+  char regname[20], tregname[20];					\
+									\
+  unw_print_abreg (regname, abreg);					\
+  unw_print_xyreg (tregname, x, ytreg);					\
+  printf ("\t"STR(fmt)":spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n",	\
+	  qp, (unsigned long) t, regname, tregname);			\
+} while (0)
+
+#define UNW_DEC_LABEL_STATE(fmt, label, arg)				  \
+  printf ("\t"STR(fmt)":label_state(label=%lu)\n", (unsigned long) label)
+
+#define UNW_DEC_COPY_STATE(fmt, label, arg)				 \
+  printf ("\t"STR(fmt)":copy_state(label=%lu)\n", (unsigned long) label)
+
+#define UNW_DEC_EPILOGUE(fmt, t, ecount, arg)		\
+  printf ("\t"STR(fmt)":epilogue(t=%lu,ecount=%lu)\n",	\
+	  (unsigned long) t, (unsigned long) ecount)
+
+#include "unwind-ia64-reader.c"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]