aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2000-10-03 20:08:50 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-10-03 20:08:50 -0700
commitfee0225a383cdc396a720a2a8639d4fb99e7f084 (patch)
tree670b15daaad2d99fa60833fe8b45cc2f759a4318
parent7e51098e709b1248a2334b7a19b6d27e6ce88cfc (diff)
downloadgcc-fee0225a383cdc396a720a2a8639d4fb99e7f084.zip
gcc-fee0225a383cdc396a720a2a8639d4fb99e7f084.tar.gz
gcc-fee0225a383cdc396a720a2a8639d4fb99e7f084.tar.bz2
configure.in (ia64-linux): Add ia64/t-glibc.
* configure.in (ia64-linux) [tmake_file]: Add ia64/t-glibc. * 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. From-SVN: r36705
-rw-r--r--gcc/config/ia64/crtbegin.asm131
-rw-r--r--gcc/config/ia64/crtend.asm54
-rw-r--r--gcc/config/ia64/fde-glibc.c141
-rw-r--r--gcc/config/ia64/frame-ia64.c572
-rw-r--r--gcc/config/ia64/frame-ia64.h36
-rw-r--r--gcc/config/ia64/t-glibc1
-rwxr-xr-xgcc/configure2
-rw-r--r--gcc/configure.in2
8 files changed, 285 insertions, 654 deletions
diff --git a/gcc/config/ia64/crtbegin.asm b/gcc/config/ia64/crtbegin.asm
index 1a8bcf1..1b57a99 100644
--- a/gcc/config/ia64/crtbegin.asm
+++ b/gcc/config/ia64/crtbegin.asm
@@ -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#
diff --git a/gcc/config/ia64/crtend.asm b/gcc/config/ia64/crtend.asm
index 07b71ea..81f9019 100644
--- a/gcc/config/ia64/crtend.asm
+++ b/gcc/config/ia64/crtend.asm
@@ -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
index 0000000..0948495
--- /dev/null
+++ b/gcc/config/ia64/fde-glibc.c
@@ -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;
+}
diff --git a/gcc/config/ia64/frame-ia64.c b/gcc/config/ia64/frame-ia64.c
index 5d5e3a3..cd0f21c 100644
--- a/gcc/config/ia64/frame-ia64.c
+++ b/gcc/config/ia64/frame-ia64.c
@@ -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);
+}
/* 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);
}
-
-
-
-#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
index 0000000..d638ca3
--- /dev/null
+++ b/gcc/config/ia64/frame-ia64.h
@@ -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
index 0000000..a105662
--- /dev/null
+++ b/gcc/config/ia64/t-glibc
@@ -0,0 +1 @@
+LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
diff --git a/gcc/configure b/gcc/configure
index b84df2b..cf21751 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -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'
diff --git a/gcc/configure.in b/gcc/configure.in
index e61abf3..3745fd6 100644
--- a/gcc/configure.in
+++ b/gcc/configure.in
@@ -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'