xref: /src/sys/tools/syscalls/core/scarg.lua (revision 9ded074e875c29cb92d5f643801990d7bb23cca4)
19ded074eSagge3--
29ded074eSagge3-- SPDX-License-Identifier: BSD-2-Clause
39ded074eSagge3--
49ded074eSagge3-- Copyright (c) 2021-2024 SRI International
59ded074eSagge3-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
69ded074eSagge3-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com>
79ded074eSagge3-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
89ded074eSagge3--
99ded074eSagge3
109ded074eSagge3local config = require("config")
119ded074eSagge3local util = require("tools.util")
129ded074eSagge3
139ded074eSagge3local scarg = {}
149ded074eSagge3
159ded074eSagge3scarg.__index = scarg
169ded074eSagge3
179ded074eSagge3-- Check this argument against config for ABI changes from native. Return TRUE
189ded074eSagge3-- if there are.
199ded074eSagge3local function checkAbiChanges(arg)
209ded074eSagge3	for k, v in pairs(config.known_abi_flags) do
219ded074eSagge3		if config.abiChanges(k) and v ~= nil then
229ded074eSagge3			for _, e in pairs(v) do
239ded074eSagge3				if arg:find(e) then
249ded074eSagge3					return true
259ded074eSagge3				end
269ded074eSagge3			end
279ded074eSagge3		end
289ded074eSagge3	end
299ded074eSagge3	return false
309ded074eSagge3end
319ded074eSagge3
329ded074eSagge3-- Strips the Microsoft(R) SAL annotations from this argument.
339ded074eSagge3local function stripArgAnnotations(arg)
349ded074eSagge3	arg = arg:gsub("_Contains_[^ ]*[_)] ?", "")
359ded074eSagge3	arg = arg:gsub("_In[^ ]*[_)] ?", "")
369ded074eSagge3	arg = arg:gsub("_Out[^ ]*[_)] ?", "")
379ded074eSagge3	return util.trim(arg)
389ded074eSagge3end
399ded074eSagge3
409ded074eSagge3-- Preprocessing of this argument.
419ded074eSagge3function scarg:init(line)
429ded074eSagge3	-- Trim whitespace and trailing comma. We don't want them here;
439ded074eSagge3	-- these can mess with our processing of this argument.
449ded074eSagge3	line = util.trim(line)	-- This provides a clearer abort error.
459ded074eSagge3	self.scarg = util.trim(line, ',')
469ded074eSagge3
479ded074eSagge3	self.arg_abi_change = checkAbiChanges(self.scarg)
489ded074eSagge3	self.changes_abi = self.arg_abi_change
499ded074eSagge3	self.scarg = stripArgAnnotations(self.scarg)
509ded074eSagge3
519ded074eSagge3	self.name = self.scarg:match("([^* ]+)$")
529ded074eSagge3	-- Our pattern might produce a Lua pattern sequence; that's a malformed
539ded074eSagge3	-- declaration.
549ded074eSagge3	local status, type = pcall(function()
559ded074eSagge3		return util.trim(self.scarg:gsub(self.name .. "$", ""), nil)
569ded074eSagge3	end)
579ded074eSagge3	if not status then
589ded074eSagge3		util.abort(1, "Malformed argument line: " .. line)
599ded074eSagge3	end
609ded074eSagge3	self.type = type
619ded074eSagge3end
629ded074eSagge3
639ded074eSagge3-- Processes this argument.
649ded074eSagge3-- Flags if there's ABI changes from native, converts this argument to the
659ded074eSagge3-- target ABI, and handles 64-bit argument pairing.
669ded074eSagge3-- Returns TRUE if this argument is processed and ready to add.
679ded074eSagge3-- Returns FALSE if it shouldn't be added (the argument type is void).
689ded074eSagge3function scarg:process()
699ded074eSagge3	if self.type ~= "" and self.name ~= "void" then
709ded074eSagge3		-- util.is64bitType() needs a bare type so check it after
719ded074eSagge3		-- argname is removed.
729ded074eSagge3		self.changes_abi = self.changes_abi or
739ded074eSagge3			(config.abiChanges("pair_64bit") and
749ded074eSagge3			util.is64bitType(self.type))
759ded074eSagge3
769ded074eSagge3		self.type = self.type:gsub("intptr_t", config.abi_intptr_t)
779ded074eSagge3		self.type = self.type:gsub("semid_t", config.abi_semid_t)
789ded074eSagge3
799ded074eSagge3		if util.isPtrType(self.type) then
809ded074eSagge3			self.type = self.type:gsub("size_t", config.abi_size_t)
819ded074eSagge3			self.type = self.type:gsub("^long", config.abi_long)
829ded074eSagge3			self.type = self.type:gsub("^u_long", config.abi_u_long)
839ded074eSagge3			self.type = self.type:gsub("^const u_long", "const " ..
849ded074eSagge3			   config.abi_u_long)
859ded074eSagge3		elseif self.type:find("^long$") then
869ded074eSagge3			self.type = config.abi_long
879ded074eSagge3		end
889ded074eSagge3
899ded074eSagge3		if util.isPtrArrayType(self.type) and
909ded074eSagge3		   config.abi_ptr_array_t ~= "" then
919ded074eSagge3			-- `* const *` -> `**`
929ded074eSagge3			self.type = self.type:gsub("[*][ ]*const[ ]*[*]", "**")
939ded074eSagge3			-- e.g., `struct aiocb **` -> `uint32_t *`
949ded074eSagge3			self.type = self.type:gsub("[^*]*[*]",
959ded074eSagge3			   config.abi_ptr_array_t .. " ", 1)
969ded074eSagge3		end
979ded074eSagge3
989ded074eSagge3		if self.arg_abi_change then
999ded074eSagge3			self.type = self.type:gsub("(struct [^ ]*)", "%1" ..
1009ded074eSagge3			    config.abi_type_suffix)
1019ded074eSagge3			self.type = self.type:gsub("(union [^ ]*)", "%1" ..
1029ded074eSagge3			    config.abi_type_suffix)
1039ded074eSagge3		end
1049ded074eSagge3		return true
1059ded074eSagge3	end
1069ded074eSagge3	return false
1079ded074eSagge3end
1089ded074eSagge3
1099ded074eSagge3-- For pairing 64-bit arguments, pad if necessary.
1109ded074eSagge3-- Returns TRUE if this argument was padded.
1119ded074eSagge3local function pad(tbl)
1129ded074eSagge3	if #tbl % 2 == 1 then
1139ded074eSagge3		table.insert(tbl, {
1149ded074eSagge3			type = "int",
1159ded074eSagge3			name = "_pad",
1169ded074eSagge3		})
1179ded074eSagge3		return true
1189ded074eSagge3	end
1199ded074eSagge3	return false
1209ded074eSagge3end
1219ded074eSagge3
1229ded074eSagge3-- To append to a system call's argument table. Appends to the end.
1239ded074eSagge3function scarg:append(tbl)
1249ded074eSagge3	if config.abiChanges("pair_64bit") and util.is64bitType(self.type) then
1259ded074eSagge3		pad(tbl)	-- Needs argument padding.
1269ded074eSagge3		table.insert(tbl, {
1279ded074eSagge3			type = "uint32_t",
1289ded074eSagge3			name = self.name .. "1",
1299ded074eSagge3		})
1309ded074eSagge3		table.insert(tbl, {
1319ded074eSagge3			type = "uint32_t",
1329ded074eSagge3			name = self.name .. "2",
1339ded074eSagge3		})
1349ded074eSagge3	else
1359ded074eSagge3		table.insert(tbl, {
1369ded074eSagge3			type = self.type,
1379ded074eSagge3			name = self.name,
1389ded074eSagge3		})
1399ded074eSagge3	end
1409ded074eSagge3end
1419ded074eSagge3
1429ded074eSagge3-- Returns TRUE if this argument has ABI changes from native.
1439ded074eSagge3-- EXAMPLE: 32-bit argument for freebsd32.
1449ded074eSagge3function scarg:changesAbi()
1459ded074eSagge3	return self.changes_abi
1469ded074eSagge3end
1479ded074eSagge3
1489ded074eSagge3function scarg:new(obj, line)
1499ded074eSagge3	obj = obj or { }
1509ded074eSagge3	setmetatable(obj, self)
1519ded074eSagge3	self.__index = self
1529ded074eSagge3
1539ded074eSagge3	-- ABI changes that we only want in this scope.
1549ded074eSagge3	self.arg_abi_change = false
1559ded074eSagge3	-- ABI changes that we want the system call object to see.
1569ded074eSagge3	self.changes_abi = false
1579ded074eSagge3
1589ded074eSagge3	obj:init(line)
1599ded074eSagge3
1609ded074eSagge3	return obj
1619ded074eSagge3end
1629ded074eSagge3
1639ded074eSagge3return scarg
164