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  }