]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use VEH for windows/amd64 exception handling
authorAlex Brainman <alex.brainman@gmail.com>
Wed, 26 Mar 2014 00:13:50 +0000 (11:13 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Wed, 26 Mar 2014 00:13:50 +0000 (11:13 +1100)
Fixes windows/amd64 build.

LGTM=rsc
R=golang-codereviews, rsc
CC=golang-codereviews
https://golang.org/cl/79470046

src/cmd/ld/pe.c
src/pkg/runtime/os_windows.c
src/pkg/runtime/os_windows_amd64.c
src/pkg/runtime/sys_windows_386.s
src/pkg/runtime/sys_windows_amd64.s

index e4848643ee73e2eb7ff50b35fc486cfce31942a0..4419471240d9f53786a849743b8de7e40e3c28ce 100644 (file)
@@ -529,49 +529,6 @@ addpersrc(void)
        dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize;
 }
 
-static void
-addexcept(IMAGE_SECTION_HEADER *text)
-{
-       IMAGE_SECTION_HEADER *pdata, *xdata;
-       vlong startoff;
-       uvlong n;
-       LSym *sym;
-
-       USED(text);
-       if(thechar != '6')
-               return;
-
-       // write unwind info
-       sym = linklookup(ctxt, "runtime.sigtramp", 0);
-       startoff = cpos();
-       lputl(9);       // version=1, flags=UNW_FLAG_EHANDLER, rest 0
-       lputl(sym->value - PEBASE);
-       lputl(0);
-
-       n = cpos() - startoff;
-       xdata = addpesection(".xdata", n, n);
-       xdata->Characteristics = IMAGE_SCN_MEM_READ|
-               IMAGE_SCN_CNT_INITIALIZED_DATA;
-       chksectoff(xdata, startoff);
-       strnput("", xdata->SizeOfRawData - n);
-
-       // write a function table entry for the whole text segment
-       startoff = cpos();
-       lputl(text->VirtualAddress);
-       lputl(text->VirtualAddress + text->VirtualSize);
-       lputl(xdata->VirtualAddress);
-
-       n = cpos() - startoff;
-       pdata = addpesection(".pdata", n, n);
-       pdata->Characteristics = IMAGE_SCN_MEM_READ|
-               IMAGE_SCN_CNT_INITIALIZED_DATA;
-       chksectoff(pdata, startoff);
-       strnput("", pdata->SizeOfRawData - n);
-
-       dd[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = pdata->VirtualAddress;
-       dd[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = pdata->VirtualSize;
-}
-
 void
 asmbpe(void)
 {
@@ -609,7 +566,6 @@ asmbpe(void)
        addexports();
        addsymtable();
        addpersrc();
-       addexcept(t);
 
        fh.NumberOfSections = nsect;
        fh.TimeDateStamp = time(0);
index af03247418f90ebaebd131dc48359d6020b18128..523efedf0a1bd13a468710cf76f3fa250245ae28 100644 (file)
@@ -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
index 27094ff497bfe2ade8d3ad8e5c54123121fc0584..1b23673af01dc6073f5ce3131ca1b868c85eafd4 100644 (file)
@@ -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
index 26dc30094faed9a32e9f545dc085bd6ed0e4e59e..3721fb4c583fae856562b27b90fbb38d0f4cd1b5 100644 (file)
@@ -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
index 288cd7748fd03855a3910a16c40cf08d434c62dc..94845903edc94bc1e209d03bee8187d8f23b5a2c 100644 (file)
@@ -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)
-
-       get_tls(CX)
-
-       // check that m exists
-       MOVQ    m(CX), AX
+       // 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)
+
+       MOVQ    0(CX), BX // ExceptionRecord*
+       MOVQ    8(CX), CX // Context*
+
+       // 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