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