Skip to content

Commit 1f1e96f

Browse files
committed
x/sys/windows: use SyscallN in mkwinsyscall
The mkwinsyscall command has a hard limit of 15 on the number of syscall arguments. Windows has several system calls with more than 15 arguments, for example CreateFontPackage has 18 arguments. If the number of arguments is higher than 15 we use SyscallN. Updates golang/go#57914
1 parent 552c4e8 commit 1f1e96f

File tree

2 files changed

+70
-3
lines changed

2 files changed

+70
-3
lines changed

Diff for: windows/mkwinsyscall/mkwinsyscall.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import (
5757
"go/parser"
5858
"go/token"
5959
"io"
60-
"io/ioutil"
6160
"log"
6261
"os"
6362
"path/filepath"
@@ -568,6 +567,8 @@ func (f *Fn) SyscallParamCount() int {
568567
return 12
569568
case n <= 15:
570569
return 15
570+
case n <= 42: // current SyscallN limit
571+
return n
571572
default:
572573
panic("too many arguments to system call")
573574
}
@@ -579,6 +580,9 @@ func (f *Fn) Syscall() string {
579580
if c == 3 {
580581
return syscalldot() + "Syscall"
581582
}
583+
if c > 15 {
584+
return syscalldot() + "SyscallN"
585+
}
582586
return syscalldot() + "Syscall" + strconv.Itoa(c)
583587
}
584588

@@ -923,7 +927,7 @@ func main() {
923927
if *filename == "" {
924928
_, err = os.Stdout.Write(data)
925929
} else {
926-
err = ioutil.WriteFile(*filename, data, 0644)
930+
err = os.WriteFile(*filename, data, 0644)
927931
}
928932
if err != nil {
929933
log.Fatal(err)
@@ -1011,7 +1015,7 @@ func {{.HelperName}}({{.HelperParamList}}) {{template "results" .}}{
10111015
10121016
{{define "results"}}{{if .Rets.List}}{{.Rets.List}} {{end}}{{end}}
10131017
1014-
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(), {{.ParamCount}}, {{.SyscallParamList}}){{end}}
1018+
{{define "syscall"}}{{.Rets.SetReturnValuesCode}}{{.Syscall}}(proc{{.DLLFuncName}}.Addr(),{{if le .ParamCount 15}} {{.ParamCount}},{{end}} {{.SyscallParamList}}){{end}}
10151019
10161020
{{define "tmpvarsreadback"}}{{range .Params}}{{if .TmpVarReadbackCode}}
10171021
{{.TmpVarReadbackCode}}{{end}}{{end}}{{end}}

Diff for: windows/mkwinsyscall/mkwinsyscall_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"go/format"
1010
"os"
1111
"path/filepath"
12+
"strings"
1213
"testing"
1314
)
1415

@@ -48,3 +49,65 @@ func TestDLLFilenameEscaping(t *testing.T) {
4849
})
4950
}
5051
}
52+
53+
func TestSyscallXGeneration(t *testing.T) {
54+
tests := []struct {
55+
name string
56+
wantsysfunc string
57+
sig string
58+
}{
59+
{
60+
name: "syscall with 2 params",
61+
wantsysfunc: "syscall.Syscall",
62+
sig: "Example(a1 *uint16, a2 *uint16) = ",
63+
},
64+
{
65+
name: "syscall with 6 params",
66+
wantsysfunc: "syscall.Syscall6",
67+
sig: "Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint) = ",
68+
},
69+
{
70+
name: "syscall with 15 params",
71+
wantsysfunc: "syscall.Syscall15",
72+
sig: strings.ReplaceAll(`Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint,
73+
a7 *uint, a8 *uint, a9 *uint, a10 *uint, a11 *uint, a12 *uint,
74+
a13 *uint, a14 *uint, a15 *uint) = `, "\n", ""),
75+
},
76+
{
77+
name: "syscall with 18 params",
78+
wantsysfunc: "syscall.SyscallN",
79+
sig: strings.ReplaceAll(`Example(a1 *uint, a2 *uint, a3 *uint, a4 *uint, a5 *uint, a6 *uint,
80+
a7 *uint, a8 *uint, a9 *uint, a10 *uint, a11 *uint, a12 *uint,
81+
a13 *uint, a14 *uint, a15 *uint, a16 *uint, a17 *uint, a18 *uint) = `, "\n", ""),
82+
},
83+
}
84+
for _, tt := range tests {
85+
t.Run(tt.name, func(t *testing.T) {
86+
// Write the syscall into a temp file for testing.
87+
prefix := "package windows\n//sys " + tt.sig
88+
suffix := ".Example"
89+
name := filepath.Join(t.TempDir(), "syscall.go")
90+
if err := os.WriteFile(name, []byte(prefix+"example"+suffix), 0666); err != nil {
91+
t.Fatal(err)
92+
}
93+
94+
// Ensure parsing, generating, and formatting run without errors.
95+
// This is good enough to show that escaping is working.
96+
src, err := ParseFiles([]string{name})
97+
if err != nil {
98+
t.Fatal(err)
99+
}
100+
var buf bytes.Buffer
101+
if err := src.Generate(&buf); err != nil {
102+
t.Fatal(err)
103+
}
104+
if _, err := format.Source(buf.Bytes()); err != nil {
105+
t.Fatal(err)
106+
}
107+
108+
if !strings.Contains(buf.String(), tt.wantsysfunc+"(") {
109+
t.Fatalf("expected syscall func %q in buffer %s", tt.wantsysfunc, buf.String())
110+
}
111+
})
112+
}
113+
}

0 commit comments

Comments
 (0)