]>
Commit | Line | Data |
---|---|---|
476d9098 | 1 | /* Darwin/powerpc host-specific hook definitions. |
83ffe9cd | 2 | Copyright (C) 2003-2023 Free Software Foundation, Inc. |
476d9098 | 3 | |
5de601cf NC |
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 | |
2f83c7d6 | 8 | by the Free Software Foundation; either version 3, or (at your |
5de601cf NC |
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 | |
2f83c7d6 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
476d9098 | 19 | |
8fcc61f8 RS |
20 | #define IN_TARGET_CODE 1 |
21 | ||
476d9098 GK |
22 | #include "config.h" |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
e11c4407 | 25 | #include "diagnostic.h" |
476d9098 GK |
26 | #include <sys/ucontext.h> |
27 | #include "hosthooks.h" | |
28 | #include "hosthooks-def.h" | |
ed23bd30 | 29 | #include "config/host-darwin.h" |
476d9098 | 30 | |
5f5bfdd0 GK |
31 | static void segv_crash_handler (int); |
32 | static void segv_handler (int, siginfo_t *, void *); | |
33 | static void darwin_rs6000_extra_signals (void); | |
476d9098 | 34 | |
4f6d8cc8 | 35 | #ifndef HAVE_DECL_SIGALTSTACK |
5f5bfdd0 GK |
36 | /* This doesn't have a prototype in signal.h in 10.2.x and earlier, |
37 | fixed in later releases. */ | |
38 | extern int sigaltstack(const struct sigaltstack *, struct sigaltstack *); | |
4f6d8cc8 GK |
39 | #endif |
40 | ||
41 | /* The fields of the mcontext_t type have acquired underscores in later | |
42 | OS versions. */ | |
43 | #ifdef HAS_MCONTEXT_T_UNDERSCORES | |
44 | #define MC_FLD(x) __ ## x | |
45 | #else | |
46 | #define MC_FLD(x) x | |
47 | #endif | |
476d9098 GK |
48 | |
49 | #undef HOST_HOOKS_EXTRA_SIGNALS | |
50 | #define HOST_HOOKS_EXTRA_SIGNALS darwin_rs6000_extra_signals | |
51 | ||
a693fbb9 GK |
52 | /* On Darwin/powerpc, hitting the stack limit turns into a SIGSEGV. |
53 | This code detects the difference between hitting the stack limit and | |
54 | a true wild pointer dereference by looking at the instruction that | |
55 | faulted; only a few kinds of instruction are used to access below | |
56 | the previous bottom of the stack. */ | |
476d9098 GK |
57 | |
58 | static void | |
5f5bfdd0 | 59 | segv_crash_handler (int sig ATTRIBUTE_UNUSED) |
476d9098 | 60 | { |
206222e0 | 61 | internal_error ("segmentation fault (code)"); |
476d9098 GK |
62 | } |
63 | ||
64 | static void | |
5f5bfdd0 GK |
65 | segv_handler (int sig ATTRIBUTE_UNUSED, |
66 | siginfo_t *sip ATTRIBUTE_UNUSED, | |
67 | void *scp) | |
476d9098 GK |
68 | { |
69 | ucontext_t *uc = (ucontext_t *)scp; | |
68e58c33 | 70 | sigset_t sigset; |
476d9098 GK |
71 | unsigned faulting_insn; |
72 | ||
73 | /* The fault might have happened when trying to run some instruction, in | |
74 | which case the next line will segfault _again_. Handle this case. */ | |
75 | signal (SIGSEGV, segv_crash_handler); | |
68e58c33 GK |
76 | sigemptyset (&sigset); |
77 | sigaddset (&sigset, SIGSEGV); | |
78 | sigprocmask (SIG_UNBLOCK, &sigset, NULL); | |
476d9098 | 79 | |
4f6d8cc8 | 80 | faulting_insn = *(unsigned *)uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0); |
476d9098 GK |
81 | |
82 | /* Note that this only has to work for GCC, so we don't have to deal | |
83 | with all the possible cases (GCC has no AltiVec code, for | |
84 | instance). It's complicated because Darwin allows stores to | |
85 | below the stack pointer, and the prologue code takes advantage of | |
86 | this. */ | |
87 | ||
88 | if ((faulting_insn & 0xFFFF8000) == 0x94218000 /* stwu %r1, -xxx(%r1) */ | |
f8ed6473 | 89 | || (faulting_insn & 0xFC1F03FF) == 0x7C01016E /* stwux xxx, %r1, xxx */ |
476d9098 GK |
90 | || (faulting_insn & 0xFC1F8000) == 0x90018000 /* stw xxx, -yyy(%r1) */ |
91 | || (faulting_insn & 0xFC1F8000) == 0xD8018000 /* stfd xxx, -yyy(%r1) */ | |
92 | || (faulting_insn & 0xFC1F8000) == 0xBC018000 /* stmw xxx, -yyy(%r1) */) | |
93 | { | |
94 | char *shell_name; | |
95 | ||
96 | fnotice (stderr, "Out of stack space.\n"); | |
97 | shell_name = getenv ("SHELL"); | |
98 | if (shell_name != NULL) | |
99 | shell_name = strrchr (shell_name, '/'); | |
100 | if (shell_name != NULL) | |
101 | { | |
102 | static const char * shell_commands[][2] = { | |
103 | { "sh", "ulimit -S -s unlimited" }, | |
104 | { "bash", "ulimit -S -s unlimited" }, | |
105 | { "tcsh", "limit stacksize unlimited" }, | |
106 | { "csh", "limit stacksize unlimited" }, | |
107 | /* zsh doesn't have "unlimited", this will work under the | |
108 | default configuration. */ | |
109 | { "zsh", "limit stacksize 32m" } | |
110 | }; | |
111 | size_t i; | |
112 | ||
113 | for (i = 0; i < ARRAY_SIZE (shell_commands); i++) | |
114 | if (strcmp (shell_commands[i][0], shell_name + 1) == 0) | |
115 | { | |
116 | fnotice (stderr, | |
9e637a26 | 117 | "Try running '%s' in the shell to raise its limit.\n", |
476d9098 GK |
118 | shell_commands[i][1]); |
119 | } | |
120 | } | |
121 | ||
505b0fd6 | 122 | if (global_dc->abort_on_error) |
992d08b1 | 123 | fancy_abort (__FILE__, __LINE__, __FUNCTION__); |
505b0fd6 | 124 | |
476d9098 GK |
125 | exit (FATAL_EXIT_CODE); |
126 | } | |
127 | ||
128 | fprintf (stderr, "[address=%08lx pc=%08x]\n", | |
4f6d8cc8 GK |
129 | uc->uc_mcontext->MC_FLD(es).MC_FLD(dar), |
130 | uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0)); | |
206222e0 | 131 | internal_error ("segmentation fault"); |
476d9098 GK |
132 | exit (FATAL_EXIT_CODE); |
133 | } | |
134 | ||
135 | static void | |
5f5bfdd0 | 136 | darwin_rs6000_extra_signals (void) |
476d9098 GK |
137 | { |
138 | struct sigaction sact; | |
139 | stack_t sigstk; | |
140 | ||
33c7eedf | 141 | sigstk.ss_sp = (char*)xmalloc (SIGSTKSZ); |
476d9098 GK |
142 | sigstk.ss_size = SIGSTKSZ; |
143 | sigstk.ss_flags = 0; | |
144 | if (sigaltstack (&sigstk, NULL) < 0) | |
40fecdd6 | 145 | fatal_error (input_location, "While setting up signal stack: %m"); |
476d9098 GK |
146 | |
147 | sigemptyset(&sact.sa_mask); | |
148 | sact.sa_flags = SA_ONSTACK | SA_SIGINFO; | |
149 | sact.sa_sigaction = segv_handler; | |
150 | if (sigaction (SIGSEGV, &sact, 0) < 0) | |
40fecdd6 | 151 | fatal_error (input_location, "While setting up signal handler: %m"); |
476d9098 | 152 | } |
18c81520 | 153 | \f |
476d9098 GK |
154 | |
155 | const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER; |