diff options
Diffstat (limited to 'gcc-4.2.1/gcc/ada/tracebak.c')
-rw-r--r-- | gcc-4.2.1/gcc/ada/tracebak.c | 501 |
1 files changed, 0 insertions, 501 deletions
diff --git a/gcc-4.2.1/gcc/ada/tracebak.c b/gcc-4.2.1/gcc/ada/tracebak.c deleted file mode 100644 index 9c25d1ee4..000000000 --- a/gcc-4.2.1/gcc/ada/tracebak.c +++ /dev/null @@ -1,501 +0,0 @@ -/**************************************************************************** - * * - * GNAT COMPILER COMPONENTS * - * * - * T R A C E B A C K * - * * - * C Implementation File * - * * - * Copyright (C) 2000-2006, AdaCore * - * * - * GNAT is free software; you can redistribute it and/or modify it under * - * terms of the GNU General Public License as published by the Free Soft- * - * ware Foundation; either version 2, or (at your option) any later ver- * - * sion. GNAT is distributed in the hope that it will be useful, but WITH- * - * OUT 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 distributed with GNAT; see file COPYING. If not, write * - * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, * - * Boston, MA 02110-1301, USA. * - * * - * As a special exception, if you link this file with other files to * - * produce an executable, this file does not by itself cause the resulting * - * executable to be covered by the GNU General Public License. This except- * - * ion does not however invalidate any other reasons why the executable * - * file might be covered by the GNU Public License. * - * * - * GNAT was originally developed by the GNAT team at New York University. * - * Extensive contributions were provided by Ada Core Technologies Inc. * - * * - ****************************************************************************/ - -/* This file contains low level support for stack unwinding using GCC intrinsic - functions. - It has been tested on the following configurations: - PowerPC/AiX - PowerPC/VxWorks - SPARC/Solaris - i386/GNU/Linux - i386/Solaris - i386/NT - i386/OS2 - i386/LynxOS - Alpha/VxWorks - Alpha/VMS -*/ - -#ifdef __alpha_vxworks -#include "vxWorks.h" -#endif - -#ifdef IN_RTS -#define POSIX -#include "tconfig.h" -#include "tsystem.h" -#else -#include "config.h" -#include "system.h" -#endif - -extern int __gnat_backtrace (void **, int, void *, void *, int); - -/* The point is to provide an implementation of the __gnat_backtrace function - above, called by the default implementation of the System.Traceback package. - - We first have a series of target specific implementations, each included - from a separate C file for readability purposes. - - Then come two flavors of a generic implementation: one relying on static - assumptions about the frame layout, and the other one using the GCC EH - infrastructure. The former uses a whole set of macros and structures which - may be tailored on a per target basis, and is activated as soon as - USE_GENERIC_UNWINDER is defined. The latter uses a small subset of the - macro definitions and is activated when USE_GCC_UNWINDER is defined. It is - only available post GCC 3.3. - - Finally, there is a default dummy implementation, necessary to make the - linker happy on platforms where the feature is not supported, but where the - function is still referenced by the default System.Traceback. */ - -#define Lock_Task system__soft_links__lock_task -extern void (*Lock_Task) (void); - -#define Unlock_Task system__soft_links__unlock_task -extern void (*Unlock_Task) (void); - -/*-------------------------------------* - *-- Target specific implementations --* - *-------------------------------------*/ - -#if defined (__alpha_vxworks) - -#include "tb-alvxw.c" - -#elif defined (__ALPHA) && defined (__VMS__) - -#include "tb-alvms.c" - -#else -/* No target specific implementation. */ - -/*----------------------------------------------------------------* - *-- Target specific definitions for the generic implementation --* - *----------------------------------------------------------------*/ - -/* The stack layout is specified by the target ABI. The "generic" scheme is - based on the following assumption: - - The stack layout from some frame pointer is such that the information - required to compute the backtrace is available at static offsets. - - For a given frame, the information we are interested in is the saved return - address (somewhere after the call instruction in the caller) and a pointer - to the caller's frame. The former is the base of the call chain information - we store in the tracebacks array. The latter allows us to loop over the - successive frames in the chain. - - To initiate the process, we retrieve an initial frame pointer using the - appropriate GCC builtin (__builtin_frame_address). - - This scheme is unfortunately not applicable on every target because the - stack layout is not necessarily regular (static) enough. On targets where - this scheme applies, the implementation relies on the following items: - - o struct layout, describing the expected stack data layout relevant to the - information we are interested in, - - o FRAME_OFFSET, the offset, from a given frame pointer, at which this - layout will be found, - - o FRAME_LEVEL, controls how many frames up we get at to start with, - from the initial frame pointer we compute by way of the GCC builtin, - - 0 is most often the appropriate value. 1 may be necessary on targets - where return addresses are saved by a function in it's caller's frame - (e.g. PPC). - - o PC_ADJUST, to account for the difference between a call point (address - of a call instruction), which is what we want in the output array, and - the associated return address, which is what we retrieve from the stack. - - o STOP_FRAME, to decide wether we reached the top of the call chain, and - thus if the process shall stop. - - : - : stack - | +----------------+ - | +-------->| : | - | | | (FRAME_OFFSET) | - | | | : | (PC_ADJUST) - | | layout:| return_address ----------------+ - | | | .... | | - +--------------- next_frame | | - | | .... | | - | | | | - | +----------------+ | +-----+ - | | : |<- Base fp | | : | - | | (FRAME_OFFSET) | (FRAME_LEVEL) | | : | - | | : | +---> | [1] - | layout:| return_address --------------------> | [0] - | | ... | (PC_ADJUST) +-----+ - +---------- next_frame | traceback[] - | ... | - | | - +----------------+ - - o BASE_SKIP, - - Since we inherently deal with return addresses, there is an implicit shift - by at least one for the initial point we are able to observe in the chain. - - On some targets (e.g. sparc-solaris), the first return address we can - easily get without special code is even our caller's return address, so - there is a initial shift of two. - - BASE_SKIP represents this initial shift, which is the minimal "skip_frames" - value we support. We could add special code for the skip_frames < BASE_SKIP - cases. This is not done currently because there is virtually no situation - in which this would be useful. - - Finally, to account for some ABI specificities, a target may (but does - not have to) define: - - o FORCE_CALL, to force a call to a dummy function at the very beginning - of the computation. See the PPC AIX target for an example where this - is useful. - - o FETCH_UP_FRAME, to force an invocation of __builtin_frame_address with a - positive argument right after a possibly forced call even if FRAME_LEVEL - is 0. See the SPARC Solaris case for an example where this is useful. - - */ - -/*--------------------------- PPC AIX/Darwin ----------------------------*/ - -#if ((defined (_POWER) && defined (_AIX)) || \ -(defined (__ppc__) && defined (__APPLE__))) - -#define USE_GENERIC_UNWINDER - -struct layout -{ - struct layout *next; - void *pad; - void *return_address; -}; - -#define FRAME_OFFSET 0 -#define PC_ADJUST -4 -#define STOP_FRAME(CURRENT, TOP_STACK) ((void *) (CURRENT) < (TOP_STACK)) - -/* The PPC ABI has an interesting specificity: the return address saved by a - function is located in it's caller's frame, and the save operation only - takes place if the function performs a call. - - To have __gnat_backtrace retrieve its own return address, we then - define ... */ - -#define FORCE_CALL 1 -#define FRAME_LEVEL 1 - -#define BASE_SKIP 1 - -/*---------------------------- PPC VxWorks------------------------------*/ - -#elif defined (_ARCH_PPC) && defined (__vxworks) - -#define USE_GENERIC_UNWINDER - -struct layout -{ - struct layout *next; - void *return_address; -}; - -#define FORCE_CALL 1 -#define FRAME_LEVEL 1 -/* See the PPC AIX case for an explanation of these values. */ - -#define FRAME_OFFSET 0 -#define PC_ADJUST -4 -#define STOP_FRAME(CURRENT, TOP_STACK) ((CURRENT)->next == 0) - -#define BASE_SKIP 1 - -/*-------------------------- SPARC Solaris -----------------------------*/ - -#elif defined (sun) && defined (sparc) - -#define USE_GENERIC_UNWINDER - -/* These definitions are inspired from the Appendix D (Software - Considerations) of the SPARC V8 architecture manual. */ - -struct layout -{ - struct layout *next; - void *return_address; -}; - -#ifdef __arch64__ -#define STACK_BIAS 2047 /* V9 ABI */ -#else -#define STACK_BIAS 0 /* V8 ABI */ -#endif - -#define FRAME_LEVEL 0 -#define FRAME_OFFSET (14 * sizeof (void*) + STACK_BIAS) -#define PC_ADJUST 0 -#define STOP_FRAME(CURRENT, TOP_STACK) \ - ((CURRENT)->return_address == 0|| (CURRENT)->next == 0 \ - || (void *) (CURRENT) < (TOP_STACK)) - -/* The sparc register windows need to be flushed before we may access them - from the stack. This is achieved by way of builtin_frame_address only - when the "count" argument is positive, so force at least one such call. */ -#define FETCH_UP_FRAME_ADDRESS - -#define BASE_SKIP 2 -/* From the frame pointer of frame N, we are accessing the flushed register - window of frame N-1 (positive offset from fp), in which we retrieve the - saved return address. We then end up with our caller's return address. */ - -/*------------------------------- x86 ----------------------------------*/ - -#elif defined (i386) - -#ifdef __WIN32 -#include <windows.h> -#define IS_BAD_PTR(ptr) (IsBadCodePtr((void *)ptr)) -#else -#define IS_BAD_PTR(ptr) 0 -#endif - -#define USE_GENERIC_UNWINDER - -struct layout -{ - struct layout *next; - void *return_address; -}; - -#define LOWEST_ADDR 0 -#define FRAME_LEVEL 1 -/* builtin_frame_address (1) is expected to work on this target, and (0) might - return the soft stack pointer, which does not designate a location where a - backchain and a return address might be found. */ - -#define FRAME_OFFSET 0 -#define PC_ADJUST -2 -#define STOP_FRAME(CURRENT, TOP_STACK) \ - (IS_BAD_PTR((long)(CURRENT)->return_address) \ - || (unsigned int)(CURRENT)->return_address < LOWEST_ADDR \ - || (CURRENT)->return_address == 0|| (CURRENT)->next == 0 \ - || (void *) (CURRENT) < (TOP_STACK)) - -#define BASE_SKIP (1+FRAME_LEVEL) - -/* On i386 architecture we check that at the call point we really have a call - insn. Possible call instructions are: - - call addr16 E8 xx xx xx xx - call reg FF Dx - call off(reg) FF xx xx - lcall addr seg 9A xx xx xx xx xx xx - - This check will not catch all cases but it will increase the backtrace - reliability on this architecture. -*/ - -#define VALID_STACK_FRAME(ptr) \ - (!IS_BAD_PTR(ptr) \ - && (((*((ptr) - 3) & 0xff) == 0xe8) \ - || ((*((ptr) - 5) & 0xff) == 0x9a) \ - || ((*((ptr) - 1) & 0xff) == 0xff) \ - || (((*(ptr) & 0xd0ff) == 0xd0ff)))) - -/*----------------------------- x86_64 ---------------------------------*/ - -#elif defined (__x86_64__) - -#define USE_GCC_UNWINDER -/* The generic unwinder is not used for this target because it is based - on frame layout assumptions that are not reliable on this target (the - rbp register is very likely used for something else than storing the - frame pointer in optimized code). Hence, we use the GCC unwinder - based on DWARF 2 call frame information, although it has the drawback - of not being able to unwind through frames compiled without DWARF 2 - information. -*/ - -#define PC_ADJUST -2 -/* The minimum size of call instructions on this architecture is 2 bytes */ - -/*----------------------------- ia64 ---------------------------------*/ - -#elif defined (__ia64__) && (defined (linux) || defined (__hpux__)) - -#define USE_GCC_UNWINDER -/* Use _Unwind_Backtrace driven exceptions on ia64 HP-UX and ia64 - GNU/Linux, where _Unwind_Backtrace is provided by the system unwind - library. On HP-UX 11.23 this requires patch PHSS_33352, which adds - _Unwind_Backtrace to the system unwind library. */ - -#define PC_ADJUST -16 -/* Every call on ia64 is part of a 128 bit bundle, so an adjustment of - minus 16 bytes from the point of return finds the address of the - previous bundle. */ - -#endif - -/*---------------------------------------------------------------------* - *-- The post GCC 3.3 infrastructure based implementation --* - *---------------------------------------------------------------------*/ - -#if defined (USE_GCC_UNWINDER) && (__GNUC__ * 10 + __GNUC_MINOR__ > 33) - -/* Conditioning the inclusion on the GCC version is useful to avoid bootstrap - path problems, since the included file refers to post 3.3 functions in - libgcc, and the stage1 compiler is unlikely to be linked against a post 3.3 - library. It actually disables the support for backtraces in this compiler - for targets defining USE_GCC_UNWINDER, which is OK since we don't use the - traceback capability in the compiler anyway. - - The condition is expressed the way above because we cannot reliably rely on - any other macro from the base compiler when compiling stage1. */ - -#include "tb-gcc.c" - -/*------------------------------------------------------------------* - *-- The generic implementation based on frame layout assumptions --* - *------------------------------------------------------------------*/ - -#elif defined (USE_GENERIC_UNWINDER) - -#ifndef CURRENT_STACK_FRAME -# define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) -#endif - -#ifndef VALID_STACK_FRAME -#define VALID_STACK_FRAME(ptr) 1 -#endif - -#ifndef MAX -#define MAX(x,y) ((x) > (y) ? (x) : (y)) -#endif - -#ifndef FORCE_CALL -#define FORCE_CALL 0 -#endif - -/* Make sure the function is not inlined. */ -static void forced_callee (void) __attribute__ ((noinline)); - -static void forced_callee (void) -{ - /* Make sure the function is not pure. */ - volatile int i __attribute__ ((unused)) = 0; -} - -int -__gnat_backtrace (void **array, - int size, - void *exclude_min, - void *exclude_max, - int skip_frames) -{ - struct layout *current; - void *top_frame; - void *top_stack; - int cnt = 0; - - if (FORCE_CALL) - forced_callee (); - - /* Force a call to builtin_frame_address with a positive argument - if required. This is necessary e.g. on sparc to have the register - windows flushed before we attempt to access them on the stack. */ -#if defined (FETCH_UP_FRAME_ADDRESS) && (FRAME_LEVEL == 0) - __builtin_frame_address (1); -#endif - - top_frame = __builtin_frame_address (FRAME_LEVEL); - top_stack = CURRENT_STACK_FRAME; - current = (struct layout *) ((size_t) top_frame + FRAME_OFFSET); - - /* Skip the number of calls we have been requested to skip, accounting for - the BASE_SKIP parameter. - - FRAME_LEVEL is meaningless for the count adjustment. It impacts where we - start retrieving data from, but how many frames "up" we start at is in - BASE_SKIP by definition. */ - - skip_frames = MAX (0, skip_frames - BASE_SKIP); - - while (cnt < skip_frames) - { - current = (struct layout *) ((size_t) current->next + FRAME_OFFSET); - cnt++; - } - - cnt = 0; - while (cnt < size) - { - if (STOP_FRAME (current, top_stack) || - !VALID_STACK_FRAME((char *)(current->return_address + PC_ADJUST))) - break; - - if (current->return_address < exclude_min - || current->return_address > exclude_max) - array[cnt++] = current->return_address + PC_ADJUST; - - current = (struct layout *) ((size_t) current->next + FRAME_OFFSET); - } - - return cnt; -} - -#else - -/* No target specific implementation and neither USE_GCC_UNWINDER not - USE_GCC_UNWINDER defined. */ - -/*------------------------------* - *-- The dummy implementation --* - *------------------------------*/ - -int -__gnat_backtrace (array, size, exclude_min, exclude_max, skip_frames) - void **array ATTRIBUTE_UNUSED; - int size ATTRIBUTE_UNUSED; - void *exclude_min ATTRIBUTE_UNUSED; - void *exclude_max ATTRIBUTE_UNUSED; - int skip_frames ATTRIBUTE_UNUSED; -{ - return 0; -} - -#endif - -#endif |