aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2014-03-26 11:13:50 +1100
committerAlex Brainman <alex.brainman@gmail.com>2014-03-26 11:13:50 +1100
commita837347dd95d045e05bf0e6df9bf1c9b157c7c53 (patch)
treee492f6c5464dfb35ddab97c86af439d3c944c802 /src/pkg/runtime
parent8c9e838f7bb06d7c3e8f411b43e5c9e4b73222ee (diff)
downloadgo-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.c3
-rw-r--r--src/pkg/runtime/os_windows_amd64.c33
-rw-r--r--src/pkg/runtime/sys_windows_386.s8
-rw-r--r--src/pkg/runtime/sys_windows_amd64.s89
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