123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /* Darwin/powerpc host-specific hook definitions.
- Copyright (C) 2003-2015 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
- GCC is distributed in the hope that it will be useful, but WITHOUT
- 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
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include <sys/ucontext.h>
- #include "hosthooks.h"
- #include "hosthooks-def.h"
- #include "diagnostic.h"
- #include "config/host-darwin.h"
- static void segv_crash_handler (int);
- static void segv_handler (int, siginfo_t *, void *);
- static void darwin_rs6000_extra_signals (void);
- #ifndef HAVE_DECL_SIGALTSTACK
- /* This doesn't have a prototype in signal.h in 10.2.x and earlier,
- fixed in later releases. */
- extern int sigaltstack(const struct sigaltstack *, struct sigaltstack *);
- #endif
- /* The fields of the mcontext_t type have acquired underscores in later
- OS versions. */
- #ifdef HAS_MCONTEXT_T_UNDERSCORES
- #define MC_FLD(x) __ ## x
- #else
- #define MC_FLD(x) x
- #endif
- #undef HOST_HOOKS_EXTRA_SIGNALS
- #define HOST_HOOKS_EXTRA_SIGNALS darwin_rs6000_extra_signals
- /* On Darwin/powerpc, hitting the stack limit turns into a SIGSEGV.
- This code detects the difference between hitting the stack limit and
- a true wild pointer dereference by looking at the instruction that
- faulted; only a few kinds of instruction are used to access below
- the previous bottom of the stack. */
- static void
- segv_crash_handler (int sig ATTRIBUTE_UNUSED)
- {
- internal_error ("Segmentation Fault (code)");
- }
- static void
- segv_handler (int sig ATTRIBUTE_UNUSED,
- siginfo_t *sip ATTRIBUTE_UNUSED,
- void *scp)
- {
- ucontext_t *uc = (ucontext_t *)scp;
- sigset_t sigset;
- unsigned faulting_insn;
- /* The fault might have happened when trying to run some instruction, in
- which case the next line will segfault _again_. Handle this case. */
- signal (SIGSEGV, segv_crash_handler);
- sigemptyset (&sigset);
- sigaddset (&sigset, SIGSEGV);
- sigprocmask (SIG_UNBLOCK, &sigset, NULL);
- faulting_insn = *(unsigned *)uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0);
- /* Note that this only has to work for GCC, so we don't have to deal
- with all the possible cases (GCC has no AltiVec code, for
- instance). It's complicated because Darwin allows stores to
- below the stack pointer, and the prologue code takes advantage of
- this. */
- if ((faulting_insn & 0xFFFF8000) == 0x94218000 /* stwu %r1, -xxx(%r1) */
- || (faulting_insn & 0xFC1F03FF) == 0x7C01016E /* stwux xxx, %r1, xxx */
- || (faulting_insn & 0xFC1F8000) == 0x90018000 /* stw xxx, -yyy(%r1) */
- || (faulting_insn & 0xFC1F8000) == 0xD8018000 /* stfd xxx, -yyy(%r1) */
- || (faulting_insn & 0xFC1F8000) == 0xBC018000 /* stmw xxx, -yyy(%r1) */)
- {
- char *shell_name;
-
- fnotice (stderr, "Out of stack space.\n");
- shell_name = getenv ("SHELL");
- if (shell_name != NULL)
- shell_name = strrchr (shell_name, '/');
- if (shell_name != NULL)
- {
- static const char * shell_commands[][2] = {
- { "sh", "ulimit -S -s unlimited" },
- { "bash", "ulimit -S -s unlimited" },
- { "tcsh", "limit stacksize unlimited" },
- { "csh", "limit stacksize unlimited" },
- /* zsh doesn't have "unlimited", this will work under the
- default configuration. */
- { "zsh", "limit stacksize 32m" }
- };
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE (shell_commands); i++)
- if (strcmp (shell_commands[i][0], shell_name + 1) == 0)
- {
- fnotice (stderr,
- "Try running '%s' in the shell to raise its limit.\n",
- shell_commands[i][1]);
- }
- }
-
- if (global_dc->abort_on_error)
- fancy_abort (__FILE__, __LINE__, __FUNCTION__);
- exit (FATAL_EXIT_CODE);
- }
- fprintf (stderr, "[address=%08lx pc=%08x]\n",
- uc->uc_mcontext->MC_FLD(es).MC_FLD(dar),
- uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0));
- internal_error ("Segmentation Fault");
- exit (FATAL_EXIT_CODE);
- }
- static void
- darwin_rs6000_extra_signals (void)
- {
- struct sigaction sact;
- stack_t sigstk;
- sigstk.ss_sp = (char*)xmalloc (SIGSTKSZ);
- sigstk.ss_size = SIGSTKSZ;
- sigstk.ss_flags = 0;
- if (sigaltstack (&sigstk, NULL) < 0)
- fatal_error (input_location, "While setting up signal stack: %m");
- sigemptyset(&sact.sa_mask);
- sact.sa_flags = SA_ONSTACK | SA_SIGINFO;
- sact.sa_sigaction = segv_handler;
- if (sigaction (SIGSEGV, &sact, 0) < 0)
- fatal_error (input_location, "While setting up signal handler: %m");
- }
- const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
|