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
This commit is contained in:
parent
7e51098e70
commit
fee0225a38
@ -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
|
||||
@ -193,33 +187,6 @@ __do_global_dtors_aux:
|
||||
{ .mfb
|
||||
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
|
||||
@ -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#
|
||||
|
@ -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#
|
||||
|
141
gcc/config/ia64/fde-glibc.c
Normal file
141
gcc/config/ia64/fde-glibc.c
Normal file
@ -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;
|
||||
}
|
@ -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 */
|
||||
|
36
gcc/config/ia64/frame-ia64.h
Normal file
36
gcc/config/ia64/frame-ia64.h
Normal file
@ -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 **);
|
1
gcc/config/ia64/t-glibc
Normal file
1
gcc/config/ia64/t-glibc
Normal file
@ -0,0 +1 @@
|
||||
LIB2ADDEH += $(srcdir)/config/ia64/fde-glibc.c
|
2
gcc/configure
vendored
2
gcc/configure
vendored
@ -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'
|
||||
|
@ -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'
|
||||
|
Loading…
Reference in New Issue
Block a user