From 2dc7552f5701c110fd54609fc8eed421cef7f20f Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Fri, 28 Mar 2014 17:35:00 +1100 Subject: [PATCH] runtime: ignore windows exception if not in Go binary LGTM=minux.ma R=golang-codereviews, minux.ma CC=golang-codereviews https://golang.org/cl/80400043 --- src/pkg/runtime/os_windows_386.c | 11 +++++++++-- src/pkg/runtime/os_windows_amd64.c | 11 +++++++++-- src/pkg/runtime/sys_windows_386.s | 31 ++++++------------------------ 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/pkg/runtime/os_windows_386.c b/src/pkg/runtime/os_windows_386.c index b49f7b6170..c36a001140 100644 --- a/src/pkg/runtime/os_windows_386.c +++ b/src/pkg/runtime/os_windows_386.c @@ -34,9 +34,9 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) { bool crash; uintptr *sp; + extern byte text[], etext[]; - switch(info->ExceptionCode) { - case DBG_PRINTEXCEPTION_C: + if(info->ExceptionCode == 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" @@ -47,7 +47,14 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) // makes the program crash instead. Maybe Windows has no // other handler registered? In any event, ignore it. return -1; + } + // Only handle exception if executing instructions in Go binary + // (not Windows library code). + if(r->Eip < (uint32)text || (uint32)etext < r->Eip) + return 0; + + switch(info->ExceptionCode) { case EXCEPTION_BREAKPOINT: // It is unclear whether this is needed, unclear whether it // would work, and unclear how to test it. Leave out for now. diff --git a/src/pkg/runtime/os_windows_amd64.c b/src/pkg/runtime/os_windows_amd64.c index 1b23673af0..7fb973cde4 100644 --- a/src/pkg/runtime/os_windows_amd64.c +++ b/src/pkg/runtime/os_windows_amd64.c @@ -42,9 +42,9 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) { bool crash; uintptr *sp; + extern byte text[], etext[]; - switch(info->ExceptionCode) { - case DBG_PRINTEXCEPTION_C: + if(info->ExceptionCode == 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" @@ -55,7 +55,14 @@ runtime·sighandler(ExceptionRecord *info, Context *r, G *gp) // makes the program crash instead. Maybe Windows has no // other handler registered? In any event, ignore it. return -1; + } + // Only handle exception if executing instructions in Go binary + // (not Windows library code). + if(r->Rip < (uint64)text || (uint64)etext < r->Rip) + return 0; + + switch(info->ExceptionCode) { case EXCEPTION_BREAKPOINT: // It is unclear whether this is needed, unclear whether it // would work, and unclear how to test it. Leave out for now. diff --git a/src/pkg/runtime/sys_windows_386.s b/src/pkg/runtime/sys_windows_386.s index 3721fb4c58..e0c0631cfc 100644 --- a/src/pkg/runtime/sys_windows_386.s +++ b/src/pkg/runtime/sys_windows_386.s @@ -74,37 +74,18 @@ TEXT runtime·setlasterror(SB),NOSPLIT,$0 // exception record and context pointers. // Return 0 for 'not handled', -1 for handled. TEXT runtime·sigtramp(SB),NOSPLIT,$0-0 - MOVL ptrs+0(FP), DI + MOVL ptrs+0(FP), CX SUBL $28, SP - MOVL 0(DI), BX // ExceptionRecord* - MOVL 4(DI), CX // Context* - - // Only handle exception if executing instructions in Go binary - // (not Windows library code). Except don't - keep reading. - // - // This sounds like a good idea but the tracebacks that - // Go provides are better than the Windows crash dialog, - // especially if it's something that Go needs to do. - // So take all the exceptions, not just the ones at Go PCs. - // If you re-enable this check by removing the JMP, you will - // need to arrange to handle exception 0x40010006 during - // non-Go code here. Right now that case is handled by sighandler - // in os_windows_386.c. - JMP skipcheckpc - MOVL $0, AX - MOVL 184(CX), DX // saved PC - CMPL DX, $text(SB) - JB vehret - CMPL DX, $etext(SB) - JA vehret - -skipcheckpc: + // save callee-saved registers MOVL BX, 12(SP) MOVL BP, 16(SP) MOVL SI, 20(SP) MOVL DI, 24(SP) + MOVL 0(CX), BX // ExceptionRecord* + MOVL 4(CX), CX // Context* + // fetch g get_tls(DX) MOVL m(DX), AX @@ -117,6 +98,7 @@ skipcheckpc: MOVL CX, 4(SP) MOVL DX, 8(SP) CALL runtime·sighandler(SB) + // AX is set to report result back to Windows // restore callee-saved registers MOVL 24(SP), DI @@ -124,7 +106,6 @@ skipcheckpc: MOVL 16(SP), BP MOVL 12(SP), BX -vehret: ADDL $28, SP // RET 4 (return and pop 4 bytes parameters) BYTE $0xC2; WORD $4 -- 2.48.1