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 137
|
// 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
// mkasm.go generates assembly trampolines to call library routines from Go.
// This program must be run after mksyscall.go.
package main
import (
"bytes"
"fmt"
"log"
"os"
"sort"
"strings"
)
func archPtrSize(arch string) int {
switch arch {
case "386", "arm":
return 4
case "amd64", "arm64", "mips64", "ppc64", "riscv64":
return 8
default:
log.Fatalf("Unknown arch %q", arch)
return 0
}
}
func generateASMFile(goos, arch string, inFileNames []string, outFileName string) map[string]bool {
trampolines := map[string]bool{}
var orderedTrampolines []string
for _, inFileName := range inFileNames {
in, err := os.ReadFile(inFileName)
if err != nil {
log.Fatalf("Failed to read file: %v", err)
}
for _, line := range strings.Split(string(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] {
orderedTrampolines = append(orderedTrampolines, fn)
trampolines[fn] = true
}
}
}
ptrSize := archPtrSize(arch)
var out bytes.Buffer
fmt.Fprintf(&out, "// go run mkasm.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, "#include \"textflag.h\"\n")
for _, fn := range orderedTrampolines {
fmt.Fprintf(&out, "\nTEXT %s_trampoline<>(SB),NOSPLIT,$0-0\n", fn)
if goos == "openbsd" && arch == "ppc64" {
fmt.Fprintf(&out, "\tCALL\t%s(SB)\n", fn)
fmt.Fprintf(&out, "\tRET\n")
} else {
fmt.Fprintf(&out, "\tJMP\t%s(SB)\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)
}
if err := os.WriteFile(outFileName, out.Bytes(), 0644); err != nil {
log.Fatalf("Failed to write assembly file %q: %v", outFileName, err)
}
return trampolines
}
const darwinTestTemplate = `// go run mkasm.go %s
// Code generated by the command above; DO NOT EDIT.
//go:build darwin
package unix
// All the _trampoline functions in zsyscall_darwin_%s.s.
var darwinTests = [...]darwinTest{
%s}
`
func writeDarwinTest(trampolines map[string]bool, fileName, arch string) {
var sortedTrampolines []string
for fn := range trampolines {
sortedTrampolines = append(sortedTrampolines, fn)
}
sort.Strings(sortedTrampolines)
var out bytes.Buffer
const prefix = "libc_"
for _, fn := range sortedTrampolines {
fmt.Fprintf(&out, fmt.Sprintf("\t{%q, %s_trampoline_addr},\n", strings.TrimPrefix(fn, prefix), fn))
}
lines := out.String()
out.Reset()
fmt.Fprintf(&out, darwinTestTemplate, strings.Join(os.Args[1:], " "), arch, lines)
if err := os.WriteFile(fileName, out.Bytes(), 0644); err != nil {
log.Fatalf("Failed to write test file %q: %v", fileName, err)
}
}
func main() {
if len(os.Args) != 3 {
log.Fatalf("Usage: %s <goos> <arch>", os.Args[0])
}
goos, arch := os.Args[1], os.Args[2]
syscallFilename := fmt.Sprintf("syscall_%s.go", goos)
syscallArchFilename := fmt.Sprintf("syscall_%s_%s.go", goos, arch)
zsyscallArchFilename := fmt.Sprintf("zsyscall_%s_%s.go", goos, arch)
zsyscallASMFileName := fmt.Sprintf("zsyscall_%s_%s.s", goos, arch)
inFileNames := []string{
syscallFilename,
syscallArchFilename,
zsyscallArchFilename,
}
trampolines := generateASMFile(goos, arch, inFileNames, zsyscallASMFileName)
if goos == "darwin" {
writeDarwinTest(trampolines, fmt.Sprintf("darwin_%s_test.go", arch), arch)
}
}
|