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  }