1
2
3
4
5
6
7 package main
8
9 import (
10 "bufio"
11 "bytes"
12 "fmt"
13 "os"
14 "os/exec"
15 "regexp"
16 "sort"
17 "strconv"
18 "strings"
19 )
20
21 var (
22 goos, goarch string
23 )
24
25
26 func cmdLine() string {
27 return "go run linux/mksysnum.go " + strings.Join(os.Args[1:], " ")
28 }
29
30
31 func goBuildTags() string {
32 return fmt.Sprintf("%s && %s", goarch, goos)
33 }
34
35 func format(name string, num int, offset int) (int, string) {
36 if num > 999 {
37
38
39 return 0, ""
40 }
41 name = strings.ToUpper(name)
42 num = num + offset
43 return num, fmt.Sprintf(" SYS_%s = %d;\n", name, num)
44 }
45
46 func checkErr(err error) {
47 if err != nil {
48 fmt.Fprintf(os.Stderr, "%v\n", err)
49 os.Exit(1)
50 }
51 }
52
53
54 type re struct {
55 str string
56 sub []string
57 }
58
59
60 func (r *re) Match(exp string) bool {
61 r.sub = regexp.MustCompile(exp).FindStringSubmatch(r.str)
62 if r.sub != nil {
63 return true
64 }
65 return false
66 }
67
68
69
70 type syscallNum struct {
71 num int
72 declaration string
73 }
74
75
76 type syscallNums []syscallNum
77
78
79 func (nums *syscallNums) addSyscallNum(num int, declaration string) {
80 if declaration == "" {
81 return
82 }
83 if len(*nums) == 0 || (*nums)[len(*nums)-1].num <= num {
84
85
86 *nums = append(*nums, syscallNum{num, declaration})
87 return
88 }
89 i := sort.Search(len(*nums), func(i int) bool { return (*nums)[i].num >= num })
90
91
92
93 for ; (*nums)[i].num == num; i++ {
94 }
95 *nums = append((*nums)[:i], append([]syscallNum{{num, declaration}}, (*nums)[i:]...)...)
96 }
97
98 func main() {
99
100 goos = os.Getenv("GOOS")
101 goarch = os.Getenv("GOARCH_TARGET")
102 if goarch == "" {
103 goarch = os.Getenv("GOARCH")
104 }
105
106 if goarch == "" || goos == "" {
107 fmt.Fprintf(os.Stderr, "GOARCH or GOOS not defined in environment\n")
108 os.Exit(1)
109 }
110
111 if os.Getenv("GOLANG_SYS_BUILD") != "docker" {
112 fmt.Fprintf(os.Stderr, "In the new build system, mksysnum should not be called directly.\n")
113 fmt.Fprintf(os.Stderr, "See README.md\n")
114 os.Exit(1)
115 }
116
117 cc := os.Getenv("CC")
118 if cc == "" {
119 fmt.Fprintf(os.Stderr, "CC is not defined in environment\n")
120 os.Exit(1)
121 }
122 args := os.Args[1:]
123 args = append([]string{"-E", "-dD"}, args...)
124 cmd, err := exec.Command(cc, args...).Output()
125 if err != nil {
126 fmt.Fprintf(os.Stderr, "can't run %s", cc)
127 os.Exit(1)
128 }
129
130 switch goarch {
131 case "riscv64", "loong64", "arm64":
132
133
134
135
136
137 if !bytes.Contains(cmd, []byte("#define __NR_arch_specific_syscall")) {
138 cmd = append(cmd, []byte("#define __NR_arch_specific_syscall 244\n")...)
139 }
140 }
141
142 s := bufio.NewScanner(strings.NewReader(string(cmd)))
143 var offset, prev, asOffset int
144 var nums syscallNums
145 for s.Scan() {
146 t := re{str: s.Text()}
147
148
149
150
151
152
153
154 if t.Match(`^#define __NR_arch_specific_syscall\s+([0-9]+)`) {
155
156 asOffset, _ = strconv.Atoi(t.sub[1])
157 }
158
159 if t.Match(`^#define __NR_Linux\s+([0-9]+)`) {
160
161 offset, _ = strconv.Atoi(t.sub[1])
162 } else if t.Match(`^#define __NR(\w*)_SYSCALL_BASE\s+([0-9]+)`) {
163
164 offset, _ = strconv.Atoi(t.sub[1])
165 } else if t.Match(`^#define __NR_syscalls\s+`) {
166
167 } else if t.Match(`^#define __NR_(\w*)Linux_syscalls\s+`) {
168
169 } else if t.Match(`^#define __NR_(\w+)\s+([0-9]+)`) {
170 prev, err = strconv.Atoi(t.sub[2])
171 checkErr(err)
172 nums.addSyscallNum(format(t.sub[1], prev, offset))
173 } else if t.Match(`^#define __NR3264_(\w+)\s+([0-9]+)`) {
174 prev, err = strconv.Atoi(t.sub[2])
175 checkErr(err)
176 nums.addSyscallNum(format(t.sub[1], prev, offset))
177 } else if t.Match(`^#define __NR_(\w+)\s+\(\w+\+\s*([0-9]+)\)`) {
178 r2, err := strconv.Atoi(t.sub[2])
179 checkErr(err)
180 nums.addSyscallNum(format(t.sub[1], prev+r2, offset))
181 } else if t.Match(`^#define __NR_(\w+)\s+\(__NR_(?:SYSCALL_BASE|Linux) \+ ([0-9]+)`) {
182 r2, err := strconv.Atoi(t.sub[2])
183 checkErr(err)
184 nums.addSyscallNum(format(t.sub[1], r2, offset))
185 } else if asOffset != 0 && t.Match(`^#define __NR_(\w+)\s+\(__NR_arch_specific_syscall \+ ([0-9]+)`) {
186 r2, err := strconv.Atoi(t.sub[2])
187 checkErr(err)
188 nums.addSyscallNum(format(t.sub[1], r2, asOffset))
189 }
190 }
191 err = s.Err()
192 checkErr(err)
193 var text strings.Builder
194 for _, num := range nums {
195 text.WriteString(num.declaration)
196 }
197 fmt.Printf(template, cmdLine(), goBuildTags(), text.String())
198 }
199
200 const template = `// %s
201 // Code generated by the command above; see README.md. DO NOT EDIT.
202
203 //go:build %s
204
205 package unix
206
207 const(
208 %s)`
209
View as plain text