github.com/guyezi/gofrontend@v0.0.0-20200228202240-7a62a49e62c0/libgo/runtime/go-signal.c (about) 1 /* go-signal.c -- signal handling for Go. 2 3 Copyright 2009 The Go Authors. All rights reserved. 4 Use of this source code is governed by a BSD-style 5 license that can be found in the LICENSE file. */ 6 7 #include <signal.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <sys/time.h> 11 #include <ucontext.h> 12 13 #include "runtime.h" 14 15 #ifndef SA_RESTART 16 #define SA_RESTART 0 17 #endif 18 19 #ifdef USING_SPLIT_STACK 20 21 extern void __splitstack_getcontext(void *context[10]); 22 23 extern void __splitstack_setcontext(void *context[10]); 24 25 extern void *__splitstack_find_context(void *context[10], size_t *, 26 void **, void **, void **); 27 28 #endif 29 30 // The rest of the signal handler, written in Go. 31 32 extern void sigtrampgo(uint32, siginfo_t *, void *) 33 __asm__(GOSYM_PREFIX "runtime.sigtrampgo"); 34 35 // The Go signal handler, written in C. This should be running on the 36 // alternate signal stack. This is responsible for setting up the 37 // split stack context so that stack guard checks will work as 38 // expected. 39 40 void sigtramp(int, siginfo_t *, void *) 41 __attribute__ ((no_split_stack)); 42 43 void sigtramp(int, siginfo_t *, void *) 44 __asm__ (GOSYM_PREFIX "runtime.sigtramp"); 45 46 #ifndef USING_SPLIT_STACK 47 48 // When not using split stacks, there are no stack checks, and there 49 // is nothing special for this function to do. 50 51 void 52 sigtramp(int sig, siginfo_t *info, void *context) 53 { 54 sigtrampgo(sig, info, context); 55 } 56 57 #else // USING_SPLIT_STACK 58 59 void 60 sigtramp(int sig, siginfo_t *info, void *context) 61 { 62 G *gp; 63 void *stack_context[10]; 64 void *stack; 65 size_t stack_size; 66 void *next_segment; 67 void *next_sp; 68 void *initial_sp; 69 uintptr sp; 70 stack_t st; 71 uintptr stsp; 72 73 gp = runtime_g(); 74 75 if (gp == nil) { 76 // Let the Go code handle this case. 77 // It should only call nosplit functions in this case. 78 sigtrampgo(sig, info, context); 79 return; 80 } 81 82 // If this signal is one for which we will panic, we are not 83 // on the alternate signal stack. It's OK to call split-stack 84 // functions here. 85 if (sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV) { 86 sigtrampgo(sig, info, context); 87 return; 88 } 89 90 // We are running on the alternate signal stack. 91 92 __splitstack_getcontext(&stack_context[0]); 93 94 stack = __splitstack_find_context((void*)(&gp->m->gsignal->stackcontext[0]), 95 &stack_size, &next_segment, 96 &next_sp, &initial_sp); 97 98 // If some non-Go code called sigaltstack, adjust. 99 sp = (uintptr)(&stack_size); 100 if (sp < (uintptr)(stack) || sp >= (uintptr)(stack) + stack_size) { 101 sigaltstack(nil, &st); 102 if ((st.ss_flags & SS_DISABLE) != 0) { 103 runtime_printf("signal %d received on thread with no signal stack\n", (int32)(sig)); 104 runtime_throw("non-Go code disabled sigaltstack"); 105 } 106 107 stsp = (uintptr)(st.ss_sp); 108 if (sp < stsp || sp >= stsp + st.ss_size) { 109 runtime_printf("signal %d received but handler not on signal stack\n", (int32)(sig)); 110 runtime_throw("non-Go code set up signal handler without SA_ONSTACK flag"); 111 } 112 113 // Unfortunately __splitstack_find_context will return NULL 114 // when it is called on a context that has never been used. 115 // There isn't much we can do but assume all is well. 116 if (stack != NULL) { 117 // Here the gc runtime adjusts the gsignal 118 // stack guard to match the values returned by 119 // sigaltstack. Unfortunately we have no way 120 // to do that. 121 runtime_printf("signal %d received on unknown signal stack\n", (int32)(sig)); 122 runtime_throw("non-Go code changed signal stack"); 123 } 124 } 125 126 // Set the split stack context so that the stack guards are 127 // checked correctly. 128 129 __splitstack_setcontext((void*)(&gp->m->gsignal->stackcontext[0])); 130 131 sigtrampgo(sig, info, context); 132 133 // We are going to return back to the signal trampoline and 134 // then to whatever we were doing before we got the signal. 135 // Restore the split stack context so that stack guards are 136 // checked correctly. 137 138 __splitstack_setcontext(&stack_context[0]); 139 } 140 141 #endif // USING_SPLIT_STACK 142 143 // C function to return the address of the sigtramp function. 144 uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp"); 145 146 uintptr 147 getSigtramp() 148 { 149 return (uintptr)(void*)sigtramp; 150 } 151 152 // C code to manage the sigaction sa_sigaction field, which is 153 // typically a union and so hard for mksysinfo.sh to handle. 154 155 uintptr getSigactionHandler(struct sigaction*) 156 __attribute__ ((no_split_stack)); 157 158 uintptr getSigactionHandler(struct sigaction*) 159 __asm__ (GOSYM_PREFIX "runtime.getSigactionHandler"); 160 161 uintptr 162 getSigactionHandler(struct sigaction* sa) 163 { 164 return (uintptr)(sa->sa_sigaction); 165 } 166 167 void setSigactionHandler(struct sigaction*, uintptr) 168 __attribute__ ((no_split_stack)); 169 170 void setSigactionHandler(struct sigaction*, uintptr) 171 __asm__ (GOSYM_PREFIX "runtime.setSigactionHandler"); 172 173 void 174 setSigactionHandler(struct sigaction* sa, uintptr handler) 175 { 176 sa->sa_sigaction = (void*)(handler); 177 } 178 179 // C code to fetch values from the siginfo_t and ucontext_t pointers 180 // passed to a signal handler. 181 182 struct getSiginfoRet { 183 uintptr sigaddr; 184 uintptr sigpc; 185 }; 186 187 struct getSiginfoRet getSiginfo(siginfo_t *, void *) 188 __asm__(GOSYM_PREFIX "runtime.getSiginfo"); 189 190 struct getSiginfoRet 191 getSiginfo(siginfo_t *info, void *context __attribute__((unused))) 192 { 193 struct getSiginfoRet ret; 194 Location loc[1]; 195 int32 n; 196 197 if (info == nil) { 198 ret.sigaddr = 0; 199 } else { 200 ret.sigaddr = (uintptr)(info->si_addr); 201 } 202 ret.sigpc = 0; 203 204 // There doesn't seem to be a portable way to get the PC. 205 // Use unportable code to pull it from context, and if that fails 206 // try a stack backtrace across the signal handler. 207 208 #if defined(__x86_64__) && defined(__linux__) 209 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP]; 210 #elif defined(__i386__) && defined(__linux__) 211 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP]; 212 #elif defined(__alpha__) && defined(__linux__) 213 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc; 214 #elif defined(__PPC__) && defined(__linux__) 215 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.regs->nip; 216 #elif defined(__PPC__) && defined(_AIX) 217 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar; 218 #elif defined(__aarch64__) && defined(__linux__) 219 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc; 220 #endif 221 222 if (ret.sigpc == 0) { 223 // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler. 224 n = runtime_callers(5, &loc[0], 1, false); 225 if (n > 0) { 226 ret.sigpc = loc[0].pc; 227 } 228 } 229 230 return ret; 231 } 232 233 // Dump registers when crashing in a signal. 234 // There is no portable way to write this, 235 // so we just have some CPU/OS specific implementations. 236 237 void dumpregs(siginfo_t *, void *) 238 __asm__(GOSYM_PREFIX "runtime.dumpregs"); 239 240 void 241 dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused))) 242 { 243 #if defined(__x86_64__) && defined(__linux__) 244 { 245 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 246 247 runtime_printf("rax %X\n", m->gregs[REG_RAX]); 248 runtime_printf("rbx %X\n", m->gregs[REG_RBX]); 249 runtime_printf("rcx %X\n", m->gregs[REG_RCX]); 250 runtime_printf("rdx %X\n", m->gregs[REG_RDX]); 251 runtime_printf("rdi %X\n", m->gregs[REG_RDI]); 252 runtime_printf("rsi %X\n", m->gregs[REG_RSI]); 253 runtime_printf("rbp %X\n", m->gregs[REG_RBP]); 254 runtime_printf("rsp %X\n", m->gregs[REG_RSP]); 255 runtime_printf("r8 %X\n", m->gregs[REG_R8]); 256 runtime_printf("r9 %X\n", m->gregs[REG_R9]); 257 runtime_printf("r10 %X\n", m->gregs[REG_R10]); 258 runtime_printf("r11 %X\n", m->gregs[REG_R11]); 259 runtime_printf("r12 %X\n", m->gregs[REG_R12]); 260 runtime_printf("r13 %X\n", m->gregs[REG_R13]); 261 runtime_printf("r14 %X\n", m->gregs[REG_R14]); 262 runtime_printf("r15 %X\n", m->gregs[REG_R15]); 263 runtime_printf("rip %X\n", m->gregs[REG_RIP]); 264 runtime_printf("rflags %X\n", m->gregs[REG_EFL]); 265 runtime_printf("cs %X\n", m->gregs[REG_CSGSFS] & 0xffff); 266 runtime_printf("fs %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff); 267 runtime_printf("gs %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff); 268 } 269 #elif defined(__i386__) && defined(__linux__) 270 { 271 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 272 273 runtime_printf("eax %x\n", m->gregs[REG_EAX]); 274 runtime_printf("ebx %x\n", m->gregs[REG_EBX]); 275 runtime_printf("ecx %x\n", m->gregs[REG_ECX]); 276 runtime_printf("edx %x\n", m->gregs[REG_EDX]); 277 runtime_printf("edi %x\n", m->gregs[REG_EDI]); 278 runtime_printf("esi %x\n", m->gregs[REG_ESI]); 279 runtime_printf("ebp %x\n", m->gregs[REG_EBP]); 280 runtime_printf("esp %x\n", m->gregs[REG_ESP]); 281 runtime_printf("eip %x\n", m->gregs[REG_EIP]); 282 runtime_printf("eflags %x\n", m->gregs[REG_EFL]); 283 runtime_printf("cs %x\n", m->gregs[REG_CS]); 284 runtime_printf("fs %x\n", m->gregs[REG_FS]); 285 runtime_printf("gs %x\n", m->gregs[REG_GS]); 286 } 287 #elif defined(__alpha__) && defined(__linux__) 288 { 289 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 290 291 runtime_printf("v0 %X\n", m->sc_regs[0]); 292 runtime_printf("t0 %X\n", m->sc_regs[1]); 293 runtime_printf("t1 %X\n", m->sc_regs[2]); 294 runtime_printf("t2 %X\n", m->sc_regs[3]); 295 runtime_printf("t3 %X\n", m->sc_regs[4]); 296 runtime_printf("t4 %X\n", m->sc_regs[5]); 297 runtime_printf("t5 %X\n", m->sc_regs[6]); 298 runtime_printf("t6 %X\n", m->sc_regs[7]); 299 runtime_printf("t7 %X\n", m->sc_regs[8]); 300 runtime_printf("s0 %X\n", m->sc_regs[9]); 301 runtime_printf("s1 %X\n", m->sc_regs[10]); 302 runtime_printf("s2 %X\n", m->sc_regs[11]); 303 runtime_printf("s3 %X\n", m->sc_regs[12]); 304 runtime_printf("s4 %X\n", m->sc_regs[13]); 305 runtime_printf("s5 %X\n", m->sc_regs[14]); 306 runtime_printf("fp %X\n", m->sc_regs[15]); 307 runtime_printf("a0 %X\n", m->sc_regs[16]); 308 runtime_printf("a1 %X\n", m->sc_regs[17]); 309 runtime_printf("a2 %X\n", m->sc_regs[18]); 310 runtime_printf("a3 %X\n", m->sc_regs[19]); 311 runtime_printf("a4 %X\n", m->sc_regs[20]); 312 runtime_printf("a5 %X\n", m->sc_regs[21]); 313 runtime_printf("t8 %X\n", m->sc_regs[22]); 314 runtime_printf("t9 %X\n", m->sc_regs[23]); 315 runtime_printf("t10 %X\n", m->sc_regs[24]); 316 runtime_printf("t11 %X\n", m->sc_regs[25]); 317 runtime_printf("ra %X\n", m->sc_regs[26]); 318 runtime_printf("t12 %X\n", m->sc_regs[27]); 319 runtime_printf("at %X\n", m->sc_regs[28]); 320 runtime_printf("gp %X\n", m->sc_regs[29]); 321 runtime_printf("sp %X\n", m->sc_regs[30]); 322 runtime_printf("pc %X\n", m->sc_pc); 323 } 324 #elif defined(__PPC__) && defined(__LITTLE_ENDIAN__) && defined(__linux__) 325 { 326 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 327 int i; 328 329 for (i = 0; i < 32; i++) 330 runtime_printf("r%d %X\n", i, m->regs->gpr[i]); 331 runtime_printf("pc %X\n", m->regs->nip); 332 runtime_printf("msr %X\n", m->regs->msr); 333 runtime_printf("cr %X\n", m->regs->ccr); 334 runtime_printf("lr %X\n", m->regs->link); 335 runtime_printf("ctr %X\n", m->regs->ctr); 336 runtime_printf("xer %X\n", m->regs->xer); 337 } 338 #elif defined(__PPC__) && defined(_AIX) 339 { 340 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 341 int i; 342 343 for (i = 0; i < 32; i++) 344 runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]); 345 runtime_printf("pc %p\n", m->jmp_context.iar); 346 runtime_printf("msr %p\n", m->jmp_context.msr); 347 runtime_printf("cr %x\n", m->jmp_context.cr); 348 runtime_printf("lr %p\n", m->jmp_context.lr); 349 runtime_printf("ctr %p\n", m->jmp_context.ctr); 350 runtime_printf("xer %x\n", m->jmp_context.xer); 351 } 352 #elif defined(__aarch64__) && defined(__linux__) 353 { 354 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 355 int i; 356 357 for (i = 0; i < 31; i++) 358 runtime_printf("x%d %X\n", i, m->regs[i]); 359 runtime_printf("sp %X\n", m->sp); 360 runtime_printf("pc %X\n", m->pc); 361 runtime_printf("pstate %X\n", m->pstate); 362 } 363 #endif 364 }