aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/ada/tracebak.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/ada/tracebak.c')
-rw-r--r--gcc-4.9/gcc/ada/tracebak.c639
1 files changed, 639 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/ada/tracebak.c b/gcc-4.9/gcc/ada/tracebak.c
new file mode 100644
index 000000000..4efb75e61
--- /dev/null
+++ b/gcc-4.9/gcc/ada/tracebak.c
@@ -0,0 +1,639 @@
+/****************************************************************************
+ * *
+ * GNAT RUN-TIME COMPONENTS *
+ * *
+ * T R A C E B A C K *
+ * *
+ * C Implementation File *
+ * *
+ * Copyright (C) 2000-2012, Free Software Foundation, Inc. *
+ * *
+ * 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 3, 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. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ * *
+ * 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/Darwin
+ PowerPC/VxWorks
+ PowerPC/LynxOS-178
+ SPARC/Solaris
+ i386/GNU/Linux
+ i386/Solaris
+ i386/NT
+ i386/OS2
+ i386/LynxOS
+ Alpha/VxWorks
+ Alpha/VMS
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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"
+/* We don't want fancy_abort here. */
+#undef abort
+#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"
+
+#elif defined (__ia64__) && defined (__VMS__)
+
+#include "tb-ivms.c"
+
+#elif defined (_WIN64) && defined (__SEH__)
+
+#include <windows.h>
+
+int
+__gnat_backtrace (void **array,
+ int size,
+ void *exclude_min,
+ void *exclude_max,
+ int skip_frames)
+{
+ CONTEXT context;
+ UNWIND_HISTORY_TABLE history;
+ int i;
+
+ /* Get the context. */
+ RtlCaptureContext (&context);
+
+ /* Setup unwind history table (a cached to speed-up unwinding). */
+ memset (&history, 0, sizeof (history));
+
+ i = 0;
+ while (1)
+ {
+ PRUNTIME_FUNCTION RuntimeFunction;
+ KNONVOLATILE_CONTEXT_POINTERS NvContext;
+ ULONG64 ImageBase;
+ VOID *HandlerData;
+ ULONG64 EstablisherFrame;
+
+ /* Get function metadata. */
+ RuntimeFunction = RtlLookupFunctionEntry
+ (context.Rip, &ImageBase, &history);
+
+ if (!RuntimeFunction)
+ {
+ /* In case of failure, assume this is a leaf function. */
+ context.Rip = *(ULONG64 *) context.Rsp;
+ context.Rsp += 8;
+ }
+ else
+ {
+ /* Unwind. */
+ memset (&NvContext, 0, sizeof (KNONVOLATILE_CONTEXT_POINTERS));
+ RtlVirtualUnwind (0, ImageBase, context.Rip, RuntimeFunction,
+ &context, &HandlerData, &EstablisherFrame,
+ &NvContext);
+ }
+
+ /* 0 means bottom of the stack. */
+ if (context.Rip == 0)
+ break;
+
+ /* Skip frames. */
+ if (skip_frames > 1)
+ {
+ skip_frames--;
+ continue;
+ }
+ /* Excluded frames. */
+ if ((void *)context.Rip >= exclude_min
+ && (void *)context.Rip <= exclude_max)
+ continue;
+
+ array[i++] = (void *)(context.Rip - 2);
+ if (i >= size)
+ break;
+ }
+ return i;
+}
+#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 address 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 address or frame pointer
+ value, 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 whether 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.
+
+ */
+
+/*------------------- Darwin 8 (OSX 10.4) or newer ----------------------*/
+#if defined (__APPLE__) \
+ && defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
+ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040
+
+#define USE_GCC_UNWINDER
+
+#if defined (__i386__) || defined (__x86_64__)
+#define PC_ADJUST -2
+#elif defined (__ppc__) || defined (__ppc64__)
+#define PC_ADJUST -4
+#else
+#error Unhandled darwin architecture.
+#endif
+
+/*---------------------- PPC AIX/PPC Lynx 178/Older Darwin ------------------*/
+#elif ((defined (_POWER) && defined (_AIX)) || \
+ (defined (__powerpc__) && defined (__Lynx__) && !defined(__ELF__)) || \
+ (defined (__ppc__) && defined (__APPLE__)))
+
+#define USE_GENERIC_UNWINDER
+
+struct layout
+{
+ struct layout *next;
+ void *pad;
+ void *return_address;
+};
+
+#define FRAME_OFFSET(FP) 0
+#define PC_ADJUST -4
+
+/* Eventhough the base PPC ABI states that a toplevel frame entry
+ should to feature a null backchain, AIX might expose a null return
+ address instead. */
+
+/* Then LynxOS-178 features yet another variation, with return_address
+ == &<entrypoint>, with two possible entry points (one for the main
+ process and one for threads). Beware that &bla returns the address
+ of a descriptor when "bla" is a function. Getting the code address
+ requires an extra dereference. */
+
+#if defined (__Lynx__)
+extern void __start(); /* process entry point. */
+extern void __runnit(); /* thread entry point. */
+#define EXTRA_STOP_CONDITION(CURRENT) \
+ ((CURRENT)->return_address == *(void**)&__start \
+ || (CURRENT)->return_address == *(void**)&__runnit)
+#else
+#define EXTRA_STOP_CONDITION(CURRENT) (0)
+#endif
+
+#define STOP_FRAME(CURRENT, TOP_STACK) \
+ (((void *) (CURRENT) < (TOP_STACK)) \
+ || (CURRENT)->return_address == NULL \
+ || EXTRA_STOP_CONDITION(CURRENT))
+
+/* 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 ELF (GNU/Linux & VxWorks) ---------------------*/
+
+#elif (defined (_ARCH_PPC) && defined (__vxworks)) || \
+ (defined (linux) && defined (__powerpc__))
+
+#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(FP) 0
+#define PC_ADJUST -4
+
+/* According to the base PPC ABI, a toplevel frame entry should feature
+ a null backchain. What happens at signal handler frontiers isn't so
+ well specified, so we add a safety guard on top. */
+
+#define STOP_FRAME(CURRENT, TOP_STACK) \
+ ((CURRENT)->next == 0 || ((long)(CURRENT)->next % __alignof__(void*)) != 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(FP) (14 * sizeof (void*) + (FP ? STACK_BIAS : 0))
+#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)
+
+#if defined (__WIN32)
+#include <windows.h>
+#define IS_BAD_PTR(ptr) (IsBadCodePtr((FARPROC)ptr))
+#elif defined (sun)
+#define IS_BAD_PTR(ptr) ((unsigned long)ptr == -1UL)
+#else
+#define IS_BAD_PTR(ptr) 0
+#endif
+
+/* Starting with GCC 4.6, -fomit-frame-pointer is turned on by default for
+ 32-bit x86/Linux as well and DWARF 2 unwind tables are emitted instead.
+ See the x86-64 case below for the drawbacks with this approach. */
+#if defined (linux) && (__GNUC__ * 10 + __GNUC_MINOR__ > 45)
+#define USE_GCC_UNWINDER
+#else
+#define USE_GENERIC_UNWINDER
+#endif
+
+struct layout
+{
+ struct layout *next;
+ void *return_address;
+};
+
+#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(FP) 0
+#define PC_ADJUST -2
+#define STOP_FRAME(CURRENT, TOP_STACK) \
+ (IS_BAD_PTR((long)(CURRENT)) \
+ || IS_BAD_PTR((long)(CURRENT)->return_address) \
+ || (CURRENT)->return_address == 0 \
+ || (void *) ((CURRENT)->next) < (TOP_STACK) \
+ || (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 -4
+
+
+#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 ATTRIBUTE_UNUSED;
+ 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 (0));
+
+ /* 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 (1));
+ 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++] = ((char *) current->return_address) + PC_ADJUST;
+
+ current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1));
+ }
+
+ return cnt;
+}
+
+#else
+
+/* No target specific implementation and neither USE_GCC_UNWINDER nor
+ USE_GENERIC_UNWINDER defined. */
+
+/*------------------------------*
+ *-- The dummy implementation --*
+ *------------------------------*/
+
+int
+__gnat_backtrace (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
+
+#ifdef __cplusplus
+}
+#endif