diff options
| author | Alex Brainman <alex.brainman@gmail.com> | 2014-03-26 11:13:50 +1100 |
|---|---|---|
| committer | Alex Brainman <alex.brainman@gmail.com> | 2014-03-26 11:13:50 +1100 |
| commit | a837347dd95d045e05bf0e6df9bf1c9b157c7c53 (patch) | |
| tree | e492f6c5464dfb35ddab97c86af439d3c944c802 /src/pkg/runtime | |
| parent | 8c9e838f7bb06d7c3e8f411b43e5c9e4b73222ee (diff) | |
| download | go-a837347dd95d045e05bf0e6df9bf1c9b157c7c53.tar.xz | |
runtime: use VEH for windows/amd64 exception handling
Fixes windows/amd64 build.
LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/79470046
Diffstat (limited to 'src/pkg/runtime')
| -rw-r--r-- | src/pkg/runtime/os_windows.c | 3 | ||||
| -rw-r--r-- | src/pkg/runtime/os_windows_amd64.c | 33 | ||||
| -rw-r--r-- | src/pkg/runtime/sys_windows_386.s | 8 | ||||
| -rw-r--r-- | src/pkg/runtime/sys_windows_amd64.s | 89 |
4 files changed, 68 insertions, 65 deletions
diff --git a/src/pkg/runtime/os_windows.c b/src/pkg/runtime/os_windows.c index af03247418..523efedf0a 100644 --- a/src/pkg/runtime/os_windows.c +++ b/src/pkg/runtime/os_windows.c @@ -248,15 +248,12 @@ runtime·minit(void) (uintptr)-1, (uintptr)-2, (uintptr)-1, &thandle, (uintptr)0, (uintptr)0, (uintptr)DUPLICATE_SAME_ACCESS); runtime·atomicstorep(&m->thread, thandle); - - runtime·install_exception_handler(); } // Called from dropm to undo the effect of an minit. void runtime·unminit(void) { - runtime·remove_exception_handler(); } #pragma textflag NOSPLIT diff --git a/src/pkg/runtime/os_windows_amd64.c b/src/pkg/runtime/os_windows_amd64.c index 27094ff497..1b23673af0 100644 --- a/src/pkg/runtime/os_windows_amd64.c +++ b/src/pkg/runtime/os_windows_amd64.c @@ -32,6 +32,11 @@ runtime·dumpregs(Context *r) runtime·printf("gs %X\n", (uint64)r->SegGs); } +#define DBG_PRINTEXCEPTION_C 0x40010006 + +// Called by sigtramp from Windows VEH handler. +// Return value signals whether the exception has been handled (-1) +// or should be made available to other handlers in the chain (0). uint32 runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) { @@ -39,8 +44,25 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) uintptr *sp; switch(info->ExceptionCode) { + case DBG_PRINTEXCEPTION_C: + // This exception is intended to be caught by debuggers. + // There is a not-very-informational message like + // "Invalid parameter passed to C runtime function" + // sitting at info->ExceptionInformation[0] (a wchar_t*), + // with length info->ExceptionInformation[1]. + // The default behavior is to ignore this exception, + // but somehow returning 0 here (meaning keep going) + // makes the program crash instead. Maybe Windows has no + // other handler registered? In any event, ignore it. + return -1; + case EXCEPTION_BREAKPOINT: - return 1; + // It is unclear whether this is needed, unclear whether it + // would work, and unclear how to test it. Leave out for now. + // This only handles breakpoint instructions written in the + // assembly sources, not breakpoints set by a debugger, and + // there are very few of the former. + break; } if(gp != nil && runtime·issigpanic(info->ExceptionCode)) { @@ -65,15 +87,16 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) r->Rsp = (uintptr)sp; } r->Rip = (uintptr)runtime·sigpanic; - return 0; + return -1; } if(runtime·panicking) // traceback already printed runtime·exit(2); runtime·panicking = 1; - runtime·printf("Exception %x %p %p\n", info->ExceptionCode, - info->ExceptionInformation[0], info->ExceptionInformation[1]); + runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode, + info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip); + runtime·printf("PC=%X\n", r->Rip); if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) { @@ -92,7 +115,7 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) runtime·crash(); runtime·exit(2); - return 0; + return -1; // not reached } void diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s index 26dc30094f..3721fb4c58 100644 --- a/src/pkg/runtime/sys_windows_386.s +++ b/src/pkg/runtime/sys_windows_386.s @@ -313,14 +313,6 @@ TEXT runtime·setldt(SB),NOSPLIT,$0 MOVL CX, 0x14(FS) RET -// void install_exception_handler() -TEXT runtime·install_exception_handler(SB),NOSPLIT,$0 - RET - -// void remove_exception_handler() -TEXT runtime·remove_exception_handler(SB),NOSPLIT,$0 - RET - // Sleep duration is in 100ns units. TEXT runtime·usleep1(SB),NOSPLIT,$0 MOVL duration+0(FP), BX diff --git a/src/pkg/runtime/sys_windows_amd64.s b/src/pkg/runtime/sys_windows_amd64.s index 288cd7748f..94845903ed 100644 --- a/src/pkg/runtime/sys_windows_amd64.s +++ b/src/pkg/runtime/sys_windows_amd64.s @@ -95,49 +95,55 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0 MOVL AX, 0x68(CX) RET -TEXT runtime·sigtramp(SB),NOSPLIT,$0 - // CX: exception record - // R8: context +// Called by Windows as a Vectored Exception Handler (VEH). +// First argument is pointer to struct containing +// exception record and context pointers. +// Return 0 for 'not handled', -1 for handled. +TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 + // CX: PEXCEPTION_POINTERS ExceptionInfo - // unwinding? - TESTL $6, 4(CX) // exception flags - MOVL $1, AX - JNZ sigdone - - // copy arguments for call to sighandler. - - // Stack adjustment is here to hide from 6l, - // which doesn't understand that sigtramp - // runs on essentially unlimited stack. - SUBQ $56, SP - MOVQ CX, 0(SP) - MOVQ R8, 8(SP) + // DI SI BP BX R12 R13 R14 R15 registers and DF flag are preserved + // as required by windows callback convention. + PUSHFQ + SUBQ $88, SP + MOVQ DI, 80(SP) + MOVQ SI, 72(SP) + MOVQ BP, 64(SP) + MOVQ BX, 56(SP) + MOVQ R12, 48(SP) + MOVQ R13, 40(SP) + MOVQ R14, 32(SP) + MOVQ R15, 24(SP) - get_tls(CX) + MOVQ 0(CX), BX // ExceptionRecord* + MOVQ 8(CX), CX // Context* - // check that m exists - MOVQ m(CX), AX + // fetch g + get_tls(DX) + MOVQ m(DX), AX CMPQ AX, $0 JNE 2(PC) CALL runtime·badsignal2(SB) - - MOVQ g(CX), CX - MOVQ CX, 16(SP) - - MOVQ BX, 24(SP) - MOVQ BP, 32(SP) - MOVQ SI, 40(SP) - MOVQ DI, 48(SP) - + MOVQ g(DX), DX + // call sighandler(ExceptionRecord*, Context*, G*) + MOVQ BX, 0(SP) + MOVQ CX, 8(SP) + MOVQ DX, 16(SP) CALL runtime·sighandler(SB) + // AX is set to report result back to Windows - MOVQ 24(SP), BX - MOVQ 32(SP), BP - MOVQ 40(SP), SI - MOVQ 48(SP), DI - ADDQ $56, SP + // restore registers as required for windows callback + MOVQ 24(SP), R15 + MOVQ 32(SP), R14 + MOVQ 40(SP), R13 + MOVQ 48(SP), R12 + MOVQ 56(SP), BX + MOVQ 64(SP), BP + MOVQ 72(SP), SI + MOVQ 80(SP), DI + ADDQ $88, SP + POPFQ -sigdone: RET TEXT runtime·ctrlhandler(SB),NOSPLIT,$8 @@ -277,13 +283,6 @@ TEXT runtime·callbackasm1(SB),NOSPLIT,$0 POPQ -8(CX)(DX*1) // restore bytes just after the args RET -TEXT runtime·setstacklimits(SB),NOSPLIT,$0 - MOVQ 0x30(GS), CX - MOVQ $0, 0x10(CX) - MOVQ $0xffffffffffff, AX - MOVQ AX, 0x08(CX) - RET - // uint32 tstart_stdcall(M *newm); TEXT runtime·tstart_stdcall(SB),NOSPLIT,$0 // CX contains first arg newm @@ -315,14 +314,6 @@ TEXT runtime·settls(SB),NOSPLIT,$0 MOVQ DI, 0x28(GS) RET -// void install_exception_handler() -TEXT runtime·install_exception_handler(SB),NOSPLIT,$0 - CALL runtime·setstacklimits(SB) - RET - -TEXT runtime·remove_exception_handler(SB),NOSPLIT,$0 - RET - // Sleep duration is in 100ns units. TEXT runtime·usleep1(SB),NOSPLIT,$0 MOVL duration+0(FP), BX |
