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