1-- 2-- SPDX-License-Identifier: BSD-2-Clause 3-- 4-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org> 5-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com> 6-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org> 7-- 8 9local syscall = require("core.syscall") 10local util = require("tools.util") 11 12local FreeBSDSyscall = {} 13 14FreeBSDSyscall.__index = FreeBSDSyscall 15 16-- For each compat option in the provided config table, process them and insert 17-- them into known_flags for class syscall. 18function FreeBSDSyscall:processCompat() 19 for _, v in pairs(self.config.compat_options) do 20 if v.stdcompat ~= nil then 21 local stdcompat = v.stdcompat 22 v.definition = "COMPAT_" .. stdcompat:upper() 23 v.compatlevel = tonumber(stdcompat:match("([0-9]+)$")) 24 v.flag = stdcompat:gsub("FREEBSD", "COMPAT") 25 v.prefix = stdcompat:lower() .. "_" 26 v.descr = stdcompat:lower() 27 end 28 29 -- Add compat option to syscall.known_flags. 30 table.insert(syscall.known_flags, v.flag) 31 end 32end 33 34function FreeBSDSyscall:parseSysfile() 35 local file = self.sysfile 36 local config = self.config 37 local commentExpr = "^%s*;.*" 38 39 if file == nil then 40 return nil, "No file given" 41 end 42 43 self.syscalls = {} 44 45 local fh, msg = io.open(file) 46 if fh == nil then 47 return nil, msg 48 end 49 50 local incs = "" 51 local defs = "" 52 local s 53 for line in fh:lines() do 54 line = line:gsub(commentExpr, "") -- Strip any comments. 55 -- NOTE: Can't use pure pattern matching here because of 56 -- the 's' test and this is shorter than a generic pattern 57 -- matching pattern. 58 if line == nil or line == "" then 59 goto skip -- Blank line, skip this line. 60 elseif s ~= nil then 61 -- If we have a partial system call object s, 62 -- then feed it one more line. 63 if s:add(line) then 64 -- Append to system call list. 65 for t in s:iter() do 66 if t:validate(t.num - 1) then 67 table.insert(self.syscalls, t) 68 else 69 util.abort(1, 70 "Skipped system call " .. 71 "at number " .. t.num) 72 end 73 end 74 s = nil 75 end 76 elseif line:match("^#%s*include") then 77 incs = incs .. line .. "\n" 78 elseif line:match("%%ABI_HEADERS%%") then 79 local h = self.config.abi_headers 80 if h ~= nil and h ~= "" then 81 incs = incs .. h .. "\n" 82 end 83 elseif line:match("^#%s*define") then 84 defs = defs .. line.. "\n" 85 elseif line:match("^#") then 86 util.abort(1, "Unsupported cpp op " .. line) 87 else 88 s = syscall:new() 89 if s:add(line) then 90 -- Append to system call list. 91 for t in s:iter() do 92 if t:validate(t.num - 1) then 93 table.insert(self.syscalls, t) 94 else 95 util.abort(1, 96 "Skipped system call " .. 97 "at number " .. t.num) 98 end 99 end 100 s = nil 101 end 102 end 103 ::skip:: 104 end 105 106 -- Special handling for linux nosys. 107 if config.syscallprefix:find("LINUX") ~= nil then 108 s = nil 109 end 110 111 if s ~= nil then 112 util.abort(1, "Dangling system call at the end") 113 end 114 115 assert(fh:close()) 116 self.includes = incs 117 self.defines = defs 118end 119 120function FreeBSDSyscall:findStructs() 121 self.structs = {} 122 123 for _, s in pairs(self.syscalls) do 124 if s:native() and not s.type.NODEF then 125 for _, v in ipairs(s.args) do 126 local name = util.structName(v.type) 127 if name ~= nil then 128 self.structs[name] = name 129 end 130 end 131 end 132 end 133end 134 135function FreeBSDSyscall:new(obj) 136 obj = obj or {} 137 setmetatable(obj, self) 138 self.__index = self 139 140 obj:processCompat() 141 obj:parseSysfile() 142 obj:findStructs() 143 144 return obj 145end 146 147return FreeBSDSyscall 148