| --[[ |
| Copyright 2016 Marek Vavrusa <mvavrusa@cloudflare.com> |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ]] |
| local jutil = require("jit.util") |
| local vmdef = require("jit.vmdef") |
| local bit = require('bit') |
| local shr, band = bit.rshift, bit.band |
| |
| -- Decode LuaJIT 2.0 Byte Format |
| -- Reference: http://wiki.luajit.org/Bytecode-2.0 |
| -- Thanks to LJ, we get code in portable bytecode with constants folded, basic |
| -- virtual registers allocated etc. |
| -- No SSA IR, type inference or advanced optimizations because the code wasn't traced yet. |
| local function decode_ins(func, pc) |
| local ins, m = jutil.funcbc(func, pc) |
| if not ins then return nil end |
| local op, ma, mb, mc = band(ins, 0xff), band(m, 7), band(m, 15*8), band(m, 15*128) |
| local a, b, c, d = band(shr(ins, 8), 0xff), nil, nil, shr(ins, 16) |
| if mb ~= 0 then |
| d = band(d, 0xff) |
| b = shr(ins, 24) |
| end |
| if ma == 5 then -- BCMuv |
| a = jutil.funcuvname(func, a) |
| end |
| if mc == 13*128 then -- BCMjump |
| c = pc+d-0x7fff |
| elseif mc == 9*128 then -- BCMint |
| c = jutil.funck(func, d) |
| elseif mc == 10*128 then -- BCMstr |
| c = jutil.funck(func, -d-1) |
| elseif mc == 5*128 then -- BCMuv |
| c = jutil.funcuvname(func, d) |
| end |
| -- Convert version-specific opcode to string |
| op = 6*op |
| op = string.sub(vmdef.bcnames, op+1, op+6):match('[^%s]+') |
| return pc, op, a, b, c, d |
| end |
| |
| -- Decoder closure |
| local function decoder(func) |
| local pc = 0 |
| return function () |
| pc = pc + 1 |
| return decode_ins(func, pc) |
| end |
| end |
| |
| -- Hexdump generated code |
| local function dump(func) |
| return require('jit.bc').dump(func) |
| end |
| |
| return { |
| decode = decode_ins, |
| decoder = decoder, |
| dump = dump, |
| funcinfo = function (...) return jutil.funcinfo(...) end, |
| } |