OSDN Git Service

* configure.in (ia64-linux) [tmake_file]: Add ia64/t-glibc.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Oct 2000 03:08:50 +0000 (03:08 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 4 Oct 2000 03:08:50 +0000 (03:08 +0000)
* config/ia64/crtbegin.asm (__EH_FRAME_BEGIN__): Remove.
(segrel_ofs): Remove.
(__ia64_app_header): New.
(frame_object): Remove.
(.init): Set __ia64_app_header when non-shared.
(__do_global_dtors_aux): Do not call __deregister_frame_info.
(__do_frame_setup): Remove.
* config/ia64/crtend.asm (__EH_FRAME_END__): Remove.
(__do_frame_setup_aux): Remove.
* config/ia64/frame-ia64.c (object_mutex): Remove.
(bad_record): Remove.
(init_object_mutex): Remove.
(init_object_mutex_once): Remove.
(fde_compare): Remove.
(__register_frame_info_aux): Remove.
(frame_init): Remove.
(find_fde): Remove.
(*): Use ISO function definitions.
(P3_record_types): Constify.
(P7_record_types, P7_additional_fields): Constify.
(P8_record_types, P8_additional_fields): Constify.
(read_P_record): Remove parenthesis warning.  Use structure
assignment instead of memcpy.
(execute_one_ia64_descriptor): Likewise.
(__build_ia64_frame_state): Use __ia64_find_fde.
(record_name, print_record, print_all_records): Remove.
* config/ia64/frame-ia64.h: New file.
* config/ia64/fde-glibc.c: New file.
* config/ia64/t-glibc: New file.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36705 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/ia64/crtbegin.asm
gcc/config/ia64/crtend.asm
gcc/config/ia64/fde-glibc.c [new file with mode: 0644]
gcc/config/ia64/frame-ia64.c
gcc/config/ia64/frame-ia64.h [new file with mode: 0644]
gcc/config/ia64/t-glibc [new file with mode: 0644]
gcc/configure
gcc/configure.in

index 1a8bcf1..1b57a99 100644 (file)
@@ -26,20 +26,19 @@ __CTOR_LIST__:
 __DTOR_LIST__:
        data8   -1
 
-.section .IA_64.unwind
-       .align  8
-__EH_FRAME_BEGIN__:
-
 .section .sdata
        .type dtor_ptr#,@object
        .size dtor_ptr#,8
 dtor_ptr:
        data8   __DTOR_LIST__# + 8
 
-       .type segrel_ofs#,@object
-       .size segrel_ofs#,8
-segrel_ofs:
+#ifndef SHARED
+       .type __ia64_app_header#,@object
+       .size __ia64_app_header#,8
+       .global __ia64_app_header
+__ia64_app_header:
        data8   @segrel(.Lsegrel_ref#)
+#endif
 
        /* A handle for __cxa_finalize to manage c++ local destructors.  */
        .global __dso_handle#
@@ -56,14 +55,6 @@ __dso_handle:
 #endif
        .hidden __dso_handle#
 
-       /* The frame object.  */
-       /* ??? How can we rationally keep this size correct?  */
-.section .bss
-       .type frame_object#,@object
-       .size frame_object#,64
-       .align 8
-frame_object:
-       .zero 64
 
 /*
  * Fragment of the ELF _fini routine that invokes our dtor cleanup.
@@ -94,25 +85,28 @@ frame_object:
          ;;
        }
 
+#ifndef SHARED
 /*
- * Fragment of the ELF _init routine that sets up the frame info.
+ * Fragment of the ELF _init routine that sets up __ia64_app_header
  */
 
 .section .init,"ax","progbits"
-       { .mlx
-         movl r2 = @gprel(__do_frame_setup#)
+.Lsegrel_ref:
+       { .mmi
+         addl r2 = @gprel(__ia64_app_header), gp
+         mov r16 = ip
          ;;
        }
-       { .mii
-         nop.m 0
-         add r2 = r2, gp
+       { .mmi
+         ld8 r3 = [r2]
          ;;
-         mov b6 = r2
-       }
-       { .bbb
-         br.call.sptk.many b0 = b6
+         sub r16 = r16, r3
          ;;
        }
+       { .mfb
+         st8 [r2] = r16
+       }
+#endif
 
 .section .text
        .align  16
@@ -194,33 +188,6 @@ __do_global_dtors_aux:
          cmp.ne p6, p0 = r0, r16
 (p6)     br.cond.sptk.few 0b
        }
-       /*
-               if (__deregister_frame_info)
-                 __deregister_frame_info(__EH_FRAME_BEGIN__)
-       */
-       { .mmi
-         mov gp = loc2
-         ;;
-         addl r16 = @ltoff(@fptr(__deregister_frame_info#)), gp
-         addl out0 = @ltoff(__EH_FRAME_BEGIN__#), gp
-         ;;
-       }
-       { .mmi
-         ld8 r16 = [r16]
-         ld8 out0 = [out0]
-         ;;
-       }
-       { .mmi
-         cmp.ne p7, p0 = r0, r16
-         ;;
-(p7)     ld8 r18 = [r16], 8
-         ;;
-       }
-       { .mib
-(p7)     ld8 gp = [r16]
-(p7)     mov b6 = r18
-(p7)     br.call.sptk.many b0 = b6
-       }
        { .mii
          mov gp = loc2
          mov b0 = loc1
@@ -232,66 +199,6 @@ __do_global_dtors_aux:
        }
        .endp   __do_global_dtors_aux#
 
-       .proc   __do_frame_setup#
-__do_frame_setup:
-       /*
-               if (__register_frame_info)
-                 __register_frame_info(__EH_FRAME_BEGIN__)
-       */
-       { .mii
-         alloc loc2 = ar.pfs, 0, 3, 2, 0
-         addl r16 = @ltoff(@fptr(__register_frame_info#)), gp
-         addl out0 = @ltoff(__EH_FRAME_BEGIN__#), gp
-       }
-       /* frame_object.pc_base = segment_base_offset;
-          pc_base is at offset 0 within frame_object.  */
-.Lsegrel_ref:
-       { .mmi
-         addl out1 = @ltoff(frame_object#), gp
-         ;;
-         addl r2 = @gprel(segrel_ofs#), gp
-         mov r3 = ip
-         ;;
-       }
-       { .mmi
-         ld8 r2 = [r2]
-         ld8 r16 = [r16]
-         mov loc0 = b0
-         ;;
-       }
-       { .mii
-         ld8 out1 = [out1]
-         cmp.ne p7, p0 = r0, r16
-         sub r3 = r3, r2
-         ;;
-       }
-       { .mmi
-         st8 [out1] = r3 
-(p7)     ld8 r18 = [r16], 8
-         mov loc1 = gp
-         ;;
-       }
-       { .mfb
-         ld8 out0 = [out0]  
-       }
-       { .mib
-(p7)     ld8 gp = [r16]
-(p7)     mov b6 = r18
-(p7)     br.call.sptk.many b0 = b6
-       }
-       { .mii
-         mov gp = loc1
-         mov b0 = loc0
-         mov ar.pfs = loc2
-       }
-       { .bbb
-         br.ret.sptk.many b0
-         ;;
-       }
-       .endp   __do_frame_setup#
-
 #ifdef SHARED
 .weak __cxa_finalize#
 #endif
-.weak __deregister_frame_info#
-.weak __register_frame_info#
index 07b71ea..81f9019 100644 (file)
@@ -26,9 +26,6 @@ __CTOR_END__:
 __DTOR_END__:
        data8   0
 
-.section .IA_64.unwind
-__EH_FRAME_END__:
-
 /*
  * Fragment of the ELF _init routine that invokes our dtor cleanup.
  *
@@ -110,54 +107,3 @@ __do_global_ctors_aux:
          ;;
        }
        .endp __do_global_ctors_aux#
-
-.section .init,"ax","progbits"
-       { .mlx
-         movl r2 = @gprel(__do_frame_setup_aux#)
-         ;;
-       }
-       { .mii
-         nop.m 0
-         add r2 = r2, gp
-         ;;
-         mov b6 = r2
-       }
-       { .bbb
-         br.call.sptk.many b0 = b6
-         ;;
-        }
-
-.text
-       .align 16
-       .proc   __do_frame_setup_aux#
-__do_frame_setup_aux:
-       /*
-               if (__register_frame_info_aux)
-                 __register_frame_info_aux(__EH_FRAME_END__)
-       */
-       alloc loc0 = ar.pfs, 0, 3, 1, 0
-       addl r14 = @ltoff(@fptr(__register_frame_info_aux#)), gp
-       mov loc1 = b0
-       ;;
-       ld8 r15 = [r14]
-       addl r16 = @ltoff(__EH_FRAME_END__#), gp
-       mov loc2 = gp
-       ;;
-       cmp.eq p6, p7 = 0, r15
-       (p6) br.cond.dptk 1f
-       ld8 r8 = [r15], 8
-       ld8 out0 = [r16]
-       ;;
-       ld8 gp = [r15]
-       mov b6 = r8
-       ;;
-       br.call.sptk.many b0 = b6
-       ;;
-1:
-       mov gp = loc2
-       mov ar.pfs = loc0
-       mov b0 = loc1
-       br.ret.sptk.many b0
-       .endp   __do_frame_setup_aux#
-
-.weak __register_frame_info_aux#
diff --git a/gcc/config/ia64/fde-glibc.c b/gcc/config/ia64/fde-glibc.c
new file mode 100644 (file)
index 0000000..0948495
--- /dev/null
@@ -0,0 +1,141 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@cygnus.com>.
+
+   This file is part of GNU CC.
+
+   GNU CC 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.
+
+   GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with other files,
+   some of which are compiled with GCC, to produce an executable,
+   this library does not by itself cause the resulting executable
+   to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Locate the FDE entry for a given address, using glibc ld.so routines
+   to avoid register/deregister calls at DSO load/unload.  */
+
+#include <stdlib.h>
+#include <link.h>
+#include <bits/libc-lock.h>
+#include "frame-ia64.h"
+
+
+/* Initialized by crtbegin from the main application.  */
+extern Elf64_Ehdr *__ia64_app_header;
+
+/* ??? A redeclaration of the lock in ld.so.  Perhaps this should
+   appear in <link.h> in a new glibc version.  */
+__libc_lock_define (extern, _dl_load_lock)
+
+/* ??? _dl_load_lock is not exported from glibc 2.1, but it is 
+   from glibc 2.2.  Remove this when folks have migrated.  */
+#pragma weak _dl_load_lock
+
+/* This always exists, even in a static application.  */
+extern struct link_map *_dl_loaded;
+
+static fde *
+find_fde_for_dso (Elf64_Addr pc, Elf64_Ehdr *ehdr)
+{
+  Elf64_Phdr *phdr, *p_unwind;
+  long n, match;
+  Elf64_Addr load_base, seg_base;
+  fde *f;
+
+  /* Verify that we are looking at an ELF header.  */
+  if (ehdr->e_ident[0] != 0x7f
+      || ehdr->e_ident[1] != 'E'
+      || ehdr->e_ident[2] != 'L'
+      || ehdr->e_ident[3] != 'F'
+      || ehdr->e_ident[EI_CLASS] != ELFCLASS64
+      || ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+      || ehdr->e_machine != EM_IA_64)
+    abort ();
+
+  match = 0;
+  phdr = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);
+  load_base = (ehdr->e_type == ET_DYN ? (Elf64_Addr)ehdr : 0);
+  p_unwind = NULL;
+
+  /* See if PC falls into one of the loaded segments.  Find the unwind
+     segment at the same time.  */
+  for (n = ehdr->e_phnum; --n >= 0; phdr++)
+    {
+      if (phdr->p_type == PT_LOAD)
+       {
+         Elf64_Addr vaddr = phdr->p_vaddr + load_base;
+         if (pc >= vaddr && pc < vaddr + phdr->p_memsz)
+           match = 1;
+       }
+      else if (phdr->p_type == PT_IA_64_UNWIND)
+       p_unwind = phdr;
+    }
+  if (!match || !p_unwind)
+    return NULL;
+
+  /* Search for the FDE within the unwind segment.  */
+  /* ??? Ideally ld would have sorted this for us by address.  Until
+     that's fixed, we must do a linear search.  */
+
+  f = (fde *) (p_unwind->p_vaddr + load_base);
+  seg_base = (Elf64_Addr) ehdr;
+  for (n = p_unwind->p_memsz / sizeof (fde); --n >= 0; ++f)
+    if (pc >= f->start_offset + seg_base && pc < f->end_offset + seg_base)
+      return f;
+
+  return NULL;
+}
+
+/* Return a pointer to the FDE for the function containing PC.  */
+fde *
+__ia64_find_fde (void *pc, void **pc_base)
+{
+  fde *ret;
+  struct link_map *map;
+
+  /* Check the main application first, hoping that most of the user's
+     code is there instead of in some library.  */
+  ret = find_fde_for_dso ((Elf64_Addr)pc, __ia64_app_header);
+  if (ret)
+    {
+      *pc_base = __ia64_app_header;
+      return ret;
+    }
+
+  /* Glibc is probably unique in that we can (with certain restrictions)
+     dynamicly load libraries into staticly linked applications.  Thus
+     we _always_ check _dl_loaded.  */
+
+  if (&_dl_load_lock)
+    __libc_lock_lock (_dl_load_lock);
+
+  for (map = _dl_loaded; map ; map = map->l_next)
+    {
+      /* Skip the main application's entry.  */
+      if (map->l_name[0] == 0)
+       continue;
+      ret = find_fde_for_dso ((Elf64_Addr)pc, (Elf64_Ehdr *)map->l_addr);
+      if (ret)
+       break;
+    }
+
+  if (&_dl_load_lock)
+    __libc_lock_unlock (_dl_load_lock);
+
+  *pc_base = (void *)(map ? map->l_addr : 0);
+  return ret;
+}
index 5d5e3a3..cd0f21c 100644 (file)
@@ -40,32 +40,14 @@ Boston, MA 02111-1307, USA.  */
 /* ??? This is not a good solution, since prototypes may be required in
    some cases for correct code.  See also libgcc2.c/crtstuff.c.  */
 #ifndef inhibit_libc
-/* fixproto guarantees these system headers exist. */
 #include <stdlib.h>
 #include <unistd.h>
-
 #else
 #include <stddef.h>
-#ifndef malloc
-extern void *malloc (size_t);
-#endif
-#ifndef free
-extern void free (void *);
-#endif
 #endif
 
 #include "defaults.h"
-#include "gthr.h"
-
-/* Define a mutex for frame information modification. */
-#ifdef __GTHREAD_MUTEX_INIT
-static __gthread_mutex_t object_mutex = __GTHREAD_MUTEX_INIT;
-#else
-static __gthread_mutex_t object_mutex;
-#endif
-
-/* This is undefined below if we need it to be an actual function.  */
-#define init_object_mutex_once()
+#include "frame-ia64.h"
 
 /* Some types used by the DWARF 2 spec.  */
 
@@ -75,141 +57,8 @@ typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
 typedef          int  saddr __attribute__ ((mode (pointer)));
 typedef unsigned char ubyte;
 
-static void bad_record (unsigned char*, int) __attribute__ ((__noreturn__));
-
-#if __GTHREADS
-#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
-
-/* Helper for init_object_mutex_once.  */
-
-static void
-init_object_mutex (void)
-{
-  __GTHREAD_MUTEX_INIT_FUNCTION (&object_mutex);
-}
-
-/* Call this to arrange to initialize the object mutex.  */
-
-#undef init_object_mutex_once
-static void
-init_object_mutex_once (void)
-{
-  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
-  __gthread_once (&once, init_object_mutex);
-}
-
-#endif /* __GTHREAD_MUTEX_INIT_FUNCTION */
-#endif /* __GTHREADS */
-
-/* This structure represents a single unwind table entry.  We lie and say
-   its the dwarf_fde structure to use the common object in frame.h */
-
-typedef struct dwarf_fde
-{
-  long start_offset;
-  long end_offset;
-  long unwind_offset;
-} unwind_table_entry;
-  
-/* Defining dwarf_fde allows us to use the common object registration.  */
-typedef unwind_table_entry dwarf_fde;
-typedef unwind_table_entry fde;
-
 #include "frame.h" 
 
-static struct object *objects = NULL;
-
-static inline saddr
-fde_compare (fde *x, fde *y)
-{
-  return (saddr)x->start_offset - (saddr)y->start_offset;
-}
-
-#include "frame.c"
-
-/* called from crtend.o to register the end of the unwind info for an
-   object.  */
-void
-__register_frame_info_aux (struct dwarf_fde *end)
-{
-  objects->fde_end = end;
-}
-  
-static void
-frame_init (struct object *ob)
-{
-  int count = 0;  /* reserve one for the dummy last entry.  */
-  fde_accumulator accu;
-  unwind_table_entry *ptr = ob->fde_begin;
-
-  if (ptr == 0)
-    return;
-
-  /* Count the number of entries objects.  */
-  for ( ; ptr < ob->fde_end; ptr++)
-    count++;
-
-  ob->pc_begin = (void *)(uaddr) - 1;
-  ob->pc_end = 0;
-
-  start_fde_sort (&accu, count);
-  for (ptr = ob->fde_begin; ptr < ob->fde_end; ptr++)
-  {
-    if (ob->pc_base + ptr->start_offset < ob->pc_begin)
-      ob->pc_begin = ob->pc_base + ptr->start_offset;
-    if (ob->pc_base + ptr->end_offset > ob->pc_end)
-      ob->pc_end = ob->pc_base + ptr->end_offset;
-    fde_insert (&accu, (fde *)ptr);
-  }
-
-  ob->fde_array = end_fde_sort (&accu, count);
-  ob->count = count;
-}
-
-/* Return a pointer to the FDE for the function containing PC.  */
-
-static fde *
-find_fde (void *pc, void **pc_base)
-{
-  struct object *ob;
-  size_t lo, hi;
-
-  *pc_base = NULL;
-
-  init_object_mutex_once ();
-  __gthread_mutex_lock (&object_mutex);
-
-  for (ob = objects; ob; ob = ob->next)
-    {
-      if (ob->pc_begin == 0)
-       frame_init (ob);
-      if (pc >= ob->pc_begin && pc < ob->pc_end)
-       break;
-    }
-
-  __gthread_mutex_unlock (&object_mutex);
-
-  if (ob == 0)
-    return 0;
-
-  *pc_base = ob->pc_base;
-  /* Standard binary search algorithm.  */
-  for (lo = 0, hi = ob->count; lo < hi; )
-    {
-      size_t i = (lo + hi) / 2;
-      fde *f = ob->fde_array[i];
-
-      if (pc - ob->pc_base < f->start_offset)
-       hi = i;
-      else if (pc - ob->pc_base >= f->end_offset)
-       lo = i + 1;
-      else
-       return f;
-    }
-
-  return 0;
-}
-
 /* Decode the unsigned LEB128 constant at BUF and return it. The value at
    MEM is updated to reflect the next position in the buffer.  */
 
@@ -232,60 +81,9 @@ read_uleb128 (unsigned char **mem)
   return result;
 }
 
-static void
-bad_record (ptr, offset)
-     unsigned char *ptr;
-     int offset;
-{
-#if 0
-  printf ("Bad unwind record format value '%x' at offset %d in record %p\n",
-         *(ptr + offset), offset , ptr);
-#endif  
-  abort ();
-}
-
-static unsigned char *read_R_record (unwind_record *, unsigned char, unsigned char *);
-static unsigned char *read_X_record (unwind_record *, unsigned char, unsigned char *);
-static unsigned char *read_B_record (unwind_record *, unsigned char, unsigned char *);
-static unsigned char *read_P_record (unwind_record *, unsigned char, unsigned char *, unwind_record *);
-
-
-/* This routine will determine what type of record the memory pointer
-   is refering to, and fill in the appropriate fields for that record type. 
-   HEADER is a pointer to the last region header unwind record.
-   DATA is a pointer to an unwind record which will be filled in.
-   PTR is a pointer to the current location in the unwind table where we
-   will read the next record from.  
-   The return value is the start of the next record.  */
-
-extern unsigned char *
-get_unwind_record (header, data, ptr)
-     unwind_record *header;
-     unwind_record *data;
-     unsigned char *ptr;
-{
-  unsigned char val = *ptr++;
-
-  if ((val & 0x80) == 0)
-    {
-      return read_R_record (data, val, ptr);
-    }
-
-  if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
-    return read_X_record (data, val, ptr);
-
-  if (header->type != body)
-    return read_P_record (data, val, ptr, header);
-  else
-    return read_B_record (data, val, ptr);
-}
-
 
 static unsigned char *
-read_R_record (data, val, ptr)
-     unwind_record *data;
-     unsigned char val;
-     unsigned char *ptr;
+read_R_record (unwind_record *data, unsigned char val, unsigned char *ptr)
 {
   if ((val & 0x40) == 0)
     {
@@ -321,17 +119,15 @@ read_R_record (data, val, ptr)
         if (val == 1)
          data->type = body;
        else
-         bad_record (ptr - 1, 0);
+         abort ();
       data->record.r.rlen = read_uleb128 (&ptr);
       return ptr;
     }
-  bad_record (ptr - 1, 0);
+  abort ();
 }
 
 static void
-process_a_b_reg_code(data, val)
-     unwind_record *data;
-     unsigned char val;
+process_a_b_reg_code(unwind_record *data, unsigned char val)
 {
   int code = (val & 0x60) >> 5;
   int reg = (val & 0x1f);
@@ -354,10 +150,7 @@ process_a_b_reg_code(data, val)
 }
 
 static unsigned char *
-read_X_record (data, val, ptr)
-     unwind_record *data;
-     unsigned char val;
-     unsigned char *ptr;
+read_X_record (unwind_record *data, unsigned char val, unsigned char *ptr)
 {
   unsigned long tmp;
   int byte1, byte2;
@@ -407,7 +200,7 @@ read_X_record (data, val, ptr)
                data->record.x.treg = BR_REG (treg);
                break;
              case 3:
-               bad_record (ptr - 3, 2);
+               abort ();
            }
          data->record.x.t = read_uleb128 (&ptr);
         }
@@ -431,16 +224,13 @@ read_X_record (data, val, ptr)
          }     
        return ptr;
       default:
-       bad_record (ptr - 1, 0);
+       abort ();
     }
   return NULL;
 }
 
 static unsigned char *
-read_B_record (data, val, ptr)
-     unwind_record *data;
-     unsigned char val;
-     unsigned char *ptr;
+read_B_record (unwind_record *data, unsigned char val, unsigned char *ptr)
 {
   if ((val & 0xc0) == 0x80)
     {
@@ -486,21 +276,21 @@ read_B_record (data, val, ptr)
       data->record.b.label = read_uleb128 (&ptr);
       return ptr;
     }
-
-  bad_record (ptr - 1, 0);
-
+  abort ();
 }
 
 /* This array is used to set the TYPE field for format P3.  */
-static unw_record_type P3_record_types[] = {
+static unw_record_type const P3_record_types[] = {
   psp_gr, rp_gr, pfs_gr, preds_gr, unat_gr, lc_gr, rp_br, rnat_gr,
-  bsp_gr, bspstore_gr, fpsr_gr, priunat_gr };
+  bsp_gr, bspstore_gr, fpsr_gr, priunat_gr
+};
 
 /* This array is used to set the TYPE field for format P7.  */
-static unw_record_type P7_record_types[] = {
+static unw_record_type const P7_record_types[] = {
   mem_stack_f, mem_stack_v, spill_base, psp_sprel, rp_when, rp_psprel,
   pfs_when, pfs_psprel, preds_when, preds_psprel, lc_when, lc_psprel,
-  unat_when, unat_psprel, fpsr_when, fpsr_psprel };
+  unat_when, unat_psprel, fpsr_when, fpsr_psprel
+};
 
 /* These values and the array are used to determine which additional ULEB128
    fields are required for the P7 format.  */
@@ -508,36 +298,36 @@ static unw_record_type P7_record_types[] = {
 #define P7_T           1
 #define P7_PSPOFF       2
 #define P7_SPOFF       3
-static unsigned char P7_additional_fields [] = {
+static unsigned char const P7_additional_fields [] = {
    P7_T_SIZE, P7_T, P7_PSPOFF, P7_SPOFF, P7_T, P7_PSPOFF, 
-   P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF };
+   P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF, P7_T, P7_PSPOFF
+};
 
 /* This array is used to set the TYPE field for format P8. 
    Note that entry 0 is not used in this array, so it is filled with
    rp_spel for completely arbitrary reasons.  */
-static unw_record_type P8_record_types[] = {
+static unw_record_type const P8_record_types[] = {
   rp_sprel, rp_sprel, pfs_sprel, preds_sprel, lc_sprel, unat_sprel, fpsr_sprel, 
   bsp_when, bsp_psprel, bsp_sprel, bspstore_when, bspstore_psprel,
   bspstore_sprel, rnat_when, rnat_psprel, rnat_sprel, priunat_when_gr,
-  priunat_psprel, priunat_sprel, priunat_when_mem };
+  priunat_psprel, priunat_sprel, priunat_when_mem
+};
 
 /* These values and the array are used to determine which additional ULEB128
    fields are required for the P8 format.  */
 #define P8_T           0
 #define P8_PSPOFF       1
 #define P8_SPOFF       2
-static unsigned char P8_additional_fields [] = {
+static unsigned char const P8_additional_fields [] = {
   P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF, P8_SPOFF,
   P8_T, P8_PSPOFF, P8_SPOFF, P8_T, P8_PSPOFF, P8_SPOFF,
-  P8_T, P8_PSPOFF, P8_SPOFF, P8_T, P8_PSPOFF, P8_SPOFF, P8_T };
+  P8_T, P8_PSPOFF, P8_SPOFF, P8_T, P8_PSPOFF, P8_SPOFF, P8_T
+};
 
 
 static unsigned char *
-read_P_record (data, val, ptr, header)
-     unwind_record *data;
-     unsigned char val;
-     unsigned char *ptr;
-     unwind_record *header;
+read_P_record (unwind_record *data, unsigned char val, unsigned char *ptr,
+              unwind_record *header)
 {
   if ((val & 0xe0) == 0x80)
     {
@@ -553,7 +343,7 @@ read_P_record (data, val, ptr, header)
       int byte1;
       data->type = br_gr;
       byte1 = *ptr++;
-      data->record.p.brmask = (val & 0x0f) << 1 + (byte1 >> 7);
+      data->record.p.brmask = ((val & 0x0f) << 1) + (byte1 >> 7);
       data->record.p.gr = GR_REG (byte1 & 0x7f);
       return ptr;
     }
@@ -569,7 +359,7 @@ read_P_record (data, val, ptr, header)
       else
         data->record.p.gr = GR_REG (byte1 & 0x7f);
       if (r > 11)
-        bad_record (ptr - 2, 0);
+        abort ();
       return ptr;
     }
 
@@ -579,8 +369,7 @@ read_P_record (data, val, ptr, header)
       int size = (header->record.r.rlen * 2 + 7) / 8;
 
       data->type = spill_mask;
-      data->record.p.imask = (unsigned char *) malloc (size);
-      memcpy (data->record.p.imask, ptr, size);
+      data->record.p.imask = ptr;
       return ptr+size;
     }
 
@@ -664,24 +453,49 @@ read_P_record (data, val, ptr, header)
   
   if (val == UNW_P10)
     {
+#if 0
       /* P10 format.  */
-      int abi = *ptr++;
-      int context = *ptr++;
+      int abi = ptr[0];
+      int context = ptr[1];
       /* TODO. something about abi entries.  */
-      return ptr;
+#endif
+      return ptr + 2;
     }
 
   return ptr;
 }
 
+/* This routine will determine what type of record the memory pointer
+   is refering to, and fill in the appropriate fields for that record type. 
+   HEADER is a pointer to the last region header unwind record.
+   DATA is a pointer to an unwind record which will be filled in.
+   PTR is a pointer to the current location in the unwind table where we
+   will read the next record from.  
+   The return value is the start of the next record.  */
+
+static unsigned char *
+get_unwind_record (unwind_record *header, unwind_record *data,
+                  unsigned char *ptr)
+{
+  unsigned char val = *ptr++;
+
+  if ((val & 0x80) == 0)
+    return read_R_record (data, val, ptr);
+
+  if (val == UNW_X1 || val == UNW_X2 || val == UNW_X3 || val == UNW_X4)
+    return read_X_record (data, val, ptr);
+
+  if (header->type != body)
+    return read_P_record (data, val, ptr, header);
+  else
+    return read_B_record (data, val, ptr);
+}
 \f
 /* Frame processing routines.  */
 
 /* Initialize a single register structure.  */
 static inline void 
-init_ia64_reg_loc (reg, size)
-     ia64_reg_loc *reg;
-     short size;
+init_ia64_reg_loc (ia64_reg_loc *reg, short size)
 {
   reg->when = -1;
   reg->loc_type = IA64_UNW_LOC_TYPE_NONE;
@@ -691,8 +505,7 @@ init_ia64_reg_loc (reg, size)
 
 /* Iniitialize an entire frame to the default of nothing.  */
 static void
-init_ia64_unwind_frame (frame) 
-     ia64_frame_state *frame;
+init_ia64_unwind_frame (ia64_frame_state *frame) 
 {
   int x;
   
@@ -726,15 +539,13 @@ init_ia64_unwind_frame (frame)
    the return value is a pointer to the start of the next descriptor.  */
 
 static void *
-execute_one_ia64_descriptor (addr, frame, len)
-     void *addr;
-     ia64_frame_state *frame;
-     long *len;
+execute_one_ia64_descriptor (void *addr, ia64_frame_state *frame, long *len)
 {
-  unwind_record r;
   /* The last region_header.  Needed to distinguish between prologue and body
      descriptors.  Also needed for length of P4 format.  */
   static unwind_record region_header;
+
+  unwind_record r;
   ia64_reg_loc *loc_ptr = NULL;
   int grmask = 0, frmask = 0;
 
@@ -750,7 +561,7 @@ execute_one_ia64_descriptor (addr, frame, len)
       case prologue:
       case body:
        *len = r.record.r.rlen;
-       memcpy (&region_header, &r, sizeof (unwind_record));
+       region_header = r;
        break;
       case prologue_gr:
         {
@@ -783,7 +594,7 @@ execute_one_ia64_descriptor (addr, frame, len)
              frame->pr.loc_type  = IA64_UNW_LOC_TYPE_GR;
              frame->pr.l.regno = reg++;
            }
-         memcpy (&region_header, &r, sizeof (unwind_record));
+         region_header = r;
          break;
        }
       case mem_stack_f:
@@ -1048,7 +859,8 @@ rse_address_add(unsigned char *addr, int nslots)
 
   new_addr = addr + 8 * (nslots + mandatory_nat_slots);
 
-  if (((long)new_addr >> 9)  != ((long)(addr + 8 * 64 * mandatory_nat_slots) >> 9))
+  if (((long)new_addr >> 9)
+      != ((long)(addr + 8 * 64 * mandatory_nat_slots) >> 9))
     new_addr += 8 * direction;
 
   if (IS_NaT_COLLECTION_ADDR(new_addr))
@@ -1061,9 +873,7 @@ rse_address_add(unsigned char *addr, int nslots)
 /* Normalize a record to originate in either a register or memory 
    location.  */
 static void
-normalize_reg_loc (frame, reg)
-     ia64_frame_state *frame;
-     ia64_reg_loc *reg;
+normalize_reg_loc (ia64_frame_state *frame, ia64_reg_loc *reg)
 {
   unsigned char *tmp;
   switch (reg->loc_type)
@@ -1122,10 +932,8 @@ normalize_reg_loc (frame, reg)
    It is executed if it is exectued at START time. It is NOT
    executed if it happens at END time. */
 static void 
-maybe_normalize_reg_loc (frame, reg, start, end)
-     ia64_frame_state *frame;
-     ia64_reg_loc *reg;
-     int start, end;
+maybe_normalize_reg_loc (ia64_frame_state *frame, ia64_reg_loc *reg,
+                        long start, long end)
 {
   if (reg->loc_type != IA64_UNW_LOC_TYPE_NONE 
       && reg->when >= start && reg->when < end)
@@ -1135,8 +943,7 @@ maybe_normalize_reg_loc (frame, reg, start, end)
 
 /* Only works for 8 byte or less registers.  */
 void *
-__get_real_reg_value (reg)
-     ia64_reg_loc *reg;
+__get_real_reg_value (ia64_reg_loc *reg)
 {
   if (reg->loc_type == IA64_UNW_LOC_TYPE_MEM)
     return *((void **)(reg->l.mem));
@@ -1147,9 +954,7 @@ __get_real_reg_value (reg)
 }
 
 void
-__set_real_reg_value (reg, val) 
-     ia64_reg_loc *reg;
-     void *val;
+__set_real_reg_value (ia64_reg_loc *reg, void *val) 
 {
   if (reg->loc_type == IA64_UNW_LOC_TYPE_MEM)
     {
@@ -1161,9 +966,7 @@ __set_real_reg_value (reg, val)
 }
 
 static void
-copy_reg_value (src, dest)
-     ia64_reg_loc *src;
-     ia64_reg_loc *dest;
+copy_reg_value (ia64_reg_loc *src, ia64_reg_loc *dest)
 {
   void **p = dest->l.mem;
   if (src->loc_type == IA64_UNW_LOC_TYPE_NONE)
@@ -1190,9 +993,7 @@ copy_reg_value (src, dest)
 /* Copy the values of any relevant saved registers in one frame 
    to another for unwinding.  */
 void 
-__copy_saved_reg_state (dest, src)
-     ia64_frame_state *dest;
-     ia64_frame_state *src;
+__copy_saved_reg_state (ia64_frame_state *dest, ia64_frame_state *src)
 {
   int x;
   for (x = 0; x < 4 ; x++)
@@ -1213,9 +1014,7 @@ __copy_saved_reg_state (dest, src)
 
 
 static void 
-process_state_between (frame, start, end)
-     ia64_frame_state *frame;
-     int start, end;
+process_state_between (ia64_frame_state *frame, long start, long end)
 {
   int x;
   /* PSP, RP, SP, and PFS are handled seperately from here. */
@@ -1253,9 +1052,7 @@ process_state_between (frame, start, end)
      that has a WHEN record beyond this time is cleared since it
      isn't relevant.  */
 static void
-frame_translate (frame, unwind_time)
-     ia64_frame_state *frame;
-     long unwind_time;
+frame_translate (ia64_frame_state *frame, long unwind_time)
 {
   /* ??? Is this supposed to mark the end of the stack?  */
   if (frame->rp.loc_type == IA64_UNW_LOC_TYPE_NONE)
@@ -1324,11 +1121,8 @@ frame_translate (frame, unwind_time)
    frame is the frame_state structure to be set up.
    Returns a pointer to the unwind info pointer for the frame.  */
 unwind_info_ptr *
-__build_ia64_frame_state (pc, frame, bsp, sp, pc_base_ptr)
-     unsigned char *pc;
-     ia64_frame_state *frame;
-     void *bsp, *sp;
-     void **pc_base_ptr;
+__build_ia64_frame_state (unsigned char *pc, ia64_frame_state *frame,
+                         void *bsp, void *sp, void **pc_base_ptr)
 {
   long len;
   int region_offset = 0;
@@ -1340,7 +1134,7 @@ __build_ia64_frame_state (pc, frame, bsp, sp, pc_base_ptr)
   int pc_offset;
   struct unwind_info_ptr *unw_info_ptr;
 
-  entry = find_fde (pc, &pc_base);
+  entry = __ia64_find_fde (pc, &pc_base);
   if (!entry)
     return 0;
 
@@ -1378,8 +1172,7 @@ __build_ia64_frame_state (pc, frame, bsp, sp, pc_base_ptr)
 
 /* Given an unwind info pointer, return the personality routine.  */
 void *
-__get_personality (ptr)
-     unwind_info_ptr *ptr;
+__get_personality (unwind_info_ptr *ptr)
 {
   void **p;
 
@@ -1396,8 +1189,7 @@ __get_personality (ptr)
 
 /* Given an unwind info pointer, return the exception table.  */
 void *
-__get_except_table (ptr)
-     unwind_info_ptr *ptr;
+__get_except_table (unwind_info_ptr *ptr)
 {
   void *table;
 
@@ -1415,9 +1207,7 @@ __get_except_table (ptr)
 
 /* Given a PFS value, and the current BSp, calculate the BSp of the caller.  */
 void *
-__calc_caller_bsp (pfs, bsp)
-     long pfs;
-     unsigned char *bsp;
+__calc_caller_bsp (long pfs, unsigned char *bsp)
 {
   int size_of_locals;
 
@@ -1459,6 +1249,8 @@ ia64_backtrace_helper (void **array, ia64_frame_state *throw_frame,
 }
 
 /* This is equivalent to glibc's backtrace(). */
+
+extern int __ia64_backtrace (void **array, int size);
   
 int
 __ia64_backtrace (void **array, int size)
@@ -1478,195 +1270,3 @@ __ia64_backtrace (void **array, int size)
   return ia64_backtrace_helper (array, &my_frame, &originator, bsp,
                                stack_pointer, size);
 }
-
-\f
-
-#ifndef inhibit_libc
-
-#if 0
-#undef NULL;
-#include <stdio.h>
-
-/* Routines required to generate debug info for the ia64
-   unwind descriptors.  */
-
-static unsigned char *record_name[] = { 
-  "prologue", "prologue_gr", "body", "mem_stack_f", "mem_stack_v", "psp_gr", 
-  "psp_sprel", "rp_when", "rp_gr", "rp_br", "rp_psprel", "rp_sprel", 
-  "pfs_when", "pfs_gr", "pfs_psprel", "pfs_sprel", "preds_when", "preds_gr", 
-  "preds_psprel", "preds_sprel", "fr_mem", "frgr_mem", "gr_gr", "gr_mem", 
-  "br_mem", "br_gr", "spill_base", "spill_mask", "unat_when", "unat_gr", 
-  "unat_psprel", "unat_sprel", "lc_when", "lc_gr", "lc_psprel", "lc_sprel", 
-  "fpsr_when", "fpsr_gr", "fpsr_psprel", "fpsr_sprel", "priunat_when_gr", 
-  "priunat_when_mem", "priunat_gr", "priunat_psprel", "priunat_sprel", 
-  "bsp_when", "bsp_gr", "bsp_psprel", "bsp_sprel", "bspstore_when", 
-  "bspstore_gr", "bspstore_psprel", "bspstore_sprel", "rnat_when", "rnat_gr", 
-  "rnat_psprel", "rnat_sprel", "epilogue", "label_state", "copy_state", 
-  "spill_psprel", "spill_sprel", "spill_reg", "spill_psprel_p", 
-  "spill_sprel_p","spill_reg_p" 
-};
-
-
-
-static void
-print_record (f, ptr)
-     FILE *f;
-     unwind_record *ptr;
-{
-  fprintf (f, " %s ",record_name[ptr->type]);
-  switch (ptr->type) 
-    {
-      case prologue:
-      case body:
-       fprintf (f, "(R1) rlen = %d", ptr->record.r.rlen);
-       break;
-      case prologue_gr:
-       fprintf (f, "(R2) rlen = %d : ", ptr->record.r.rlen);
-       fprintf (f, "grmask = %x, grsave = r%d", ptr->record.r.mask, 
-                                                ptr->record.r.grsave);
-       break;
-      case mem_stack_f:
-       fprintf (f, "(P7) t = %d, size = %d", ptr->record.p.t, 
-                                        ptr->record.p.size);
-       break;
-      case mem_stack_v:
-       fprintf (f, "(P7) t = %d", ptr->record.p.t);
-       break;
-      case psp_gr:
-      case rp_gr:
-      case pfs_gr:
-      case preds_gr:
-      case unat_gr:
-      case lc_gr:
-      case fpsr_gr:
-      case priunat_gr:
-      case bsp_gr:
-      case bspstore_gr:
-      case rnat_gr:
-       fprintf (f, "(P3) r%d", ptr->record.p.gr);
-       break;
-      case rp_br:
-       fprintf (f, "(P3) b%d", ptr->record.p.br);
-       break;
-      case psp_sprel:
-       fprintf (f, "(P7) spoff = %d", ptr->record.p.spoff);
-       break;
-      case rp_when:
-      case pfs_when:
-      case preds_when:
-      case unat_when:
-      case lc_when:
-      case fpsr_when:
-       fprintf (f, "(P7) t = %d", ptr->record.p.t);
-       break;
-      case rp_psprel:
-      case pfs_psprel:
-      case preds_psprel:
-      case unat_psprel:
-      case lc_psprel:
-      case fpsr_psprel:
-      case spill_base:
-       fprintf (f, "(P7) pspoff = %d", ptr->record.p.pspoff, 0);
-       break;
-      case rp_sprel:
-      case pfs_sprel:
-      case preds_sprel:
-      case unat_sprel:
-      case lc_sprel:
-      case fpsr_sprel:
-      case priunat_sprel:
-      case bsp_sprel:
-      case bspstore_sprel:
-      case rnat_sprel:
-       fprintf (f, "(P8) spoff = %d", ptr->record.p.spoff);
-       break;
-      case fr_mem:
-      case gr_mem:
-       fprintf (f, "(P6) rmask = %x", ptr->record.p.rmask);
-       break;
-      case frgr_mem:
-       fprintf (f, "(P5) grmask = %x,  frmask = %x", ptr->record.p.grmask, 
-                                                ptr->record.p.frmask);
-       break;
-      case gr_gr:
-       fprintf (f, "(P9) grmask = %x  gr = r%d\n", ptr->record.p.grmask, 
-                                              ptr->record.p.gr);
-       break;
-      case br_mem:
-       fprintf (f, "(P1) brmask = %x", ptr->record.p.brmask);
-       break;
-      case br_gr:
-       fprintf (f, "(P2) brmask = %x,  gr = r%d", ptr->record.p.brmask, 
-                                             ptr->record.p.gr);
-       break;
-      case spill_mask:
-       fprintf (f, "spill mask....  unimplemented");
-       break;
-      case priunat_when_gr:
-      case priunat_when_mem:
-      case bsp_when:
-      case bspstore_when:
-      case rnat_when:
-       fprintf (f, "(P8) t = %d\n", ptr->record.p.t);
-       break;
-      case priunat_psprel:
-      case bsp_psprel:
-      case bspstore_psprel:
-      case rnat_psprel:
-       fprintf (f, "(P8) pspoff = %d", ptr->record.p.pspoff);
-       break;
-      case epilogue:
-       fprintf (f, "epilogue record unimplemented.");
-       break;
-      case label_state:
-       fprintf (f, "label_state record unimplemented.");
-       break;
-      case copy_state:
-       fprintf (f, "copy_state record unimplemented.");
-       break;
-      case spill_psprel:
-      case spill_sprel:
-      case spill_reg:
-      case spill_psprel_p:
-      case spill_sprel_p:
-      case spill_reg_p:
-       fprintf (f, "spill_* record unimplemented.");
-       break;
-      default:
-       fprintf (f, "record_type_not_valid");
-       break;
-    }
-  fprintf (f, "\n");
-  
-}
-
-static void
-print_all_records (f, mem, size)
-     FILE *f;
-     unsigned char *mem;
-     int size;
-{
-  unsigned char *end = mem + size;
-  unwind_record r;
-  static unwind_record region_header;
-
-  fprintf (f, "UNWIND IMAGE:\n");
-  while (mem < end) 
-    {
-      mem = get_unwind_record (&region_header, &r, mem);
-      print_record (f, &r);
-      switch (r.type)
-       {
-       case prologue:
-       case body:
-       case prologue_gr:
-         memcpy (region_header, r, sizeof (unwind_record));
-         break;
-       default:
-         break;
-       }
-    }
-  fprintf (f, "--end unwind image--\n\n");
-}
-#endif /* If 0 */
-#endif /* inhibit_libc */
diff --git a/gcc/config/ia64/frame-ia64.h b/gcc/config/ia64/frame-ia64.h
new file mode 100644 (file)
index 0000000..d638ca3
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Contributed by Andrew MacLeod  <amacleod@cygnus.com>
+                  Andrew Haley  <aph@cygnus.com>
+
+   This file is part of GNU CC.
+
+   GNU CC 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.
+
+   GNU CC 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 GNU CC; see the file COPYING.  If not, write to
+   the Free Software Foundation, 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* This structure represents a single unwind table entry.  We lie and say
+   its the dwarf_fde structure to use the common object in frame.h */
+
+typedef struct dwarf_fde
+{
+  long start_offset;
+  long end_offset;
+  long unwind_offset;
+} unwind_table_entry;
+  
+/* Defining dwarf_fde allows us to use the common object registration.  */
+typedef unwind_table_entry dwarf_fde;
+typedef unwind_table_entry fde;
+
+extern fde *__ia64_find_fde (void *, void **);
diff --git a/gcc/config/ia64/t-glibc b/gcc/config/ia64/t-glibc
new file mode 100644 (file)
index 0000000..a105662
--- /dev/null
@@ -0,0 +1 @@
+LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
index b84df2b..cf21751 100755 (executable)
@@ -5059,7 +5059,7 @@ for machine in $build $host $target; do
                ;;
        ia64*-*-linux*)
                tm_file=ia64/linux.h
-               tmake_file="t-linux ia64/t-ia64"
+               tmake_file="t-linux ia64/t-ia64 ia64/t-glibc"
                target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
                if test x$enable_threads = xyes; then
                        thread_file='posix'
index e61abf3..3745fd6 100644 (file)
@@ -2046,7 +2046,7 @@ changequote([,])dnl
                ;;
        ia64*-*-linux*)
                tm_file=ia64/linux.h
-               tmake_file="t-linux ia64/t-ia64"
+               tmake_file="t-linux ia64/t-ia64 ia64/t-glibc"
                target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
                if test x$enable_threads = xyes; then
                        thread_file='posix'