xref: /freebsd/sys/tools/syscalls/scripts/systrace_args.lua (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
1#!/usr/libexec/flua
2--
3-- SPDX-License-Identifier: BSD-2-Clause
4--
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
10-- Setup to be a module, or ran as its own script.
11local systrace_args = {}
12local script = not pcall(debug.getlocal, 4, 1)	-- TRUE if script.
13if script then
14	-- Add library root to the package path.
15	local path = arg[0]:gsub("/[^/]+.lua$", "")
16	package.path = package.path .. ";" .. path .. "/../?.lua"
17end
18
19local FreeBSDSyscall = require("core.freebsd-syscall")
20local util = require("tools.util")
21local generator = require("tools.generator")
22
23-- File has not been decided yet; config will decide file.  Default defined as
24-- /dev/null.
25systrace_args.file = "/dev/null"
26
27function systrace_args.generate(tbl, config, fh)
28	-- Grab the master system calls table.
29	local s = tbl.syscalls
30
31	-- Bind the generator to the parameter file.
32	local gen = generator:new({}, fh)
33	gen.storage_levels = {}	-- make sure storage is clear
34
35	-- 64-bit padding preprocessor directive.
36	gen:pad64(config.abiChanges("pair_64bit"))
37
38	-- Write the generated preamble.
39	gen:preamble(
40	    "System call argument to DTrace register array conversion.\n" ..
41	    "\n" ..
42	    "This file is part of the DTrace syscall provider.")
43
44	gen:write(string.format([[
45static void
46systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
47{
48	int64_t *iarg = (int64_t *)uarg;
49	int a = 0;
50	switch (sysnum) {
51]]))
52
53	gen:store(string.format([[
54static void
55systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
56{
57	const char *p = NULL;
58	switch (sysnum) {
59]]), 1)
60
61	gen:store(string.format([[
62static void
63systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
64{
65	const char *p = NULL;
66	switch (sysnum) {
67]]), 2)
68
69	for _, v in pairs(s) do
70
71		-- Handle non compat:
72		if v:native() then
73			gen:write(string.format([[
74	/* %s */
75	case %d: {
76]], v.name, v.num))
77
78			gen:store(string.format([[
79	/* %s */
80	case %d:
81]], v.name, v.num), 1)
82
83			gen:store(string.format([[
84	/* %s */
85	case %d:
86]], v.name, v.num), 2)
87
88			local n_args = #v.args
89			if v.type.SYSMUX then
90				n_args = 0
91			end
92
93			if #v.args > 0 and not v.type.SYSMUX then
94				local padding = ""
95
96				gen:write(string.format([[
97		struct %s *p = params;
98]],
99				    v.arg_alias))
100
101				gen:store([[
102		switch (ndx) {
103]],
104				    1)
105
106				for idx, arg in ipairs(v.args) do
107					local argtype = util.trim(
108						arg.type:gsub(
109						    "__restrict$", ""), nil)
110					if argtype == "int" and
111					    arg.name == "_pad" and
112					    config.abiChanges("pair_64bit") then
113						gen:store(
114						    "#ifdef PAD64_REQUIRED\n",
115						    1)
116					end
117
118					-- Pointer arg?
119					local desc
120					if argtype:find("*") then
121						desc = "userland " .. argtype
122					else
123						desc = argtype;
124					end
125
126					gen:store(string.format([[
127		case %d%s:
128			p = "%s";
129			break;
130]],
131					    idx - 1, padding, desc), 1)
132
133					if argtype == "int" and
134					    arg.name == "_pad" and
135					   config.abiChanges("pair_64bit") then
136						padding = " - _P_"
137						gen:store([[
138#define _P_ 0
139#else
140#define _P_ 1
141#endif
142]],
143					    1)
144					end
145
146					if util.isPtrType(argtype,
147					    config.abi_intptr_t) then
148						gen:write(string.format([[
149		uarg[a++] = (%s)p->%s; /* %s */
150]],
151						    config.ptr_intptr_t_cast,
152						    arg.name, argtype))
153					elseif argtype == "union l_semun" then
154						gen:write(string.format([[
155		uarg[a++] = p->%s.buf; /* %s */
156]],
157						    arg.name, argtype))
158					elseif argtype:sub(1,1) == "u" or
159					    argtype == "size_t" then
160						gen:write(string.format([[
161		uarg[a++] = p->%s; /* %s */
162]],
163						    arg.name, argtype))
164					else
165						if argtype == "int" and
166						    arg.name == "_pad" and
167						    config.abiChanges(
168						    "pair_64bit") then
169							gen:write([[
170#ifdef PAD64_REQUIRED
171]])
172						end
173
174						gen:write(string.format([[
175		iarg[a++] = p->%s; /* %s */
176]],
177						    arg.name, argtype))
178
179						if argtype == "int" and
180						    arg.name == "_pad" and
181						    config.abiChanges(
182						    "pair_64bit") then
183							gen:write("#endif\n")
184						end
185					end
186				end
187
188				gen:store([[
189		default:
190			break;
191		};
192]],
193				    1)
194
195				if padding ~= "" then
196					gen:store("#undef _P_\n\n", 1)
197				end
198
199				gen:store(string.format([[
200		if (ndx == 0 || ndx == 1)
201			p = "%s";
202		break;
203]], v.ret), 2)
204		end
205
206		gen:write(string.format("\t\t*n_args = %d;\n\t\tbreak;\n\t}\n",
207		    n_args))
208		gen:store("\t\tbreak;\n", 1)
209
210		-- Handle compat (everything >= FREEBSD3):
211		-- Do nothing, only for native.
212		end
213	end
214
215	gen:write([[
216	default:
217		*n_args = 0;
218		break;
219	};
220}
221]])
222	gen:store([[
223	default:
224		break;
225	};
226	if (p != NULL)
227		strlcpy(desc, p, descsz);
228}
229]], 1)
230	gen:store([[
231	default:
232		break;
233	};
234	if (p != NULL)
235		strlcpy(desc, p, descsz);
236}
237]], 2)
238
239	-- Write all stored lines.
240	if gen.storage_levels ~= nil then
241		gen:writeStorage()
242	end
243
244end
245
246-- Entry of script:
247if script then
248	local config = require("config")
249
250	if #arg < 1 or #arg > 2 then
251		error("usage: " .. arg[0] .. " syscall.master")
252	end
253
254	local sysfile, configfile = arg[1], arg[2]
255
256	config.merge(configfile)
257	config.mergeCompat()
258
259	-- The parsed system call table.
260	local tbl = FreeBSDSyscall:new{sysfile = sysfile, config = config}
261
262	systrace_args.file = config.systrace	-- change file here
263	systrace_args.generate(tbl, config, systrace_args.file)
264end
265
266-- Return the module.
267return systrace_args
268