Commit ab4578ad authored by Alex Brainman's avatar Alex Brainman

[dev.cc] runtime: convert remaining windows C code to Go

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/177090043
parent f4a52545
......@@ -152,5 +152,5 @@ func handlecompletion(gpp **g, op *net_op, errno int32, qty uint32) {
}
op.errno = errno
op.qty = qty
netpollready(gpp, op.pd, mode)
netpollready((**g)(noescape(unsafe.Pointer(gpp))), op.pd, mode)
}
This diff is collapsed.
......@@ -2,63 +2,60 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.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);
package runtime
import (
"unsafe"
)
var text struct{}
func dumpregs(r *context) {
print("eax ", hex(r.eax), "\n")
print("ebx ", hex(r.ebx), "\n")
print("ecx ", hex(r.ecx), "\n")
print("edx ", hex(r.edx), "\n")
print("edi ", hex(r.edi), "\n")
print("esi ", hex(r.esi), "\n")
print("ebp ", hex(r.ebp), "\n")
print("esp ", hex(r.esp), "\n")
print("eip ", hex(r.eip), "\n")
print("eflags ", hex(r.eflags), "\n")
print("cs ", hex(r.segcs), "\n")
print("fs ", hex(r.segfs), "\n")
print("gs ", hex(r.seggs), "\n")
}
bool
runtime·isgoexception(ExceptionRecord *info, Context *r)
{
extern byte runtime·text[], runtime·etext[];
func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary
// (not Windows library code).
if(r->Eip < (uint32)runtime·text || (uint32)runtime·etext < r->Eip)
return false;
// (not Windows library code).
if r.eip < uint32(uintptr(unsafe.Pointer(&text))) || uint32(uintptr(unsafe.Pointer(&etext))) < r.eip {
return false
}
if(!runtime·issigpanic(info->ExceptionCode))
return false;
if issigpanic(info.exceptioncode) == 0 {
return false
}
return true;
return true
}
// Called by sigtramp from Windows VEH handler.
// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
uint32
runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
{
uintptr *sp;
if(!runtime·isgoexception(info, r))
return EXCEPTION_CONTINUE_SEARCH;
func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
if !isgoexception(info, r) {
return _EXCEPTION_CONTINUE_SEARCH
}
// 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;
gp.sig = info.exceptioncode
gp.sigcode0 = uintptr(info.exceptioninformation[0])
gp.sigcode1 = uintptr(info.exceptioninformation[1])
gp.sigpc = uintptr(r.eip)
// Only push runtime·sigpanic if r->eip != 0.
// If r->eip == 0, probably panicked because of a
......@@ -66,63 +63,56 @@ runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
// 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;
if r.eip != 0 {
sp := unsafe.Pointer(uintptr(r.esp))
sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
*((*uintptr)(sp)) = uintptr(r.eip)
r.esp = uint32(uintptr(sp))
}
r->Eip = (uintptr)runtime·sigpanic;
return EXCEPTION_CONTINUE_EXECUTION;
r.eip = uint32(funcPC(sigpanic))
return _EXCEPTION_CONTINUE_EXECUTION
}
// lastcontinuehandler is reached, because runtime cannot handle
// current exception. lastcontinuehandler will print crash info and exit.
uint32
runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
{
bool crash;
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
(uintptr)info->ExceptionInformation[0], (uintptr)info->ExceptionInformation[1], (uintptr)r->Eip);
runtime·printf("PC=%x\n", r->Eip);
if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = g->m->lockedg;
func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
_g_ := getg()
if panicking != 0 { // traceback already printed
exit(2)
}
panicking = 1
print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.eip), "\n")
print("PC=", hex(r.eip), "\n")
if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
print("signal arrived during cgo execution\n")
gp = _g_.m.lockedg
}
print("\n")
var docrash bool
if gotraceback(&docrash) > 0 {
tracebacktrap(uintptr(r.eip), uintptr(r.esp), 0, gp)
tracebackothers(gp)
dumpregs(r)
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·tracebacktrap(r->Eip, r->Esp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
if docrash {
crash()
}
if(crash)
runtime·crash();
runtime·exit(2);
return 0; // not reached
exit(2)
return 0 // not reached
}
void
runtime·sigenable(uint32 sig)
{
USED(sig);
func sigenable(sig uint32) {
}
void
runtime·sigdisable(uint32 sig)
{
USED(sig);
func sigdisable(sig uint32) {
}
void
runtime·dosigprof(Context *r, G *gp, M *mp)
{
runtime·sigprof((uint8*)r->Eip, (uint8*)r->Esp, nil, gp, mp);
func dosigprof(r *context, gp *g, mp *m) {
sigprof((*byte)(unsafe.Pointer(uintptr(r.eip))), (*byte)(unsafe.Pointer(uintptr(r.esp))), nil, gp, mp)
}
......@@ -2,71 +2,68 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "defs_GOOS_GOARCH.h"
#include "os_GOOS.h"
void
runtime·dumpregs(Context *r)
{
runtime·printf("rax %X\n", r->Rax);
runtime·printf("rbx %X\n", r->Rbx);
runtime·printf("rcx %X\n", r->Rcx);
runtime·printf("rdx %X\n", r->Rdx);
runtime·printf("rdi %X\n", r->Rdi);
runtime·printf("rsi %X\n", r->Rsi);
runtime·printf("rbp %X\n", r->Rbp);
runtime·printf("rsp %X\n", r->Rsp);
runtime·printf("r8 %X\n", r->R8 );
runtime·printf("r9 %X\n", r->R9 );
runtime·printf("r10 %X\n", r->R10);
runtime·printf("r11 %X\n", r->R11);
runtime·printf("r12 %X\n", r->R12);
runtime·printf("r13 %X\n", r->R13);
runtime·printf("r14 %X\n", r->R14);
runtime·printf("r15 %X\n", r->R15);
runtime·printf("rip %X\n", r->Rip);
runtime·printf("rflags %X\n", r->EFlags);
runtime·printf("cs %X\n", (uint64)r->SegCs);
runtime·printf("fs %X\n", (uint64)r->SegFs);
runtime·printf("gs %X\n", (uint64)r->SegGs);
package runtime
import (
"unsafe"
)
var text struct{}
func dumpregs(r *context) {
print("rax ", hex(r.rax), "\n")
print("rbx ", hex(r.rbx), "\n")
print("rcx ", hex(r.rcx), "\n")
print("rdi ", hex(r.rdi), "\n")
print("rsi ", hex(r.rsi), "\n")
print("rbp ", hex(r.rbp), "\n")
print("rsp ", hex(r.rsp), "\n")
print("r8 ", hex(r.r8), "\n")
print("r9 ", hex(r.r9), "\n")
print("r10 ", hex(r.r10), "\n")
print("r11 ", hex(r.r11), "\n")
print("r12 ", hex(r.r12), "\n")
print("r13 ", hex(r.r13), "\n")
print("r14 ", hex(r.r14), "\n")
print("r15 ", hex(r.r15), "\n")
print("rip ", hex(r.rip), "\n")
print("rflags ", hex(r.eflags), "\n")
print("cs ", hex(r.segcs), "\n")
print("fs ", hex(r.segfs), "\n")
print("gs ", hex(r.seggs), "\n")
}
bool
runtime·isgoexception(ExceptionRecord *info, Context *r)
{
extern byte runtime·text[], runtime·etext[];
func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary
// (not Windows library code).
if(r->Rip < (uint64)runtime·text || (uint64)runtime·etext < r->Rip)
return false;
// (not Windows library code).
if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip {
return false
}
if(!runtime·issigpanic(info->ExceptionCode))
return false;
if issigpanic(info.exceptioncode) == 0 {
return false
}
return true;
return true
}
// Called by sigtramp from Windows VEH handler.
// Return value signals whether the exception has been handled (EXCEPTION_CONTINUE_EXECUTION)
// or should be made available to other handlers in the chain (EXCEPTION_CONTINUE_SEARCH).
uint32
runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
{
uintptr *sp;
if(!runtime·isgoexception(info, r))
return EXCEPTION_CONTINUE_SEARCH;
func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
if !isgoexception(info, r) {
return _EXCEPTION_CONTINUE_SEARCH
}
// 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->Rip;
gp.sig = info.exceptioncode
gp.sigcode0 = uintptr(info.exceptioninformation[0])
gp.sigcode1 = uintptr(info.exceptioninformation[1])
gp.sigpc = uintptr(r.rip)
// Only push runtime·sigpanic if r->rip != 0.
// If r->rip == 0, probably panicked because of a
......@@ -74,77 +71,67 @@ runtime·exceptionhandler(ExceptionRecord *info, Context *r, G *gp)
// 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->Rip != 0) {
sp = (uintptr*)r->Rsp;
*--sp = r->Rip;
r->Rsp = (uintptr)sp;
if r.rip != 0 {
sp := unsafe.Pointer(uintptr(r.rsp))
sp = add(sp, ^uintptr(unsafe.Sizeof(uintptr(0))-1)) // sp--
*((*uintptr)(sp)) = uintptr(r.rip)
r.rsp = uint64(uintptr(sp))
}
r->Rip = (uintptr)runtime·sigpanic;
return EXCEPTION_CONTINUE_EXECUTION;
r.rip = uint64(funcPC(sigpanic))
return _EXCEPTION_CONTINUE_EXECUTION
}
// It seems Windows searches ContinueHandler's list even
// if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION.
// firstcontinuehandler will stop that search,
// if exceptionhandler did the same earlier.
uint32
runtime·firstcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
{
USED(gp);
if(!runtime·isgoexception(info, r))
return EXCEPTION_CONTINUE_SEARCH;
return EXCEPTION_CONTINUE_EXECUTION;
func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 {
if !isgoexception(info, r) {
return _EXCEPTION_CONTINUE_SEARCH
}
return _EXCEPTION_CONTINUE_EXECUTION
}
// lastcontinuehandler is reached, because runtime cannot handle
// current exception. lastcontinuehandler will print crash info and exit.
uint32
runtime·lastcontinuehandler(ExceptionRecord *info, Context *r, G *gp)
{
bool crash;
func lastcontinuehandler(info *exceptionrecord, r *context, gp *g) uint32 {
_g_ := getg()
if(runtime·panicking) // traceback already printed
runtime·exit(2);
runtime·panicking = 1;
if panicking != 0 { // traceback already printed
exit(2)
}
panicking = 1
runtime·printf("Exception %x %p %p %p\n", info->ExceptionCode,
info->ExceptionInformation[0], info->ExceptionInformation[1], r->Rip);
print("Exception ", hex(info.exceptioncode), " ", hex(info.exceptioninformation[0]), " ", hex(info.exceptioninformation[1]), " ", hex(r.rip), "\n")
print("PC=", hex(r.rip), "\n")
if _g_.m.lockedg != nil && _g_.m.ncgo > 0 && gp == _g_.m.g0 {
print("signal arrived during cgo execution\n")
gp = _g_.m.lockedg
}
print("\n")
runtime·printf("PC=%X\n", r->Rip);
if(g->m->lockedg != nil && g->m->ncgo > 0 && gp == g->m->g0) {
runtime·printf("signal arrived during cgo execution\n");
gp = g->m->lockedg;
var docrash bool
if gotraceback(&docrash) > 0 {
tracebacktrap(uintptr(r.rip), uintptr(r.rsp), 0, gp)
tracebackothers(gp)
dumpregs(r)
}
runtime·printf("\n");
if(runtime·gotraceback(&crash)){
runtime·tracebacktrap(r->Rip, r->Rsp, 0, gp);
runtime·tracebackothers(gp);
runtime·dumpregs(r);
if docrash {
crash()
}
if(crash)
runtime·crash();
runtime·exit(2);
return 0; // not reached
exit(2)
return 0 // not reached
}
void
runtime·sigenable(uint32 sig)
{
USED(sig);
func sigenable(sig uint32) {
}
void
runtime·sigdisable(uint32 sig)
{
USED(sig);
func sigdisable(sig uint32) {
}
void
runtime·dosigprof(Context *r, G *gp, M *mp)
{
runtime·sigprof((uint8*)r->Rip, (uint8*)r->Rsp, nil, gp, mp);
func dosigprof(r *context, gp *g, mp *m) {
sigprof((*byte)(unsafe.Pointer(uintptr(r.rip))), (*byte)(unsafe.Pointer(uintptr(r.rsp))), nil, gp, mp)
}
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import "unsafe"
// Call a Windows function with stdcall conventions,
// and switch to os stack during the call.
func asmstdcall(fn unsafe.Pointer)
func getlasterror() uint32
func setlasterror(err uint32)
// Function to be called by windows CreateThread
// to start new os thread.
func tstart_stdcall(newm *m) uint32
func ctrlhandler(_type uint32) uint32
// TODO(brainman): should not need those
const (
_NSIG = 65
)
This diff is collapsed.
......@@ -4,24 +4,8 @@
package runtime
import "unsafe"
type stdFunction *byte
func stdcall0(fn stdFunction) uintptr
func stdcall1(fn stdFunction, a0 uintptr) uintptr
func stdcall2(fn stdFunction, a0, a1 uintptr) uintptr
func stdcall3(fn stdFunction, a0, a1, a2 uintptr) uintptr
func stdcall4(fn stdFunction, a0, a1, a2, a3 uintptr) uintptr
func stdcall5(fn stdFunction, a0, a1, a2, a3, a4 uintptr) uintptr
func stdcall6(fn stdFunction, a0, a1, a2, a3, a4, a5 uintptr) uintptr
func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr
func asmstdcall(fn unsafe.Pointer)
func getlasterror() uint32
func setlasterror(err uint32)
func usleep1(usec uint32)
func os_sigpipe() {
gothrow("too many writes on closed pipe")
}
......
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
extern void *runtime·LoadLibrary;
extern void *runtime·GetProcAddress;
extern void *runtime·GetQueuedCompletionStatusEx;
// Call a Windows function with stdcall conventions,
// and switch to os stack during the call.
void runtime·asmstdcall(void *c);
void *runtime·stdcall0(void *fn);
void *runtime·stdcall1(void *fn, uintptr a0);
void *runtime·stdcall2(void *fn, uintptr a0, uintptr a1);
void *runtime·stdcall3(void *fn, uintptr a0, uintptr a1, uintptr a2);
void *runtime·stdcall4(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3);
void *runtime·stdcall5(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4);
void *runtime·stdcall6(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5);
void *runtime·stdcall7(void *fn, uintptr a0, uintptr a1, uintptr a2, uintptr a3, uintptr a4, uintptr a5, uintptr a6);
uint32 runtime·getlasterror(void);
void runtime·setlasterror(uint32 err);
// Function to be called by windows CreateThread
// to start new os thread.
uint32 runtime·tstart_stdcall(M *newm);
uint32 runtime·issigpanic(uint32);
void runtime·sigpanic(void);
uint32 runtime·ctrlhandler(uint32 type);
// Windows dll function to go callback entry.
byte *runtime·compilecallback(Eface fn, bool cleanstack);
void *runtime·callbackasm(void);
void runtime·install_exception_handler(void);
void runtime·remove_exception_handler(void);
// TODO(brainman): should not need those
enum {
NSIG = 65,
};
......@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// +build !solaris
// +build !windows
package runtime
......
......@@ -41,20 +41,20 @@ func callbackasmAddr(i int) uintptr {
func compileCallback(fn eface, cleanstack bool) (code uintptr) {
if fn._type == nil || (fn._type.kind&kindMask) != kindFunc {
panic("compilecallback: not a function")
panic("compileCallback: not a function")
}
ft := (*functype)(unsafe.Pointer(fn._type))
if len(ft.out) != 1 {
panic("compilecallback: function must have one output parameter")
if ft.out.len != 1 {
panic("compileCallback: function must have one output parameter")
}
uintptrSize := unsafe.Sizeof(uintptr(0))
if t := (**_type)(unsafe.Pointer(&ft.out[0])); (*t).size != uintptrSize {
panic("compilecallback: output parameter size is wrong")
if t := (**_type)(unsafe.Pointer(ft.out.array)); (*t).size != uintptrSize {
panic("compileCallback: output parameter size is wrong")
}
argsize := uintptr(0)
for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
for _, t := range (*[1024](*_type))(unsafe.Pointer(ft.in.array))[:ft.in.len] {
if (*t).size > uintptrSize {
panic("compilecallback: input parameter size is wrong")
panic("compileCallback: input parameter size is wrong")
}
argsize += uintptrSize
}
......@@ -87,8 +87,6 @@ func compileCallback(fn eface, cleanstack bool) (code uintptr) {
return callbackasmAddr(n)
}
func getLoadLibrary() uintptr
//go:nosplit
func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
var c libcall
......@@ -103,8 +101,6 @@ func syscall_loadlibrary(filename *uint16) (handle, err uintptr) {
return
}
func getGetProcAddress() uintptr
//go:nosplit
func syscall_getprocaddress(handle uintptr, procname *byte) (outhandle, err uintptr) {
var c libcall
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment