1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
// Copyright 2018 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.
//go:build ignore
// +build ignore
// mkasm_darwin.go generates assembly trampolines to call libSystem routines from Go.
//This program must be run after mksyscall.go.
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"sort"
"strings"
)
const ptrsize = 8 // Pointer size. All supported platforms are 64-bit.
func writeASMFile(in string, fileName string, buildTags string) map[string]bool {
trampolines := map[string]bool{}
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "//go:build %s\n", buildTags)
fmt.Fprintf(&out, "// +build %s\n", buildTags)
fmt.Fprintf(&out, "\n")
fmt.Fprintf(&out, "#include \"textflag.h\"\n")
for _, line := range strings.Split(in, "\n") {
const prefix = "var "
const suffix = "_trampoline_addr uintptr"
if !strings.HasPrefix(line, prefix) || !strings.HasSuffix(line, suffix) {
continue
}
fn := strings.TrimSuffix(strings.TrimPrefix(line, prefix), suffix)
if !trampolines[fn] {
trampolines[fn] = true
fmt.Fprintf(&out, "\nTEXT %s_trampoline<>(SB),NOSPLIT,$0-0\n", fn)
fmt.Fprintf(&out, "\tJMP\t%s(SB)\n\n", fn)
fmt.Fprintf(&out, "GLOBL\t·%s_trampoline_addr(SB), RODATA, $%d\n", fn, ptrsize)
fmt.Fprintf(&out, "DATA\t·%s_trampoline_addr(SB)/%d, $%s_trampoline<>(SB)\n", fn, ptrsize, fn)
}
}
err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write %s: %s", fileName, err)
}
return trampolines
}
const darwinTestTemplate = `// go run mkasm_darwin.go %s
// Code generated by the command above; DO NOT EDIT.
//go:build darwin && go1.12
// +build darwin,go1.12
package unix
// All the _trampoline functions in zsyscall_darwin_%s.s.
var darwinTests = [...]darwinTest{
%s}
`
func writeDarwinTest(trampolines map[string]bool, fileName, arch string) {
// sort trampolines
sorted := make([]string, len(trampolines))
i := 0
for trampoline := range trampolines {
sorted[i] = trampoline
i++
}
sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
var out bytes.Buffer
const prefix = "libc_"
for _, trampoline := range sorted {
fmt.Fprintf(&out, fmt.Sprintf("\t{%q, %s_trampoline_addr},\n", strings.TrimPrefix(trampoline, prefix), trampoline))
}
lines := out.String()
out.Reset()
fmt.Fprintf(&out, darwinTestTemplate, strings.Join(os.Args[1:], " "), arch, lines)
err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
if err != nil {
log.Fatalf("can't write %s: %s", fileName, err)
}
}
func main() {
in1, err := ioutil.ReadFile("syscall_darwin.go")
if err != nil {
log.Fatalf("can't open syscall_darwin.go: %s", err)
}
arch := os.Args[1]
in2, err := ioutil.ReadFile(fmt.Sprintf("syscall_darwin_%s.go", arch))
if err != nil {
log.Fatalf("can't open syscall_darwin_%s.go: %s", arch, err)
}
in3, err := ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.go", arch))
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.go: %s", arch, err)
}
in := string(in1) + string(in2) + string(in3)
trampolines := writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.s", arch), "go1.12")
in1, err = ioutil.ReadFile("syscall_darwin.1_13.go")
if err != nil {
log.Fatalf("can't open syscall_darwin.1_13.go: %s", err)
}
in2, err = ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.1_13.go", arch))
if err != nil {
log.Fatalf("can't open zsyscall_darwin_%s.1_13.go: %s", arch, err)
}
in = string(in1) + string(in2)
trampolines2 := writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.1_13.s", arch), "go1.13")
// merge trampolines
for trampoline := range trampolines2 {
trampolines[trampoline] = true
}
writeDarwinTest(trampolines, fmt.Sprintf("darwin_%s_test.go", arch), arch)
}
|