00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include <signal.h>
00025 #include <sys/ucontext.h>
00026 #include <sys/mman.h>
00027 #include "hosthooks.h"
00028 #include "hosthooks-def.h"
00029 #include "toplev.h"
00030 #include "diagnostic.h"
00031
00032 static void segv_crash_handler (int);
00033 static void segv_handler (int, siginfo_t *, void *);
00034 static void darwin_rs6000_extra_signals (void);
00035
00036
00037
00038 extern int sigaltstack(const struct sigaltstack *, struct sigaltstack *);
00039
00040 #undef HOST_HOOKS_EXTRA_SIGNALS
00041 #define HOST_HOOKS_EXTRA_SIGNALS darwin_rs6000_extra_signals
00042
00043
00044
00045
00046
00047
00048
00049 static void
00050 segv_crash_handler (int sig ATTRIBUTE_UNUSED)
00051 {
00052 internal_error ("Segmentation Fault (code)");
00053 }
00054
00055 static void
00056 segv_handler (int sig ATTRIBUTE_UNUSED,
00057 siginfo_t *sip ATTRIBUTE_UNUSED,
00058 void *scp)
00059 {
00060 ucontext_t *uc = (ucontext_t *)scp;
00061 unsigned faulting_insn;
00062
00063
00064
00065 signal (SIGSEGV, segv_crash_handler);
00066
00067 faulting_insn = *(unsigned *)uc->uc_mcontext->ss.srr0;
00068
00069
00070
00071
00072
00073
00074
00075 if ((faulting_insn & 0xFFFF8000) == 0x94218000
00076 || (faulting_insn & 0xFFFF03FF) == 0x7C21016E
00077 || (faulting_insn & 0xFC1F8000) == 0x90018000
00078 || (faulting_insn & 0xFC1F8000) == 0xD8018000
00079 || (faulting_insn & 0xFC1F8000) == 0xBC018000 )
00080 {
00081 char *shell_name;
00082
00083 fnotice (stderr, "Out of stack space.\n");
00084 shell_name = getenv ("SHELL");
00085 if (shell_name != NULL)
00086 shell_name = strrchr (shell_name, '/');
00087 if (shell_name != NULL)
00088 {
00089 static const char * shell_commands[][2] = {
00090 { "sh", "ulimit -S -s unlimited" },
00091 { "bash", "ulimit -S -s unlimited" },
00092 { "tcsh", "limit stacksize unlimited" },
00093 { "csh", "limit stacksize unlimited" },
00094
00095
00096 { "zsh", "limit stacksize 32m" }
00097 };
00098 size_t i;
00099
00100 for (i = 0; i < ARRAY_SIZE (shell_commands); i++)
00101 if (strcmp (shell_commands[i][0], shell_name + 1) == 0)
00102 {
00103 fnotice (stderr,
00104 "Try running '%s' in the shell to raise its limit.\n",
00105 shell_commands[i][1]);
00106 }
00107 }
00108
00109 if (global_dc->abort_on_error)
00110 abort ();
00111
00112 exit (FATAL_EXIT_CODE);
00113 }
00114
00115 fprintf (stderr, "[address=%08lx pc=%08x]\n",
00116 uc->uc_mcontext->es.dar, uc->uc_mcontext->ss.srr0);
00117 internal_error ("Segmentation Fault");
00118 exit (FATAL_EXIT_CODE);
00119 }
00120
00121 static void
00122 darwin_rs6000_extra_signals (void)
00123 {
00124 struct sigaction sact;
00125 stack_t sigstk;
00126
00127 sigstk.ss_sp = xmalloc (SIGSTKSZ);
00128 sigstk.ss_size = SIGSTKSZ;
00129 sigstk.ss_flags = 0;
00130 if (sigaltstack (&sigstk, NULL) < 0)
00131 fatal_error ("While setting up signal stack: %m");
00132
00133 sigemptyset(&sact.sa_mask);
00134 sact.sa_flags = SA_ONSTACK | SA_SIGINFO;
00135 sact.sa_sigaction = segv_handler;
00136 if (sigaction (SIGSEGV, &sact, 0) < 0)
00137 fatal_error ("While setting up signal handler: %m");
00138 }
00139
00140 #undef HOST_HOOKS_GT_PCH_GET_ADDRESS
00141 #define HOST_HOOKS_GT_PCH_GET_ADDRESS darwin_rs6000_gt_pch_get_address
00142 #undef HOST_HOOKS_GT_PCH_USE_ADDRESS
00143 #define HOST_HOOKS_GT_PCH_USE_ADDRESS darwin_rs6000_gt_pch_use_address
00144
00145
00146 static char pch_address_space[1024*1024*1024] __attribute__((aligned (4096)));
00147
00148
00149
00150 static void *
00151 darwin_rs6000_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED)
00152 {
00153 if (sz <= sizeof (pch_address_space))
00154 return pch_address_space;
00155 else
00156 return NULL;
00157 }
00158
00159
00160
00161
00162 static int
00163 darwin_rs6000_gt_pch_use_address (void *addr, size_t sz, int fd, size_t off)
00164 {
00165 const size_t pagesize = getpagesize();
00166 void *mmap_result;
00167 int ret;
00168
00169 if ((size_t)pch_address_space % pagesize != 0
00170 || sizeof (pch_address_space) % pagesize != 0)
00171 abort ();
00172
00173 ret = (addr == pch_address_space && sz <= sizeof (pch_address_space));
00174 if (! ret)
00175 sz = 0;
00176
00177
00178 sz = (sz + pagesize - 1) / pagesize * pagesize;
00179
00180 if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0)
00181 fatal_error ("couldn't unmap pch_address_space: %m\n");
00182
00183 if (ret)
00184 {
00185 mmap_result = mmap (addr, sz,
00186 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
00187 fd, off);
00188
00189
00190 ret = mmap_result != (void *) MAP_FAILED;
00191
00192
00193 if (ret && mmap_result != addr)
00194 abort ();
00195 }
00196
00197 return ret;
00198 }
00199
00200
00201 const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;