1-- 2-- SPDX-License-Identifier: BSD-2-Clause 3-- 4-- Copyright (c) 2021-2024 SRI International 5-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org> 6-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com> 7-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org> 8-- 9 10local config = require("config") 11local util = require("tools.util") 12 13local scarg = {} 14 15scarg.__index = scarg 16 17-- Check this argument against config for ABI changes from native. Return TRUE 18-- if there are. 19local function checkAbiChanges(arg) 20 for k, v in pairs(config.known_abi_flags) do 21 if config.abiChanges(k) and v ~= nil then 22 for _, e in pairs(v) do 23 if arg:find(e) then 24 return true 25 end 26 end 27 end 28 end 29 return false 30end 31 32-- Strips the Microsoft(R) SAL annotations from this argument. 33local function stripArgAnnotations(arg) 34 arg = arg:gsub("_Contains_[^ ]*[_)] ?", "") 35 arg = arg:gsub("_In[^ ]*[_)] ?", "") 36 arg = arg:gsub("_Out[^ ]*[_)] ?", "") 37 return util.trim(arg) 38end 39 40-- Preprocessing of this argument. 41function scarg:init(line) 42 -- Trim whitespace and trailing comma. We don't want them here; 43 -- these can mess with our processing of this argument. 44 line = util.trim(line) -- This provides a clearer abort error. 45 self.scarg = util.trim(line, ',') 46 47 self.arg_abi_change = checkAbiChanges(self.scarg) 48 self.changes_abi = self.arg_abi_change 49 self.scarg = stripArgAnnotations(self.scarg) 50 51 self.name = self.scarg:match("([^* ]+)$") 52 -- Our pattern might produce a Lua pattern sequence; that's a malformed 53 -- declaration. 54 local status, type = pcall(function() 55 return util.trim(self.scarg:gsub(self.name .. "$", ""), nil) 56 end) 57 if not status then 58 util.abort(1, "Malformed argument line: " .. line) 59 end 60 self.type = type 61end 62 63-- Processes this argument. 64-- Flags if there's ABI changes from native, converts this argument to the 65-- target ABI, and handles 64-bit argument pairing. 66-- Returns TRUE if this argument is processed and ready to add. 67-- Returns FALSE if it shouldn't be added (the argument type is void). 68function scarg:process() 69 if self.type ~= "" and self.name ~= "void" then 70 -- util.is64bitType() needs a bare type so check it after 71 -- argname is removed. 72 self.changes_abi = self.changes_abi or 73 (config.abiChanges("pair_64bit") and 74 util.is64bitType(self.type)) 75 76 self.type = self.type:gsub("intptr_t", config.abi_intptr_t) 77 self.type = self.type:gsub("semid_t", config.abi_semid_t) 78 79 if util.isPtrType(self.type) then 80 self.type = self.type:gsub("size_t", config.abi_size_t) 81 self.type = self.type:gsub("^long", config.abi_long) 82 self.type = self.type:gsub("^u_long", config.abi_u_long) 83 self.type = self.type:gsub("^const u_long", "const " .. 84 config.abi_u_long) 85 elseif self.type:find("^long$") then 86 self.type = config.abi_long 87 end 88 89 if util.isPtrArrayType(self.type) and 90 config.abi_ptr_array_t ~= "" then 91 -- `* const *` -> `**` 92 self.type = self.type:gsub("[*][ ]*const[ ]*[*]", "**") 93 -- e.g., `struct aiocb **` -> `uint32_t *` 94 self.type = self.type:gsub("[^*]*[*]", 95 config.abi_ptr_array_t .. " ", 1) 96 end 97 98 if self.arg_abi_change then 99 self.type = self.type:gsub("(struct [^ ]*)", "%1" .. 100 config.abi_type_suffix) 101 self.type = self.type:gsub("(union [^ ]*)", "%1" .. 102 config.abi_type_suffix) 103 end 104 return true 105 end 106 return false 107end 108 109-- For pairing 64-bit arguments, pad if necessary. 110-- Returns TRUE if this argument was padded. 111local function pad(tbl) 112 if #tbl % 2 == 1 then 113 table.insert(tbl, { 114 type = "int", 115 name = "_pad", 116 }) 117 return true 118 end 119 return false 120end 121 122-- To append to a system call's argument table. Appends to the end. 123function scarg:append(tbl) 124 if config.abiChanges("pair_64bit") and util.is64bitType(self.type) then 125 pad(tbl) -- Needs argument padding. 126 table.insert(tbl, { 127 type = "uint32_t", 128 name = self.name .. "1", 129 }) 130 table.insert(tbl, { 131 type = "uint32_t", 132 name = self.name .. "2", 133 }) 134 else 135 table.insert(tbl, { 136 type = self.type, 137 name = self.name, 138 }) 139 end 140end 141 142-- Returns TRUE if this argument has ABI changes from native. 143-- EXAMPLE: 32-bit argument for freebsd32. 144function scarg:changesAbi() 145 return self.changes_abi 146end 147 148function scarg:new(obj, line) 149 obj = obj or { } 150 setmetatable(obj, self) 151 self.__index = self 152 153 -- ABI changes that we only want in this scope. 154 self.arg_abi_change = false 155 -- ABI changes that we want the system call object to see. 156 self.changes_abi = false 157 158 obj:init(line) 159 160 return obj 161end 162 163return scarg 164