aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/init.c
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2009-04-16 14:52:28 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2009-04-16 14:52:28 +0200
commitd15d61c671cb02b6dce9d583962750875e3178e9 (patch)
tree30c6a373132e5d4e1de4bb03bdf7beda67d1d2a3 /gcc/ada/init.c
parent0a0a18c30fbacdade52fa538575ff4889e145275 (diff)
downloadgcc-d15d61c671cb02b6dce9d583962750875e3178e9.zip
gcc-d15d61c671cb02b6dce9d583962750875e3178e9.tar.gz
gcc-d15d61c671cb02b6dce9d583962750875e3178e9.tar.bz2
[multiple changes]
2009-04-16 Tristan Gingold <gingold@adacore.com> * init.c: Detect real stack overflow on Darwin. * system-darwin-x86.ads: Use stack probing on darwin x86. 2009-04-16 Ed Schonberg <schonberg@adacore.com> * sem_attr.adb (Analyze_Attribute, case 'Address): It is illegal to take the address of an intrinsic subprogram. 2009-04-16 Vincent Celier <celier@adacore.com> * g-trasym-unimplemented.ads, g-trasym-unimplemented.adb: New file. * g-trasym.ads: Update comments. 2009-04-16 Vasiliy Fofanov <fofanov@adacore.com> * tracebak.c (STOP_FRAME): Verify validity of the current address before dereferencing. From-SVN: r146182
Diffstat (limited to 'gcc/ada/init.c')
-rw-r--r--gcc/ada/init.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index e86a975..fab0942 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -2098,6 +2098,8 @@ __gnat_install_handler(void)
#elif defined(__APPLE__)
#include <signal.h>
+#include <mach/mach_vm.h>
+#include <mach/vm_statistics.h>
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
char __gnat_alternate_stack[64 * 1024]; /* 2 * MINSIGSTKSZ */
@@ -2108,6 +2110,31 @@ static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
#define UC_RESET_ALT_STACK 0x80000000
extern int sigreturn (void *uc, int flavour);
+/* Return true if ADDR is within a stack guard area. */
+static int
+__gnat_is_stack_guard (mach_vm_address_t addr)
+{
+ kern_return_t kret;
+ vm_region_submap_info_data_64_t info;
+ mach_vm_address_t start;
+ mach_vm_size_t size;
+ natural_t depth;
+ mach_msg_type_number_t count;
+
+ count = VM_REGION_SUBMAP_INFO_COUNT_64;
+ start = addr;
+ size = -1;
+ depth = 9999;
+ kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
+ (vm_region_recurse_info_t) &info, &count);
+ if (kret == KERN_SUCCESS
+ && addr >= start && addr < (start + size)
+ && info.protection == VM_PROT_NONE
+ && info.user_tag == VM_MEMORY_STACK)
+ return 1;
+ return 0;
+}
+
static void
__gnat_error_handler (int sig, siginfo_t * si, void * uc)
{
@@ -2118,9 +2145,16 @@ __gnat_error_handler (int sig, siginfo_t * si, void * uc)
{
case SIGSEGV:
case SIGBUS:
- /* FIXME: we need to detect the case of a *real* SIGSEGV. */
- exception = &storage_error;
- msg = "stack overflow or erroneous memory access";
+ if (__gnat_is_stack_guard ((mach_vm_address_t)si->si_addr))
+ {
+ exception = &storage_error;
+ msg = "stack overflow";
+ }
+ else
+ {
+ exception = &constraint_error;
+ msg = "erroneous memory access";
+ }
/* Reset the use of alt stack, so that the alt stack will be used
for the next signal delivery. */
sigreturn (NULL, UC_RESET_ALT_STACK);