13cab2bb3Spatrick#!/usr/bin/awk -f 23cab2bb3Spatrick 33cab2bb3Spatrick#===-- generate_netbsd_ioctls.awk ------------------------------------------===# 43cab2bb3Spatrick# 53cab2bb3Spatrick# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 63cab2bb3Spatrick# See https://llvm.org/LICENSE.txt for license information. 73cab2bb3Spatrick# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 83cab2bb3Spatrick# 93cab2bb3Spatrick#===------------------------------------------------------------------------===# 103cab2bb3Spatrick# 113cab2bb3Spatrick# This file is a generator of: 123cab2bb3Spatrick# - include/sanitizer/sanitizer_interceptors_ioctl_netbsd.inc 133cab2bb3Spatrick# 143cab2bb3Spatrick# This script reads public headers from a NetBSD host. 153cab2bb3Spatrick# 163cab2bb3Spatrick# This script shall be executed only on the newest NetBSD version. 173cab2bb3Spatrick# This script will emit compat code for the older releases. 183cab2bb3Spatrick# 193cab2bb3Spatrick# NetBSD minimal version supported 9.0. 203cab2bb3Spatrick# NetBSD current version supported 9.99.26. 213cab2bb3Spatrick# 223cab2bb3Spatrick#===------------------------------------------------------------------------===# 233cab2bb3Spatrick 243cab2bb3SpatrickBEGIN { 25*810390e3Srobert # hardcode the script name 263cab2bb3Spatrick script_name = "generate_netbsd_ioctls.awk" 273cab2bb3Spatrick outputinc = "../lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc" 283cab2bb3Spatrick 293cab2bb3Spatrick # assert that we are in the directory with scripts 303cab2bb3Spatrick in_utils = system("test -f " script_name " && exit 1 || exit 0") 313cab2bb3Spatrick if (in_utils == 0) { 323cab2bb3Spatrick usage() 333cab2bb3Spatrick } 343cab2bb3Spatrick 353cab2bb3Spatrick # assert 0 argument passed 363cab2bb3Spatrick if (ARGC != 1) { 373cab2bb3Spatrick usage() 383cab2bb3Spatrick } 393cab2bb3Spatrick 403cab2bb3Spatrick # accept overloading CLANGFORMAT from environment 413cab2bb3Spatrick clangformat = "clang-format" 423cab2bb3Spatrick if ("CLANGFORMAT" in ENVIRON) { 433cab2bb3Spatrick clangformat = ENVIRON["CLANGFORMAT"] 443cab2bb3Spatrick } 453cab2bb3Spatrick 463cab2bb3Spatrick # accept overloading ROOTDIR from environment 473cab2bb3Spatrick rootdir = "/usr/include/" 483cab2bb3Spatrick if ("ROOTDIR" in ENVIRON) { 493cab2bb3Spatrick rootdir = ENVIRON["ROOTDIR"] 503cab2bb3Spatrick } 513cab2bb3Spatrick 523cab2bb3Spatrick # detect and register files to detect ioctl() definitions 533cab2bb3Spatrick ARGC = 1 543cab2bb3Spatrick cmd = "find " rootdir " -type f -name '*.h'" 553cab2bb3Spatrick while (cmd | getline) { 563cab2bb3Spatrick ARGV[ARGC++] = $0 573cab2bb3Spatrick } 583cab2bb3Spatrick close(cmd) 593cab2bb3Spatrick 603cab2bb3Spatrick ioctl_table_max = 0 613cab2bb3Spatrick} 623cab2bb3Spatrick 633cab2bb3Spatrick# Scan RCS ID 643cab2bb3SpatrickFNR == 1 { 653cab2bb3Spatrick fname[ioctl_table_max] = substr(FILENAME, length(rootdir) + 1) 663cab2bb3Spatrick} 673cab2bb3Spatrick 683cab2bb3Spatrick# _IO 693cab2bb3Spatrick/[^a-zA-Z0-9_]_IO[W]*[R]*[ ]*\(/ && $2 ~ /^[A-Z_]+$/ { 703cab2bb3Spatrick if ($0 ~ /RAIDFRAME_GET_ACCTOTALS/ || 713cab2bb3Spatrick $0 ~ /ALTQATTACH/ || 723cab2bb3Spatrick $0 ~ /ALTQDETACH/ || 733cab2bb3Spatrick $0 ~ /ALTQENABLE/ || 743cab2bb3Spatrick $0 ~ /ALTQDISABLE/ || 753cab2bb3Spatrick $0 ~ /ALTQCLEAR/ || 763cab2bb3Spatrick $0 ~ /ALTQCONFIG/ || 773cab2bb3Spatrick $0 ~ /ALTQADDCLASS/ || 783cab2bb3Spatrick $0 ~ /ALTQMODCLASS/ || 793cab2bb3Spatrick $0 ~ /ALTQDELCLASS/ || 803cab2bb3Spatrick $0 ~ /ALTQADDFILTER/ || 813cab2bb3Spatrick $0 ~ /ALTQDELFILTER/ || 823cab2bb3Spatrick $0 ~ /ALTQGETSTATS/ || 833cab2bb3Spatrick $0 ~ /ALTQGETCNTR/ || 843cab2bb3Spatrick $0 ~ /HFSC_IF_ATTACH/ || 853cab2bb3Spatrick $0 ~ /HFSC_MOD_CLASS/ || 863cab2bb3Spatrick $0 ~ /HLCD_DISPCTL/ || 873cab2bb3Spatrick $0 ~ /HLCD_RESET/ || 883cab2bb3Spatrick $0 ~ /HLCD_CLEAR/ || 893cab2bb3Spatrick $0 ~ /HLCD_CURSOR_LEFT/ || 903cab2bb3Spatrick $0 ~ /HLCD_CURSOR_RIGHT/ || 913cab2bb3Spatrick $0 ~ /HLCD_GET_CURSOR_POS/ || 923cab2bb3Spatrick $0 ~ /HLCD_SET_CURSOR_POS/ || 933cab2bb3Spatrick $0 ~ /HLCD_GETC/ || 943cab2bb3Spatrick $0 ~ /HLCD_PUTC/ || 953cab2bb3Spatrick $0 ~ /HLCD_SHIFT_LEFT/ || 963cab2bb3Spatrick $0 ~ /HLCD_SHIFT_RIGHT/ || 973cab2bb3Spatrick $0 ~ /HLCD_HOME/ || 983cab2bb3Spatrick $0 ~ /HLCD_WRITE/ || 993cab2bb3Spatrick $0 ~ /HLCD_READ/ || 1003cab2bb3Spatrick $0 ~ /HLCD_REDRAW/ || 1013cab2bb3Spatrick $0 ~ /HLCD_WRITE_INST/ || 1023cab2bb3Spatrick $0 ~ /HLCD_WRITE_DATA/ || 1033cab2bb3Spatrick $0 ~ /HLCD_GET_INFO/ || 1043cab2bb3Spatrick $0 ~ /HLCD_GET_CHIPNO/ || 1053cab2bb3Spatrick $0 ~ /HLCD_SET_CHIPNO/ || 1063cab2bb3Spatrick $0 ~ /RAIDFRAME_TEST_ACC/ || 1073cab2bb3Spatrick $0 ~ /FBIOGINFO/ || 1083cab2bb3Spatrick $0 ~ /FBIOSATTR/ || 1093cab2bb3Spatrick $0 ~ /OBIOCDISK/ || 1103cab2bb3Spatrick $0 ~ /OBIOCVOL/ || 1113cab2bb3Spatrick $0 ~ /BIOCSORTIMEOUT/ || 1123cab2bb3Spatrick $0 ~ /BIOCGORTIMEOUT/ || 1133cab2bb3Spatrick $0 ~ /PPPIOCSPASS/ || 1143cab2bb3Spatrick $0 ~ /PPPIOCSACTIVE/ || 1153cab2bb3Spatrick $0 ~ /PPPIOCSIPASS/ || 1163cab2bb3Spatrick $0 ~ /PPPIOCSOPASS/ || 1173cab2bb3Spatrick $0 ~ /PPPIOCSIACTIVE/ || 1183cab2bb3Spatrick $0 ~ /PPPIOCSOACTIVE/ || 1193cab2bb3Spatrick $0 ~ /SIOCPROXY/ || 1203cab2bb3Spatrick $0 ~ /SIOCXRAWATM/ || 1213cab2bb3Spatrick $0 ~ /AGPIOC_RESERVE/ || 1223cab2bb3Spatrick $0 ~ /AGPIOC_PROTECT/ || 1233cab2bb3Spatrick $0 ~ /CDIOCREADSUBCHANNEL_BUF/ || 1243cab2bb3Spatrick $0 ~ /CDIOREADTOCENTRIES_BUF/ || 1253cab2bb3Spatrick $0 ~ /MMCGETDISCINFO/ || 1263cab2bb3Spatrick $0 ~ /MMCGETTRACKINFO/ || 1273cab2bb3Spatrick $0 ~ /MMCOP/ || 1283cab2bb3Spatrick $0 ~ /MMCSETUPWRITEPARAMS/ || 1293cab2bb3Spatrick $0 ~ /DIOCGPARTINFO/ || 1303cab2bb3Spatrick $0 ~ /ODIOCGDINFO/ || 1313cab2bb3Spatrick $0 ~ /ODIOCSDINFO/ || 1323cab2bb3Spatrick $0 ~ /ODIOCWDINFO/ || 1333cab2bb3Spatrick $0 ~ /ODIOCGDEFLABEL/ || 1343cab2bb3Spatrick $0 ~ /GPIOPINREAD/ || 1353cab2bb3Spatrick $0 ~ /GPIOPINWRITE/ || 1363cab2bb3Spatrick $0 ~ /GPIOPINTOGGLE/ || 1373cab2bb3Spatrick $0 ~ /GPIOPINCTL/ || 1383cab2bb3Spatrick $0 ~ /GPIODETACH/ || 1393cab2bb3Spatrick $0 ~ /SEQUENCER_PERCMODE/ || 1403cab2bb3Spatrick $0 ~ /SEQUENCER_TESTMIDI/ || 1413cab2bb3Spatrick $0 ~ /SEQUENCER_MIDI_INFO/ || 1423cab2bb3Spatrick $0 ~ /SEQUENCER_ID/ || 1433cab2bb3Spatrick $0 ~ /SEQUENCER_CONTROL/ || 1443cab2bb3Spatrick $0 ~ /SEQUENCER_REMOVESAMPLE/ || 1453cab2bb3Spatrick $0 ~ /EVTCHN_RESET/ || 1463cab2bb3Spatrick $0 ~ /EVTCHN_BIND/ || 1473cab2bb3Spatrick $0 ~ /EVTCHN_UNBIND/) { 1483cab2bb3Spatrick # broken entry, incomplete definition of the 3rd parameterm etc 1493cab2bb3Spatrick next 1503cab2bb3Spatrick } 1513cab2bb3Spatrick 1523cab2bb3Spatrick if ($0 ~ /APM_IOC_STANDBY/ || 1533cab2bb3Spatrick $0 ~ /APM_IOC_SUSPEND/ || 1543cab2bb3Spatrick $0 ~ /SCIOC_USE_ADF/ || 1553cab2bb3Spatrick $0 ~ /SCBUSIOLLSCAN/ || 1563cab2bb3Spatrick $0 ~ /UTOPPYIOCANCEL/ || 1573cab2bb3Spatrick $0 ~ /JOY_GET_X_OFFSET/ || 1583cab2bb3Spatrick $0 ~ /CHIOGPICKER/ || 1593cab2bb3Spatrick $0 ~ /SLIOCGUNIT/ || 1603cab2bb3Spatrick $0 ~ /TUNSLMODE/ || 1613cab2bb3Spatrick $0 ~ /CBQ_IF_ATTACH/ || 1623cab2bb3Spatrick $0 ~ /CDNR_IF_ATTACH/ || 1633cab2bb3Spatrick $0 ~ /RIO_IF_ATTACH/ || 1643cab2bb3Spatrick $0 ~ /CBQ_IF_DETACH/ || 1653cab2bb3Spatrick $0 ~ /HFSC_IF_DETACH/ || 1663cab2bb3Spatrick $0 ~ /WFQ_IF_DETACH/ || 1673cab2bb3Spatrick $0 ~ /RIO_IF_DETACH/ || 1683cab2bb3Spatrick $0 ~ /FIFOQ_IF_DETACH/ || 1693cab2bb3Spatrick $0 ~ /RED_IF_DETACH/ || 1703cab2bb3Spatrick $0 ~ /CDNR_ENABLE/ || 1713cab2bb3Spatrick $0 ~ /HFSC_ENABLE/ || 1723cab2bb3Spatrick $0 ~ /WFQ_ENABLE/ || 1733cab2bb3Spatrick $0 ~ /RIO_ENABLE/ || 1743cab2bb3Spatrick $0 ~ /FIFOQ_ENABLE/ || 1753cab2bb3Spatrick $0 ~ /RED_ENABLE/ || 1763cab2bb3Spatrick $0 ~ /BLUE_ENABLE/ || 1773cab2bb3Spatrick $0 ~ /CDNR_DISABLE/ || 1783cab2bb3Spatrick $0 ~ /HFSC_DISABLE/ || 1793cab2bb3Spatrick $0 ~ /WFQ_DISABLE/ || 1803cab2bb3Spatrick $0 ~ /RIO_DISABLE/ || 1813cab2bb3Spatrick $0 ~ /FIFOQ_DISABLE/ || 1823cab2bb3Spatrick $0 ~ /PRIQ_DISABLE/ || 1833cab2bb3Spatrick $0 ~ /CDNR_DEL_FILTER/ || 1843cab2bb3Spatrick $0 ~ /JOBS_DEL_CLASS/ || 1853cab2bb3Spatrick $0 ~ /JOBS_DEL_FILTER/ || 1863cab2bb3Spatrick $0 ~ /JOBS_GETSTATS/ || 1873cab2bb3Spatrick $0 ~ /WFQ_GET_STATS/ || 1883cab2bb3Spatrick $0 ~ /CBQ_ADD_FILTER/ || 1893cab2bb3Spatrick $0 ~ /HFSC_ADD_FILTER/ || 1903cab2bb3Spatrick $0 ~ /JOBS_ADD_FILTER/ || 1913cab2bb3Spatrick $0 ~ /RED_IF_ATTACH/ || 1923cab2bb3Spatrick $0 ~ /FIFOQ_IF_ATTACH/ || 1933cab2bb3Spatrick $0 ~ /BLUE_IF_DETACH/ || 1943cab2bb3Spatrick $0 ~ /CBQ_DISABLE/ || 1953cab2bb3Spatrick $0 ~ /RED_DISABLE/ || 1963cab2bb3Spatrick $0 ~ /CBQ_CLEAR_HIERARCHY/ || 1973cab2bb3Spatrick $0 ~ /HFSC_DEL_CLASS/ || 1983cab2bb3Spatrick $0 ~ /PRIQ_IF_DETACH/ || 1993cab2bb3Spatrick $0 ~ /PRIQ_ENABLE/ || 2003cab2bb3Spatrick $0 ~ /WFQ_IF_ATTACH/ || 2013cab2bb3Spatrick $0 ~ /POWER_IOC_GET_TYPE_WITH_LOSSAGE/ || 2023cab2bb3Spatrick $0 ~ /HFSC_DEL_FILTER/) { 2033cab2bb3Spatrick # There are entries with duplicate codes.. disable the less used ones 2043cab2bb3Spatrick next 2053cab2bb3Spatrick } 2063cab2bb3Spatrick 2073cab2bb3Spatrick if ($2 in known) { 2083cab2bb3Spatrick # Avoid duplicates 2093cab2bb3Spatrick # There are entries compatible with K&R and ANSI preprocessor 2103cab2bb3Spatrick next 2113cab2bb3Spatrick } 2123cab2bb3Spatrick 2133cab2bb3Spatrick known[$2] = 1 2143cab2bb3Spatrick 2153cab2bb3Spatrick ioctl_name[ioctl_table_max] = $2 2163cab2bb3Spatrick 2173cab2bb3Spatrick split($3, a, "(") 2183cab2bb3Spatrick a3 = a[1] 2193cab2bb3Spatrick if (a3 ~ /_IO[ ]*$/) { 2203cab2bb3Spatrick ioctl_mode[ioctl_table_max] = "NONE" 2213cab2bb3Spatrick } else if (a3 ~ /_IOR[ ]*$/) { 2223cab2bb3Spatrick ioctl_mode[ioctl_table_max] = "WRITE" 2233cab2bb3Spatrick } else if (a3 ~ /_IOW[ ]*$/) { 2243cab2bb3Spatrick ioctl_mode[ioctl_table_max] = "READ" 2253cab2bb3Spatrick } else if (a3 ~ /_IOWR[ ]*$/) { 2263cab2bb3Spatrick ioctl_mode[ioctl_table_max] = "READWRITE" 2273cab2bb3Spatrick } else { 2283cab2bb3Spatrick print "Unknown mode, cannot parse: '" $3 "'" 2293cab2bb3Spatrick } 2303cab2bb3Spatrick 2313cab2bb3Spatrick # This !NONE check allows to skip some unparsable entries 2323cab2bb3Spatrick if (ioctl_mode[ioctl_table_max] != "NONE") { 2333cab2bb3Spatrick n = split($0, a, ",") 2343cab2bb3Spatrick if (n == 3) { 2353cab2bb3Spatrick gsub(/^[ ]+/, "", a[3]) 2363cab2bb3Spatrick match(a[3], /[a-zA-Z0-9_* ]+/) 2373cab2bb3Spatrick type = get_type(substr(a[3], 0, RLENGTH)) 2383cab2bb3Spatrick ioctl_type[ioctl_table_max] = type 2393cab2bb3Spatrick } 2403cab2bb3Spatrick } 2413cab2bb3Spatrick 2423cab2bb3Spatrick ioctl_table_max++ 2433cab2bb3Spatrick} 2443cab2bb3Spatrick 2453cab2bb3SpatrickEND { 2463cab2bb3Spatrick # empty files? 2473cab2bb3Spatrick if (NR < 1 && !abnormal_exit) { 2483cab2bb3Spatrick usage() 2493cab2bb3Spatrick } 2503cab2bb3Spatrick 2513cab2bb3Spatrick # Handle abnormal exit 2523cab2bb3Spatrick if (abnormal_exit) { 2533cab2bb3Spatrick exit(abnormal_exit) 2543cab2bb3Spatrick } 2553cab2bb3Spatrick 2563cab2bb3Spatrick # Add compat entries 2573cab2bb3Spatrick add_compat("dev/filemon/filemon.h (compat <= 9.99.26)", "FILEMON_SET_FD", "READWRITE", "sizeof(int)") 2583cab2bb3Spatrick add_compat("", "FILEMON_SET_PID", "READWRITE", "sizeof(int)") 2591f9cb04fSpatrick add_compat("dev/usb/urio.h (compat <= 9.99.43)", "URIO_SEND_COMMAND", "READWRITE", "struct_urio_command_sz") 2601f9cb04fSpatrick add_compat("", "URIO_RECV_COMMAND", "READWRITE", "struct_urio_command_sz") 2613cab2bb3Spatrick 2623cab2bb3Spatrick # Generate sanitizer_interceptors_ioctl_netbsd.inc 2633cab2bb3Spatrick 2643cab2bb3Spatrick # open pipe 2653cab2bb3Spatrick cmd = clangformat " > " outputinc 2663cab2bb3Spatrick 2673cab2bb3Spatrick pcmd("//===-- sanitizer_interceptors_ioctl_netbsd.inc -----------------*- C++ -*-===//") 2683cab2bb3Spatrick pcmd("//") 2693cab2bb3Spatrick pcmd("// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.") 2703cab2bb3Spatrick pcmd("// See https://llvm.org/LICENSE.txt for license information.") 2713cab2bb3Spatrick pcmd("// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception") 2723cab2bb3Spatrick pcmd("//") 2733cab2bb3Spatrick pcmd("//===----------------------------------------------------------------------===//") 2743cab2bb3Spatrick pcmd("//") 2753cab2bb3Spatrick pcmd("// Ioctl handling in common sanitizer interceptors.") 2763cab2bb3Spatrick pcmd("//===----------------------------------------------------------------------===//") 2773cab2bb3Spatrick pcmd("") 2783cab2bb3Spatrick pcmd("#if SANITIZER_NETBSD") 2793cab2bb3Spatrick pcmd("") 2803cab2bb3Spatrick pcmd("#include \"sanitizer_flags.h\"") 2813cab2bb3Spatrick pcmd("") 2823cab2bb3Spatrick pcmd("struct ioctl_desc {") 2833cab2bb3Spatrick pcmd(" unsigned req;") 2843cab2bb3Spatrick pcmd(" // FIXME: support read+write arguments. Currently READWRITE and WRITE do the") 2853cab2bb3Spatrick pcmd(" // same thing.") 2863cab2bb3Spatrick pcmd(" // XXX: The declarations below may use WRITE instead of READWRITE, unless") 2873cab2bb3Spatrick pcmd(" // explicitly noted.") 2883cab2bb3Spatrick pcmd(" enum {") 2893cab2bb3Spatrick pcmd(" NONE,") 2903cab2bb3Spatrick pcmd(" READ,") 2913cab2bb3Spatrick pcmd(" WRITE,") 2923cab2bb3Spatrick pcmd(" READWRITE,") 2933cab2bb3Spatrick pcmd(" CUSTOM") 2943cab2bb3Spatrick pcmd(" } type : 3;") 2953cab2bb3Spatrick pcmd(" unsigned size : 29;") 2963cab2bb3Spatrick pcmd(" const char* name;") 2973cab2bb3Spatrick pcmd("};") 2983cab2bb3Spatrick pcmd("") 2993cab2bb3Spatrick pcmd("const unsigned ioctl_table_max = " ioctl_table_max ";") 3003cab2bb3Spatrick pcmd("static ioctl_desc ioctl_table[ioctl_table_max];") 3013cab2bb3Spatrick pcmd("static unsigned ioctl_table_size = 0;") 3023cab2bb3Spatrick pcmd("") 3033cab2bb3Spatrick pcmd("// This can not be declared as a global, because references to struct_*_sz") 3043cab2bb3Spatrick pcmd("// require a global initializer. And this table must be available before global") 3053cab2bb3Spatrick pcmd("// initializers are run.") 3063cab2bb3Spatrick pcmd("static void ioctl_table_fill() {") 3073cab2bb3Spatrick pcmd("#define _(rq, tp, sz) \\") 3083cab2bb3Spatrick pcmd(" if (IOCTL_##rq != IOCTL_NOT_PRESENT) { \\") 3093cab2bb3Spatrick pcmd(" CHECK(ioctl_table_size < ioctl_table_max); \\") 3103cab2bb3Spatrick pcmd(" ioctl_table[ioctl_table_size].req = IOCTL_##rq; \\") 3113cab2bb3Spatrick pcmd(" ioctl_table[ioctl_table_size].type = ioctl_desc::tp; \\") 3123cab2bb3Spatrick pcmd(" ioctl_table[ioctl_table_size].size = sz; \\") 3133cab2bb3Spatrick pcmd(" ioctl_table[ioctl_table_size].name = #rq; \\") 3143cab2bb3Spatrick pcmd(" ++ioctl_table_size; \\") 3153cab2bb3Spatrick pcmd(" }") 3163cab2bb3Spatrick pcmd("") 3173cab2bb3Spatrick 3183cab2bb3Spatrick for (i = 0; i < ioctl_table_max; i++) { 3193cab2bb3Spatrick if (i in fname && fname[i] == "dev/nvmm/nvmm_ioctl.h") { 3203cab2bb3Spatrick pcmd("#if defined(__x86_64__)") 3213cab2bb3Spatrick } 3223cab2bb3Spatrick if (i in fname) { 3233cab2bb3Spatrick pcmd(" /* Entries from file: " fname[i] " */") 3243cab2bb3Spatrick } 3253cab2bb3Spatrick 3263cab2bb3Spatrick if (i in ioctl_type) { 3273cab2bb3Spatrick type = ioctl_type[i] 3283cab2bb3Spatrick } else { 3293cab2bb3Spatrick type = "0" 3303cab2bb3Spatrick } 3313cab2bb3Spatrick 3323cab2bb3Spatrick pcmd(" _(" ioctl_name[i] ", " ioctl_mode[i] "," type ");") 3333cab2bb3Spatrick 3343cab2bb3Spatrick if (ioctl_name[i] == "NVMM_IOC_CTL") { 3353cab2bb3Spatrick pcmd("#endif") 3363cab2bb3Spatrick } 3373cab2bb3Spatrick } 3383cab2bb3Spatrick 3393cab2bb3Spatrick pcmd("#undef _") 340*810390e3Srobert pcmd("}") 3413cab2bb3Spatrick pcmd("") 3423cab2bb3Spatrick pcmd("static bool ioctl_initialized = false;") 3433cab2bb3Spatrick pcmd("") 3443cab2bb3Spatrick pcmd("struct ioctl_desc_compare {") 3453cab2bb3Spatrick pcmd(" bool operator()(const ioctl_desc& left, const ioctl_desc& right) const {") 3463cab2bb3Spatrick pcmd(" return left.req < right.req;") 3473cab2bb3Spatrick pcmd(" }") 3483cab2bb3Spatrick pcmd("};") 3493cab2bb3Spatrick pcmd("") 3503cab2bb3Spatrick pcmd("static void ioctl_init() {") 3513cab2bb3Spatrick pcmd(" ioctl_table_fill();") 3523cab2bb3Spatrick pcmd(" Sort(ioctl_table, ioctl_table_size, ioctl_desc_compare());") 3533cab2bb3Spatrick pcmd("") 3543cab2bb3Spatrick pcmd(" bool bad = false;") 3553cab2bb3Spatrick pcmd(" for (unsigned i = 0; i < ioctl_table_size - 1; ++i) {") 3563cab2bb3Spatrick pcmd(" if (ioctl_table[i].req >= ioctl_table[i + 1].req) {") 3573cab2bb3Spatrick pcmd(" Printf(\"Duplicate or unsorted ioctl request id %x >= %x (%s vs %s)\\n\",") 3583cab2bb3Spatrick pcmd(" ioctl_table[i].req, ioctl_table[i + 1].req, ioctl_table[i].name,") 3593cab2bb3Spatrick pcmd(" ioctl_table[i + 1].name);") 3603cab2bb3Spatrick pcmd(" bad = true;") 3613cab2bb3Spatrick pcmd(" }") 3623cab2bb3Spatrick pcmd(" }") 3633cab2bb3Spatrick pcmd("") 3643cab2bb3Spatrick pcmd(" if (bad) Die();") 3653cab2bb3Spatrick pcmd("") 3663cab2bb3Spatrick pcmd(" ioctl_initialized = true;") 3673cab2bb3Spatrick pcmd("}") 3683cab2bb3Spatrick pcmd("") 3693cab2bb3Spatrick pcmd("static const ioctl_desc *ioctl_table_lookup(unsigned req) {") 3703cab2bb3Spatrick pcmd(" int left = 0;") 3713cab2bb3Spatrick pcmd(" int right = ioctl_table_size;") 3723cab2bb3Spatrick pcmd(" while (left < right) {") 3733cab2bb3Spatrick pcmd(" int mid = (left + right) / 2;") 3743cab2bb3Spatrick pcmd(" if (ioctl_table[mid].req < req)") 3753cab2bb3Spatrick pcmd(" left = mid + 1;") 3763cab2bb3Spatrick pcmd(" else") 3773cab2bb3Spatrick pcmd(" right = mid;") 3783cab2bb3Spatrick pcmd(" }") 3793cab2bb3Spatrick pcmd(" if (left == right && ioctl_table[left].req == req)") 3803cab2bb3Spatrick pcmd(" return ioctl_table + left;") 3813cab2bb3Spatrick pcmd(" else") 3823cab2bb3Spatrick pcmd(" return nullptr;") 3833cab2bb3Spatrick pcmd("}") 3843cab2bb3Spatrick pcmd("") 3853cab2bb3Spatrick pcmd("static bool ioctl_decode(unsigned req, ioctl_desc *desc) {") 3863cab2bb3Spatrick pcmd(" CHECK(desc);") 3873cab2bb3Spatrick pcmd(" desc->req = req;") 3883cab2bb3Spatrick pcmd(" desc->name = \"<DECODED_IOCTL>\";") 3893cab2bb3Spatrick pcmd(" desc->size = IOC_SIZE(req);") 3903cab2bb3Spatrick pcmd(" // Sanity check.") 3913cab2bb3Spatrick pcmd(" if (desc->size > 0xFFFF) return false;") 3923cab2bb3Spatrick pcmd(" unsigned dir = IOC_DIR(req);") 3933cab2bb3Spatrick pcmd(" switch (dir) {") 3943cab2bb3Spatrick pcmd(" case IOC_NONE:") 3953cab2bb3Spatrick pcmd(" desc->type = ioctl_desc::NONE;") 3963cab2bb3Spatrick pcmd(" break;") 3973cab2bb3Spatrick pcmd(" case IOC_READ | IOC_WRITE:") 3983cab2bb3Spatrick pcmd(" desc->type = ioctl_desc::READWRITE;") 3993cab2bb3Spatrick pcmd(" break;") 4003cab2bb3Spatrick pcmd(" case IOC_READ:") 4013cab2bb3Spatrick pcmd(" desc->type = ioctl_desc::WRITE;") 4023cab2bb3Spatrick pcmd(" break;") 4033cab2bb3Spatrick pcmd(" case IOC_WRITE:") 4043cab2bb3Spatrick pcmd(" desc->type = ioctl_desc::READ;") 4053cab2bb3Spatrick pcmd(" break;") 4063cab2bb3Spatrick pcmd(" default:") 4073cab2bb3Spatrick pcmd(" return false;") 4083cab2bb3Spatrick pcmd(" }") 4093cab2bb3Spatrick pcmd(" // Size can be 0 iff type is NONE.") 4103cab2bb3Spatrick pcmd(" if ((desc->type == IOC_NONE) != (desc->size == 0)) return false;") 4113cab2bb3Spatrick pcmd(" // Sanity check.") 4123cab2bb3Spatrick pcmd(" if (IOC_TYPE(req) == 0) return false;") 4133cab2bb3Spatrick pcmd(" return true;") 4143cab2bb3Spatrick pcmd("}") 4153cab2bb3Spatrick pcmd("") 4163cab2bb3Spatrick pcmd("static const ioctl_desc *ioctl_lookup(unsigned req) {") 4173cab2bb3Spatrick pcmd(" const ioctl_desc *desc = ioctl_table_lookup(req);") 4183cab2bb3Spatrick pcmd(" if (desc) return desc;") 4193cab2bb3Spatrick pcmd("") 4203cab2bb3Spatrick pcmd(" // Try stripping access size from the request id.") 4213cab2bb3Spatrick pcmd(" desc = ioctl_table_lookup(req & ~(IOC_SIZEMASK << IOC_SIZESHIFT));") 4223cab2bb3Spatrick pcmd(" // Sanity check: requests that encode access size are either read or write and") 4233cab2bb3Spatrick pcmd(" // have size of 0 in the table.") 4243cab2bb3Spatrick pcmd(" if (desc && desc->size == 0 &&") 4253cab2bb3Spatrick pcmd(" (desc->type == ioctl_desc::READWRITE || desc->type == ioctl_desc::WRITE ||") 4263cab2bb3Spatrick pcmd(" desc->type == ioctl_desc::READ))") 4273cab2bb3Spatrick pcmd(" return desc;") 4283cab2bb3Spatrick pcmd(" return nullptr;") 4293cab2bb3Spatrick pcmd("}") 4303cab2bb3Spatrick pcmd("") 4313cab2bb3Spatrick pcmd("static void ioctl_common_pre(void *ctx, const ioctl_desc *desc, int d,") 4323cab2bb3Spatrick pcmd(" unsigned request, void *arg) {") 4333cab2bb3Spatrick pcmd(" if (desc->type == ioctl_desc::READ || desc->type == ioctl_desc::READWRITE) {") 4343cab2bb3Spatrick pcmd(" unsigned size = desc->size ? desc->size : IOC_SIZE(request);") 4353cab2bb3Spatrick pcmd(" COMMON_INTERCEPTOR_READ_RANGE(ctx, arg, size);") 4363cab2bb3Spatrick pcmd(" }") 4373cab2bb3Spatrick pcmd(" if (desc->type != ioctl_desc::CUSTOM)") 4383cab2bb3Spatrick pcmd(" return;") 4393cab2bb3Spatrick pcmd(" if (request == IOCTL_SIOCGIFCONF) {") 4403cab2bb3Spatrick pcmd(" struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;") 4413cab2bb3Spatrick pcmd(" COMMON_INTERCEPTOR_READ_RANGE(ctx, (char*)&ifc->ifc_len,") 4423cab2bb3Spatrick pcmd(" sizeof(ifc->ifc_len));") 4433cab2bb3Spatrick pcmd(" }") 4443cab2bb3Spatrick pcmd("}") 4453cab2bb3Spatrick pcmd("") 4463cab2bb3Spatrick pcmd("static void ioctl_common_post(void *ctx, const ioctl_desc *desc, int res, int d,") 4473cab2bb3Spatrick pcmd(" unsigned request, void *arg) {") 4483cab2bb3Spatrick pcmd(" if (desc->type == ioctl_desc::WRITE || desc->type == ioctl_desc::READWRITE) {") 4493cab2bb3Spatrick pcmd(" // FIXME: add verbose output") 4503cab2bb3Spatrick pcmd(" unsigned size = desc->size ? desc->size : IOC_SIZE(request);") 4513cab2bb3Spatrick pcmd(" COMMON_INTERCEPTOR_WRITE_RANGE(ctx, arg, size);") 4523cab2bb3Spatrick pcmd(" }") 4533cab2bb3Spatrick pcmd(" if (desc->type != ioctl_desc::CUSTOM)") 4543cab2bb3Spatrick pcmd(" return;") 4553cab2bb3Spatrick pcmd(" if (request == IOCTL_SIOCGIFCONF) {") 4563cab2bb3Spatrick pcmd(" struct __sanitizer_ifconf *ifc = (__sanitizer_ifconf *)arg;") 4573cab2bb3Spatrick pcmd(" COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifc->ifc_ifcu.ifcu_req, ifc->ifc_len);") 4583cab2bb3Spatrick pcmd(" }") 4593cab2bb3Spatrick pcmd("}") 4603cab2bb3Spatrick pcmd("") 4613cab2bb3Spatrick pcmd("#endif // SANITIZER_NETBSD") 4623cab2bb3Spatrick 4633cab2bb3Spatrick close(cmd) 4643cab2bb3Spatrick} 4653cab2bb3Spatrick 4663cab2bb3Spatrickfunction usage() 4673cab2bb3Spatrick{ 4683cab2bb3Spatrick print "Usage: " script_name 4693cab2bb3Spatrick abnormal_exit = 1 4703cab2bb3Spatrick exit 1 4713cab2bb3Spatrick} 4723cab2bb3Spatrick 4733cab2bb3Spatrickfunction pcmd(string) 4743cab2bb3Spatrick{ 4753cab2bb3Spatrick print string | cmd 4763cab2bb3Spatrick} 4773cab2bb3Spatrick 4783cab2bb3Spatrickfunction get_type(string) 4793cab2bb3Spatrick{ 4803cab2bb3Spatrick if (string == "int") { 4813cab2bb3Spatrick return "sizeof(int)" 4823cab2bb3Spatrick } else if (string == "unsigned int" || string == "u_int" || string == "uint") { 4833cab2bb3Spatrick return "sizeof(unsigned int)" 4843cab2bb3Spatrick } else if (string == "long") { 4853cab2bb3Spatrick return "sizeof(long)" 4863cab2bb3Spatrick } else if (string == "unsigned long" || string == "u_long") { 4873cab2bb3Spatrick return "sizeof(unsigned long)" 4883cab2bb3Spatrick } else if (string == "short") { 4893cab2bb3Spatrick return "sizeof(short)" 4903cab2bb3Spatrick } else if (string == "unsigned short") { 4913cab2bb3Spatrick return "sizeof(unsigned short)" 4923cab2bb3Spatrick } else if (string == "char") { 4933cab2bb3Spatrick return "sizeof(char)" 4943cab2bb3Spatrick } else if (string == "signed char") { 4953cab2bb3Spatrick return "sizeof(signed char)" 4963cab2bb3Spatrick } else if (string == "unsigned char") { 4973cab2bb3Spatrick return "sizeof(unsigned char)" 4983cab2bb3Spatrick } else if (string == "uint8_t") { 4993cab2bb3Spatrick return "sizeof(u8)" 5003cab2bb3Spatrick } else if (string == "uint16_t") { 5013cab2bb3Spatrick return "sizeof(u16)" 5023cab2bb3Spatrick } else if (string == "u_int32_t" || string == "uint32_t") { 5033cab2bb3Spatrick return "sizeof(u32)" 5043cab2bb3Spatrick } else if (string == "u_int64_t" || string == "uint64_t") { 5053cab2bb3Spatrick return "sizeof(u64)" 5063cab2bb3Spatrick } else if (string ~ /\*$/) { 5073cab2bb3Spatrick return "sizeof(uptr)" 5083cab2bb3Spatrick } else if (string == "off_t") { 5093cab2bb3Spatrick return "sizeof(uptr)" 5103cab2bb3Spatrick } else if (string == "pid_t" || string == "kbd_t") { 5113cab2bb3Spatrick return "sizeof(int)" 5123cab2bb3Spatrick } else if (string == "daddr_t" || string == "dev_t") { 5133cab2bb3Spatrick return "sizeof(u64)" 5143cab2bb3Spatrick } else if (substr(string, 0, 7) == "struct " ) { 5153cab2bb3Spatrick gsub(/ /, "", string) 5163cab2bb3Spatrick return "struct_" substr(string, 7) "_sz" 5173cab2bb3Spatrick } else if (string == "scsireq_t") { 5183cab2bb3Spatrick return "struct_scsireq_sz" 5193cab2bb3Spatrick } else if (string == "tone_t") { 5203cab2bb3Spatrick return "struct_tone_sz" 5213cab2bb3Spatrick } else if (string == "union twe_statrequest") { 5223cab2bb3Spatrick return "union_twe_statrequest_sz" 5233cab2bb3Spatrick } else if (string == "usb_device_descriptor_t") { 5243cab2bb3Spatrick return "struct_usb_device_descriptor_sz" 5253cab2bb3Spatrick } else if (string == "v4l2_std_id") { 5263cab2bb3Spatrick return "sizeof(u64)" 5273cab2bb3Spatrick } else if (string == "vtmode_t") { 5283cab2bb3Spatrick return "struct_vt_mode_sz" 5293cab2bb3Spatrick } else if (string == "_old_mixer_info") { 5303cab2bb3Spatrick return "struct__old_mixer_info_sz" 5313cab2bb3Spatrick } else if (string == "agp_allocate") { 5323cab2bb3Spatrick return "struct__agp_allocate_sz" 5333cab2bb3Spatrick } else if (string == "agp_bind") { 5343cab2bb3Spatrick return "struct__agp_bind_sz" 5353cab2bb3Spatrick } else if (string == "agp_info") { 5363cab2bb3Spatrick return "struct__agp_info_sz" 5373cab2bb3Spatrick } else if (string == "agp_region") { 5383cab2bb3Spatrick return "struct__agp_region_sz" 5393cab2bb3Spatrick } else if (string == "agp_setup") { 5403cab2bb3Spatrick return "struct__agp_setup_sz" 5413cab2bb3Spatrick } else if (string == "agp_unbind") { 5423cab2bb3Spatrick return "struct__agp_unbind_sz" 5433cab2bb3Spatrick } else if (string == "atareq_t") { 5443cab2bb3Spatrick return "struct_atareq_sz" 5453cab2bb3Spatrick } else if (string == "cpustate_t") { 5463cab2bb3Spatrick return "struct_cpustate_sz" 5473cab2bb3Spatrick } else if (string == "dmx_caps_t") { 5483cab2bb3Spatrick return "struct_dmx_caps_sz" 5493cab2bb3Spatrick } else if (string == "dmx_source_t") { 5503cab2bb3Spatrick return "enum_dmx_source_sz" 5513cab2bb3Spatrick } else if (string == "dvd_authinfo") { 5523cab2bb3Spatrick return "union_dvd_authinfo_sz" 5533cab2bb3Spatrick } else if (string == "dvd_struct") { 5543cab2bb3Spatrick return "union_dvd_struct_sz" 5553cab2bb3Spatrick } else if (string == "enum v4l2_priority") { 5563cab2bb3Spatrick return "enum_v4l2_priority_sz" 5573cab2bb3Spatrick } else if (string == "envsys_basic_info_t") { 5583cab2bb3Spatrick return "struct_envsys_basic_info_sz" 5593cab2bb3Spatrick } else if (string == "envsys_tre_data_t") { 5603cab2bb3Spatrick return "struct_envsys_tre_data_sz" 5613cab2bb3Spatrick } else if (string == "ext_accm") { 5623cab2bb3Spatrick return "(8 * sizeof(u32))" 5633cab2bb3Spatrick } else if (string == "fe_sec_mini_cmd_t") { 5643cab2bb3Spatrick return "enum_fe_sec_mini_cmd_sz" 5653cab2bb3Spatrick } else if (string == "fe_sec_tone_mode_t") { 5663cab2bb3Spatrick return "enum_fe_sec_tone_mode_sz" 5673cab2bb3Spatrick } else if (string == "fe_sec_voltage_t") { 5683cab2bb3Spatrick return "enum_fe_sec_voltage_sz" 5693cab2bb3Spatrick } else if (string == "fe_status_t") { 5703cab2bb3Spatrick return "enum_fe_status_sz" 5713cab2bb3Spatrick } else if (string == "gdt_ctrt_t") { 5723cab2bb3Spatrick return "struct_gdt_ctrt_sz" 5733cab2bb3Spatrick } else if (string == "gdt_event_t") { 5743cab2bb3Spatrick return "struct_gdt_event_sz" 5753cab2bb3Spatrick } else if (string == "gdt_osv_t") { 5763cab2bb3Spatrick return "struct_gdt_osv_sz" 5773cab2bb3Spatrick } else if (string == "gdt_rescan_t") { 5783cab2bb3Spatrick return "struct_gdt_rescan_sz" 5793cab2bb3Spatrick } else if (string == "gdt_statist_t") { 5803cab2bb3Spatrick return "struct_gdt_statist_sz" 5813cab2bb3Spatrick } else if (string == "gdt_ucmd_t") { 5823cab2bb3Spatrick return "struct_gdt_ucmd_sz" 5833cab2bb3Spatrick } else if (string == "iscsi_conn_status_parameters_t") { 5843cab2bb3Spatrick return "struct_iscsi_conn_status_parameters_sz" 5853cab2bb3Spatrick } else if (string == "iscsi_get_version_parameters_t") { 5863cab2bb3Spatrick return "struct_iscsi_get_version_parameters_sz" 5873cab2bb3Spatrick } else if (string == "iscsi_iocommand_parameters_t") { 5883cab2bb3Spatrick return "struct_iscsi_iocommand_parameters_sz" 5893cab2bb3Spatrick } else if (string == "iscsi_login_parameters_t") { 5903cab2bb3Spatrick return "struct_iscsi_login_parameters_sz" 5913cab2bb3Spatrick } else if (string == "iscsi_logout_parameters_t") { 5923cab2bb3Spatrick return "struct_iscsi_logout_parameters_sz" 5933cab2bb3Spatrick } else if (string == "iscsi_register_event_parameters_t") { 5943cab2bb3Spatrick return "struct_iscsi_register_event_parameters_sz" 5953cab2bb3Spatrick } else if (string == "iscsi_remove_parameters_t") { 5963cab2bb3Spatrick return "struct_iscsi_remove_parameters_sz" 5973cab2bb3Spatrick } else if (string == "iscsi_send_targets_parameters_t") { 5983cab2bb3Spatrick return "struct_iscsi_send_targets_parameters_sz" 5993cab2bb3Spatrick } else if (string == "iscsi_set_node_name_parameters_t") { 6003cab2bb3Spatrick return "struct_iscsi_set_node_name_parameters_sz" 6013cab2bb3Spatrick } else if (string == "iscsi_wait_event_parameters_t") { 6023cab2bb3Spatrick return "struct_iscsi_wait_event_parameters_sz" 6033cab2bb3Spatrick } else if (string == "isp_stats_t") { 6043cab2bb3Spatrick return "struct_isp_stats_sz" 6053cab2bb3Spatrick } else if (string == "lsenable_t") { 6063cab2bb3Spatrick return "struct_lsenable_sz" 6073cab2bb3Spatrick } else if (string == "lsdisable_t") { 6083cab2bb3Spatrick return "struct_lsdisable_sz" 6093cab2bb3Spatrick } else if (string == "mixer_ctrl_t") { 6103cab2bb3Spatrick return "struct_mixer_ctrl_sz" 6113cab2bb3Spatrick } else if (string == "mixer_devinfo_t") { 6123cab2bb3Spatrick return "struct_mixer_devinfo_sz" 6133cab2bb3Spatrick } else if (string == "mpu_command_rec") { 6143cab2bb3Spatrick return "struct_mpu_command_rec_sz" 6153cab2bb3Spatrick } else if (string == "rndstat_t") { 6163cab2bb3Spatrick return "struct_rndstat_sz" 6173cab2bb3Spatrick } else if (string == "rndstat_name_t") { 6183cab2bb3Spatrick return "struct_rndstat_name_sz" 6193cab2bb3Spatrick } else if (string == "rndctl_t") { 6203cab2bb3Spatrick return "struct_rndctl_sz" 6213cab2bb3Spatrick } else if (string == "rnddata_t") { 6223cab2bb3Spatrick return "struct_rnddata_sz" 6233cab2bb3Spatrick } else if (string == "rndpoolstat_t") { 6243cab2bb3Spatrick return "struct_rndpoolstat_sz" 6253cab2bb3Spatrick } else if (string == "rndstat_est_t") { 6263cab2bb3Spatrick return "struct_rndstat_est_sz" 6273cab2bb3Spatrick } else if (string == "rndstat_est_name_t") { 6283cab2bb3Spatrick return "struct_rndstat_est_name_sz" 6293cab2bb3Spatrick } else if (string == "pps_params_t") { 6303cab2bb3Spatrick return "struct_pps_params_sz" 6313cab2bb3Spatrick } else if (string == "pps_info_t") { 6323cab2bb3Spatrick return "struct_pps_info_sz" 6333cab2bb3Spatrick } else if (string == "linedn_t") { 6343cab2bb3Spatrick return "(32 * sizeof(char))" 6353cab2bb3Spatrick } else if (string == "mixer_info") { 6363cab2bb3Spatrick return "struct_mixer_info_sz" 6373cab2bb3Spatrick } else if (string == "RF_SparetWait_t") { 6383cab2bb3Spatrick return "struct_RF_SparetWait_sz" 6393cab2bb3Spatrick } else if (string == "RF_ComponentLabel_t") { 6403cab2bb3Spatrick return "struct_RF_ComponentLabel_sz" 6413cab2bb3Spatrick } else if (string == "RF_SingleComponent_t") { 6423cab2bb3Spatrick return "struct_RF_SingleComponent_sz" 6433cab2bb3Spatrick } else if (string == "RF_ProgressInfo_t") { 6443cab2bb3Spatrick return "struct_RF_ProgressInfo_sz" 6453cab2bb3Spatrick } else if (string == "nvlist_ref_t") { 6463cab2bb3Spatrick return "struct_nvlist_ref_sz" 6473cab2bb3Spatrick } else if (string == "spi_ioctl_transfer_t") { 6483cab2bb3Spatrick return "struct_spi_ioctl_transfer_sz" 6493cab2bb3Spatrick } else if (string == "spi_ioctl_configure_t") { 6503cab2bb3Spatrick return "struct_spi_ioctl_configure_sz" 6513cab2bb3Spatrick } else { 6523cab2bb3Spatrick print "Unrecognized entry: " string 6533cab2bb3Spatrick print "Aborting" 6543cab2bb3Spatrick abnormal_exit = 1 6553cab2bb3Spatrick exit 1 6563cab2bb3Spatrick } 6573cab2bb3Spatrick 6583cab2bb3Spatrick return string 6593cab2bb3Spatrick} 6603cab2bb3Spatrick 6613cab2bb3Spatrickfunction add_compat(path, name, mode, type) 6623cab2bb3Spatrick{ 6633cab2bb3Spatrick if (path != "") { 6643cab2bb3Spatrick fname[ioctl_table_max] = path 6653cab2bb3Spatrick } 6663cab2bb3Spatrick ioctl_name[ioctl_table_max] = name 6673cab2bb3Spatrick ioctl_mode[ioctl_table_max] = mode 6683cab2bb3Spatrick ioctl_type[ioctl_table_max] = type 6693cab2bb3Spatrick ioctl_table_max++ 6703cab2bb3Spatrick} 671