Commit 67bb1502 authored by Marek Vavruša's avatar Marek Vavruša

lua/bpf: cleanup, nicer code dump format

parent d28957ef
...@@ -879,7 +879,7 @@ local BC = { ...@@ -879,7 +879,7 @@ local BC = {
CALL = function (a, b, _, d) -- A = A(A+1, ..., A+D-1) CALL = function (a, b, _, d) -- A = A(A+1, ..., A+D-1)
CALL(a, b, d) CALL(a, b, d)
end, end,
JMP = function (a, _, c, d) -- JMP JMP = function (a, _, c, _) -- JMP
-- Discard unused slots after jump -- Discard unused slots after jump
for i, _ in pairs(V) do for i, _ in pairs(V) do
if i >= a then V[i] = {} end if i >= a then V[i] = {} end
...@@ -958,7 +958,7 @@ end ...@@ -958,7 +958,7 @@ end
vset(stackslots) vset(stackslots)
vset(stackslots+1) vset(stackslots+1)
return setmetatable(BC, { return setmetatable(BC, {
__index = function (t, k, v) __index = function (_, k, _)
if type(k) == 'number' then if type(k) == 'number' then
local op_str = string.sub(require('jit.vmdef').bcnames, 6*k+1, 6*k+6) local op_str = string.sub(require('jit.vmdef').bcnames, 6*k+1, 6*k+6)
error(string.format("NYI: opcode '0x%02x' (%-04s)", k, op_str)) error(string.format("NYI: opcode '0x%02x' (%-04s)", k, op_str))
...@@ -992,7 +992,9 @@ return setmetatable(BC, { ...@@ -992,7 +992,9 @@ return setmetatable(BC, {
end end
-- Emitted code dump -- Emitted code dump
local function dump_mem(cls, ins) local function dump_mem(cls, ins, _, fuse)
-- This is a very dense MEM instruction decoder without much explanation
-- Refer to https://www.kernel.org/doc/Documentation/networking/filter.txt for instruction format
local mode = bit.band(ins.code, 0xe0) local mode = bit.band(ins.code, 0xe0)
if mode == BPF.XADD then cls = 5 end -- The only mode if mode == BPF.XADD then cls = 5 end -- The only mode
local op_1 = {'LD', 'LDX', 'ST', 'STX', '', 'XADD'} local op_1 = {'LD', 'LDX', 'ST', 'STX', '', 'XADD'}
...@@ -1004,7 +1006,7 @@ local function dump_mem(cls, ins) ...@@ -1004,7 +1006,7 @@ local function dump_mem(cls, ins)
if cls == BPF.LDX then src = string.format('[R%d%+d]', ins.src_reg, off) end if cls == BPF.LDX then src = string.format('[R%d%+d]', ins.src_reg, off) end
if mode == BPF.ABS then src = string.format('[%d]', ins.imm) end if mode == BPF.ABS then src = string.format('[%d]', ins.imm) end
if mode == BPF.IND then src = string.format('[R%d%+d]', ins.src_reg, ins.imm) end if mode == BPF.IND then src = string.format('[R%d%+d]', ins.src_reg, ins.imm) end
return string.format('%s\t%s\t%s', name, dst, src) return string.format('%s\t%s\t%s', fuse and '' or name, fuse and '' or dst, src)
end end
local function dump_alu(cls, ins, pc) local function dump_alu(cls, ins, pc)
...@@ -1017,6 +1019,8 @@ local function dump_alu(cls, ins, pc) ...@@ -1017,6 +1019,8 @@ local function dump_alu(cls, ins, pc)
'skb_get_tunnel_key', 'skb_set_tunnel_key', 'perf_event_read', 'redirect', 'get_route_realm', 'skb_get_tunnel_key', 'skb_set_tunnel_key', 'perf_event_read', 'redirect', 'get_route_realm',
'perf_event_output', 'skb_load_bytes'} 'perf_event_output', 'skb_load_bytes'}
local op = 0 local op = 0
-- This is a very dense ALU instruction decoder without much explanation
-- Refer to https://www.kernel.org/doc/Documentation/networking/filter.txt for instruction format
for i = 0,13 do if 0x10 * i == bit.band(ins.code, 0xf0) then op = i + 1 break end end for i = 0,13 do if 0x10 * i == bit.band(ins.code, 0xf0) then op = i + 1 break end end
local name = (cls == 5) and jmp[op] or alu[op] local name = (cls == 5) and jmp[op] or alu[op]
local src = (bit.band(ins.code, 0x08) == BPF.X) and 'R'..ins.src_reg or '#'..ins.imm local src = (bit.band(ins.code, 0x08) == BPF.X) and 'R'..ins.src_reg or '#'..ins.imm
...@@ -1032,16 +1036,19 @@ local function dump(code) ...@@ -1032,16 +1036,19 @@ local function dump(code)
[0] = dump_mem, [1] = dump_mem, [2] = dump_mem, [3] = dump_mem, [0] = dump_mem, [1] = dump_mem, [2] = dump_mem, [3] = dump_mem,
[4] = dump_alu, [5] = dump_alu, [7] = dump_alu, [4] = dump_alu, [5] = dump_alu, [7] = dump_alu,
} }
local fused = false
for i = 0, code.pc - 1 do for i = 0, code.pc - 1 do
local ins = code.insn[i] local ins = code.insn[i]
local cls = bit.band(ins.code, 0x07) local cls = bit.band(ins.code, 0x07)
print(string.format('%04u\t%s', i, cls_map[cls](cls, ins, i))) local line = cls_map[cls](cls, ins, i, fused)
print(string.format('%04u\t%s', i, line))
fused = string.find(line, 'LDDW', 1)
end end
end end
local function compile(prog, params) local function compile(prog, params)
-- Create code emitter sandbox, include caller locals -- Create code emitter sandbox, include caller locals
local env = { pkt=proto.pkt, BPF=BPF } local env = { pkt=proto.pkt, BPF=BPF, ffi=ffi }
-- Include upvalues up to 4 nested scopes back -- Include upvalues up to 4 nested scopes back
-- the narrower scope overrides broader scope -- the narrower scope overrides broader scope
for k = 5, 2, -1 do for k = 5, 2, -1 do
...@@ -1102,7 +1109,7 @@ local bpf_map_mt = { ...@@ -1102,7 +1109,7 @@ local bpf_map_mt = {
cur_key = ffi.new(ffi.typeof(t.key)) cur_key = ffi.new(ffi.typeof(t.key))
end end
local ok, err = S.bpf_map_op(S.c.BPF_CMD.MAP_GET_NEXT_KEY, map.fd, cur_key, next_key) local ok, err = S.bpf_map_op(S.c.BPF_CMD.MAP_GET_NEXT_KEY, map.fd, cur_key, next_key)
if not ok then return nil end if not ok then return nil, err end
-- Get next value -- Get next value
assert(S.bpf_map_op(S.c.BPF_CMD.MAP_LOOKUP_ELEM, map.fd, next_key, map.val)) assert(S.bpf_map_op(S.c.BPF_CMD.MAP_LOOKUP_ELEM, map.fd, next_key, map.val))
return next_key[0], map.val[0] return next_key[0], map.val[0]
...@@ -1316,5 +1323,5 @@ return setmetatable({ ...@@ -1316,5 +1323,5 @@ return setmetatable({
end, end,
ntoh = builtins.ntoh, hton = builtins.hton, ntoh = builtins.ntoh, hton = builtins.hton,
}, { }, {
__call = function (t, prog) return compile(prog) end, __call = function (_, prog) return compile(prog) end,
}) })
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment