Commit 7d091bfd authored by Alex Brainman's avatar Alex Brainman

go.sys/windows: use $GOROOT/src/pkg/syscall/mksyscall_windows.go to generate syscalls

Also zsyscall_windows_386.go and zsyscall_windows_amd64.go
have same contents, so merge them into single file.

LGTM=r
R=r
CC=golang-codereviews
https://golang.org/cl/124430043
parent dc3c21c6
# Copyright 2014 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.
all: zsyscall_windows.go
TMP=/tmp/mksyscall_windows
zsyscall_windows.go: syscall_windows.go security_windows.go
go build -o $(TMP) $(GOROOT)/src/pkg/syscall/mksyscall_windows.go
GOOS=windows $(TMP) $^ | gofmt > $@
rm $(TMP)
#!/usr/bin/env bash
# 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.
# The windows package provides access to the raw system call
# interface of the underlying operating system. Porting Go to
# a new architecture/operating system combination requires
# some manual effort, though there are tools that automate
# much of the process. The auto-generated files have names
# beginning with z.
#
# This script runs or (given -n) prints suggested commands to generate z files
# for the current system. Running those commands is not automatic.
# This script is documentation more than anything else.
#
# * asm_${GOOS}_${GOARCH}.s
#
# This hand-written assembly file implements system call dispatch.
# There are three entry points:
#
# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr);
# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr);
#
# The first and second are the standard ones; they differ only in
# how many arguments can be passed to the kernel.
# The third is for low-level use by the ForkExec wrapper;
# unlike the first two, it does not call into the scheduler to
# let it know that a system call is running.
#
# * syscall_${GOOS}.go
#
# This hand-written Go file implements system calls that need
# special handling and lists "//sys" comments giving prototypes
# for ones that can be auto-generated. Mksyscall reads those
# comments to generate the stubs.
#
# * syscall_${GOOS}_${GOARCH}.go
#
# Same as syscall_${GOOS}.go except that it contains code specific
# to ${GOOS} on one particular architecture.
#
# * types_${GOOS}.c
#
# This hand-written C file includes standard C headers and then
# creates typedef or enum names beginning with a dollar sign
# (use of $ in variable names is a gcc extension). The hardest
# part about preparing this file is figuring out which headers to
# include and which symbols need to be #defined to get the
# actual data structures that pass through to the kernel system calls.
# Some C libraries present alternate versions for binary compatibility
# and translate them on the way in and out of system calls, but
# there is almost always a #define that can get the real ones.
# See types_darwin.c and types_linux.c for examples.
#
# * zerror_${GOOS}_${GOARCH}.go
#
# This machine-generated file defines the system's error numbers,
# error strings, and signal numbers. The generator is "mkerrors.sh".
# Usually no arguments are needed, but mkerrors.sh will pass its
# arguments on to godefs.
#
# * zsyscall_${GOOS}_${GOARCH}.go
#
# Generated by mksyscall.pl; see syscall_${GOOS}.go above.
#
# * zsysnum_${GOOS}_${GOARCH}.go
#
# Generated by mksysnum_${GOOS}.
#
# * ztypes_${GOOS}_${GOARCH}.go
#
# Generated by godefs; see types_${GOOS}.c above.
GOOSARCH="${GOOS}_${GOARCH}"
# defaults
mksyscall="./mksyscall.pl"
mkerrors="./mkerrors.sh"
zerrors="zerrors_$GOOSARCH.go"
mksysctl=""
zsysctl="zsysctl_$GOOSARCH.go"
mksysnum=
mktypes=
run="sh"
case "$1" in
-syscalls)
for i in zsyscall*go
do
sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i
rm _$i
done
exit 0
;;
-n)
run="cat"
shift
esac
case "$#" in
0)
;;
*)
echo 'usage: mkall.sh [-n]' 1>&2
exit 2
esac
case "$GOOSARCH" in
_* | *_ | _)
echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2
exit 1
;;
windows_*)
mksyscall=
mkerrors=
zerrors=
;;
*)
echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2
exit 1
;;
esac
(
if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi
case "$GOOS" in
windows)
echo "GOOS= GOARCH= go build mksyscall_windows.go"
echo "./mksyscall_windows syscall_windows.go security_windows.go syscall_$GOOSARCH.go |gofmt >zsyscall_$GOOSARCH.go"
echo "rm -f ./mksyscall_windows"
;;
esac
if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi
if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi
if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi
) | $run
......@@ -3,19 +3,13 @@
:: license that can be found in the LICENSE file.
@echo off
if exist mkall.sh goto dirok
echo mkall_windows.bat must be run from src\pkg\syscall directory
if exist syscall_windows.go goto dirok
echo mkall_windows.bat must be run from go.sys\windows directory
goto :end
:dirok
if "%1"=="386" goto :paramok
if "%1"=="amd64" goto :paramok
echo parameters must be 386 or amd64
goto :end
:paramok
go build mksyscall_windows.go
.\mksyscall_windows syscall_windows.go security_windows.go syscall_windows_%1.go |gofmt >zsyscall_windows_%1.go
go build -o mksyscall_windows.exe %GOROOT%\src\pkg\syscall\mksyscall_windows.go
mksyscall_windows.exe syscall_windows.go security_windows.go |gofmt >zsyscall_windows.go
del mksyscall_windows.exe
:end
\ No newline at end of file
:end
#!/usr/bin/env perl
# 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.
# This program reads a file containing function prototypes
# (like syscall_windows.go) and generates system call bodies.
# The prototypes are marked by lines beginning with "//sys"
# and read like func declarations if //sys is replaced by func, but:
# * The parameter lists must give a name for each argument.
# This includes return parameters.
# * The parameter lists must give a type for each argument:
# the (x, y, z int) shorthand is not allowed.
# * If the return parameter is an error number, it must be named errno.
# A line beginning with //sysnb is like //sys, except that the
# goroutine will not be suspended during the execution of the system
# call. This must only be used for system calls which can never
# block, as otherwise the system call could cause all goroutines to
# hang.
use strict;
my $cmdline = "mksyscall.pl " . join(' ', @ARGV);
my $errors = 0;
my $_32bit = "";
my $plan9 = 0;
my $openbsd = 0;
my $netbsd = 0;
my $dragonfly = 0;
my $nacl = 0;
my $arm = 0; # 64-bit value should use (even, odd)-pair
if($ARGV[0] eq "-b32") {
$_32bit = "big-endian";
shift;
} elsif($ARGV[0] eq "-l32") {
$_32bit = "little-endian";
shift;
}
if($ARGV[0] eq "-plan9") {
$plan9 = 1;
shift;
}
if($ARGV[0] eq "-openbsd") {
$openbsd = 1;
shift;
}
if($ARGV[0] eq "-netbsd") {
$netbsd = 1;
shift;
}
if($ARGV[0] eq "-dragonfly") {
$dragonfly = 1;
shift;
}
if($ARGV[0] eq "-nacl") {
$nacl = 1;
shift;
}
if($ARGV[0] eq "-arm") {
$arm = 1;
shift;
}
if($ARGV[0] =~ /^-/) {
print STDERR "usage: mksyscall.pl [-b32 | -l32] [file ...]\n";
exit 1;
}
sub parseparamlist($) {
my ($list) = @_;
$list =~ s/^\s*//;
$list =~ s/\s*$//;
if($list eq "") {
return ();
}
return split(/\s*,\s*/, $list);
}
sub parseparam($) {
my ($p) = @_;
if($p !~ /^(\S*) (\S*)$/) {
print STDERR "$ARGV:$.: malformed parameter: $p\n";
$errors = 1;
return ("xx", "int");
}
return ($1, $2);
}
my $text = "";
while(<>) {
chomp;
s/\s+/ /g;
s/^\s+//;
s/\s+$//;
my $nonblock = /^\/\/sysnb /;
next if !/^\/\/sys / && !$nonblock;
# Line must be of the form
# func Open(path string, mode int, perm int) (fd int, errno error)
# Split into name, in params, out params.
if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*((?i)SYS_[A-Z0-9_]+))?$/) {
print STDERR "$ARGV:$.: malformed //sys declaration\n";
$errors = 1;
next;
}
my ($func, $in, $out, $sysname) = ($2, $3, $4, $5);
# Split argument lists on comma.
my @in = parseparamlist($in);
my @out = parseparamlist($out);
# Try in vain to keep people from editing this file.
# The theory is that they jump into the middle of the file
# without reading the header.
$text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
# Go function header.
my $out_decl = @out ? sprintf(" (%s)", join(', ', @out)) : "";
$text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out_decl;
# Check if err return available
my $errvar = "";
foreach my $p (@out) {
my ($name, $type) = parseparam($p);
if($type eq "error") {
$errvar = $name;
last;
}
}
# Prepare arguments to Syscall.
my @args = ();
my $n = 0;
foreach my $p (@in) {
my ($name, $type) = parseparam($p);
if($type =~ /^\*/) {
push @args, "uintptr(unsafe.Pointer($name))";
} elsif($type eq "string" && $errvar ne "") {
$text .= "\tvar _p$n *byte\n";
$text .= "\t_p$n, $errvar = BytePtrFromString($name)\n";
$text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
$n++;
} elsif($type eq "string") {
print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
$text .= "\tvar _p$n *byte\n";
$text .= "\t_p$n, _ = BytePtrFromString($name)\n";
push @args, "uintptr(unsafe.Pointer(_p$n))";
$n++;
} elsif($type =~ /^\[\](.*)/) {
# Convert slice into pointer, length.
# Have to be careful not to take address of &a[0] if len == 0:
# pass dummy pointer in that case.
# Used to pass nil, but some OSes or simulators reject write(fd, nil, 0).
$text .= "\tvar _p$n unsafe.Pointer\n";
$text .= "\tif len($name) > 0 {\n\t\t_p$n = unsafe.Pointer(\&${name}[0])\n\t}";
$text .= " else {\n\t\t_p$n = unsafe.Pointer(&_zero)\n\t}";
$text .= "\n";
push @args, "uintptr(_p$n)", "uintptr(len($name))";
$n++;
} elsif($type eq "int64" && ($openbsd || $netbsd)) {
push @args, "0";
if($_32bit eq "big-endian") {
push @args, "uintptr($name>>32)", "uintptr($name)";
} elsif($_32bit eq "little-endian") {
push @args, "uintptr($name)", "uintptr($name>>32)";
} else {
push @args, "uintptr($name)";
}
} elsif($type eq "int64" && $dragonfly) {
if ($func !~ /^extp(read|write)/i) {
push @args, "0";
}
if($_32bit eq "big-endian") {
push @args, "uintptr($name>>32)", "uintptr($name)";
} elsif($_32bit eq "little-endian") {
push @args, "uintptr($name)", "uintptr($name>>32)";
} else {
push @args, "uintptr($name)";
}
} elsif($type eq "int64" && $_32bit ne "") {
if(@args % 2 && $arm) {
# arm abi specifies 64-bit argument uses
# (even, odd) pair
push @args, "0"
}
if($_32bit eq "big-endian") {
push @args, "uintptr($name>>32)", "uintptr($name)";
} else {
push @args, "uintptr($name)", "uintptr($name>>32)";
}
} else {
push @args, "uintptr($name)";
}
}
# Determine which form to use; pad args with zeros.
my $asm = "Syscall";
if ($nonblock) {
$asm = "RawSyscall";
}
if(@args <= 3) {
while(@args < 3) {
push @args, "0";
}
} elsif(@args <= 6) {
$asm .= "6";
while(@args < 6) {
push @args, "0";
}
} elsif(@args <= 9) {
$asm .= "9";
while(@args < 9) {
push @args, "0";
}
} else {
print STDERR "$ARGV:$.: too many arguments to system call\n";
}
# System call number.
if($sysname eq "") {
$sysname = "SYS_$func";
$sysname =~ s/([a-z])([A-Z])/${1}_$2/g; # turn FooBar into Foo_Bar
$sysname =~ y/a-z/A-Z/;
if($nacl) {
$sysname =~ y/A-Z/a-z/;
}
}
# Actual call.
my $args = join(', ', @args);
my $call = "$asm($sysname, $args)";
# Assign return values.
my $body = "";
my @ret = ("_", "_", "_");
my $do_errno = 0;
for(my $i=0; $i<@out; $i++) {
my $p = $out[$i];
my ($name, $type) = parseparam($p);
my $reg = "";
if($name eq "err" && !$plan9) {
$reg = "e1";
$ret[2] = $reg;
$do_errno = 1;
} elsif($name eq "err" && $plan9) {
$ret[0] = "r0";
$ret[2] = "e1";
next;
} else {
$reg = sprintf("r%d", $i);
$ret[$i] = $reg;
}
if($type eq "bool") {
$reg = "$reg != 0";
}
if($type eq "int64" && $_32bit ne "") {
# 64-bit number in r1:r0 or r0:r1.
if($i+2 > @out) {
print STDERR "$ARGV:$.: not enough registers for int64 return\n";
}
if($_32bit eq "big-endian") {
$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
} else {
$reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
}
$ret[$i] = sprintf("r%d", $i);
$ret[$i+1] = sprintf("r%d", $i+1);
}
if($reg ne "e1" || $plan9) {
$body .= "\t$name = $type($reg)\n";
}
}
if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
$text .= "\t$call\n";
} else {
$text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
}
$text .= $body;
if ($plan9 && $ret[2] eq "e1") {
$text .= "\tif int32(r0) == -1 {\n";
$text .= "\t\terr = e1\n";
$text .= "\t}\n";
} elsif ($do_errno) {
$text .= "\tif e1 != 0 {\n";
$text .= "\t\terr = e1\n";
$text .= "\t}\n";
}
$text .= "\treturn\n";
$text .= "}\n\n";
}
chomp $text;
chomp $text;
if($errors) {
exit 1;
}
print <<EOF;
// $cmdline
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package windows
import "unsafe"
$text
EOF
exit 0;
This diff is collapsed.
// go build mksyscall_windows.go && ./mksyscall_windows syscall_windows.go security_windows.go syscall_windows_amd64.go
// go build mksyscall_windows.go && ./mksyscall_windows syscall_windows.go security_windows.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package windows
import "syscall"
import "unsafe"
import "syscall"
var (
modkernel32 = NewLazyDLL("kernel32.dll")
modadvapi32 = NewLazyDLL("advapi32.dll")
modshell32 = NewLazyDLL("shell32.dll")
modmswsock = NewLazyDLL("mswsock.dll")
modcrypt32 = NewLazyDLL("crypt32.dll")
modws2_32 = NewLazyDLL("ws2_32.dll")
moddnsapi = NewLazyDLL("dnsapi.dll")
modiphlpapi = NewLazyDLL("iphlpapi.dll")
modsecur32 = NewLazyDLL("secur32.dll")
modnetapi32 = NewLazyDLL("netapi32.dll")
moduserenv = NewLazyDLL("userenv.dll")
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
modshell32 = syscall.NewLazyDLL("shell32.dll")
modmswsock = syscall.NewLazyDLL("mswsock.dll")
modcrypt32 = syscall.NewLazyDLL("crypt32.dll")
modws2_32 = syscall.NewLazyDLL("ws2_32.dll")
moddnsapi = syscall.NewLazyDLL("dnsapi.dll")
modiphlpapi = syscall.NewLazyDLL("iphlpapi.dll")
modsecur32 = syscall.NewLazyDLL("secur32.dll")
modnetapi32 = syscall.NewLazyDLL("netapi32.dll")
moduserenv = syscall.NewLazyDLL("userenv.dll")
procGetLastError = modkernel32.NewProc("GetLastError")
procLoadLibraryW = modkernel32.NewProc("LoadLibraryW")
......@@ -172,7 +172,7 @@ func GetLastError() (lasterr error) {
func LoadLibrary(libname string) (handle Handle, err error) {
var _p0 *uint16
_p0, err = UTF16PtrFromString(libname)
_p0, err = syscall.UTF16PtrFromString(libname)
if err != nil {
return
}
......@@ -202,7 +202,7 @@ func FreeLibrary(handle Handle) (err error) {
func GetProcAddress(module Handle, procname string) (proc uintptr, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(procname)
_p0, err = syscall.BytePtrFromString(procname)
if err != nil {
return
}
......@@ -1554,7 +1554,7 @@ func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32
func GetHostByName(name string) (h *Hostent, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
_p0, err = syscall.BytePtrFromString(name)
if err != nil {
return
}
......@@ -1572,12 +1572,12 @@ func GetHostByName(name string) (h *Hostent, err error) {
func GetServByName(name string, proto string) (s *Servent, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
_p0, err = syscall.BytePtrFromString(name)
if err != nil {
return
}
var _p1 *byte
_p1, err = BytePtrFromString(proto)
_p1, err = syscall.BytePtrFromString(proto)
if err != nil {
return
}
......@@ -1601,7 +1601,7 @@ func Ntohs(netshort uint16) (u uint16) {
func GetProtoByName(name string) (p *Protoent, err error) {
var _p0 *byte
_p0, err = BytePtrFromString(name)
_p0, err = syscall.BytePtrFromString(name)
if err != nil {
return
}
......@@ -1619,7 +1619,7 @@ func GetProtoByName(name string) (p *Protoent, err error) {
func DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) {
var _p0 *uint16
_p0, status = UTF16PtrFromString(name)
_p0, status = syscall.UTF16PtrFromString(name)
if status != nil {
return
}
......
This diff is collapsed.
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