* *
* C Implementation File *
* *
- * Copyright (C) 2000-2006, AdaCore *
+ * Copyright (C) 2000-2009, 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- *
functions.
It has been tested on the following configurations:
PowerPC/AiX
+ PowerPC/Darwin
PowerPC/VxWorks
SPARC/Solaris
i386/GNU/Linux
#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);
#include "tb-alvms.c"
+#elif defined (__ia64__) && defined (__VMS__)
+
+#include "tb-ivms.c"
+
#else
+
/* No target specific implementation. */
/*----------------------------------------------------------------*
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
+ 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
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_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,
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
+ o STOP_FRAME, to decide whether we reached the top of the call chain, and
thus if the process shall stop.
:
void *return_address;
};
-#define FRAME_OFFSET 0
+#define FRAME_OFFSET(FP) 0
#define PC_ADJUST -4
#define STOP_FRAME(CURRENT, TOP_STACK) ((void *) (CURRENT) < (TOP_STACK))
#define BASE_SKIP 1
-/*---------------------------- PPC VxWorks------------------------------*/
+/*-------------------- PPC ELF (GNU/Linux & VxWorks) ---------------------*/
-#elif defined (_ARCH_PPC) && defined (__vxworks)
+#elif (defined (_ARCH_PPC) && defined (__vxworks)) || \
+ (defined (linux) && defined (__powerpc__))
#define USE_GENERIC_UNWINDER
#define FRAME_LEVEL 1
/* See the PPC AIX case for an explanation of these values. */
-#define FRAME_OFFSET 0
+#define FRAME_OFFSET(FP) 0
#define PC_ADJUST -4
#define STOP_FRAME(CURRENT, TOP_STACK) ((CURRENT)->next == 0)
#endif
#define FRAME_LEVEL 0
-#define FRAME_OFFSET (14 * sizeof (void*) + STACK_BIAS)
+#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
+/* 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
#elif defined (i386)
-#ifdef __WIN32
+#if defined (__WIN32)
#include <windows.h>
#define IS_BAD_PTR(ptr) (IsBadCodePtr((void *)ptr))
+#elif defined (sun)
+#define IS_BAD_PTR(ptr) ((unsigned long)ptr == -1UL)
#else
#define IS_BAD_PTR(ptr) 0
#endif
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 FRAME_OFFSET(FP) 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 \
+ (IS_BAD_PTR((long)(CURRENT)) \
+ || IS_BAD_PTR((long)(CURRENT)->return_address) \
|| (CURRENT)->return_address == 0|| (CURRENT)->next == 0 \
|| (void *) (CURRENT) < (TOP_STACK))
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
+ 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);
top_frame = __builtin_frame_address (FRAME_LEVEL);
top_stack = CURRENT_STACK_FRAME;
- current = (struct layout *) ((size_t) top_frame + FRAME_OFFSET);
+ 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.
while (cnt < skip_frames)
{
- current = (struct layout *) ((size_t) current->next + FRAME_OFFSET);
+ current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1));
cnt++;
}
|| current->return_address > exclude_max)
array[cnt++] = current->return_address + PC_ADJUST;
- current = (struct layout *) ((size_t) current->next + FRAME_OFFSET);
+ current = (struct layout *) ((size_t) current->next + FRAME_OFFSET (1));
}
return cnt;
*------------------------------*/
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;
+__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;
}