diff options
author | Richard Henderson <rth@gcc.gnu.org> | 2000-10-03 20:08:50 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-10-03 20:08:50 -0700 |
commit | fee0225a383cdc396a720a2a8639d4fb99e7f084 (patch) | |
tree | 670b15daaad2d99fa60833fe8b45cc2f759a4318 | |
parent | 7e51098e709b1248a2334b7a19b6d27e6ce88cfc (diff) | |
download | gcc-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.asm | 131 | ||||
-rw-r--r-- | gcc/config/ia64/crtend.asm | 54 | ||||
-rw-r--r-- | gcc/config/ia64/fde-glibc.c | 141 | ||||
-rw-r--r-- | gcc/config/ia64/frame-ia64.c | 572 | ||||
-rw-r--r-- | gcc/config/ia64/frame-ia64.h | 36 | ||||
-rw-r--r-- | gcc/config/ia64/t-glibc | 1 | ||||
-rwxr-xr-x | gcc/configure | 2 | ||||
-rw-r--r-- | gcc/configure.in | 2 |
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 (®ion_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 (®ion_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 (®ion_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' |