-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlauncher.go
More file actions
130 lines (113 loc) · 2.67 KB
/
launcher.go
File metadata and controls
130 lines (113 loc) · 2.67 KB
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
// This is the code of the launcher process that detects the microarchitecture
// the process is being run on, and launches the appropriate GOAMD64 variant
// that is embedded in the binary.
//
// This code is not compiled in this directory: instead it is copied (together
// with go.mod/go.sum) into the temp directory where the compiled GOAMD64
// variants are output, and it is then compiled from there.
//go:build mgo_launcher && linux && amd64
package main
import (
_ "embed"
"fmt"
"os"
"runtime"
"runtime/debug"
"syscall"
"unsafe"
"github.com/klauspost/cpuid/v2"
"golang.org/x/sys/unix"
)
var (
//go:embed mgo.v1
v1 string
//go:embed mgo.v2
v2 string
//go:embed mgo.v3
v3 string
//go:embed mgo.v4
v4 string
)
func init() {
runtime.GOMAXPROCS(1)
debug.SetGCPercent(-1)
}
func main() {
var level int
switch os.Getenv("GOAMD64") {
case "v1":
level = 1
case "v2":
level = 2
case "v3":
level = 3
case "v4":
level = 4
default:
level = cpuid.CPU.X64Level()
}
v := v1
switch level {
case 2:
v = v2
case 3:
v = v3
case 4:
v = v4
}
switch os.Getenv("MGODEBUG") {
case "extract":
os.Stdout.WriteString(v)
os.Exit(0)
case "log":
fmt.Fprintf(os.Stderr, "[mgo] launcher: starting variant GOAMD64=v%d\n", level)
}
exe := os.Args[0]
if _exe, _ := os.Executable(); _exe != "" {
exe = _exe
}
exe = fmt.Sprintf("%s [GOAMD64=v%d]", exe, level)
// TODO: create fd pointing directly to the data embedded in the launcher?
// TODO: handle via O_TMPFILE the case in which the executable does not fit into a memfd
fd, err := unix.MemfdCreate(exe, unix.MFD_CLOEXEC)
if err != nil {
panicf("creating memfd: %w", err)
}
defer unix.Close(fd)
written, err := syscall.Write(fd, unsafe.Slice(unsafe.StringData(v), len(v)))
if err != nil {
panicf("writing to memfd: %w", err)
} else if written != len(v) {
panic("short write to memfd")
}
// TODO: seal the memfd?
s, err := syscall.BytePtrFromString("")
if err != nil {
panicf("converting path: %w", err)
}
defer runtime.KeepAlive(s)
argv, err := syscall.SlicePtrFromStrings(os.Args)
if err != nil {
panicf("converting args: %w", err)
}
defer runtime.KeepAlive(argv)
envp, err := syscall.SlicePtrFromStrings(os.Environ())
if err != nil {
panicf("converting environ: %w", err)
}
defer runtime.KeepAlive(envp)
ret, _, errno := syscall.Syscall6(
unix.SYS_EXECVEAT,
uintptr(fd),
uintptr(unsafe.Pointer(s)),
uintptr(unsafe.Pointer(&argv[0])),
uintptr(unsafe.Pointer(&envp[0])),
unix.AT_EMPTY_PATH,
0, /* unused */
)
// execveat returns only in case of failure
panicf("execveat: %d %w", ret, errno)
}
func panicf(format string, args ...any) {
panic(fmt.Errorf(format, args...))
}