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}