github.com/golang/gofrontend@v0.0.0-20240429183944-60f985a78526/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 void *find_stack; 66 size_t stack_size; 67 void *next_segment; 68 void *next_sp; 69 void *initial_sp; 70 uintptr sp; 71 stack_t st; 72 uintptr stsp; 73 74 gp = runtime_g(); 75 76 if (gp == nil) { 77 // Let the Go code handle this case. 78 // It should only call nosplit functions in this case. 79 sigtrampgo(sig, info, context); 80 return; 81 } 82 83 // If this signal is one for which we will panic, we are not 84 // on the alternate signal stack. It's OK to call split-stack 85 // functions here. 86 if (sig == SIGBUS || sig == SIGFPE || sig == SIGSEGV) { 87 sigtrampgo(sig, info, context); 88 return; 89 } 90 91 // We are running on the alternate signal stack. 92 93 __splitstack_getcontext(&stack_context[0]); 94 95 find_stack = 96 __splitstack_find_context((void*)(&gp->m->gsignal->stackcontext[0]), 97 &stack_size, &next_segment, 98 &next_sp, &initial_sp); 99 stack = find_stack; 100 if (stack == NULL) { 101 stack = gp->m->gsignalstack; 102 stack_size = gp->m->gsignalstacksize; 103 } 104 105 // If some non-Go code called sigaltstack, adjust. 106 sp = (uintptr)(&stack_size); 107 if (sp < (uintptr)(stack) || sp >= (uintptr)(stack) + stack_size) { 108 sigaltstack(nil, &st); 109 if ((st.ss_flags & SS_DISABLE) != 0) { 110 runtime_printf("signal %d received on thread with no signal stack\n", (int32)(sig)); 111 runtime_throw("non-Go code disabled sigaltstack"); 112 } 113 114 stsp = (uintptr)(st.ss_sp); 115 if (sp < stsp || sp >= stsp + st.ss_size) { 116 runtime_printf("signal %d received but handler not on signal stack\n", (int32)(sig)); 117 runtime_throw("non-Go code set up signal handler without SA_ONSTACK flag"); 118 } 119 120 // Unfortunately __splitstack_find_context will return NULL 121 // when it is called on a context that has never been used. 122 // There isn't much we can do but assume all is well. 123 if (find_stack != NULL) { 124 // Here the gc runtime adjusts the gsignal 125 // stack guard to match the values returned by 126 // sigaltstack. Unfortunately we have no way 127 // to do that. 128 runtime_printf("signal %d received on unknown signal stack\n", (int32)(sig)); 129 runtime_throw("non-Go code changed signal stack"); 130 } 131 } 132 133 // Set the split stack context so that the stack guards are 134 // checked correctly. 135 136 __splitstack_setcontext((void*)(&gp->m->gsignal->stackcontext[0])); 137 138 sigtrampgo(sig, info, context); 139 140 // We are going to return back to the signal trampoline and 141 // then to whatever we were doing before we got the signal. 142 // Restore the split stack context so that stack guards are 143 // checked correctly. 144 145 __splitstack_setcontext(&stack_context[0]); 146 } 147 148 #endif // USING_SPLIT_STACK 149 150 // C function to return the address of the sigtramp function. 151 uintptr getSigtramp(void) __asm__ (GOSYM_PREFIX "runtime.getSigtramp"); 152 153 uintptr 154 getSigtramp() 155 { 156 return (uintptr)(void*)sigtramp; 157 } 158 159 // C code to manage the sigaction sa_sigaction field, which is 160 // typically a union and so hard for mksysinfo.sh to handle. 161 162 uintptr getSigactionHandler(struct sigaction*) 163 __attribute__ ((no_split_stack)); 164 165 uintptr getSigactionHandler(struct sigaction*) 166 __asm__ (GOSYM_PREFIX "runtime.getSigactionHandler"); 167 168 uintptr 169 getSigactionHandler(struct sigaction* sa) 170 { 171 return (uintptr)(sa->sa_sigaction); 172 } 173 174 void setSigactionHandler(struct sigaction*, uintptr) 175 __attribute__ ((no_split_stack)); 176 177 void setSigactionHandler(struct sigaction*, uintptr) 178 __asm__ (GOSYM_PREFIX "runtime.setSigactionHandler"); 179 180 void 181 setSigactionHandler(struct sigaction* sa, uintptr handler) 182 { 183 sa->sa_sigaction = (void*)(handler); 184 } 185 186 #ifdef __linux__ 187 188 // Workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=27417 189 #ifndef sigev_notify_thread_id 190 #define sigev_notify_thread_id _sigev_un._tid 191 #endif 192 193 void setSigeventTID(struct sigevent*, int32_t) 194 __asm__ (GOSYM_PREFIX "runtime.setSigeventTID"); 195 196 void 197 setSigeventTID(struct sigevent *sev, int32_t v) 198 { 199 sev->sigev_notify_thread_id = v; 200 } 201 202 #endif // defined(__linux__) 203 204 // C code to fetch values from the siginfo_t and ucontext_t pointers 205 // passed to a signal handler. 206 207 uintptr getSiginfoCode(siginfo_t *) 208 __attribute__ ((no_split_stack)); 209 210 uintptr getSiginfoCode(siginfo_t *) 211 __asm__ (GOSYM_PREFIX "runtime.getSiginfoCode"); 212 213 uintptr 214 getSiginfoCode(siginfo_t *info) 215 { 216 return (uintptr)(info->si_code); 217 } 218 219 #if defined(__sparc__) && defined(__arch64__) && defined(__linux__) 220 #define gregs mc_gregs 221 #endif 222 223 struct getSiginfoRet { 224 uintptr sigaddr; 225 uintptr sigpc; 226 }; 227 228 struct getSiginfoRet getSiginfo(siginfo_t *, void *) 229 __asm__(GOSYM_PREFIX "runtime.getSiginfo"); 230 231 struct getSiginfoRet 232 getSiginfo(siginfo_t *info, void *context __attribute__((unused))) 233 { 234 struct getSiginfoRet ret; 235 Location loc[1]; 236 int32 n; 237 238 if (info == nil) { 239 ret.sigaddr = 0; 240 } else { 241 ret.sigaddr = (uintptr)(info->si_addr); 242 } 243 ret.sigpc = 0; 244 245 // There doesn't seem to be a portable way to get the PC. 246 // Use unportable code to pull it from context, and if that fails 247 // try a stack backtrace across the signal handler. 248 249 #if defined(__x86_64__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 250 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP]; 251 #elif defined(__i386__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 252 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP]; 253 #elif defined(__alpha__) && defined(__linux__) 254 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc; 255 #elif defined(__PPC64__) && defined(__linux__) 256 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gp_regs[32]; 257 #elif defined(__PPC__) && defined(__linux__) 258 # if defined(__GLIBC__) 259 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.uc_regs->gregs[32]; 260 # else 261 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[32]; 262 # endif 263 #elif defined(__PPC__) && defined(_AIX) 264 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar; 265 #elif defined(__aarch64__) && defined(__linux__) 266 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc; 267 #elif defined(__NetBSD__) 268 ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context))); 269 #endif 270 #if defined(__sparc__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 271 ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_PC]; 272 #endif 273 274 if (ret.sigpc == 0) { 275 // Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler. 276 n = runtime_callers(5, &loc[0], 1, false); 277 if (n > 0) { 278 ret.sigpc = loc[0].pc; 279 } 280 } 281 282 return ret; 283 } 284 285 // Dump registers when crashing in a signal. 286 // There is no portable way to write this, 287 // so we just have some CPU/OS specific implementations. 288 289 void dumpregs(siginfo_t *, void *) 290 __asm__(GOSYM_PREFIX "runtime.dumpregs"); 291 292 void 293 dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused))) 294 { 295 #if defined(__x86_64__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 296 { 297 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 298 299 runtime_printf("rax %X\n", m->gregs[REG_RAX]); 300 runtime_printf("rbx %X\n", m->gregs[REG_RBX]); 301 runtime_printf("rcx %X\n", m->gregs[REG_RCX]); 302 runtime_printf("rdx %X\n", m->gregs[REG_RDX]); 303 runtime_printf("rdi %X\n", m->gregs[REG_RDI]); 304 runtime_printf("rsi %X\n", m->gregs[REG_RSI]); 305 runtime_printf("rbp %X\n", m->gregs[REG_RBP]); 306 runtime_printf("rsp %X\n", m->gregs[REG_RSP]); 307 runtime_printf("r8 %X\n", m->gregs[REG_R8]); 308 runtime_printf("r9 %X\n", m->gregs[REG_R9]); 309 runtime_printf("r10 %X\n", m->gregs[REG_R10]); 310 runtime_printf("r11 %X\n", m->gregs[REG_R11]); 311 runtime_printf("r12 %X\n", m->gregs[REG_R12]); 312 runtime_printf("r13 %X\n", m->gregs[REG_R13]); 313 runtime_printf("r14 %X\n", m->gregs[REG_R14]); 314 runtime_printf("r15 %X\n", m->gregs[REG_R15]); 315 runtime_printf("rip %X\n", m->gregs[REG_RIP]); 316 #if defined(REG_EFL) 317 runtime_printf("rflags %X\n", m->gregs[REG_EFL]); 318 #elif defined(REG_RFL) 319 runtime_printf("rflags %X\n", m->gregs[REG_RFL]); 320 #endif 321 #if defined(REG_CSGSFS) 322 runtime_printf("cs %X\n", m->gregs[REG_CSGSFS] & 0xffff); 323 runtime_printf("fs %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff); 324 runtime_printf("gs %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff); 325 #elif defined(REG_CS) && defined(REG_FS) && defined(REG_GS) 326 runtime_printf("cs %X\n", m->gregs[REG_CS]); 327 runtime_printf("fs %X\n", m->gregs[REG_FS]); 328 runtime_printf("gs %X\n", m->gregs[REG_GS]); 329 #endif 330 } 331 #elif defined(__i386__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 332 { 333 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 334 335 runtime_printf("eax %x\n", m->gregs[REG_EAX]); 336 runtime_printf("ebx %x\n", m->gregs[REG_EBX]); 337 runtime_printf("ecx %x\n", m->gregs[REG_ECX]); 338 runtime_printf("edx %x\n", m->gregs[REG_EDX]); 339 runtime_printf("edi %x\n", m->gregs[REG_EDI]); 340 runtime_printf("esi %x\n", m->gregs[REG_ESI]); 341 runtime_printf("ebp %x\n", m->gregs[REG_EBP]); 342 runtime_printf("esp %x\n", m->gregs[REG_ESP]); 343 runtime_printf("eip %x\n", m->gregs[REG_EIP]); 344 runtime_printf("eflags %x\n", m->gregs[REG_EFL]); 345 runtime_printf("cs %x\n", m->gregs[REG_CS]); 346 runtime_printf("fs %x\n", m->gregs[REG_FS]); 347 runtime_printf("gs %x\n", m->gregs[REG_GS]); 348 } 349 #elif defined(__alpha__) && defined(__linux__) 350 { 351 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 352 353 runtime_printf("v0 %X\n", m->sc_regs[0]); 354 runtime_printf("t0 %X\n", m->sc_regs[1]); 355 runtime_printf("t1 %X\n", m->sc_regs[2]); 356 runtime_printf("t2 %X\n", m->sc_regs[3]); 357 runtime_printf("t3 %X\n", m->sc_regs[4]); 358 runtime_printf("t4 %X\n", m->sc_regs[5]); 359 runtime_printf("t5 %X\n", m->sc_regs[6]); 360 runtime_printf("t6 %X\n", m->sc_regs[7]); 361 runtime_printf("t7 %X\n", m->sc_regs[8]); 362 runtime_printf("s0 %X\n", m->sc_regs[9]); 363 runtime_printf("s1 %X\n", m->sc_regs[10]); 364 runtime_printf("s2 %X\n", m->sc_regs[11]); 365 runtime_printf("s3 %X\n", m->sc_regs[12]); 366 runtime_printf("s4 %X\n", m->sc_regs[13]); 367 runtime_printf("s5 %X\n", m->sc_regs[14]); 368 runtime_printf("fp %X\n", m->sc_regs[15]); 369 runtime_printf("a0 %X\n", m->sc_regs[16]); 370 runtime_printf("a1 %X\n", m->sc_regs[17]); 371 runtime_printf("a2 %X\n", m->sc_regs[18]); 372 runtime_printf("a3 %X\n", m->sc_regs[19]); 373 runtime_printf("a4 %X\n", m->sc_regs[20]); 374 runtime_printf("a5 %X\n", m->sc_regs[21]); 375 runtime_printf("t8 %X\n", m->sc_regs[22]); 376 runtime_printf("t9 %X\n", m->sc_regs[23]); 377 runtime_printf("t10 %X\n", m->sc_regs[24]); 378 runtime_printf("t11 %X\n", m->sc_regs[25]); 379 runtime_printf("ra %X\n", m->sc_regs[26]); 380 runtime_printf("t12 %X\n", m->sc_regs[27]); 381 runtime_printf("at %X\n", m->sc_regs[28]); 382 runtime_printf("gp %X\n", m->sc_regs[29]); 383 runtime_printf("sp %X\n", m->sc_regs[30]); 384 runtime_printf("pc %X\n", m->sc_pc); 385 } 386 #elif defined(__PPC__) && defined(__linux__) 387 { 388 int i; 389 390 # if defined(__PPC64__) 391 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 392 393 for (i = 0; i < 32; i++) 394 runtime_printf("r%d %X\n", i, m->gp_regs[i]); 395 runtime_printf("pc %X\n", m->gp_regs[32]); 396 runtime_printf("msr %X\n", m->gp_regs[33]); 397 runtime_printf("cr %X\n", m->gp_regs[38]); 398 runtime_printf("lr %X\n", m->gp_regs[36]); 399 runtime_printf("ctr %X\n", m->gp_regs[35]); 400 runtime_printf("xer %X\n", m->gp_regs[37]); 401 # else 402 # if defined(__GLIBC__) 403 mcontext_t *m = ((ucontext_t*)(context))->uc_mcontext.uc_regs; 404 # else 405 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 406 # endif 407 408 for (i = 0; i < 32; i++) 409 runtime_printf("r%d %x\n", i, m->gregs[i]); 410 runtime_printf("pc %x\n", m->gregs[32]); 411 runtime_printf("msr %x\n", m->gregs[33]); 412 runtime_printf("cr %x\n", m->gregs[38]); 413 runtime_printf("lr %x\n", m->gregs[36]); 414 runtime_printf("ctr %x\n", m->gregs[35]); 415 runtime_printf("xer %x\n", m->gregs[37]); 416 # endif 417 } 418 #elif defined(__PPC__) && defined(_AIX) 419 { 420 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 421 int i; 422 423 for (i = 0; i < 32; i++) 424 runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]); 425 runtime_printf("pc %p\n", m->jmp_context.iar); 426 runtime_printf("msr %p\n", m->jmp_context.msr); 427 runtime_printf("cr %x\n", m->jmp_context.cr); 428 runtime_printf("lr %p\n", m->jmp_context.lr); 429 runtime_printf("ctr %p\n", m->jmp_context.ctr); 430 runtime_printf("xer %x\n", m->jmp_context.xer); 431 } 432 #elif defined(__aarch64__) && defined(__linux__) 433 { 434 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 435 int i; 436 437 for (i = 0; i < 31; i++) 438 runtime_printf("x%d %X\n", i, m->regs[i]); 439 runtime_printf("sp %X\n", m->sp); 440 runtime_printf("pc %X\n", m->pc); 441 runtime_printf("pstate %X\n", m->pstate); 442 } 443 #elif defined(__sparc__) && (defined(__linux__) || (defined(__sun__) && defined(__svr4__))) 444 { 445 mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext; 446 447 #ifdef __sparcv9 448 #define REG_FMT "%X" 449 #else 450 #define REG_FMT "%x" 451 #endif 452 453 #ifdef REG_CCR 454 runtime_printf("ccr " REG_FMT "\n", m->gregs[REG_CCR]); 455 #else 456 runtime_printf("psr " REG_FMT "\n", m->gregs[REG_PSR]); 457 #endif 458 runtime_printf("pc " REG_FMT "\n", m->gregs[REG_PC]); 459 runtime_printf("npc " REG_FMT "\n", m->gregs[REG_nPC]); 460 runtime_printf("y " REG_FMT "\n", m->gregs[REG_Y]); 461 runtime_printf("g1 " REG_FMT "\n", m->gregs[REG_G1]); 462 runtime_printf("g2 " REG_FMT "\n", m->gregs[REG_G2]); 463 runtime_printf("g3 " REG_FMT "\n", m->gregs[REG_G3]); 464 runtime_printf("g4 " REG_FMT "\n", m->gregs[REG_G4]); 465 runtime_printf("g5 " REG_FMT "\n", m->gregs[REG_G5]); 466 runtime_printf("g6 " REG_FMT "\n", m->gregs[REG_G6]); 467 runtime_printf("g7 " REG_FMT "\n", m->gregs[REG_G7]); 468 runtime_printf("o0 " REG_FMT "\n", m->gregs[REG_O0]); 469 runtime_printf("o1 " REG_FMT "\n", m->gregs[REG_O1]); 470 runtime_printf("o2 " REG_FMT "\n", m->gregs[REG_O2]); 471 runtime_printf("o3 " REG_FMT "\n", m->gregs[REG_O3]); 472 runtime_printf("o4 " REG_FMT "\n", m->gregs[REG_O4]); 473 runtime_printf("o5 " REG_FMT "\n", m->gregs[REG_O5]); 474 runtime_printf("o6 " REG_FMT "\n", m->gregs[REG_O6]); 475 runtime_printf("o7 " REG_FMT "\n", m->gregs[REG_O7]); 476 #if defined(REG_ASI) && defined(REG_FPRS) && !defined(__linux__) 477 runtime_printf("asi " REG_FMT "\n", m->gregs[REG_ASI]); 478 runtime_printf("fprs " REG_FMT "\n", m->gregs[REG_FPRS]); 479 #endif 480 } 481 #endif 482 }