xref: /aosp_15_r20/external/bcc/src/lua/bpf/cdef.lua (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1*387f9dfdSAndroid Build Coastguard Worker--[[
2*387f9dfdSAndroid Build Coastguard WorkerCopyright 2016 Marek Vavrusa <[email protected]>
3*387f9dfdSAndroid Build Coastguard Worker
4*387f9dfdSAndroid Build Coastguard WorkerLicensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Workeryou may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard WorkerYou may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker
8*387f9dfdSAndroid Build Coastguard Workerhttp://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker
10*387f9dfdSAndroid Build Coastguard WorkerUnless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Workerdistributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard WorkerWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard WorkerSee the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Workerlimitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker]]
16*387f9dfdSAndroid Build Coastguard Workerlocal ffi = require('ffi')
17*387f9dfdSAndroid Build Coastguard Workerlocal bit = require('bit')
18*387f9dfdSAndroid Build Coastguard Workerlocal has_syscall, S = pcall(require, 'syscall')
19*387f9dfdSAndroid Build Coastguard Workerlocal M = {}
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Workerffi.cdef [[
22*387f9dfdSAndroid Build Coastguard Workerstruct bpf {
23*387f9dfdSAndroid Build Coastguard Worker	/* Instruction classes */
24*387f9dfdSAndroid Build Coastguard Worker	static const int LD   = 0x00;
25*387f9dfdSAndroid Build Coastguard Worker	static const int LDX  = 0x01;
26*387f9dfdSAndroid Build Coastguard Worker	static const int ST   = 0x02;
27*387f9dfdSAndroid Build Coastguard Worker	static const int STX  = 0x03;
28*387f9dfdSAndroid Build Coastguard Worker	static const int ALU  = 0x04;
29*387f9dfdSAndroid Build Coastguard Worker	static const int JMP  = 0x05;
30*387f9dfdSAndroid Build Coastguard Worker	static const int ALU64 = 0x07;
31*387f9dfdSAndroid Build Coastguard Worker	/* ld/ldx fields */
32*387f9dfdSAndroid Build Coastguard Worker	static const int W    = 0x00;
33*387f9dfdSAndroid Build Coastguard Worker	static const int H    = 0x08;
34*387f9dfdSAndroid Build Coastguard Worker	static const int B    = 0x10;
35*387f9dfdSAndroid Build Coastguard Worker	static const int ABS  = 0x20;
36*387f9dfdSAndroid Build Coastguard Worker	static const int IND  = 0x40;
37*387f9dfdSAndroid Build Coastguard Worker	static const int MEM  = 0x60;
38*387f9dfdSAndroid Build Coastguard Worker	static const int LEN  = 0x80;
39*387f9dfdSAndroid Build Coastguard Worker	static const int MSH  = 0xa0;
40*387f9dfdSAndroid Build Coastguard Worker	/* alu/jmp fields */
41*387f9dfdSAndroid Build Coastguard Worker	static const int ADD  = 0x00;
42*387f9dfdSAndroid Build Coastguard Worker	static const int SUB  = 0x10;
43*387f9dfdSAndroid Build Coastguard Worker	static const int MUL  = 0x20;
44*387f9dfdSAndroid Build Coastguard Worker	static const int DIV  = 0x30;
45*387f9dfdSAndroid Build Coastguard Worker	static const int OR   = 0x40;
46*387f9dfdSAndroid Build Coastguard Worker	static const int AND  = 0x50;
47*387f9dfdSAndroid Build Coastguard Worker	static const int LSH  = 0x60;
48*387f9dfdSAndroid Build Coastguard Worker	static const int RSH  = 0x70;
49*387f9dfdSAndroid Build Coastguard Worker	static const int NEG  = 0x80;
50*387f9dfdSAndroid Build Coastguard Worker	static const int MOD  = 0x90;
51*387f9dfdSAndroid Build Coastguard Worker	static const int XOR  = 0xa0;
52*387f9dfdSAndroid Build Coastguard Worker	static const int JA   = 0x00;
53*387f9dfdSAndroid Build Coastguard Worker	static const int JEQ  = 0x10;
54*387f9dfdSAndroid Build Coastguard Worker	static const int JGT  = 0x20;
55*387f9dfdSAndroid Build Coastguard Worker	static const int JGE  = 0x30;
56*387f9dfdSAndroid Build Coastguard Worker	static const int JSET = 0x40;
57*387f9dfdSAndroid Build Coastguard Worker	static const int K    = 0x00;
58*387f9dfdSAndroid Build Coastguard Worker	static const int X    = 0x08;
59*387f9dfdSAndroid Build Coastguard Worker	static const int JNE  = 0x50;	/* jump != */
60*387f9dfdSAndroid Build Coastguard Worker	static const int JSGT = 0x60;	/* SGT is signed '>', GT in x86 */
61*387f9dfdSAndroid Build Coastguard Worker	static const int JSGE = 0x70;	/* SGE is signed '>=', GE in x86 */
62*387f9dfdSAndroid Build Coastguard Worker	static const int CALL = 0x80;	/* function call */
63*387f9dfdSAndroid Build Coastguard Worker	static const int EXIT = 0x90;	/* function return */
64*387f9dfdSAndroid Build Coastguard Worker	/* ld/ldx fields */
65*387f9dfdSAndroid Build Coastguard Worker	static const int DW    = 0x18;	/* double word */
66*387f9dfdSAndroid Build Coastguard Worker	static const int XADD  = 0xc0;	/* exclusive add */
67*387f9dfdSAndroid Build Coastguard Worker	/* alu/jmp fields */
68*387f9dfdSAndroid Build Coastguard Worker	static const int MOV   = 0xb0;	/* mov reg to reg */
69*387f9dfdSAndroid Build Coastguard Worker	static const int ARSH  = 0xc0;	/* sign extending arithmetic shift right */
70*387f9dfdSAndroid Build Coastguard Worker	/* change endianness of a register */
71*387f9dfdSAndroid Build Coastguard Worker	static const int END   = 0xd0;	/* flags for endianness conversion: */
72*387f9dfdSAndroid Build Coastguard Worker	static const int TO_LE = 0x00;	/* convert to little-endian */
73*387f9dfdSAndroid Build Coastguard Worker	static const int TO_BE = 0x08;	/* convert to big-endian */
74*387f9dfdSAndroid Build Coastguard Worker	/* misc */
75*387f9dfdSAndroid Build Coastguard Worker	static const int PSEUDO_MAP_FD = 0x01;
76*387f9dfdSAndroid Build Coastguard Worker	/* helper functions */
77*387f9dfdSAndroid Build Coastguard Worker	static const int F_CURRENT_CPU    = 0xffffffff;
78*387f9dfdSAndroid Build Coastguard Worker	static const int F_USER_STACK     = 1 << 8;
79*387f9dfdSAndroid Build Coastguard Worker	static const int F_FAST_STACK_CMP = 1 << 9;
80*387f9dfdSAndroid Build Coastguard Worker	static const int F_REUSE_STACKID  = 1 << 10;
81*387f9dfdSAndroid Build Coastguard Worker	/* special offsets for ancillary data */
82*387f9dfdSAndroid Build Coastguard Worker	static const int NET_OFF          = -0x100000;
83*387f9dfdSAndroid Build Coastguard Worker	static const int LL_OFF           = -0x200000;
84*387f9dfdSAndroid Build Coastguard Worker};
85*387f9dfdSAndroid Build Coastguard Worker/* eBPF commands */
86*387f9dfdSAndroid Build Coastguard Workerstruct bpf_cmd {
87*387f9dfdSAndroid Build Coastguard Worker	static const int MAP_CREATE       = 0;
88*387f9dfdSAndroid Build Coastguard Worker	static const int MAP_LOOKUP_ELEM  = 1;
89*387f9dfdSAndroid Build Coastguard Worker	static const int MAP_UPDATE_ELEM  = 2;
90*387f9dfdSAndroid Build Coastguard Worker	static const int MAP_DELETE_ELEM  = 3;
91*387f9dfdSAndroid Build Coastguard Worker	static const int MAP_GET_NEXT_KEY = 4;
92*387f9dfdSAndroid Build Coastguard Worker	static const int PROG_LOAD        = 5;
93*387f9dfdSAndroid Build Coastguard Worker	static const int OBJ_PIN          = 6;
94*387f9dfdSAndroid Build Coastguard Worker	static const int OBJ_GET          = 7;
95*387f9dfdSAndroid Build Coastguard Worker};
96*387f9dfdSAndroid Build Coastguard Worker/* eBPF helpers */
97*387f9dfdSAndroid Build Coastguard Workerstruct bpf_func_id {
98*387f9dfdSAndroid Build Coastguard Worker	static const int unspec               = 0;
99*387f9dfdSAndroid Build Coastguard Worker	static const int map_lookup_elem      = 1;
100*387f9dfdSAndroid Build Coastguard Worker	static const int map_update_elem      = 2;
101*387f9dfdSAndroid Build Coastguard Worker	static const int map_delete_elem      = 3;
102*387f9dfdSAndroid Build Coastguard Worker	static const int probe_read           = 4;
103*387f9dfdSAndroid Build Coastguard Worker	static const int ktime_get_ns         = 5;
104*387f9dfdSAndroid Build Coastguard Worker	static const int trace_printk         = 6;
105*387f9dfdSAndroid Build Coastguard Worker	static const int get_prandom_u32      = 7;
106*387f9dfdSAndroid Build Coastguard Worker	static const int get_smp_processor_id = 8;
107*387f9dfdSAndroid Build Coastguard Worker	static const int skb_store_bytes      = 9;
108*387f9dfdSAndroid Build Coastguard Worker	static const int l3_csum_replace      = 10;
109*387f9dfdSAndroid Build Coastguard Worker	static const int l4_csum_replace      = 11;
110*387f9dfdSAndroid Build Coastguard Worker	static const int tail_call            = 12;
111*387f9dfdSAndroid Build Coastguard Worker	static const int clone_redirect       = 13;
112*387f9dfdSAndroid Build Coastguard Worker	static const int get_current_pid_tgid = 14;
113*387f9dfdSAndroid Build Coastguard Worker	static const int get_current_uid_gid  = 15;
114*387f9dfdSAndroid Build Coastguard Worker	static const int get_current_comm     = 16;
115*387f9dfdSAndroid Build Coastguard Worker	static const int get_cgroup_classid   = 17;
116*387f9dfdSAndroid Build Coastguard Worker	static const int skb_vlan_push        = 18;
117*387f9dfdSAndroid Build Coastguard Worker	static const int skb_vlan_pop         = 19;
118*387f9dfdSAndroid Build Coastguard Worker	static const int skb_get_tunnel_key   = 20;
119*387f9dfdSAndroid Build Coastguard Worker	static const int skb_set_tunnel_key   = 21;
120*387f9dfdSAndroid Build Coastguard Worker	static const int perf_event_read      = 22;
121*387f9dfdSAndroid Build Coastguard Worker	static const int redirect             = 23;
122*387f9dfdSAndroid Build Coastguard Worker	static const int get_route_realm      = 24;
123*387f9dfdSAndroid Build Coastguard Worker	static const int perf_event_output    = 25;
124*387f9dfdSAndroid Build Coastguard Worker	static const int skb_load_bytes       = 26;
125*387f9dfdSAndroid Build Coastguard Worker	static const int get_stackid          = 27;
126*387f9dfdSAndroid Build Coastguard Worker};
127*387f9dfdSAndroid Build Coastguard Worker/* BPF_MAP_STACK_TRACE structures and constants */
128*387f9dfdSAndroid Build Coastguard Workerstatic const int BPF_MAX_STACK_DEPTH = 127;
129*387f9dfdSAndroid Build Coastguard Workerstruct bpf_stacktrace {
130*387f9dfdSAndroid Build Coastguard Worker	uint64_t ip[BPF_MAX_STACK_DEPTH];
131*387f9dfdSAndroid Build Coastguard Worker};
132*387f9dfdSAndroid Build Coastguard Worker]]
133*387f9dfdSAndroid Build Coastguard Worker
134*387f9dfdSAndroid Build Coastguard Worker-- Compatibility: ljsyscall doesn't have support for BPF syscall
135*387f9dfdSAndroid Build Coastguard Workerif not has_syscall or not S.bpf then
136*387f9dfdSAndroid Build Coastguard Worker	error("ljsyscall doesn't support bpf(), must be updated")
137*387f9dfdSAndroid Build Coastguard Workerelse
138*387f9dfdSAndroid Build Coastguard Worker	local strflag = require('syscall.helpers').strflag
139*387f9dfdSAndroid Build Coastguard Worker	-- Compatibility: ljsyscall<=0.12
140*387f9dfdSAndroid Build Coastguard Worker	if not S.c.BPF_MAP.LRU_HASH then
141*387f9dfdSAndroid Build Coastguard Worker		S.c.BPF_MAP = strflag {
142*387f9dfdSAndroid Build Coastguard Worker			UNSPEC           = 0,
143*387f9dfdSAndroid Build Coastguard Worker			HASH             = 1,
144*387f9dfdSAndroid Build Coastguard Worker			ARRAY            = 2,
145*387f9dfdSAndroid Build Coastguard Worker			PROG_ARRAY       = 3,
146*387f9dfdSAndroid Build Coastguard Worker			PERF_EVENT_ARRAY = 4,
147*387f9dfdSAndroid Build Coastguard Worker			PERCPU_HASH      = 5,
148*387f9dfdSAndroid Build Coastguard Worker			PERCPU_ARRAY     = 6,
149*387f9dfdSAndroid Build Coastguard Worker			STACK_TRACE      = 7,
150*387f9dfdSAndroid Build Coastguard Worker			CGROUP_ARRAY     = 8,
151*387f9dfdSAndroid Build Coastguard Worker			LRU_HASH         = 9,
152*387f9dfdSAndroid Build Coastguard Worker			LRU_PERCPU_HASH  = 10,
153*387f9dfdSAndroid Build Coastguard Worker			LPM_TRIE         = 11,
154*387f9dfdSAndroid Build Coastguard Worker			ARRAY_OF_MAPS    = 12,
155*387f9dfdSAndroid Build Coastguard Worker			HASH_OF_MAPS     = 13,
156*387f9dfdSAndroid Build Coastguard Worker			DEVMAP           = 14,
157*387f9dfdSAndroid Build Coastguard Worker			SOCKMAP          = 15,
158*387f9dfdSAndroid Build Coastguard Worker			CPUMAP           = 16,
159*387f9dfdSAndroid Build Coastguard Worker		}
160*387f9dfdSAndroid Build Coastguard Worker	end
161*387f9dfdSAndroid Build Coastguard Worker	if not S.c.BPF_PROG.TRACEPOINT then
162*387f9dfdSAndroid Build Coastguard Worker		S.c.BPF_PROG = strflag {
163*387f9dfdSAndroid Build Coastguard Worker			UNSPEC           = 0,
164*387f9dfdSAndroid Build Coastguard Worker			SOCKET_FILTER    = 1,
165*387f9dfdSAndroid Build Coastguard Worker			KPROBE           = 2,
166*387f9dfdSAndroid Build Coastguard Worker			SCHED_CLS        = 3,
167*387f9dfdSAndroid Build Coastguard Worker			SCHED_ACT        = 4,
168*387f9dfdSAndroid Build Coastguard Worker			TRACEPOINT       = 5,
169*387f9dfdSAndroid Build Coastguard Worker			XDP              = 6,
170*387f9dfdSAndroid Build Coastguard Worker			PERF_EVENT       = 7,
171*387f9dfdSAndroid Build Coastguard Worker			CGROUP_SKB       = 8,
172*387f9dfdSAndroid Build Coastguard Worker			CGROUP_SOCK      = 9,
173*387f9dfdSAndroid Build Coastguard Worker			LWT_IN           = 10,
174*387f9dfdSAndroid Build Coastguard Worker			LWT_OUT          = 11,
175*387f9dfdSAndroid Build Coastguard Worker			LWT_XMIT         = 12,
176*387f9dfdSAndroid Build Coastguard Worker			SOCK_OPS         = 13,
177*387f9dfdSAndroid Build Coastguard Worker			SK_SKB           = 14,
178*387f9dfdSAndroid Build Coastguard Worker			CGROUP_DEVICE    = 15,
179*387f9dfdSAndroid Build Coastguard Worker			SK_MSG           = 16,
180*387f9dfdSAndroid Build Coastguard Worker			RAW_TRACEPOINT   = 17,
181*387f9dfdSAndroid Build Coastguard Worker			CGROUP_SOCK_ADDR = 18,
182*387f9dfdSAndroid Build Coastguard Worker		}
183*387f9dfdSAndroid Build Coastguard Worker	end
184*387f9dfdSAndroid Build Coastguard Workerend
185*387f9dfdSAndroid Build Coastguard Worker
186*387f9dfdSAndroid Build Coastguard Worker-- Compatibility: metatype for stacktrace
187*387f9dfdSAndroid Build Coastguard Workerlocal function stacktrace_iter(t, i)
188*387f9dfdSAndroid Build Coastguard Worker	i = i + 1
189*387f9dfdSAndroid Build Coastguard Worker	if i < #t and t.ip[i] > 0 then
190*387f9dfdSAndroid Build Coastguard Worker		return i, t.ip[i]
191*387f9dfdSAndroid Build Coastguard Worker	end
192*387f9dfdSAndroid Build Coastguard Workerend
193*387f9dfdSAndroid Build Coastguard Workerffi.metatype('struct bpf_stacktrace', {
194*387f9dfdSAndroid Build Coastguard Worker	__len = function (t) return ffi.sizeof(t.ip) / ffi.sizeof(t.ip[0]) end,
195*387f9dfdSAndroid Build Coastguard Worker	__ipairs = function (t) return stacktrace_iter, t, -1 end,
196*387f9dfdSAndroid Build Coastguard Worker})
197*387f9dfdSAndroid Build Coastguard Worker
198*387f9dfdSAndroid Build Coastguard Worker-- Reflect cdata type
199*387f9dfdSAndroid Build Coastguard Workerfunction M.typename(v)
200*387f9dfdSAndroid Build Coastguard Worker	if not v or type(v) ~= 'cdata' then return nil end
201*387f9dfdSAndroid Build Coastguard Worker	return string.match(tostring(ffi.typeof(v)), '<([^>]+)')
202*387f9dfdSAndroid Build Coastguard Workerend
203*387f9dfdSAndroid Build Coastguard Worker
204*387f9dfdSAndroid Build Coastguard Worker-- Reflect if cdata type can be pointer (accepts array or pointer)
205*387f9dfdSAndroid Build Coastguard Workerfunction M.isptr(v, noarray)
206*387f9dfdSAndroid Build Coastguard Worker	local ctname = M.typename(v)
207*387f9dfdSAndroid Build Coastguard Worker	if ctname then
208*387f9dfdSAndroid Build Coastguard Worker		ctname = string.sub(ctname, -1)
209*387f9dfdSAndroid Build Coastguard Worker		ctname = ctname == '*' or (not noarray and ctname == ']')
210*387f9dfdSAndroid Build Coastguard Worker	end
211*387f9dfdSAndroid Build Coastguard Worker	return ctname
212*387f9dfdSAndroid Build Coastguard Workerend
213*387f9dfdSAndroid Build Coastguard Worker
214*387f9dfdSAndroid Build Coastguard Worker-- Return true if variable is a non-nil constant that can be used as immediate value
215*387f9dfdSAndroid Build Coastguard Worker-- e.g. result of KSHORT and KNUM
216*387f9dfdSAndroid Build Coastguard Workerfunction M.isimmconst(v)
217*387f9dfdSAndroid Build Coastguard Worker	return (type(v.const) == 'number' and not ffi.istype(v.type, ffi.typeof('void')))
218*387f9dfdSAndroid Build Coastguard Worker		or type(v.const) == 'cdata' and ffi.istype(v.type, ffi.typeof('uint64_t')) -- Lua numbers are at most 52 bits
219*387f9dfdSAndroid Build Coastguard Worker		or type(v.const) == 'cdata' and ffi.istype(v.type, ffi.typeof('int64_t'))
220*387f9dfdSAndroid Build Coastguard Workerend
221*387f9dfdSAndroid Build Coastguard Worker
222*387f9dfdSAndroid Build Coastguard Workerfunction M.osversion()
223*387f9dfdSAndroid Build Coastguard Worker	-- We have no better way to extract current kernel hex-string other
224*387f9dfdSAndroid Build Coastguard Worker	-- than parsing headers, compiling a helper function or reading /proc
225*387f9dfdSAndroid Build Coastguard Worker	local ver_str, count = S.sysctl('kernel.version'):match('%d+.%d+.%d+'), 2
226*387f9dfdSAndroid Build Coastguard Worker	if not ver_str then -- kernel.version is freeform, fallback to kernel.osrelease
227*387f9dfdSAndroid Build Coastguard Worker		ver_str = S.sysctl('kernel.osrelease'):match('%d+.%d+.%d+')
228*387f9dfdSAndroid Build Coastguard Worker	end
229*387f9dfdSAndroid Build Coastguard Worker	local version = 0
230*387f9dfdSAndroid Build Coastguard Worker	for i in ver_str:gmatch('%d+') do -- Convert 'X.Y.Z' to 0xXXYYZZ
231*387f9dfdSAndroid Build Coastguard Worker		version = bit.bor(version, bit.lshift(tonumber(i), 8*count))
232*387f9dfdSAndroid Build Coastguard Worker		count = count - 1
233*387f9dfdSAndroid Build Coastguard Worker	end
234*387f9dfdSAndroid Build Coastguard Worker	return version
235*387f9dfdSAndroid Build Coastguard Workerend
236*387f9dfdSAndroid Build Coastguard Worker
237*387f9dfdSAndroid Build Coastguard Workerfunction M.event_reader(reader, event_type)
238*387f9dfdSAndroid Build Coastguard Worker	-- Caller can specify event message binary format
239*387f9dfdSAndroid Build Coastguard Worker	if event_type then
240*387f9dfdSAndroid Build Coastguard Worker		assert(type(event_type) == 'string' and ffi.typeof(event_type), 'not a valid type for event reader')
241*387f9dfdSAndroid Build Coastguard Worker		event_type = ffi.typeof(event_type .. '*') -- Convert type to pointer-to-type
242*387f9dfdSAndroid Build Coastguard Worker	end
243*387f9dfdSAndroid Build Coastguard Worker	-- Wrap reader in interface that can interpret read event messages
244*387f9dfdSAndroid Build Coastguard Worker	return setmetatable({reader=reader,type=event_type}, {__index = {
245*387f9dfdSAndroid Build Coastguard Worker		block = function(_ --[[self]])
246*387f9dfdSAndroid Build Coastguard Worker			return S.select { readfds = {reader.fd} }
247*387f9dfdSAndroid Build Coastguard Worker		end,
248*387f9dfdSAndroid Build Coastguard Worker		next = function(_ --[[self]], k)
249*387f9dfdSAndroid Build Coastguard Worker			local len, ev = reader:next(k)
250*387f9dfdSAndroid Build Coastguard Worker			-- Filter out only sample frames
251*387f9dfdSAndroid Build Coastguard Worker			while ev and ev.type ~= S.c.PERF_RECORD.SAMPLE do
252*387f9dfdSAndroid Build Coastguard Worker				len, ev = reader:next(len)
253*387f9dfdSAndroid Build Coastguard Worker			end
254*387f9dfdSAndroid Build Coastguard Worker			if ev and event_type then
255*387f9dfdSAndroid Build Coastguard Worker				-- The perf event reader returns framed data with header and variable length
256*387f9dfdSAndroid Build Coastguard Worker				-- This is going skip the frame header and cast data to given type
257*387f9dfdSAndroid Build Coastguard Worker				ev = ffi.cast(event_type, ffi.cast('char *', ev) + ffi.sizeof('struct perf_event_header') + ffi.sizeof('uint32_t'))
258*387f9dfdSAndroid Build Coastguard Worker			end
259*387f9dfdSAndroid Build Coastguard Worker			return len, ev
260*387f9dfdSAndroid Build Coastguard Worker		end,
261*387f9dfdSAndroid Build Coastguard Worker		read = function(self)
262*387f9dfdSAndroid Build Coastguard Worker			return self.next, self, nil
263*387f9dfdSAndroid Build Coastguard Worker		end,
264*387f9dfdSAndroid Build Coastguard Worker	}})
265*387f9dfdSAndroid Build Coastguard Workerend
266*387f9dfdSAndroid Build Coastguard Worker
267*387f9dfdSAndroid Build Coastguard Workerfunction M.tracepoint_type(tp)
268*387f9dfdSAndroid Build Coastguard Worker	-- Read tracepoint format string
269*387f9dfdSAndroid Build Coastguard Worker	local fp = assert(io.open('/sys/kernel/debug/tracing/events/'..tp..'/format', 'r'))
270*387f9dfdSAndroid Build Coastguard Worker	local fmt = fp:read '*a'
271*387f9dfdSAndroid Build Coastguard Worker	fp:close()
272*387f9dfdSAndroid Build Coastguard Worker	-- Parse struct fields
273*387f9dfdSAndroid Build Coastguard Worker	local fields = {}
274*387f9dfdSAndroid Build Coastguard Worker	for f in fmt:gmatch 'field:([^;]+;)' do
275*387f9dfdSAndroid Build Coastguard Worker		table.insert(fields, f)
276*387f9dfdSAndroid Build Coastguard Worker	end
277*387f9dfdSAndroid Build Coastguard Worker	return string.format('struct { %s }', table.concat(fields))
278*387f9dfdSAndroid Build Coastguard Workerend
279*387f9dfdSAndroid Build Coastguard Worker
280*387f9dfdSAndroid Build Coastguard Workerreturn M
281