blob: 9406c4ff228aa4828750b33e9fd1fb57e06ab157 [file] [log] [blame]
Kamil Rytarowski39628a72018-02-15 02:43:02 +00001#!/usr/bin/awk -f
2
3#===-- generate_netbsd_syscalls.awk ----------------------------------------===#
4#
5# The LLVM Compiler Infrastructure
6#
7# This file is distributed under the University of Illinois Open Source
8# License. See LICENSE.TXT for details.
9#
10#===------------------------------------------------------------------------===#
11#
12# This file is a generator of:
13# - include/sanitizer/netbsd_syscall_hooks.h
14# - lib/sanitizer_common/sanitizer_syscalls_netbsd.inc
15#
16# This script accepts on the input syscalls.master by default located in the
17# /usr/src/sys/kern/syscalls.master path in the NetBSD distribution.
18#
19# NetBSD version 8.0.
20#
21#===------------------------------------------------------------------------===#
22
23BEGIN {
24 # harcode the script name
25 script_name = "generate_netbsd_syscalls.awk"
26 outputh = "../include/sanitizer/netbsd_syscall_hooks.h"
27 outputinc = "../lib/sanitizer_common/sanitizer_syscalls_netbsd.inc"
28
29 # assert that we are in the directory with scripts
30 in_utils = system("test -f " script_name " && exit 1 || exit 0")
31 if (in_utils == 0) {
32 usage()
33 }
34
35 # assert 1 argument passed
36 if (ARGC != 2) {
37 usage()
38 }
39
40 # assert argument is a valid file path to syscall.master
41 if (system("test -f " ARGV[1]) != 0) {
42 usage()
43 }
44
45 # sanity check that the path ends with "syscall.master"
46 if (ARGV[1] !~ /syscalls\.master$/) {
47 usage()
48 }
49
50 # accept overloading CLANGFORMAT from environment
51 clangformat = "clang-format"
52 if ("CLANGFORMAT" in ENVIRON) {
53 clangformat = ENVIRON["CLANGFORMAT"]
54 }
55
56 # parsing specific symbols
57 parsingheader=1
58
59 parsedsyscalls=0
60
61 # Hardcoded in algorithm
62 SYS_MAXSYSARGS=8
63}
64
65# Parse the RCS ID from syscall.master
66parsingheader == 1 && NR == 1 {
67 if (match($0, /\$[^$]+\$/)) {
68 # trim initial 'NetBSD: ' and trailing ' $'
69 syscallmasterversion = substr($0, RSTART + 9, RLENGTH - 11)
70 } else {
71 # wrong file?
72 usage()
73 }
74}
75
76# skip the following lines
77# - empty
78NF == 0 {
79 next
80}
81# - comment
82$1 == ";" {
83 next
84}
85
86# separator between the header and table with syscalls
87$0 == "%%" {
88 parsingheader = 0
89 next
90}
91
92# preserve 'if/elif/else/endif' C preprocessor as-is
93parsingheader == 0 && $0 ~ /^#/ {
94 if (parsedsyscalls in ifelifelseendif) {
95 ifelifelseendif[parsedsyscalls] = ifelifelseendif[parsedsyscalls] "\n" $0
96 } else {
97 ifelifelseendif[parsedsyscalls] = $0
98 }
99 next
100}
101
102# parsing of syscall definitions
103parsingheader == 0 && $1 ~ /^[0-9]+$/ {
104 # first join multiple lines into single one
105 while (sub(/\\$/, "")) {
106 getline line
107 $0 = $0 "" line
108 }
109
110 # Skip unwanted syscalls
111 skip=0
112 if ($0 ~ /OBSOL/ || $0 ~ /EXCL/ || $0 ~ /UNIMPL/) {
113 skip=1
114 }
115
116 # Compose the syscall name
117 # - compat?
118 compat=""
119 if (match($0, /COMPAT_[0-9]+/)) {
120 compat = tolower(substr($0, RSTART, RLENGTH))
121 }
122 # - alias name?
123 alias=""
124 if ($(NF) != "}" && !skip) {
125 alias = alias "" $(NF)
126 }
127 # - compat version?
128 compatver=""
129 if (match($0, /\|[0-9]+\|/)) {
130 compatver = tolower(substr($0, RSTART + 1, RLENGTH - 2))
131 }
132 # - basename?
133 basename=""
134 if (skip) {
135 basename = $1
136 } else {
137 if (match($0, /\|[_a-z0-9]+\(/)) {
138 basename = tolower(substr($0, RSTART + 1, RLENGTH - 2))
139 }
140 }
141
142 syscallname=""
143
144 if (skip) {
145 syscallname= syscallname "$"
146 }
147
148 if (length(compat) > 0) {
149 syscallname = syscallname "" compat "_"
150 }
151 if (length(alias) > 0) {
152 syscallname = syscallname "" alias
153 } else {
154 if (length(compatver) > 0) {
155 syscallname = syscallname "__" basename "" compatver
156 } else {
157 syscallname = syscallname "" basename
158 }
159 }
160
161 # Store the syscallname
162 syscalls[parsedsyscalls]=syscallname
163
164 # Extract syscall arguments
165 if (match($0, /\([^)]+\)/)) {
166 args = substr($0, RSTART + 1, RLENGTH - 2)
167
168 if (args == "void") {
169 syscallargs[parsedsyscalls] = "void"
170 syscallfullargs[parsedsyscalls] = "void"
171 } else {
172 # Normalize 'type * argument' to 'type *argument'
173 gsub("\\*[ \t]+", "*", args)
174
175 n = split(args, a, ",")
176
177 # Handle the first argument
178 match(a[1], /[*_a-z0-9\[\]]+$/)
179 syscallfullargs[parsedsyscalls] = substr(a[1], RSTART) "_"
180
181 gsub(".+[ *]", "", a[1])
182 syscallargs[parsedsyscalls] = a[1]
183
184 # Handle the rest of arguments
185 for (i = 2; i <= n; i++) {
186 match(a[i], /[*_a-zA-Z0-9\[\]]+$/)
187 fs = substr(a[i], RSTART)
188 if (fs ~ /\[/) {
189 sub(/\[/, "_[", fs)
190 } else {
191 fs = fs "_"
192 }
193 syscallfullargs[parsedsyscalls] = syscallfullargs[parsedsyscalls] "$" fs
194 gsub(".+[ *]", "", a[i])
195 syscallargs[parsedsyscalls] = syscallargs[parsedsyscalls] "$" a[i]
196 }
197
198 # Handle array arguments for syscall(2) and __syscall(2)
199 nargs = "arg0$arg1$arg2$arg3$arg4$arg5$arg6$arg7"
200 gsub(/args\[SYS_MAXSYSARGS\]/, nargs, syscallargs[parsedsyscalls])
201 }
202 }
203
204 parsedsyscalls++
205
206 # Done with this line
207 next
208}
209
210
211END {
212 # empty file?
213 if (NR < 1 && !abnormal_exit) {
214 usage()
215 }
216
217 # Handle abnormal exit
218 if (abnormal_exit) {
219 exit(abnormal_exit)
220 }
221
222 # Generate sanitizer_syscalls_netbsd.inc
223
224 # open pipe
225 cmd = clangformat " > " outputh
226
227 pcmd("//===-- netbsd_syscall_hooks.h --------------------------------------------===//")
228 pcmd("//")
229 pcmd("// The LLVM Compiler Infrastructure")
230 pcmd("//")
231 pcmd("// This file is distributed under the University of Illinois Open Source")
232 pcmd("// License. See LICENSE.TXT for details.")
233 pcmd("//")
234 pcmd("//===----------------------------------------------------------------------===//")
235 pcmd("//")
236 pcmd("// This file is a part of public sanitizer interface.")
237 pcmd("//")
238 pcmd("// System call handlers.")
239 pcmd("//")
240 pcmd("// Interface methods declared in this header implement pre- and post- syscall")
241 pcmd("// actions for the active sanitizer.")
242 pcmd("// Usage:")
243 pcmd("// __sanitizer_syscall_pre_getfoo(...args...);")
244 pcmd("// long long res = syscall(SYS_getfoo, ...args...);")
245 pcmd("// __sanitizer_syscall_post_getfoo(res, ...args...);")
246 pcmd("//")
247 pcmd("// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!")
248 pcmd("//")
249 pcmd("// Generated with: " script_name)
250 pcmd("// Generated date: " strftime("%F"))
251 pcmd("// Generated from: " syscallmasterversion)
252 pcmd("//")
253 pcmd("//===----------------------------------------------------------------------===//")
254 pcmd("#ifndef SANITIZER_NETBSD_SYSCALL_HOOKS_H")
255 pcmd("#define SANITIZER_NETBSD_SYSCALL_HOOKS_H")
256 pcmd("")
257
258 # TODO
259
260 pcmd("")
261 pcmd("#ifdef __cplusplus")
262 pcmd("extern \"C\" {")
263 pcmd("#endif")
264 pcmd("")
265 pcmd("// Private declarations. Do not call directly from user code. Use macros above.")
266 pcmd("")
267 pcmd("// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!")
268 pcmd("")
269
270 # TODO
271
272 pcmd("")
273 pcmd("#ifdef __cplusplus")
274 pcmd("} // extern \"C\"")
275 pcmd("#endif")
276
277 pcmd("")
278 pcmd("// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!")
279 pcmd("")
280
281 pcmd("#endif // SANITIZER_NETBSD_SYSCALL_HOOKS_H")
282
283 close(cmd)
284
285 # Generate sanitizer_syscalls_netbsd.inc
286
287 # open pipe
288 cmd = clangformat " > " outputinc
289
290 pcmd("//===-- sanitizer_syscalls_netbsd.inc ---------------------------*- C++ -*-===//")
291 pcmd("//")
292 pcmd("// The LLVM Compiler Infrastructure")
293 pcmd("//")
294 pcmd("// This file is distributed under the University of Illinois Open Source")
295 pcmd("// License. See LICENSE.TXT for details.")
296 pcmd("//")
297 pcmd("//===----------------------------------------------------------------------===//")
298 pcmd("//")
299 pcmd("// Common syscalls handlers for tools like AddressSanitizer,")
300 pcmd("// ThreadSanitizer, MemorySanitizer, etc.")
301 pcmd("//")
302 pcmd("// This file should be included into the tool's interceptor file,")
303 pcmd("// which has to define it's own macros:")
304 pcmd("// COMMON_SYSCALL_PRE_READ_RANGE")
305 pcmd("// Called in prehook for regions that will be read by the kernel and")
306 pcmd("// must be initialized.")
307 pcmd("// COMMON_SYSCALL_PRE_WRITE_RANGE")
308 pcmd("// Called in prehook for regions that will be written to by the kernel")
309 pcmd("// and must be addressable. The actual write range may be smaller than")
310 pcmd("// reported in the prehook. See POST_WRITE_RANGE.")
311 pcmd("// COMMON_SYSCALL_POST_READ_RANGE")
312 pcmd("// Called in posthook for regions that were read by the kernel. Does")
313 pcmd("// not make much sense.")
314 pcmd("// COMMON_SYSCALL_POST_WRITE_RANGE")
315 pcmd("// Called in posthook for regions that were written to by the kernel")
316 pcmd("// and are now initialized.")
317 pcmd("// COMMON_SYSCALL_ACQUIRE(addr)")
318 pcmd("// Acquire memory visibility from addr.")
319 pcmd("// COMMON_SYSCALL_RELEASE(addr)")
320 pcmd("// Release memory visibility to addr.")
321 pcmd("// COMMON_SYSCALL_FD_CLOSE(fd)")
322 pcmd("// Called before closing file descriptor fd.")
323 pcmd("// COMMON_SYSCALL_FD_ACQUIRE(fd)")
324 pcmd("// Acquire memory visibility from fd.")
325 pcmd("// COMMON_SYSCALL_FD_RELEASE(fd)")
326 pcmd("// Release memory visibility to fd.")
327 pcmd("// COMMON_SYSCALL_PRE_FORK()")
328 pcmd("// Called before fork syscall.")
329 pcmd("// COMMON_SYSCALL_POST_FORK(long long res)")
330 pcmd("// Called after fork syscall.")
331 pcmd("//")
332 pcmd("// DO NOT EDIT! THIS FILE HAS BEEN GENERATED!")
333 pcmd("//")
334 pcmd("// Generated with: " script_name)
335 pcmd("// Generated date: " strftime("%F"))
336 pcmd("// Generated from: " syscallmasterversion)
337 pcmd("//")
338 pcmd("//===----------------------------------------------------------------------===//")
339 pcmd("")
340 pcmd("#include \"sanitizer_platform.h\"")
341 pcmd("#if SANITIZER_NETBSD")
342 pcmd("")
343 pcmd("#include \"sanitizer_libc.h\"")
344 pcmd("")
345 pcmd("#define PRE_SYSCALL(name) \\")
346 pcmd(" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_pre_impl_##name")
347 pcmd("#define PRE_READ(p, s) COMMON_SYSCALL_PRE_READ_RANGE(p, s)")
348 pcmd("#define PRE_WRITE(p, s) COMMON_SYSCALL_PRE_WRITE_RANGE(p, s)")
349 pcmd("")
350 pcmd("#define POST_SYSCALL(name) \\")
351 pcmd(" SANITIZER_INTERFACE_ATTRIBUTE void __sanitizer_syscall_post_impl_##name")
352 pcmd("#define POST_READ(p, s) COMMON_SYSCALL_POST_READ_RANGE(p, s)")
353 pcmd("#define POST_WRITE(p, s) COMMON_SYSCALL_POST_WRITE_RANGE(p, s)")
354 pcmd("")
355 pcmd("#ifndef COMMON_SYSCALL_ACQUIRE")
356 pcmd("# define COMMON_SYSCALL_ACQUIRE(addr) ((void)(addr))")
357 pcmd("#endif")
358 pcmd("")
359 pcmd("#ifndef COMMON_SYSCALL_RELEASE")
360 pcmd("# define COMMON_SYSCALL_RELEASE(addr) ((void)(addr))")
361 pcmd("#endif")
362 pcmd("")
363 pcmd("#ifndef COMMON_SYSCALL_FD_CLOSE")
364 pcmd("# define COMMON_SYSCALL_FD_CLOSE(fd) ((void)(fd))")
365 pcmd("#endif")
366 pcmd("")
367 pcmd("#ifndef COMMON_SYSCALL_FD_ACQUIRE")
368 pcmd("# define COMMON_SYSCALL_FD_ACQUIRE(fd) ((void)(fd))")
369 pcmd("#endif")
370 pcmd("")
371 pcmd("#ifndef COMMON_SYSCALL_FD_RELEASE")
372 pcmd("# define COMMON_SYSCALL_FD_RELEASE(fd) ((void)(fd))")
373 pcmd("#endif")
374 pcmd("")
375 pcmd("#ifndef COMMON_SYSCALL_PRE_FORK")
376 pcmd("# define COMMON_SYSCALL_PRE_FORK() {}")
377 pcmd("#endif")
378 pcmd("")
379 pcmd("#ifndef COMMON_SYSCALL_POST_FORK")
380 pcmd("# define COMMON_SYSCALL_POST_FORK(res) {}")
381 pcmd("#endif")
382 pcmd("")
383 pcmd("// FIXME: do some kind of PRE_READ for all syscall arguments (int(s) and such).")
384 pcmd("")
385 pcmd("extern \"C\" {")
386
387 # TODO
388
389 pcmd("} // extern \"C\"")
390 pcmd("")
391 pcmd("#undef PRE_SYSCALL")
392 pcmd("#undef PRE_READ")
393 pcmd("#undef PRE_WRITE")
394 pcmd("#undef POST_SYSCALL")
395 pcmd("#undef POST_READ")
396 pcmd("#undef POST_WRITE")
397 pcmd("")
398 pcmd("#endif // SANITIZER_NETBSD")
399
400 close(cmd)
401
402 # Hack for preprocessed code
403 system("sed -i 's,^ \\([^ ]\\), \\1,' " outputinc)
404}
405
406function usage()
407{
408 print "Usage: " script_name " syscalls.master"
409 abnormal_exit = 1
410 exit 1
411}
412
413function pcmd(string)
414{
415 print string | cmd
416}