Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/powerpcspe/host-darwin.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Darwin/powerpc host-specific hook definitions. | |
2 Copyright (C) 2003-2017 Free Software Foundation, Inc. | |
3 | |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published | |
8 by the Free Software Foundation; either version 3, or (at your | |
9 option) any later version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
14 License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "diagnostic.h" | |
24 #include <sys/ucontext.h> | |
25 #include "hosthooks.h" | |
26 #include "hosthooks-def.h" | |
27 #include "config/host-darwin.h" | |
28 | |
29 static void segv_crash_handler (int); | |
30 static void segv_handler (int, siginfo_t *, void *); | |
31 static void darwin_rs6000_extra_signals (void); | |
32 | |
33 #ifndef HAVE_DECL_SIGALTSTACK | |
34 /* This doesn't have a prototype in signal.h in 10.2.x and earlier, | |
35 fixed in later releases. */ | |
36 extern int sigaltstack(const struct sigaltstack *, struct sigaltstack *); | |
37 #endif | |
38 | |
39 /* The fields of the mcontext_t type have acquired underscores in later | |
40 OS versions. */ | |
41 #ifdef HAS_MCONTEXT_T_UNDERSCORES | |
42 #define MC_FLD(x) __ ## x | |
43 #else | |
44 #define MC_FLD(x) x | |
45 #endif | |
46 | |
47 #undef HOST_HOOKS_EXTRA_SIGNALS | |
48 #define HOST_HOOKS_EXTRA_SIGNALS darwin_rs6000_extra_signals | |
49 | |
50 /* On Darwin/powerpc, hitting the stack limit turns into a SIGSEGV. | |
51 This code detects the difference between hitting the stack limit and | |
52 a true wild pointer dereference by looking at the instruction that | |
53 faulted; only a few kinds of instruction are used to access below | |
54 the previous bottom of the stack. */ | |
55 | |
56 static void | |
57 segv_crash_handler (int sig ATTRIBUTE_UNUSED) | |
58 { | |
59 internal_error ("Segmentation Fault (code)"); | |
60 } | |
61 | |
62 static void | |
63 segv_handler (int sig ATTRIBUTE_UNUSED, | |
64 siginfo_t *sip ATTRIBUTE_UNUSED, | |
65 void *scp) | |
66 { | |
67 ucontext_t *uc = (ucontext_t *)scp; | |
68 sigset_t sigset; | |
69 unsigned faulting_insn; | |
70 | |
71 /* The fault might have happened when trying to run some instruction, in | |
72 which case the next line will segfault _again_. Handle this case. */ | |
73 signal (SIGSEGV, segv_crash_handler); | |
74 sigemptyset (&sigset); | |
75 sigaddset (&sigset, SIGSEGV); | |
76 sigprocmask (SIG_UNBLOCK, &sigset, NULL); | |
77 | |
78 faulting_insn = *(unsigned *)uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0); | |
79 | |
80 /* Note that this only has to work for GCC, so we don't have to deal | |
81 with all the possible cases (GCC has no AltiVec code, for | |
82 instance). It's complicated because Darwin allows stores to | |
83 below the stack pointer, and the prologue code takes advantage of | |
84 this. */ | |
85 | |
86 if ((faulting_insn & 0xFFFF8000) == 0x94218000 /* stwu %r1, -xxx(%r1) */ | |
87 || (faulting_insn & 0xFC1F03FF) == 0x7C01016E /* stwux xxx, %r1, xxx */ | |
88 || (faulting_insn & 0xFC1F8000) == 0x90018000 /* stw xxx, -yyy(%r1) */ | |
89 || (faulting_insn & 0xFC1F8000) == 0xD8018000 /* stfd xxx, -yyy(%r1) */ | |
90 || (faulting_insn & 0xFC1F8000) == 0xBC018000 /* stmw xxx, -yyy(%r1) */) | |
91 { | |
92 char *shell_name; | |
93 | |
94 fnotice (stderr, "Out of stack space.\n"); | |
95 shell_name = getenv ("SHELL"); | |
96 if (shell_name != NULL) | |
97 shell_name = strrchr (shell_name, '/'); | |
98 if (shell_name != NULL) | |
99 { | |
100 static const char * shell_commands[][2] = { | |
101 { "sh", "ulimit -S -s unlimited" }, | |
102 { "bash", "ulimit -S -s unlimited" }, | |
103 { "tcsh", "limit stacksize unlimited" }, | |
104 { "csh", "limit stacksize unlimited" }, | |
105 /* zsh doesn't have "unlimited", this will work under the | |
106 default configuration. */ | |
107 { "zsh", "limit stacksize 32m" } | |
108 }; | |
109 size_t i; | |
110 | |
111 for (i = 0; i < ARRAY_SIZE (shell_commands); i++) | |
112 if (strcmp (shell_commands[i][0], shell_name + 1) == 0) | |
113 { | |
114 fnotice (stderr, | |
115 "Try running '%s' in the shell to raise its limit.\n", | |
116 shell_commands[i][1]); | |
117 } | |
118 } | |
119 | |
120 if (global_dc->abort_on_error) | |
121 fancy_abort (__FILE__, __LINE__, __FUNCTION__); | |
122 | |
123 exit (FATAL_EXIT_CODE); | |
124 } | |
125 | |
126 fprintf (stderr, "[address=%08lx pc=%08x]\n", | |
127 uc->uc_mcontext->MC_FLD(es).MC_FLD(dar), | |
128 uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0)); | |
129 internal_error ("Segmentation Fault"); | |
130 exit (FATAL_EXIT_CODE); | |
131 } | |
132 | |
133 static void | |
134 darwin_rs6000_extra_signals (void) | |
135 { | |
136 struct sigaction sact; | |
137 stack_t sigstk; | |
138 | |
139 sigstk.ss_sp = (char*)xmalloc (SIGSTKSZ); | |
140 sigstk.ss_size = SIGSTKSZ; | |
141 sigstk.ss_flags = 0; | |
142 if (sigaltstack (&sigstk, NULL) < 0) | |
143 fatal_error (input_location, "While setting up signal stack: %m"); | |
144 | |
145 sigemptyset(&sact.sa_mask); | |
146 sact.sa_flags = SA_ONSTACK | SA_SIGINFO; | |
147 sact.sa_sigaction = segv_handler; | |
148 if (sigaction (SIGSEGV, &sact, 0) < 0) | |
149 fatal_error (input_location, "While setting up signal handler: %m"); | |
150 } | |
151 | |
152 | |
153 const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; |