• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--[[
2Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com>
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15]]
16local jutil = require("jit.util")
17local vmdef = require("jit.vmdef")
18local bit = require('bit')
19local shr, band = bit.rshift, bit.band
20
21-- Decode LuaJIT 2.0 Byte Format
22-- Reference: http://wiki.luajit.org/Bytecode-2.0
23-- Thanks to LJ, we get code in portable bytecode with constants folded, basic
24-- virtual registers allocated etc.
25-- No SSA IR, type inference or advanced optimizations because the code wasn't traced yet.
26local function decode_ins(func, pc)
27	local ins, m = jutil.funcbc(func, pc)
28	if not ins then return nil end
29	local op, ma, mb, mc = band(ins, 0xff), band(m, 7), band(m, 15*8), band(m, 15*128)
30	local a, b, c, d = band(shr(ins, 8), 0xff), nil, nil, shr(ins, 16)
31	if mb ~= 0 then
32		d = band(d, 0xff)
33		b = shr(ins, 24)
34	end
35	if ma == 5 then          -- BCMuv
36	    a = jutil.funcuvname(func, a)
37	end
38	if mc == 13*128 then     -- BCMjump
39		c = pc+d-0x7fff
40	elseif mc == 14*128 then -- BCMcdata
41		c = jutil.funck(func, -d-1)
42	elseif mc == 9*128 then  -- BCMint
43		c = jutil.funck(func, d)
44	elseif mc == 10*128 then -- BCMstr
45		c = jutil.funck(func, -d-1)
46	elseif mc == 5*128 then  -- BCMuv
47	    c = jutil.funcuvname(func, d)
48	end
49	-- Convert version-specific opcode to string
50	op = 6*op
51	op = string.sub(vmdef.bcnames, op+1, op+6):match('[^%s]+')
52	return pc, op, a, b, c, d
53end
54
55-- Decoder closure
56local function decoder(func)
57	local pc = 0
58	return function ()
59		pc = pc + 1
60		return decode_ins(func, pc)
61	end
62end
63
64-- Hexdump generated code
65local function dump(func)
66	return require('jit.bc').dump(func)
67end
68
69return {
70	decode = decode_ins,
71	decoder = decoder,
72	dump = dump,
73	funcinfo = function (...) return jutil.funcinfo(...) end,
74}