(root)/
gcc-13.2.0/
libgo/
runtime/
go-signal.c
       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  struct getSiginfoRet {
     220  	uintptr sigaddr;
     221  	uintptr sigpc;
     222  };
     223  
     224  struct getSiginfoRet getSiginfo(siginfo_t *, void *)
     225  	__asm__(GOSYM_PREFIX "runtime.getSiginfo");
     226  
     227  struct getSiginfoRet
     228  getSiginfo(siginfo_t *info, void *context __attribute__((unused)))
     229  {
     230  	struct getSiginfoRet ret;
     231  	Location loc[1];
     232  	int32 n;
     233  
     234  	if (info == nil) {
     235  		ret.sigaddr = 0;
     236  	} else {
     237  		ret.sigaddr = (uintptr)(info->si_addr);
     238  	}
     239  	ret.sigpc = 0;
     240  
     241  	// There doesn't seem to be a portable way to get the PC.
     242  	// Use unportable code to pull it from context, and if that fails
     243  	// try a stack backtrace across the signal handler.
     244  
     245  #if defined(__x86_64__) && defined(__linux__)
     246  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_RIP];
     247  #elif defined(__i386__) && defined(__linux__)
     248  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[REG_EIP];
     249  #elif defined(__alpha__) && defined(__linux__)
     250  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.sc_pc;
     251  #elif defined(__PPC64__) && defined(__linux__)
     252  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gp_regs[32];
     253  #elif defined(__PPC__) && defined(__linux__)
     254  # if defined(__GLIBC__)
     255  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.uc_regs->gregs[32];
     256  # else
     257  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.gregs[32];
     258  # endif
     259  #elif defined(__PPC__) && defined(_AIX)
     260  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.jmp_context.iar;
     261  #elif defined(__aarch64__) && defined(__linux__)
     262  	ret.sigpc = ((ucontext_t*)(context))->uc_mcontext.pc;
     263  #elif defined(__NetBSD__)
     264  	ret.sigpc = _UC_MACHINE_PC(((ucontext_t*)(context)));
     265  #endif
     266  
     267  	if (ret.sigpc == 0) {
     268  		// Skip getSiginfo/sighandler/sigtrampgo/sigtramp/handler.
     269  		n = runtime_callers(5, &loc[0], 1, false);
     270  		if (n > 0) {
     271  			ret.sigpc = loc[0].pc;
     272  		}
     273  	}
     274  
     275  	return ret;
     276  }
     277  
     278  // Dump registers when crashing in a signal.
     279  // There is no portable way to write this,
     280  // so we just have some CPU/OS specific implementations.
     281  
     282  void dumpregs(siginfo_t *, void *)
     283  	__asm__(GOSYM_PREFIX "runtime.dumpregs");
     284  
     285  void
     286  dumpregs(siginfo_t *info __attribute__((unused)), void *context __attribute__((unused)))
     287  {
     288  #if defined(__x86_64__) && defined(__linux__)
     289  	{
     290  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     291  
     292  		runtime_printf("rax    %X\n", m->gregs[REG_RAX]);
     293  		runtime_printf("rbx    %X\n", m->gregs[REG_RBX]);
     294  		runtime_printf("rcx    %X\n", m->gregs[REG_RCX]);
     295  		runtime_printf("rdx    %X\n", m->gregs[REG_RDX]);
     296  		runtime_printf("rdi    %X\n", m->gregs[REG_RDI]);
     297  		runtime_printf("rsi    %X\n", m->gregs[REG_RSI]);
     298  		runtime_printf("rbp    %X\n", m->gregs[REG_RBP]);
     299  		runtime_printf("rsp    %X\n", m->gregs[REG_RSP]);
     300  		runtime_printf("r8     %X\n", m->gregs[REG_R8]);
     301  		runtime_printf("r9     %X\n", m->gregs[REG_R9]);
     302  		runtime_printf("r10    %X\n", m->gregs[REG_R10]);
     303  		runtime_printf("r11    %X\n", m->gregs[REG_R11]);
     304  		runtime_printf("r12    %X\n", m->gregs[REG_R12]);
     305  		runtime_printf("r13    %X\n", m->gregs[REG_R13]);
     306  		runtime_printf("r14    %X\n", m->gregs[REG_R14]);
     307  		runtime_printf("r15    %X\n", m->gregs[REG_R15]);
     308  		runtime_printf("rip    %X\n", m->gregs[REG_RIP]);
     309  		runtime_printf("rflags %X\n", m->gregs[REG_EFL]);
     310  		runtime_printf("cs     %X\n", m->gregs[REG_CSGSFS] & 0xffff);
     311  		runtime_printf("fs     %X\n", (m->gregs[REG_CSGSFS] >> 16) & 0xffff);
     312  		runtime_printf("gs     %X\n", (m->gregs[REG_CSGSFS] >> 32) & 0xffff);
     313  	  }
     314  #elif defined(__i386__) && defined(__linux__)
     315  	{
     316  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     317  
     318  		runtime_printf("eax    %x\n", m->gregs[REG_EAX]);
     319  		runtime_printf("ebx    %x\n", m->gregs[REG_EBX]);
     320  		runtime_printf("ecx    %x\n", m->gregs[REG_ECX]);
     321  		runtime_printf("edx    %x\n", m->gregs[REG_EDX]);
     322  		runtime_printf("edi    %x\n", m->gregs[REG_EDI]);
     323  		runtime_printf("esi    %x\n", m->gregs[REG_ESI]);
     324  		runtime_printf("ebp    %x\n", m->gregs[REG_EBP]);
     325  		runtime_printf("esp    %x\n", m->gregs[REG_ESP]);
     326  		runtime_printf("eip    %x\n", m->gregs[REG_EIP]);
     327  		runtime_printf("eflags %x\n", m->gregs[REG_EFL]);
     328  		runtime_printf("cs     %x\n", m->gregs[REG_CS]);
     329  		runtime_printf("fs     %x\n", m->gregs[REG_FS]);
     330  		runtime_printf("gs     %x\n", m->gregs[REG_GS]);
     331  	  }
     332  #elif defined(__alpha__) && defined(__linux__)
     333  	{
     334  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     335  
     336  		runtime_printf("v0  %X\n", m->sc_regs[0]);
     337  		runtime_printf("t0  %X\n", m->sc_regs[1]);
     338  		runtime_printf("t1  %X\n", m->sc_regs[2]);
     339  		runtime_printf("t2  %X\n", m->sc_regs[3]);
     340  		runtime_printf("t3  %X\n", m->sc_regs[4]);
     341  		runtime_printf("t4  %X\n", m->sc_regs[5]);
     342  		runtime_printf("t5  %X\n", m->sc_regs[6]);
     343  		runtime_printf("t6  %X\n", m->sc_regs[7]);
     344  		runtime_printf("t7  %X\n", m->sc_regs[8]);
     345  		runtime_printf("s0  %X\n", m->sc_regs[9]);
     346  		runtime_printf("s1  %X\n", m->sc_regs[10]);
     347  		runtime_printf("s2  %X\n", m->sc_regs[11]);
     348  		runtime_printf("s3  %X\n", m->sc_regs[12]);
     349  		runtime_printf("s4  %X\n", m->sc_regs[13]);
     350  		runtime_printf("s5  %X\n", m->sc_regs[14]);
     351  		runtime_printf("fp  %X\n", m->sc_regs[15]);
     352  		runtime_printf("a0  %X\n", m->sc_regs[16]);
     353  		runtime_printf("a1  %X\n", m->sc_regs[17]);
     354  		runtime_printf("a2  %X\n", m->sc_regs[18]);
     355  		runtime_printf("a3  %X\n", m->sc_regs[19]);
     356  		runtime_printf("a4  %X\n", m->sc_regs[20]);
     357  		runtime_printf("a5  %X\n", m->sc_regs[21]);
     358  		runtime_printf("t8  %X\n", m->sc_regs[22]);
     359  		runtime_printf("t9  %X\n", m->sc_regs[23]);
     360  		runtime_printf("t10 %X\n", m->sc_regs[24]);
     361  		runtime_printf("t11 %X\n", m->sc_regs[25]);
     362  		runtime_printf("ra  %X\n", m->sc_regs[26]);
     363  		runtime_printf("t12 %X\n", m->sc_regs[27]);
     364  		runtime_printf("at  %X\n", m->sc_regs[28]);
     365  		runtime_printf("gp  %X\n", m->sc_regs[29]);
     366  		runtime_printf("sp  %X\n", m->sc_regs[30]);
     367  		runtime_printf("pc  %X\n", m->sc_pc);
     368  	  }
     369  #elif defined(__PPC__) && defined(__linux__)
     370  	  {
     371  		int i;
     372  
     373  # if defined(__PPC64__)
     374  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     375  
     376  		for (i = 0; i < 32; i++)
     377  			runtime_printf("r%d %X\n", i, m->gp_regs[i]);
     378  		runtime_printf("pc  %X\n", m->gp_regs[32]);
     379  		runtime_printf("msr %X\n", m->gp_regs[33]);
     380  		runtime_printf("cr  %X\n", m->gp_regs[38]);
     381  		runtime_printf("lr  %X\n", m->gp_regs[36]);
     382  		runtime_printf("ctr %X\n", m->gp_regs[35]);
     383  		runtime_printf("xer %X\n", m->gp_regs[37]);
     384  # else
     385  #  if defined(__GLIBC__)
     386  		mcontext_t *m = ((ucontext_t*)(context))->uc_mcontext.uc_regs;
     387  #  else
     388  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     389  #  endif
     390  
     391  		for (i = 0; i < 32; i++)
     392  			runtime_printf("r%d %x\n", i, m->gregs[i]);
     393  		runtime_printf("pc  %x\n", m->gregs[32]);
     394  		runtime_printf("msr %x\n", m->gregs[33]);
     395  		runtime_printf("cr  %x\n", m->gregs[38]);
     396  		runtime_printf("lr  %x\n", m->gregs[36]);
     397  		runtime_printf("ctr %x\n", m->gregs[35]);
     398  		runtime_printf("xer %x\n", m->gregs[37]);
     399  # endif
     400  	  }
     401  #elif defined(__PPC__) && defined(_AIX)
     402  	  {
     403  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     404  		int i;
     405  
     406  		for (i = 0; i < 32; i++)
     407  			runtime_printf("r%d %p\n", i, m->jmp_context.gpr[i]);
     408  		runtime_printf("pc  %p\n", m->jmp_context.iar);
     409  		runtime_printf("msr %p\n", m->jmp_context.msr);
     410  		runtime_printf("cr  %x\n", m->jmp_context.cr);
     411  		runtime_printf("lr  %p\n", m->jmp_context.lr);
     412  		runtime_printf("ctr %p\n", m->jmp_context.ctr);
     413  		runtime_printf("xer %x\n", m->jmp_context.xer);
     414  	  }
     415  #elif defined(__aarch64__) && defined(__linux__)
     416  	  {
     417  		mcontext_t *m = &((ucontext_t*)(context))->uc_mcontext;
     418  		int i;
     419  
     420  		for (i = 0; i < 31; i++)
     421  			runtime_printf("x%d    %X\n", i, m->regs[i]);
     422  		runtime_printf("sp     %X\n", m->sp);
     423  		runtime_printf("pc     %X\n", m->pc);
     424  		runtime_printf("pstate %X\n", m->pstate);
     425  	  }
     426  #endif
     427  }