blob: fc39a3011b11d5146c37d52a6f9fc559fefb5fb2 [file] [log] [blame]
Kamil Rytarowski5ffda0c2018-02-15 03:36:16 +00001#!/usr/bin/awk -f
2
3#===-- generate_netbsd_ioctls.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/sanitizer_interceptors_ioctl_netbsd.inc
14#
15# This script reads public headers from a NetBSD host.
16#
17#===------------------------------------------------------------------------===#
18
19BEGIN {
20 # harcode the script name
21 script_name = "generate_netbsd_ioctls.awk"
22 outputinc = "../lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc"
23
24 # assert that we are in the directory with scripts
25 in_utils = system("test -f " script_name " && exit 1 || exit 0")
26 if (in_utils == 0) {
27 usage()
28 }
29
30 # assert 0 argument passed
31 if (ARGC != 1) {
32 usage()
33 }
34
35 # accept overloading CLANGFORMAT from environment
36 clangformat = "clang-format"
37 if ("CLANGFORMAT" in ENVIRON) {
38 clangformat = ENVIRON["CLANGFORMAT"]
39 }
40
41 # accept overloading ROOTDIR from environment
42 rootdir = "/usr/include/"
43 if ("ROOTDIR" in ENVIRON) {
44 rootdir = ENVIRON["ROOTDIR"]
45 }
46
47 # hardcode list of headers with ioctl(2) entries
48 # List generated manually with the following script:
49 # for w in `find /usr/include/ -type f -name '*.h' -exec echo {} \;`; \
50 # do awk '/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {got=1} END{if(got) {print ARGV[1]}}' $w; \
51 # done|awk '{print " ARGV[ARGC++] = rootdir \"" substr($0, 14) "\""}'
52
53 ARGV[ARGC++] = rootdir "altq/altq_afmap.h"
54 ARGV[ARGC++] = rootdir "altq/altq.h"
55 ARGV[ARGC++] = rootdir "altq/altq_blue.h"
56 ARGV[ARGC++] = rootdir "altq/altq_cbq.h"
57 ARGV[ARGC++] = rootdir "altq/altq_cdnr.h"
58 ARGV[ARGC++] = rootdir "altq/altq_fifoq.h"
59 ARGV[ARGC++] = rootdir "altq/altq_hfsc.h"
60 ARGV[ARGC++] = rootdir "altq/altq_jobs.h"
61 ARGV[ARGC++] = rootdir "altq/altq_priq.h"
62 ARGV[ARGC++] = rootdir "altq/altq_red.h"
63 ARGV[ARGC++] = rootdir "altq/altq_rio.h"
64 ARGV[ARGC++] = rootdir "altq/altq_wfq.h"
65 ARGV[ARGC++] = rootdir "crypto/cryptodev.h"
66 ARGV[ARGC++] = rootdir "dev/apm/apmio.h"
67 ARGV[ARGC++] = rootdir "dev/dm/netbsd-dm.h"
68 ARGV[ARGC++] = rootdir "dev/dmover/dmover_io.h"
69 ARGV[ARGC++] = rootdir "dev/dtv/dtvio_demux.h"
70 ARGV[ARGC++] = rootdir "dev/dtv/dtvio_frontend.h"
71 ARGV[ARGC++] = rootdir "dev/filemon/filemon.h"
72 ARGV[ARGC++] = rootdir "dev/hdaudio/hdaudioio.h"
73 ARGV[ARGC++] = rootdir "dev/hdmicec/hdmicecio.h"
74 ARGV[ARGC++] = rootdir "dev/hpc/hpcfbio.h"
75 ARGV[ARGC++] = rootdir "dev/i2o/iopio.h"
76 ARGV[ARGC++] = rootdir "dev/ic/athioctl.h"
77 ARGV[ARGC++] = rootdir "dev/ic/bt8xx.h"
78 ARGV[ARGC++] = rootdir "dev/ic/hd44780var.h"
79 ARGV[ARGC++] = rootdir "dev/ic/icp_ioctl.h"
80 ARGV[ARGC++] = rootdir "dev/ic/isp_ioctl.h"
81 ARGV[ARGC++] = rootdir "dev/ic/mlxio.h"
82 ARGV[ARGC++] = rootdir "dev/ic/nvmeio.h"
83 ARGV[ARGC++] = rootdir "dev/ir/irdaio.h"
84 ARGV[ARGC++] = rootdir "dev/isa/satlinkio.h"
85 ARGV[ARGC++] = rootdir "dev/isa/isvio.h"
86 ARGV[ARGC++] = rootdir "dev/isa/wtreg.h"
87 ARGV[ARGC++] = rootdir "dev/iscsi/iscsi_ioctl.h"
88 ARGV[ARGC++] = rootdir "dev/ofw/openfirmio.h"
89 ARGV[ARGC++] = rootdir "dev/pci/amrio.h"
90 ARGV[ARGC++] = rootdir "dev/pci/mlyio.h"
91 ARGV[ARGC++] = rootdir "dev/pci/pciio.h"
92 ARGV[ARGC++] = rootdir "dev/pci/tweio.h"
93 ARGV[ARGC++] = rootdir "dev/pcmcia/if_cnwioctl.h"
94 ARGV[ARGC++] = rootdir "dev/pcmcia/if_rayreg.h"
95 ARGV[ARGC++] = rootdir "dev/raidframe/raidframeio.h"
96 ARGV[ARGC++] = rootdir "dev/sbus/mbppio.h"
97 ARGV[ARGC++] = rootdir "dev/scsipi/ses.h"
98 ARGV[ARGC++] = rootdir "dev/sun/disklabel.h"
99 ARGV[ARGC++] = rootdir "dev/sun/fbio.h"
100 ARGV[ARGC++] = rootdir "dev/sun/kbio.h"
101 ARGV[ARGC++] = rootdir "dev/sun/vuid_event.h"
102 ARGV[ARGC++] = rootdir "dev/tc/sticio.h"
103 ARGV[ARGC++] = rootdir "dev/usb/ukyopon.h"
104 ARGV[ARGC++] = rootdir "dev/usb/urio.h"
105 ARGV[ARGC++] = rootdir "dev/usb/usb.h"
106 ARGV[ARGC++] = rootdir "dev/usb/utoppy.h"
107 ARGV[ARGC++] = rootdir "dev/vme/xio.h"
108 ARGV[ARGC++] = rootdir "dev/wscons/wsdisplay_usl_io.h"
109 ARGV[ARGC++] = rootdir "dev/wscons/wsconsio.h"
110 ARGV[ARGC++] = rootdir "dev/biovar.h"
111 ARGV[ARGC++] = rootdir "dev/md.h"
112 ARGV[ARGC++] = rootdir "dev/ccdvar.h"
113 ARGV[ARGC++] = rootdir "dev/cgdvar.h"
114 ARGV[ARGC++] = rootdir "dev/fssvar.h"
115 ARGV[ARGC++] = rootdir "dev/bluetooth/btdev.h"
116 ARGV[ARGC++] = rootdir "dev/bluetooth/btsco.h"
117 ARGV[ARGC++] = rootdir "dev/kttcpio.h"
118 ARGV[ARGC++] = rootdir "dev/lockstat.h"
119 ARGV[ARGC++] = rootdir "dev/vndvar.h"
120 ARGV[ARGC++] = rootdir "dev/spkrio.h"
121 ARGV[ARGC++] = rootdir "net/bpf.h"
122 ARGV[ARGC++] = rootdir "net/if_atm.h"
123 ARGV[ARGC++] = rootdir "net/if_gre.h"
124 ARGV[ARGC++] = rootdir "net/if_ppp.h"
125 ARGV[ARGC++] = rootdir "net/npf.h"
126 ARGV[ARGC++] = rootdir "net/if_pppoe.h"
127 ARGV[ARGC++] = rootdir "net/if_sppp.h"
128 ARGV[ARGC++] = rootdir "net/if_srt.h"
129 ARGV[ARGC++] = rootdir "net/if_tap.h"
130 ARGV[ARGC++] = rootdir "net/if_tun.h"
131 ARGV[ARGC++] = rootdir "net/pfvar.h"
132 ARGV[ARGC++] = rootdir "net/slip.h"
133 ARGV[ARGC++] = rootdir "netbt/hci.h"
134 ARGV[ARGC++] = rootdir "netinet/ip_nat.h"
135 ARGV[ARGC++] = rootdir "netinet/ip_proxy.h"
136 ARGV[ARGC++] = rootdir "netinet6/in6_var.h"
137 ARGV[ARGC++] = rootdir "netnatm/natm.h"
138 ARGV[ARGC++] = rootdir "netsmb/smb_dev.h"
139 ARGV[ARGC++] = rootdir "sys/agpio.h"
140 ARGV[ARGC++] = rootdir "sys/audioio.h"
141 ARGV[ARGC++] = rootdir "sys/ataio.h"
142 ARGV[ARGC++] = rootdir "sys/cdio.h"
143 ARGV[ARGC++] = rootdir "sys/chio.h"
144 ARGV[ARGC++] = rootdir "sys/clockctl.h"
145 ARGV[ARGC++] = rootdir "sys/cpuio.h"
146 ARGV[ARGC++] = rootdir "sys/dkio.h"
147 ARGV[ARGC++] = rootdir "sys/drvctlio.h"
148 ARGV[ARGC++] = rootdir "sys/dvdio.h"
149 ARGV[ARGC++] = rootdir "sys/envsys.h"
150 ARGV[ARGC++] = rootdir "sys/event.h"
151 ARGV[ARGC++] = rootdir "sys/fdio.h"
152 ARGV[ARGC++] = rootdir "sys/filio.h"
153 ARGV[ARGC++] = rootdir "sys/gpio.h"
154 ARGV[ARGC++] = rootdir "sys/ioctl.h"
155 ARGV[ARGC++] = rootdir "sys/ioctl_compat.h"
156 ARGV[ARGC++] = rootdir "sys/joystick.h"
157 ARGV[ARGC++] = rootdir "sys/ksyms.h"
158 ARGV[ARGC++] = rootdir "sys/lua.h"
159 ARGV[ARGC++] = rootdir "sys/midiio.h"
160 ARGV[ARGC++] = rootdir "sys/mtio.h"
161 ARGV[ARGC++] = rootdir "sys/power.h"
162 ARGV[ARGC++] = rootdir "sys/radioio.h"
163 ARGV[ARGC++] = rootdir "sys/rndio.h"
164 ARGV[ARGC++] = rootdir "sys/scanio.h"
165 ARGV[ARGC++] = rootdir "sys/scsiio.h"
166 ARGV[ARGC++] = rootdir "sys/sockio.h"
167 ARGV[ARGC++] = rootdir "sys/timepps.h"
168 ARGV[ARGC++] = rootdir "sys/ttycom.h"
169 ARGV[ARGC++] = rootdir "sys/verified_exec.h"
170 ARGV[ARGC++] = rootdir "sys/videoio.h"
171 ARGV[ARGC++] = rootdir "sys/wdog.h"
172 ARGV[ARGC++] = rootdir "soundcard.h"
173 ARGV[ARGC++] = rootdir "xen/xenio.h"
174
175 ioctl_table_max = 0
176}
177
178# Scan RCS ID
179FNR == 1 {
180 fname[ioctl_table_max] = substr(FILENAME, length(rootdir) + 1)
181}
182
183# _IO
184/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ {
185 if ($0 ~ /RAIDFRAME_GET_ACCTOTALS/ ||
186 $0 ~ /ALTQATTACH/ ||
187 $0 ~ /ALTQDETACH/ ||
188 $0 ~ /ALTQENABLE/ ||
189 $0 ~ /ALTQDISABLE/ ||
190 $0 ~ /ALTQCLEAR/ ||
191 $0 ~ /ALTQCONFIG/ ||
192 $0 ~ /ALTQADDCLASS/ ||
193 $0 ~ /ALTQMODCLASS/ ||
194 $0 ~ /ALTQDELCLASS/ ||
195 $0 ~ /ALTQADDFILTER/ ||
196 $0 ~ /ALTQDELFILTER/ ||
197 $0 ~ /ALTQGETSTATS/ ||
198 $0 ~ /ALTQGETCNTR/ ||
199 $0 ~ /HLCD_DISPCTL/ ||
200 $0 ~ /HLCD_RESET/ ||
201 $0 ~ /HLCD_CLEAR/ ||
202 $0 ~ /HLCD_CURSOR_LEFT/ ||
203 $0 ~ /HLCD_CURSOR_RIGHT/ ||
204 $0 ~ /HLCD_GET_CURSOR_POS/ ||
205 $0 ~ /HLCD_SET_CURSOR_POS/ ||
206 $0 ~ /HLCD_GETC/ ||
207 $0 ~ /HLCD_PUTC/ ||
208 $0 ~ /HLCD_SHIFT_LEFT/ ||
209 $0 ~ /HLCD_SHIFT_RIGHT/ ||
210 $0 ~ /HLCD_HOME/ ||
211 $0 ~ /HLCD_WRITE/ ||
212 $0 ~ /HLCD_READ/ ||
213 $0 ~ /HLCD_REDRAW/ ||
214 $0 ~ /HLCD_WRITE_INST/ ||
215 $0 ~ /HLCD_WRITE_DATA/ ||
216 $0 ~ /HLCD_GET_INFO/ ||
217 $0 ~ /HLCD_GET_CHIPNO/ ||
218 $0 ~ /HLCD_SET_CHIPNO/ ||
219 $0 ~ /RAIDFRAME_TEST_ACC/ ||
220 $0 ~ /FBIOGINFO/ ||
221 $0 ~ /FBIOSATTR/ ||
222 $0 ~ /OBIOCDISK/ ||
223 $0 ~ /OBIOCVOL/ ||
224 $0 ~ /BIOCSORTIMEOUT/ ||
225 $0 ~ /BIOCGORTIMEOUT/ ||
226 $0 ~ /PPPIOCSPASS/ ||
227 $0 ~ /PPPIOCSACTIVE/ ||
228 $0 ~ /PPPIOCSIPASS/ ||
229 $0 ~ /PPPIOCSOPASS/ ||
230 $0 ~ /PPPIOCSIACTIVE/ ||
231 $0 ~ /PPPIOCSOACTIVE/ ||
232 $0 ~ /SIOCPROXY/ ||
233 $0 ~ /SIOCXRAWATM/ ||
234 $0 ~ /AGPIOC_RESERVE/ ||
235 $0 ~ /AGPIOC_PROTECT/ ||
236 $0 ~ /CDIOCREADSUBCHANNEL_BUF/ ||
237 $0 ~ /CDIOREADTOCENTRIES_BUF/ ||
238 $0 ~ /MMCGETDISCINFO/ ||
239 $0 ~ /MMCGETTRACKINFO/ ||
240 $0 ~ /MMCOP/ ||
241 $0 ~ /MMCSETUPWRITEPARAMS/ ||
242 $0 ~ /DIOCGPARTINFO/ ||
243 $0 ~ /ODIOCGDINFO/ ||
244 $0 ~ /ODIOCSDINFO/ ||
245 $0 ~ /ODIOCWDINFO/ ||
246 $0 ~ /ODIOCGDEFLABEL/ ||
247 $0 ~ /GPIOPINREAD/ ||
248 $0 ~ /GPIOPINWRITE/ ||
249 $0 ~ /GPIOPINTOGGLE/ ||
250 $0 ~ /GPIOPINCTL/ ||
251 $0 ~ /GPIODETACH/ ||
252 $0 ~ /SEQUENCER_PERCMODE/ ||
253 $0 ~ /SEQUENCER_TESTMIDI/ ||
254 $0 ~ /SEQUENCER_MIDI_INFO/ ||
255 $0 ~ /SEQUENCER_ID/ ||
256 $0 ~ /SEQUENCER_CONTROL/ ||
257 $0 ~ /SEQUENCER_REMOVESAMPLE/ ||
258 $0 ~ /EVTCHN_RESET/ ||
259 $0 ~ /EVTCHN_BIND/ ||
260 $0 ~ /EVTCHN_UNBIND/) {
261 # broken entry, incomplete definition of the 3rd parameterm etc
262 next
263 }
264
265 if ($0 ~ /APM_IOC_STANDBY/ ||
266 $0 ~ /APM_IOC_SUSPEND/ ||
267 $0 ~ /SCIOC_USE_ADF/ ||
268 $0 ~ /SCBUSIOLLSCAN/ ||
269 $0 ~ /UTOPPYIOCANCEL/ ||
270 $0 ~ /JOY_GET_X_OFFSET/ ||
271 $0 ~ /CHIOGPICKER/ ||
272 $0 ~ /SLIOCGUNIT/ ||
273 $0 ~ /SATIOSBUFSIZE/ ||
274 $0 ~ /TUNSLMODE/ ||
275 $0 ~ /CBQ_IF_ATTACH/ ||
276 $0 ~ /CDNR_IF_ATTACH/ ||
277 $0 ~ /RIO_IF_ATTACH/ ||
278 $0 ~ /CBQ_IF_DETACH/ ||
279 $0 ~ /HFSC_IF_DETACH/ ||
280 $0 ~ /WFQ_IF_DETACH/ ||
281 $0 ~ /RIO_IF_DETACH/ ||
282 $0 ~ /FIFOQ_IF_DETACH/ ||
283 $0 ~ /RED_IF_DETACH/ ||
284 $0 ~ /CDNR_ENABLE/ ||
285 $0 ~ /HFSC_ENABLE/ ||
286 $0 ~ /WFQ_ENABLE/ ||
287 $0 ~ /RIO_ENABLE/ ||
288 $0 ~ /FIFOQ_ENABLE/ ||
289 $0 ~ /RED_ENABLE/ ||
290 $0 ~ /BLUE_ENABLE/ ||
291 $0 ~ /CDNR_DISABLE/ ||
292 $0 ~ /HFSC_DISABLE/ ||
293 $0 ~ /WFQ_DISABLE/ ||
294 $0 ~ /RIO_DISABLE/ ||
295 $0 ~ /FIFOQ_DISABLE/ ||
296 $0 ~ /PRIQ_DISABLE/ ||
297 $0 ~ /CDNR_DEL_FILTER/ ||
298 $0 ~ /JOBS_DEL_CLASS/ ||
299 $0 ~ /JOBS_DEL_FILTER/ ||
300 $0 ~ /JOBS_GETSTATS/ ||
301 $0 ~ /WFQ_GET_STATS/ ||
302 $0 ~ /CBQ_ADD_FILTER/ ||
303 $0 ~ /HFSC_ADD_FILTER/ ||
304 $0 ~ /JOBS_ADD_FILTER/ ||
305 $0 ~ /RED_IF_ATTACH/ ||
306 $0 ~ /FIFOQ_IF_ATTACH/ ||
307 $0 ~ /BLUE_IF_DETACH/ ||
308 $0 ~ /CBQ_DISABLE/ ||
309 $0 ~ /RED_DISABLE/ ||
310 $0 ~ /CBQ_CLEAR_HIERARCHY/ ||
311 $0 ~ /HFSC_DEL_CLASS/ ||
312 $0 ~ /PRIQ_IF_DETACH/ ||
313 $0 ~ /PRIQ_ENABLE/ ||
314 $0 ~ /WFQ_IF_ATTACH/ ||
315 $0 ~ /HFSC_DEL_FILTER/) {
316 # There are entries with duplicate codes.. disable the less used ones
317 next
318 }
319
320 if ($2 in known) {
321 # Avoid duplicates
322 # There are entries compatible with K&R and ANSI preprocessor
323 next
324 }
325
326 known[$2] = 1
327
328 ioctl_name[ioctl_table_max] = $2
329
330 split($3, a, "(")
331 a3 = a[1]
332 if (a3 ~ /_IO[ ]*$/) {
333 ioctl_mode[ioctl_table_max] = "NONE"
334 } else if (a3 ~ /_IOR[ ]*$/) {
335 ioctl_mode[ioctl_table_max] = "WRITE"
336 } else if (a3 ~ /_IOW[ ]*$/) {
337 ioctl_mode[ioctl_table_max] = "READ"
338 } else if (a3 ~ /_IOWR[ ]*$/) {
339 ioctl_mode[ioctl_table_max] = "READWRITE"
340 } else {
341 print "Unknown mode, cannot parse: '" $3 "'"
342 }
343
344 # This !NONE check allows to skip some unparsable entries
345 if (ioctl_mode[ioctl_table_max] != "NONE") {
346 # special cases first
347 if ($0 ~ /POWER_IOC_GET_TYPE_WITH_LOSSAGE/) {
348 ioctl_type[ioctl_table_max] = "sizeof(uptr)"
349 } else {
350 n = split($0, a, ",")
351 if (n == 3) {
352 gsub(/^[ ]+/, "", a[3])
353 match(a[3], /[a-zA-Z0-9_* ]+/)
354 type = get_type(substr(a[3], 0, RLENGTH))
355 ioctl_type[ioctl_table_max] = type
356 }
357 }
358 }
359
360 ioctl_table_max++
361}
362
363END {
364 # empty files?
365 if (NR < 1 && !abnormal_exit) {
366 usage()
367 }
368
369 # Handle abnormal exit
370 if (abnormal_exit) {
371 exit(abnormal_exit)
372 }
373
374 # Generate sanitizer_interceptors_ioctl_netbsd.inc
375
376 # open pipe
377 cmd = clangformat " > " outputinc
378
379 pcmd("//===-- sanitizer_interceptors_ioctl_netbsd.inc -----------------*- C++ -*-===//")
380 pcmd("//")
381 pcmd("// The LLVM Compiler Infrastructure")
382 pcmd("//")
383 pcmd("// This file is distributed under the University of Illinois Open Source")
384 pcmd("// License. See LICENSE.TXT for details.")
385 pcmd("//")
386 pcmd("//===----------------------------------------------------------------------===//")
387 pcmd("//")
388 pcmd("// Ioctl handling in common sanitizer interceptors.")
389 pcmd("//===----------------------------------------------------------------------===//")
390 pcmd("")
391 pcmd("#if SANITIZER_NETBSD")
392 pcmd("")
393 pcmd("#include \"sanitizer_flags.h\"")
394 pcmd("")
395 pcmd("struct ioctl_desc {")
396 pcmd(" unsigned req;")
397 pcmd(" // FIXME: support read+write arguments. Currently READWRITE and WRITE do the")
398 pcmd(" // same thing.")
399 pcmd(" // XXX: The declarations below may use WRITE instead of READWRITE, unless")
400 pcmd(" // explicitly noted.")
401 pcmd(" enum {")
402 pcmd(" NONE,")
403 pcmd(" READ,")
404 pcmd(" WRITE,")
405 pcmd(" READWRITE,")
406 pcmd(" CUSTOM")
407 pcmd(" } type : 3;")
408 pcmd(" unsigned size : 29;")
409 pcmd(" const char* name;")
410 pcmd("};")
411 pcmd("")
412 pcmd("const unsigned ioctl_table_max = " ioctl_table_max ";")
413 pcmd("static ioctl_desc ioctl_table[ioctl_table_max];")
414 pcmd("static unsigned ioctl_table_size = 0;")
415 pcmd("")
416 pcmd("// This can not be declared as a global, because references to struct_*_sz")
417 pcmd("// require a global initializer. And this table must be available before global")
418 pcmd("// initializers are run.")
419 pcmd("static void ioctl_table_fill() {")
420 pcmd("#define _(rq, tp, sz) \\")
421 pcmd(" if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \\")
422 pcmd(" CHECK(ioctl_table_size < ioctl_table_max); \\")
423 pcmd(" ioctl_table[ioctl_table_size].req = IOCTL_##rq; \\")
424 pcmd(" ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \\")
425 pcmd(" ioctl_table[ioctl_table_size].size = sz; \\")
426 pcmd(" ioctl_table[ioctl_table_size].name = #rq; \\")
427 pcmd(" ++ioctl_table_size; \\")
428 pcmd(" }")
429 pcmd("")
430
431 for (i = 0; i < ioctl_table_max; i++) {
432 if (i in fname) {
433 pcmd(" /* Entries from file: " fname[i] " */")
434 }
435
436 if (i in ioctl_type) {
437 type = ioctl_type[i]
438 } else {
439 type = "0"
440 }
441
442 pcmd(" _(" ioctl_name[i] ", " ioctl_mode[i] "," type ");")
443 }
444
445 pcmd("#undef _")
446 pcmd("}")
447 pcmd("")
448 pcmd("static bool ioctl_initialized = false;")
449 pcmd("")
450 pcmd("struct ioctl_desc_compare {")
451 pcmd(" bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {")
452 pcmd(" return left.req < right.req;")
453 pcmd(" }")
454 pcmd("};")
455 pcmd("")
456 pcmd("static void ioctl_init() {")
457 pcmd(" ioctl_table_fill();")
458 pcmd(" InternalSort(&ioctl_table, ioctl_table_size, ioctl_desc_compare());")
459 pcmd("")
460 pcmd(" bool bad = false;")
461 pcmd(" for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {")
462 pcmd(" if (ioctl_table[i].req >= ioctl_table[i + 1].req) {")
463 pcmd(" Printf(\"Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\\n\",")
464 pcmd(" ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,")
465 pcmd(" ioctl_table[i + 1].name);")
466 pcmd(" bad = true;")
467 pcmd(" }")
468 pcmd(" }")
469 pcmd("")
470 pcmd(" if (bad) Die();")
471 pcmd("")
472 pcmd(" ioctl_initialized = true;")
473 pcmd("}")
474 pcmd("")
475 pcmd("static const ioctl_desc *ioctl_table_lookup(unsigned req) {")
476 pcmd(" int left = 0;")
477 pcmd(" int right = ioctl_table_size;")
478 pcmd(" while (left < right) {")
479 pcmd(" int mid = (left + right) / 2;")
480 pcmd(" if (ioctl_table[mid].req < req)")
481 pcmd(" left = mid + 1;")
482 pcmd(" else")
483 pcmd(" right = mid;")
484 pcmd(" }")
485 pcmd(" if (left == right && ioctl_table[left].req == req)")
486 pcmd(" return ioctl_table + left;")
487 pcmd(" else")
488 pcmd(" return nullptr;")
489 pcmd("}")
490 pcmd("")
491 pcmd("static bool ioctl_decode(unsigned req, ioctl_desc *desc) {")
492 pcmd(" CHECK(desc);")
493 pcmd(" desc->req = req;")
494 pcmd(" desc->name = \"<DECODED_IOCTL>\";")
495 pcmd(" desc->size = IOC_SIZE(req);")
496 pcmd(" // Sanity check.")
497 pcmd(" if (desc->size > 0xFFFF) return false;")
498 pcmd(" unsigned dir = IOC_DIR(req);")
499 pcmd(" switch (dir) {")
500 pcmd(" case IOC_NONE:")
501 pcmd(" desc->type = ioctl_desc::NONE;")
502 pcmd(" break;")
503 pcmd(" case IOC_READ | IOC_WRITE:")
504 pcmd(" desc->type = ioctl_desc::READWRITE;")
505 pcmd(" break;")
506 pcmd(" case IOC_READ:")
507 pcmd(" desc->type = ioctl_desc::WRITE;")
508 pcmd(" break;")
509 pcmd(" case IOC_WRITE:")
510 pcmd(" desc->type = ioctl_desc::READ;")
511 pcmd(" break;")
512 pcmd(" default:")
513 pcmd(" return false;")
514 pcmd(" }")
515 pcmd(" // Size can be 0 iff type is NONE.")
516 pcmd(" if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;")
517 pcmd(" // Sanity check.")
518 pcmd(" if (IOC_TYPE(req) == 0) return false;")
519 pcmd(" return true;")
520 pcmd("}")
521 pcmd("")
522 pcmd("static const ioctl_desc *ioctl_lookup(unsigned req) {")
523 pcmd(" const ioctl_desc *desc = ioctl_table_lookup(req);")
524 pcmd(" if (desc) return desc;")
525 pcmd("")
526 pcmd(" // Try stripping access size from the request id.")
527 pcmd(" desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));")
528 pcmd(" // Sanity check: requests that encode access size are either read or write and")
529 pcmd(" // have size of 0 in the table.")
530 pcmd(" if (desc && desc->size == 0 &&")
531 pcmd(" (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||")
532 pcmd(" desc->type == ioctl_desc::READ))")
533 pcmd(" return desc;")
534 pcmd(" return nullptr;")
535 pcmd("}")
536 pcmd("")
537 pcmd("static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,")
538 pcmd(" unsigned request, void *arg) {")
539 pcmd(" if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {")
540 pcmd(" unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
541 pcmd(" COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);")
542 pcmd(" }")
543 pcmd(" if (desc->type != ioctl_desc::CUSTOM)")
544 pcmd(" return;")
545 pcmd(" if (request == IOCTL_SIOCGIFCONF) {")
546 pcmd(" struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
547 pcmd(" COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,")
548 pcmd(" sizeof(ifc->ifc_len));")
549 pcmd(" }")
550 pcmd("}")
551 pcmd("")
552 pcmd("static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,")
553 pcmd(" unsigned request, void *arg) {")
554 pcmd(" if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {")
555 pcmd(" // FIXME: add verbose output")
556 pcmd(" unsigned size = desc->size ? desc->size : IOC_SIZE(request);")
557 pcmd(" COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);")
558 pcmd(" }")
559 pcmd(" if (desc->type != ioctl_desc::CUSTOM)")
560 pcmd(" return;")
561 pcmd(" if (request == IOCTL_SIOCGIFCONF) {")
562 pcmd(" struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;")
563 pcmd(" COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);")
564 pcmd(" }")
565 pcmd("}")
566 pcmd("")
567 pcmd("#endif // SANITIZER_NETBSD")
568
569 close(cmd)
570}
571
572function usage()
573{
574 print "Usage: " script_name
575 abnormal_exit = 1
576 exit 1
577}
578
579function pcmd(string)
580{
581 print string | cmd
582}
583
584function get_type(string)
585{
586 if (string == "int") {
587 return "sizeof(int)"
588 } else if (string == "unsigned int" || string == "u_int" || string == "uint") {
589 return "sizeof(unsigned int)"
590 } else if (string == "long") {
591 return "sizeof(long)"
592 } else if (string == "unsigned long" || string == "u_long") {
593 return "sizeof(unsigned long)"
594 } else if (string == "short") {
595 return "sizeof(short)"
596 } else if (string == "unsigned short") {
597 return "sizeof(unsigned short)"
598 } else if (string == "char") {
599 return "sizeof(char)"
600 } else if (string == "signed char") {
601 return "sizeof(signed char)"
602 } else if (string == "unsigned char") {
603 return "sizeof(unsigned char)"
604 } else if (string == "uint8_t") {
605 return "sizeof(u8)"
606 } else if (string == "uint16_t") {
607 return "sizeof(u16)"
608 } else if (string == "u_int32_t" || string == "uint32_t") {
609 return "sizeof(u32)"
610 } else if (string ~ /\*$/) {
611 return "sizeof(uptr)"
612 } else if (string == "off_t") {
613 return "sizeof(uptr)"
614 } else if (string == "pid_t" || string == "kbd_t") {
615 return "sizeof(int)"
616 } else if (string == "daddr_t" || string == "dev_t") {
617 return "sizeof(u64)"
618 } else if (substr(string, 0, 7) == "struct " ) {
619 gsub(/ /, "", string)
620 return "struct_" substr(string, 7) "_sz"
621 } else if (string == "scsireq_t") {
622 return "struct_scsireq_sz"
623 } else if (string == "tone_t") {
624 return "struct_tone_sz"
625 } else if (string == "union twe_statrequest") {
626 return "union_twe_statrequest_sz"
627 } else if (string == "usb_device_descriptor_t") {
628 return "struct_usb_device_descriptor_sz"
629 } else if (string == "v4l2_std_id") {
630 return "sizeof(u64)"
631 } else if (string == "vtmode_t") {
632 return "struct_vt_mode_sz"
633 } else if (string == "_old_mixer_info") {
634 return "struct__old_mixer_info_sz"
635 } else if (string == "agp_allocate") {
636 return "struct__agp_allocate_sz"
637 } else if (string == "agp_bind") {
638 return "struct__agp_bind_sz"
639 } else if (string == "agp_info") {
640 return "struct__agp_info_sz"
641 } else if (string == "agp_region") {
642 return "struct__agp_region_sz"
643 } else if (string == "agp_setup") {
644 return "struct__agp_setup_sz"
645 } else if (string == "agp_unbind") {
646 return "struct__agp_unbind_sz"
647 } else if (string == "atareq_t") {
648 return "struct_atareq_sz"
649 } else if (string == "cpustate_t") {
650 return "struct_cpustate_sz"
651 } else if (string == "dmx_caps_t") {
652 return "struct_dmx_caps_sz"
653 } else if (string == "dmx_source_t") {
654 return "enum_dmx_source_sz"
655 } else if (string == "dvd_authinfo") {
656 return "union_dvd_authinfo_sz"
657 } else if (string == "dvd_struct") {
658 return "union_dvd_struct_sz"
659 } else if (string == "enum v4l2_priority") {
660 return "enum_v4l2_priority_sz"
661 } else if (string == "envsys_basic_info_t") {
662 return "struct_envsys_basic_info_sz"
663 } else if (string == "envsys_tre_data_t") {
664 return "struct_envsys_tre_data_sz"
665 } else if (string == "ext_accm") {
666 return "(8 * sizeof(u32))"
667 } else if (string == "fe_sec_mini_cmd_t") {
668 return "enum_fe_sec_mini_cmd_sz"
669 } else if (string == "fe_sec_tone_mode_t") {
670 return "enum_fe_sec_tone_mode_sz"
671 } else if (string == "fe_sec_voltage_t") {
672 return "enum_fe_sec_voltage_sz"
673 } else if (string == "fe_status_t") {
674 return "enum_fe_status_sz"
675 } else if (string == "gdt_ctrt_t") {
676 return "struct_gdt_ctrt_sz"
677 } else if (string == "gdt_event_t") {
678 return "struct_gdt_event_sz"
679 } else if (string == "gdt_osv_t") {
680 return "struct_gdt_osv_sz"
681 } else if (string == "gdt_rescan_t") {
682 return "struct_gdt_rescan_sz"
683 } else if (string == "gdt_statist_t") {
684 return "struct_gdt_statist_sz"
685 } else if (string == "gdt_ucmd_t") {
686 return "struct_gdt_ucmd_sz"
687 } else if (string == "iscsi_conn_status_parameters_t") {
688 return "struct_iscsi_conn_status_parameters_sz"
689 } else if (string == "iscsi_get_version_parameters_t") {
690 return "struct_iscsi_get_version_parameters_sz"
691 } else if (string == "iscsi_iocommand_parameters_t") {
692 return "struct_iscsi_iocommand_parameters_sz"
693 } else if (string == "iscsi_login_parameters_t") {
694 return "struct_iscsi_login_parameters_sz"
695 } else if (string == "iscsi_logout_parameters_t") {
696 return "struct_iscsi_logout_parameters_sz"
697 } else if (string == "iscsi_register_event_parameters_t") {
698 return "struct_iscsi_register_event_parameters_sz"
699 } else if (string == "iscsi_remove_parameters_t") {
700 return "struct_iscsi_remove_parameters_sz"
701 } else if (string == "iscsi_send_targets_parameters_t") {
702 return "struct_iscsi_send_targets_parameters_sz"
703 } else if (string == "iscsi_set_node_name_parameters_t") {
704 return "struct_iscsi_set_node_name_parameters_sz"
705 } else if (string == "iscsi_wait_event_parameters_t") {
706 return "struct_iscsi_wait_event_parameters_sz"
707 } else if (string == "isp_stats_t") {
708 return "struct_isp_stats_sz"
709 } else if (string == "lsenable_t") {
710 return "struct_lsenable_sz"
711 } else if (string == "lsdisable_t") {
712 return "struct_lsdisable_sz"
713 } else if (string == "mixer_ctrl_t") {
714 return "struct_mixer_ctrl_sz"
715 } else if (string == "mixer_devinfo_t") {
716 return "struct_mixer_devinfo_sz"
717 } else if (string == "mpu_command_rec") {
718 return "struct_mpu_command_rec_sz"
719 } else if (string == "rndstat_t") {
720 return "struct_rndstat_sz"
721 } else if (string == "rndstat_name_t") {
722 return "struct_rndstat_name_sz"
723 } else if (string == "rndctl_t") {
724 return "struct_rndctl_sz"
725 } else if (string == "rnddata_t") {
726 return "struct_rnddata_sz"
727 } else if (string == "rndpoolstat_t") {
728 return "struct_rndpoolstat_sz"
729 } else if (string == "rndstat_est_t") {
730 return "struct_rndstat_est_sz"
731 } else if (string == "rndstat_est_name_t") {
732 return "struct_rndstat_est_name_sz"
733 } else if (string == "pps_params_t") {
734 return "struct_pps_params_sz"
735 } else if (string == "pps_info_t") {
736 return "struct_pps_info_sz"
737 } else if (string == "linedn_t") {
738 return "(32 * sizeof(char))"
739 } else if (string == "mixer_info") {
740 return "struct_mixer_info_sz"
741 } else if (string == "RF_SparetWait_t") {
742 return "struct_RF_SparetWait_sz"
743 } else if (string == "RF_ComponentLabel_t") {
744 return "struct_RF_ComponentLabel_sz"
745 } else if (string == "RF_SingleComponent_t") {
746 return "struct_RF_SingleComponent_sz"
747 } else if (string == "RF_ProgressInfo_t") {
748 return "struct_RF_ProgressInfo_sz"
749 } else {
750 print "Unrecognized entry: " string
751 print "Aborting"
752 abnormal_exit = 1
753 exit 1
754 }
755
756 return string
757}