diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
commit | 758ff64c69e34965f8af5b2d6ffd65e8d7ab2150 (patch) | |
tree | 6d6b34f8c678862fe9b56c945a7b63f68502c245 /src/pkg/runtime/windows/386 | |
parent | 3e45412327a2654a77944249962b3652e6142299 (diff) | |
download | golang-upstream/2011-02-01.1.tar.gz |
Imported Upstream version 2011-02-01.1upstream/2011-02-01.1
Diffstat (limited to 'src/pkg/runtime/windows/386')
-rw-r--r-- | src/pkg/runtime/windows/386/defs.h | 61 | ||||
-rw-r--r-- | src/pkg/runtime/windows/386/rt0.s | 8 | ||||
-rw-r--r-- | src/pkg/runtime/windows/386/signal.c | 79 | ||||
-rw-r--r-- | src/pkg/runtime/windows/386/sys.s | 145 |
4 files changed, 262 insertions, 31 deletions
diff --git a/src/pkg/runtime/windows/386/defs.h b/src/pkg/runtime/windows/386/defs.h index f5a16367e..a2a882103 100644 --- a/src/pkg/runtime/windows/386/defs.h +++ b/src/pkg/runtime/windows/386/defs.h @@ -10,8 +10,69 @@ enum { PROT_EXEC = 0x4, MAP_ANON = 0x1, MAP_PRIVATE = 0x2, + EXCEPTION_ACCESS_VIOLATION = 0xc0000005, + EXCEPTION_BREAKPOINT = 0x80000003, + EXCEPTION_FLT_DENORMAL_OPERAND = 0xc000008d, + EXCEPTION_FLT_DIVIDE_BY_ZERO = 0xc000008e, + EXCEPTION_FLT_INEXACT_RESULT = 0xc000008f, + EXCEPTION_FLT_OVERFLOW = 0xc0000091, + EXCEPTION_FLT_UNDERFLOW = 0xc0000093, + EXCEPTION_INT_DIVIDE_BY_ZERO = 0xc0000094, + EXCEPTION_INT_OVERFLOW = 0xc0000095, }; // Types #pragma pack on + +typedef struct ExceptionRecord ExceptionRecord; +struct ExceptionRecord { + uint32 ExceptionCode; + uint32 ExceptionFlags; + ExceptionRecord *ExceptionRecord; + void *ExceptionAddress; + uint32 NumberParameters; + uint32 ExceptionInformation[15]; +}; + +typedef struct FloatingSaveArea FloatingSaveArea; +struct FloatingSaveArea { + uint32 ControlWord; + uint32 StatusWord; + uint32 TagWord; + uint32 ErrorOffset; + uint32 ErrorSelector; + uint32 DataOffset; + uint32 DataSelector; + uint8 RegisterArea[80]; + uint32 Cr0NpxState; +}; + +typedef struct Context Context; +struct Context { + uint32 ContextFlags; + uint32 Dr0; + uint32 Dr1; + uint32 Dr2; + uint32 Dr3; + uint32 Dr6; + uint32 Dr7; + FloatingSaveArea FloatSave; + uint32 SegGs; + uint32 SegFs; + uint32 SegEs; + uint32 SegDs; + uint32 Edi; + uint32 Esi; + uint32 Ebx; + uint32 Edx; + uint32 Ecx; + uint32 Eax; + uint32 Ebp; + uint32 Eip; + uint32 SegCs; + uint32 EFlags; + uint32 Esp; + uint32 SegSs; + uint8 ExtendedRegisters[512]; +}; #pragma pack off diff --git a/src/pkg/runtime/windows/386/rt0.s b/src/pkg/runtime/windows/386/rt0.s index e379830fb..3b023de2f 100644 --- a/src/pkg/runtime/windows/386/rt0.s +++ b/src/pkg/runtime/windows/386/rt0.s @@ -3,4 +3,12 @@ // license that can be found in the LICENSE file. TEXT _rt0_386_windows(SB),7,$0 + // Set up SEH frame for bootstrap m + PUSHL $runtime·sigtramp(SB) + PUSHL 0(FS) + MOVL SP, 0(FS) + JMP _rt0_386(SB) + +DATA runtime·iswindows(SB)/4, $1 +GLOBL runtime·iswindows(SB), $4 diff --git a/src/pkg/runtime/windows/386/signal.c b/src/pkg/runtime/windows/386/signal.c index 2ae79e5b5..69178cdd0 100644 --- a/src/pkg/runtime/windows/386/signal.c +++ b/src/pkg/runtime/windows/386/signal.c @@ -3,6 +3,26 @@ // license that can be found in the LICENSE file. #include "runtime.h" +#include "defs.h" +#include "os.h" + +void +runtime·dumpregs(Context *r) +{ + runtime·printf("eax %x\n", r->Eax); + runtime·printf("ebx %x\n", r->Ebx); + runtime·printf("ecx %x\n", r->Ecx); + runtime·printf("edx %x\n", r->Edx); + runtime·printf("edi %x\n", r->Edi); + runtime·printf("esi %x\n", r->Esi); + runtime·printf("ebp %x\n", r->Ebp); + runtime·printf("esp %x\n", r->Esp); + runtime·printf("eip %x\n", r->Eip); + runtime·printf("eflags %x\n", r->EFlags); + runtime·printf("cs %x\n", r->SegCs); + runtime·printf("fs %x\n", r->SegFs); + runtime·printf("gs %x\n", r->SegGs); +} void runtime·initsig(int32) @@ -15,3 +35,62 @@ runtime·signame(int32) return runtime·emptystring; } +uint32 +runtime·sighandler(ExceptionRecord *info, void *frame, Context *r) +{ + uintptr *sp; + G *gp; + + USED(frame); + + switch(info->ExceptionCode) { + case EXCEPTION_BREAKPOINT: + r->Eip--; // because 8l generates 2 bytes for INT3 + return 1; + } + + if((gp = m->curg) != nil && runtime·issigpanic(info->ExceptionCode)) { + // Make it look like a call to the signal func. + // Have to pass arguments out of band since + // augmenting the stack frame would break + // the unwinding code. + gp->sig = info->ExceptionCode; + gp->sigcode0 = info->ExceptionInformation[0]; + gp->sigcode1 = info->ExceptionInformation[1]; + gp->sigpc = r->Eip; + + // Only push runtime·sigpanic if r->eip != 0. + // If r->eip == 0, probably panicked because of a + // call to a nil func. Not pushing that onto sp will + // make the trace look like a call to runtime·sigpanic instead. + // (Otherwise the trace will end at runtime·sigpanic and we + // won't get to see who faulted.) + if(r->Eip != 0) { + sp = (uintptr*)r->Esp; + *--sp = r->Eip; + r->Esp = (uintptr)sp; + } + r->Eip = (uintptr)runtime·sigpanic; + return 0; + } + + 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("PC=%x\n", r->Eip); + runtime·printf("\n"); + + if(runtime·gotraceback()){ + runtime·traceback((void*)r->Eip, (void*)r->Esp, 0, m->curg); + runtime·tracebackothers(m->curg); + runtime·dumpregs(r); + } + + runtime·breakpoint(); + runtime·exit(2); + return 0; +} diff --git a/src/pkg/runtime/windows/386/sys.s b/src/pkg/runtime/windows/386/sys.s index 7f99b34de..d1a8a49a9 100644 --- a/src/pkg/runtime/windows/386/sys.s +++ b/src/pkg/runtime/windows/386/sys.s @@ -5,7 +5,7 @@ #include "386/asm.h" // void *stdcall_raw(void *fn, int32 count, uintptr *args) -TEXT runtime·stdcall_raw(SB),7,$4 +TEXT runtime·stdcall_raw(SB),7,$0 // Copy arguments from stack. MOVL fn+0(FP), AX MOVL count+4(FP), CX // words @@ -14,17 +14,18 @@ TEXT runtime·stdcall_raw(SB),7,$4 // Switch to m->g0 if needed. get_tls(DI) MOVL m(DI), DX - MOVL g(DI), SI - MOVL SI, 0(SP) // save g - MOVL SP, m_gostack(DX) // save SP + MOVL 0(FS), SI + MOVL SI, m_sehframe(DX) MOVL m_g0(DX), SI CMPL g(DI), SI - JEQ 3(PC) + MOVL SP, BX + JEQ 2(PC) MOVL (m_sched+gobuf_sp)(DX), SP + PUSHL BX + PUSHL g(DI) MOVL SI, g(DI) // Copy args to new stack. - SUBL $(10*4), SP // padding MOVL CX, BX SALL $2, BX SUBL BX, SP // room for args @@ -38,28 +39,122 @@ TEXT runtime·stdcall_raw(SB),7,$4 // Restore original SP, g. get_tls(DI) - MOVL m(DI), DX - MOVL m_gostack(DX), SP // restore SP - MOVL 0(SP), SI // restore g - MOVL SI, g(DI) + POPL g(DI) + POPL SP // Someday the convention will be D is always cleared. CLD - RET + RET + +// faster get/set last error +TEXT runtime·getlasterror(SB),7,$0 + MOVL 0x34(FS), AX + RET + +TEXT runtime·setlasterror(SB),7,$0 + MOVL err+0(FP), AX + MOVL AX, 0x34(FS) + RET + +TEXT runtime·sigtramp(SB),7,$0 + PUSHL BP // cdecl + PUSHL 0(FS) + CALL runtime·sigtramp1(SB) + POPL 0(FS) + POPL BP + RET + +TEXT runtime·sigtramp1(SB),0,$16-28 + // unwinding? + MOVL info+12(FP), BX + MOVL 4(BX), CX // exception flags + ANDL $6, CX + MOVL $1, AX + JNZ sigdone + + // place ourselves at the top of the SEH chain to + // ensure SEH frames lie within thread stack bounds + MOVL frame+16(FP), CX // our SEH frame + MOVL CX, 0(FS) + + // copy arguments for call to sighandler + MOVL BX, 0(SP) + MOVL CX, 4(SP) + MOVL context+20(FP), BX + MOVL BX, 8(SP) + MOVL dispatcher+24(FP), BX + MOVL BX, 12(SP) + + CALL runtime·sighandler(SB) + TESTL AX, AX + JZ sigdone + + // call windows default handler early + MOVL 4(SP), BX // our SEH frame + MOVL 0(BX), BX // SEH frame of default handler + MOVL BX, 4(SP) // set establisher frame + CALL 4(BX) + +sigdone: + RET + +// Called from dynamic function created by ../thread.c compilecallback, +// running on Windows stack (not Go stack). +// BX, BP, SI, DI registers and DF flag are preserved +// as required by windows callback convention. +// AX = address of go func we need to call +// DX = total size of arguments +// +TEXT runtime·callbackasm+0(SB),7,$0 + LEAL 8(SP), CX + + // save registers as required for windows callback + PUSHL 0(FS) + PUSHL DI + PUSHL SI + PUSHL BP + PUSHL BX + PUSHL DX + PUSHL CX + PUSHL AX + + // reinstall our SEH handler + get_tls(CX) + MOVL m(CX), CX + MOVL m_sehframe(CX), CX + MOVL CX, 0(FS) + CLD + + CALL runtime·cgocallback(SB) + + // restore registers as required for windows callback + POPL CX + POPL CX + POPL DX + POPL BX + POPL BP + POPL SI + POPL DI + POPL 0(FS) + CLD + + RET // void tstart(M *newm); TEXT runtime·tstart(SB),7,$0 MOVL newm+4(SP), CX // m MOVL m_g0(CX), DX // g - MOVL SP, DI // remember stack + // Set up SEH frame + PUSHL $runtime·sigtramp(SB) + PUSHL 0(FS) + MOVL SP, 0(FS) // Layout new m scheduler stack on os stack. MOVL SP, AX - SUBL $256, AX // just some space for ourselves MOVL AX, g_stackbase(DX) - SUBL $8192, AX // stack size + SUBL $(64*1024), AX // stack size MOVL AX, g_stackguard(DX) // Set up tls. @@ -68,20 +163,17 @@ TEXT runtime·tstart(SB),7,$0 MOVL CX, m(SI) MOVL DX, g(SI) - // Use scheduler stack now. - MOVL g_stackbase(DX), SP - // Someday the convention will be D is always cleared. CLD - PUSHL DI // original stack - - CALL runtime·stackcheck(SB) // clobbers AX,CX + CALL runtime·stackcheck(SB) // clobbers AX,CX CALL runtime·mstart(SB) - POPL DI // original stack - MOVL DI, SP + // Pop SEH frame + MOVL 0(FS), SP + POPL 0(FS) + POPL CX RET @@ -107,12 +199,3 @@ TEXT runtime·setldt(SB),7,$0 MOVL address+4(FP), CX MOVL CX, 0x2c(FS) RET - -// for now, return 0,0. only used for internal performance monitoring. -TEXT runtime·gettime(SB),7,$0 - MOVL sec+0(FP), DI - MOVL $0, (DI) - MOVL $0, 4(DI) // zero extend 32 -> 64 bits - MOVL usec+4(FP), DI - MOVL $0, (DI) - RET |