Lua 5.3 Assembler/Disassembler, Analyzer and Binary Plugin (#3836) (#7197)

* Added Lua 5.3 Assembly and Disassembly
* Implemented Lua 5.3 Binary Analyzer #3836
* removed unnecesasry prints for lua implementation #3836

* implemented caching for parsing the lua-file #3836 grouped global data together
* added mnemonics to analyzer and fixed a wrong instructionname
* replaced llx and llu with PFMT64x
* removed trailing whitespaces from lua 5.3 assembler and binary analyzer
* made all functions in lua53 plugins that are possible static
This commit is contained in:
Cararasu 2017-04-03 11:59:17 +02:00 committed by radare
parent 59158d01fe
commit 16c2fd2fe4
17 changed files with 1716 additions and 4 deletions

View File

@ -0,0 +1,392 @@
#include <r_types.h>
#ifdef LUA_DEBUG
#define Dprintf(...) eprintf(__VA_ARGS__)
#else
#define Dprintf(...)
#endif
struct{
int intSize;
int sizeSize;
int instructionSize;
int luaIntSize;
int luaNumberSize;
RList* functionList;
} lua53_data;
static ut64 parseNumber(const ut8* data, ut64 bytesize){
int i;
ut64 res = 0;
for(i = 0; i < bytesize;i++){
res |= ((ut64)data[i]) << (8*i);
}
return res;
}
#define parseInt(data) parseNumber(data, lua53_data.intSize)
#define parseSize(data) parseNumber(data, lua53_data.sizeSize)
#define parseInstruction(data) parseNumber(data, lua53_data.instructionSize)
#define parseLuaInt(data) parseNumber(data, lua53_data.luaIntSize)
#define parseLuaNumber(data) parseNumber(data, lua53_data.luaNumberSize)
typedef struct lua_function{
ut64 offset;
char* name_ptr;//only valid in onFunction methon
ut64 name_size;
ut64 lineDefined;
ut64 lastLineDefined;
ut8 numParams;
ut8 isVarArg;
ut8 maxStackSize;
struct lua_function* parent_func;//if != NULL, should always be valid
ut64 const_size;
ut64 code_size;
ut64 upvalue_size;
ut64 protos_size;
ut64 const_offset;
ut64 code_offset;
ut64 upvalue_offset;
ut64 protos_offset;
ut64 debug_offset;
ut64 size;
} LuaFunction;
RList *lua53_function_list;
struct lua_parse_struct;
typedef void (*OnFunction) (LuaFunction* function, struct lua_parse_struct* parseStruct);
typedef void (*OnString) (const ut8* data, ut64 offset, ut64 size, struct lua_parse_struct* parseStruct);
typedef void (*OnConst) (const ut8* data, ut64 offset, ut64 size, struct lua_parse_struct* parseStruct);
typedef struct lua_parse_struct{
OnString onString;
OnFunction onFunction;
OnConst onConst;
void* data;
} ParseStruct;
LuaFunction* lua53findLuaFunctionByCodeAddr(ut64 addr){
if(!lua53_data.functionList)
return NULL;
LuaFunction *function = NULL;
RListIter *iter = NULL;
r_list_foreach (lua53_data.functionList, iter, function) {
if(function->code_offset + lua53_data.intSize <= addr && addr < function->const_offset)
return function;
}
return NULL;
}
static int storeLuaFunction(LuaFunction* function){
if(!lua53_data.functionList){
lua53_data.functionList = r_list_new ();
if(!lua53_data.functionList){
return 0;
}
}
r_list_append (lua53_data.functionList,function);
return 1;
}
static LuaFunction* findLuaFunction(ut64 addr){
if(!lua53_data.functionList)
return NULL;
LuaFunction *function = NULL;
RListIter *iter = NULL;
r_list_foreach (lua53_data.functionList, iter, function) {
Dprintf ("Search 0x%"PFMT64x"\n",function->offset);
if(function->offset == addr)
return function;
}
return NULL;
}
ut64 lua53parseHeader (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
ut64 lua53parseFunction (const ut8* data, ut64 offset, const ut64 size, LuaFunction* parent_func, ParseStruct* parseStruct);
static ut64 parseString (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
static ut64 parseStringR (const ut8* data, ut64 offset, const ut64 size, char** str_ptr, ut64* str_len, ParseStruct* parseStruct);
static ut64 parseCode (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
static ut64 parseConstants (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
static ut64 parseUpvalues (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
static ut64 parseProtos (const ut8* data, ut64 offset, const ut64 size, LuaFunction* func, ParseStruct* parseStruct);
static ut64 parseDebug (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct);
ut64 lua53parseHeader(const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
if (data && offset + 16 <= size && !memcmp (data + offset, "\x1bLua", 4)) {//check the header
offset += 4;
if(data[offset + 0] != '\x53')//check version
return 0;
//skip format byte
offset += 2;
if(memcmp (data + offset, "\x19\x93\r\n\x1a\n", 6))//for version 5.3
return 0;
offset += 6;
lua53_data.intSize = data[offset + 0];
lua53_data.sizeSize = data[offset + 1];
lua53_data.instructionSize = data[offset + 2];
lua53_data.luaIntSize = data[offset + 3];
lua53_data.luaNumberSize = data[offset + 4];
Dprintf ("Int Size: %i\n",lua53_data.intSize);
Dprintf ("Size Size: %i\n",lua53_data.sizeSize);
Dprintf ("Instruction Size: %i\n",lua53_data.instructionSize);
Dprintf ("Lua Int Size: %i\n",lua53_data.luaIntSize);
Dprintf ("Lua Number Size: %i\n",lua53_data.luaNumberSize);
offset += 5;
if(offset + lua53_data.luaIntSize + lua53_data.luaNumberSize >= size)//check again the remainingsize because an int and number is appended to the header
return 0;
if(parseLuaInt (data + offset) != 0x5678)//check the appended integer
return 0;
offset += lua53_data.luaIntSize;
ut64 num = parseLuaNumber (data + offset);
if(*((double*)&num) != 370.5)//check the appended number
return 0;
offset += lua53_data.luaNumberSize;
Dprintf ("Is a Lua Binary\n");
return offset;
}
return 0;
}
ut64 lua53parseFunction (const ut8* data, ut64 offset, const ut64 size, LuaFunction* parent_func, ParseStruct* parseStruct){
Dprintf ("Function 0x%"PFMT64x"\n",offset);
LuaFunction* function = findLuaFunction (offset);
if(function){//if a function object was cached
Dprintf ("Found cached Functione: 0x%"PFMT64x"\n",function->offset);
if(parseStruct != NULL && parseStruct->onString != NULL)
parseConstants (data, function->const_offset, size, parseStruct);
parseProtos (data, function->protos_offset, size, function, parseStruct);
if(parseStruct != NULL && parseStruct->onString != NULL)
parseDebug (data, function->debug_offset, size, parseStruct);
if(parseStruct != NULL && parseStruct->onFunction != NULL)
parseStruct->onFunction (function, parseStruct);
return offset + function->size;
}else{
ut64 baseoffset = offset;
function = R_NEW0 (LuaFunction);
function->parent_func = parent_func;
function->offset = offset;
offset = parseStringR (data, offset, size, &function->name_ptr, &function->name_size, parseStruct);
if(offset == 0) return 0;
function->lineDefined = parseInt (data + offset);
Dprintf ("Line Defined: %"PFMT64x"\n",function->lineDefined);
function->lastLineDefined = parseInt (data + offset + lua53_data.intSize);
Dprintf ("Last Line Defined: %"PFMT64x"\n",function->lastLineDefined);
offset += lua53_data.intSize*2;
function->numParams = data[offset + 0];
Dprintf ("Param Count: %d\n",function->numParams);
function->isVarArg = data[offset + 1];
Dprintf ("Is VarArgs: %d\n",function->isVarArg);
function->maxStackSize = data[offset + 2];
Dprintf ("Max Stack Size: %d\n",function->maxStackSize);
offset += 3;
function->code_offset = offset;
function->code_size = parseInt (data + offset);
offset = parseCode (data, offset, size, parseStruct);
if(offset == 0) return 0;
function->const_offset = offset;
function->const_size = parseInt (data + offset);
offset = parseConstants (data, offset, size, parseStruct);
if(offset == 0) return 0;
function->upvalue_offset = offset;
function->upvalue_size = parseInt (data + offset);
offset = parseUpvalues (data, offset, size, parseStruct);
if(offset == 0) return 0;
function->protos_offset = offset;
function->protos_size = parseInt (data + offset);
offset = parseProtos (data, offset, size, function, parseStruct);
if(offset == 0) return 0;
function->debug_offset = offset;
offset = parseDebug (data, offset, size, parseStruct);
if(offset == 0) return 0;
function->size = offset - baseoffset;
if(parseStruct && parseStruct->onFunction)
parseStruct->onFunction (function, parseStruct);
if(!storeLuaFunction (function)){
free (function);
}
return offset;
}
}
static ut64 parseCode(const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
if(offset + lua53_data.intSize >= size)
return 0;
ut64 length = parseInt (data + offset);
offset += lua53_data.intSize;
if(offset + length*lua53_data.instructionSize >= size)
return 0;
Dprintf ("Function has %"PFMT64x" Instructions\n",length);
return offset + length*lua53_data.instructionSize;
}
static ut64 parseConstants(const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
if(offset + lua53_data.intSize >= size)
return 0;
ut64 length = parseInt (data + offset);
offset += lua53_data.intSize;
Dprintf ("Function has %"PFMT64x" Constants\n",length);
int i;
for(i = 0;i < length; i++){
Dprintf ("%d: ",i);
ut8 type = data[offset + 0];
offset += 1;
switch(type){
case 0://Nil
Dprintf ("Nil\n");
break;
case 1://Boolean
Dprintf ("Boolean %d\n",data[offset + 0]);
offset += 1;
break;
case (3 | (0 << 4))://Number
{
#ifdef LUA_DEBUG
ut64 num = parseLuaNumber (data + offset);
Dprintf ("Number %f\n",*((double*)&num));
#endif
offset += lua53_data.luaNumberSize;
}
break;
case (3 | (1 << 4))://Integer
Dprintf ("Integer %"PFMT64x"\n",parseLuaInt (data + offset));
offset += lua53_data.luaIntSize;
break;
case (4 | (0 << 4))://Short String
case (4 | (1 << 4))://Long String
offset = parseString (data,offset,size,parseStruct);
break;
default:
Dprintf ("Invalid\n");
return 0;
}
}
return offset;
}
static ut64 parseUpvalues(const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
if(offset + lua53_data.intSize >= size)
return 0;
ut64 length = parseInt (data + offset);
offset += lua53_data.intSize;
Dprintf ("Function has %"PFMT64x" Upvalues\n",length);
int i;
for(i = 0;i < length; i++){
Dprintf ("%d: inStack: %d id: %d\n",i,data[offset + 0],data[offset + 1]);
offset += 2;
}
return offset;
}
static ut64 parseProtos(const ut8* data, ut64 offset, const ut64 size, LuaFunction* func, ParseStruct* parseStruct){
if(offset + lua53_data.intSize >= size)
return 0;
ut64 length = parseInt (data + offset);
offset += lua53_data.intSize;
Dprintf ("Function has %"PFMT64x" Prototypes\n",length);
int i;
for(i = 0;i < length; i++){
offset = lua53parseFunction (data,offset,size,func,parseStruct);
if(offset == 0)
return 0;
}
return offset;
}
static ut64 parseDebug(const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
if(offset + lua53_data.intSize >= size)
return 0;
ut64 length = parseInt (data + offset);
offset += lua53_data.intSize;
if(length != 0){
Dprintf ("Instruction-Line Mappings %"PFMT64x"\n",length);
if(offset + lua53_data.intSize * length >= size)
return 0;
int i;
for(i = 0;i < length; i++){
Dprintf ("Instruction %d Line %"PFMT64x"\n",i,parseInt (data + offset));
offset += lua53_data.intSize;
}
}
if(offset + lua53_data.intSize >= size)
return 0;
length = parseInt (data + offset);
offset += lua53_data.intSize;
if(length != 0){
Dprintf ("LiveRanges: %"PFMT64x"\n",length);
int i;
for(i = 0;i < length; i++){
Dprintf ("LiveRange %d:\n",i);
offset = parseString (data,offset,size,parseStruct);
if(offset == 0) return 0;
#ifdef LUA_DEBUG
ut64 num1 = parseInt (data + offset);
#endif
offset += lua53_data.intSize;
#ifdef LUA_DEBUG
ut64 num2 = parseInt (data + offset);
#endif
offset += lua53_data.intSize;
}
}
if(offset + lua53_data.intSize >= size)
return 0;
length = parseInt (data + offset);
offset += lua53_data.intSize;
if(length != 0){
Dprintf ("Up-Values: %"PFMT64x"\n",length);
int i;
for(i = 0;i < length; i++){
Dprintf ("Up-Value %d:\n",i);
offset = parseString (data,offset,size,parseStruct);
if(offset == 0) return 0;
}
}
return offset;
}
static ut64 parseString (const ut8* data, ut64 offset, const ut64 size, ParseStruct* parseStruct){
return parseStringR (data,offset,size,0,0,parseStruct);
}
static ut64 parseStringR (const ut8* data, ut64 offset, const ut64 size, char** str_ptr, ut64* str_len, ParseStruct* parseStruct){
ut64 functionNameSize = data[offset + 0];
offset += 1;
if(functionNameSize == 0xFF){
functionNameSize = parseSize(data + offset);
offset += lua53_data.sizeSize;
}
if(functionNameSize != 0){
if(str_ptr)
*str_ptr = (char*)data + offset;
if(str_len)
*str_len = functionNameSize - 1;
if(parseStruct && parseStruct->onString)
parseStruct->onString (data, offset, functionNameSize - 1, parseStruct);
Dprintf ("String %.*s\n",(int)(functionNameSize - 1),data + offset);
offset += functionNameSize - 1;
}
return offset;
}

View File

@ -12,7 +12,7 @@ all: ${ALL_TARGETS} ;
ALL_TARGETS=
# TODO: rename to enabled plugins
ARCHS=null.mk x86_udis.mk ppc_gnu.mk ppc_cs.mk arm_gnu.mk avr.mk xap.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk cr16.mk v850.mk msp430.mk sparc_gnu.mk sparc_cs.mk x86_cs.mk cris.mk 6502.mk snes.mk riscv.mk vax.mk xtensa.mk rsp.mk
ARCHS=null.mk x86_udis.mk ppc_gnu.mk ppc_cs.mk arm_gnu.mk avr.mk xap.mk dalvik.mk sh.mk ebc.mk gb.mk malbolge.mk ws.mk h8300.mk cr16.mk v850.mk msp430.mk sparc_gnu.mk sparc_cs.mk x86_cs.mk cris.mk 6502.mk snes.mk riscv.mk vax.mk xtensa.mk rsp.mk lua53.mk
include $(ARCHS)
clean:

223
libr/anal/p/anal_lua53.c Normal file
View File

@ -0,0 +1,223 @@
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_anal.h>
#include "../../asm/arch/lua53/lua53.c"
#include "../arch/lua53/lua53_parser.c"
static int lua53_anal_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
if (!op) return 0;
memset (op, 0, sizeof (RAnalOp));
const ut32 instruction = getInstruction (data);
ut32 extraArg = 0;
op->addr = addr;
op->size = 4;
op->type = R_ANAL_OP_TYPE_UNK;
op->eob = false;
if(GET_OPCODE (instruction) > OP_EXTRAARG)
return op->size;
op->mnemonic = strdup(instruction_names[GET_OPCODE (instruction)]);
switch( GET_OPCODE (instruction) ){
case OP_MOVE:/* A B R(A) := R(B) */
op->type = R_ANAL_OP_TYPE_MOV;
break;
case OP_LOADK:/* A Bx R(A) := Kst(Bx) */
op->type = R_ANAL_OP_TYPE_LOAD;
break;
case OP_LOADKX:/* A R(A) := Kst(extra arg) */
op->type = R_ANAL_OP_TYPE_LOAD;
extraArg = getInstruction (data + 4);
if(GET_OPCODE (extraArg) == OP_EXTRAARG){
op->size = 8;
}
break;
case OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */
op->type = R_ANAL_OP_TYPE_CJMP;
op->val = !!GETARG_B (instruction);
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_LOADNIL:/* A B R(A), R(A+1), ..., R(A+B) := nil */
break;
case OP_GETUPVAL:/* A B R(A) := UpValue[B] */
case OP_GETTABUP:/* A B C R(A) := UpValue[B][RK(C)] */
op->type = R_ANAL_OP_TYPE_LOAD;
break;
case OP_GETTABLE:/* A B C R(A) := R(B)[RK(C)] */
break;
case OP_SETTABUP:/* A B C UpValue[A][RK(B)] := RK(C) */
case OP_SETUPVAL:/* A B UpValue[B] := R(A) */
op->type = R_ANAL_OP_TYPE_STORE;
break;
case OP_SETTABLE:/* A B C R(A)[RK(B)] := RK(C) */
break;
case OP_NEWTABLE:/* A B C R(A) := {} (size = B,C) */
op->type = R_ANAL_OP_TYPE_NEW;
break;
case OP_SELF:/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
break;
case OP_ADD:/* A B C R(A) := RK(B) + RK(C) */
op->type = R_ANAL_OP_TYPE_ADD;
break;
case OP_SUB:/* A B C R(A) := RK(B) - RK(C) */
op->type = R_ANAL_OP_TYPE_SUB;
break;
case OP_MUL:/* A B C R(A) := RK(B) * RK(C) */
op->type = R_ANAL_OP_TYPE_MUL;
break;
case OP_MOD:/* A B C R(A) := RK(B) % RK(C) */
op->type = R_ANAL_OP_TYPE_MOD;
break;
case OP_POW:/* A B C R(A) := RK(B) ^ RK(C) */
break;
case OP_DIV:/* A B C R(A) := RK(B) / RK(C) */
op->type = R_ANAL_OP_TYPE_DIV;
break;
case OP_IDIV:/* A B C R(A) := RK(B) // RK(C) */
op->type = R_ANAL_OP_TYPE_DIV;
break;
case OP_BAND:/* A B C R(A) := RK(B) & RK(C) */
op->type = R_ANAL_OP_TYPE_AND;
break;
case OP_BOR:/* A B C R(A) := RK(B) | RK(C) */
op->type = R_ANAL_OP_TYPE_OR;
break;
case OP_BXOR:/* A B C R(A) := RK(B) ~ RK(C) */
op->type = R_ANAL_OP_TYPE_XOR;
break;
case OP_SHL:/* A B C R(A) := RK(B) << RK(C) */
op->type = R_ANAL_OP_TYPE_SHL;
break;
case OP_SHR:/* A B C R(A) := RK(B) >> RK(C) */
op->type = R_ANAL_OP_TYPE_SHR;
break;
case OP_UNM:/* A B R(A) := -R(B) */
break;
case OP_BNOT:/* A B R(A) := ~R(B) */
op->type = R_ANAL_OP_TYPE_CPL;
break;
case OP_NOT:/* A B R(A) := not R(B) */
op->type = R_ANAL_OP_TYPE_NOT;
break;
case OP_LEN:/* A B R(A) := length of R(B) */
break;
case OP_CONCAT:/* A B C R(A) := R(B).. ... ..R(C) */
break;
case OP_JMP:/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 4*(GETARG_sBx (instruction));
op->fail = op->addr + 4;
break;
case OP_EQ:/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_LT:/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_LE:/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_TEST:/* A C if not (R(A) <=> C) then pc++ */
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_TESTSET:/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
op->type = R_ANAL_OP_TYPE_CMOV;
op->jump = op->addr + 8;
op->fail = op->addr + 4;
break;
case OP_CALL:/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
op->type = R_ANAL_OP_TYPE_RCALL;
break;
case OP_TAILCALL:/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
op->type = R_ANAL_OP_TYPE_RCALL;
op->type2 = R_ANAL_OP_TYPE_RET;
op->eob = true;
op->stackop = R_ANAL_STACK_INC;
op->stackptr = -4;
break;
case OP_RETURN:/* A B return R(A), ... ,R(A+B-2) (see note) */
op->type = R_ANAL_OP_TYPE_RET;
op->eob = true;
op->stackop = R_ANAL_STACK_INC;
op->stackptr = -4;
break;
case OP_FORLOOP:/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 4 + 4*(GETARG_sBx (instruction));
op->fail = op->addr + 4;
break;
case OP_FORPREP:/* A sBx R(A)-=R(A+2); pc+=sBx */
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = op->addr + 4 + 4*(GETARG_sBx (instruction));
op->fail = op->addr + 4;
break;
case OP_TFORCALL:/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
op->type = R_ANAL_OP_TYPE_RCALL;
break;
case OP_TFORLOOP:/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = op->addr + 4 + 4*(GETARG_sBx (instruction));
op->fail = op->addr + 4;
break;
case OP_SETLIST:/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
op->type = R_ANAL_OP_TYPE_STORE;
break;
case OP_CLOSURE:/* A Bx R(A) := closure(KPROTO[Bx]) */
case OP_VARARG:/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
case OP_EXTRAARG:/* Ax extra (larger) argument for previous opcode */
break;
}
return op->size;
}
static int lua53_anal_fcn(RAnal *a, RAnalFunction *fcn, ut64 addr, const ut8 *data, int len, int reftype){
Dprintf ("Analyze Function: 0x%"PFMT64x"\n",addr);
LuaFunction* function = lua53findLuaFunctionByCodeAddr (addr);
if(function){
fcn->maxstack = function->maxStackSize;
fcn->nargs = function->numParams;
}
fcn->addr = addr;
return 0;
}
static int finit(void *user) {
if(lua53_data.functionList){
r_list_free (lua53_data.functionList);
lua53_data.functionList = 0;
}
return 0;
}
RAnalPlugin r_anal_plugin_lua53 = {
.name = "lua53",
.desc = "LUA 5.3 analysis plugin",
.arch = "lua53",
.license = "MIT",
.bits = 32,
.desc = "LUA 5.3 VM code analysis plugin",
.op = &lua53_anal_op,
.fcn = &lua53_anal_fcn,
.esil = false,
.fini = &finit,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_lua53,
.version = R2_VERSION
};
#endif

12
libr/anal/p/lua53.mk Normal file
View File

@ -0,0 +1,12 @@
OBJ_LUA53=anal_lua53.o
include $(CURDIR)capstone.mk
STATIC_OBJ+=$(OBJ_LUA53)
TARGET_LUA53=anal_lua53.${EXT_SO}
ALL_TARGETS+=${TARGET_LUA53}
${TARGET_LUA53}: ${OBJ_LUA53}
${CC} ${CFLAGS} $(call libname,anal_lua53) $(CS_CFLAGS) \
-o anal_LUA53.${EXT_SO} ${OBJ_LUA53} $(CS_LDFLAGS)

415
libr/asm/arch/lua53/lua53.c Normal file
View File

@ -0,0 +1,415 @@
#include <r_asm.h>
#include <stdio.h>
#include "lua53.h"
#define isAlpha(x) (('a' <= (x) && 'z' >= (x)) || ('A' <= (x) && 'Z' >= (x)))
#define isNumeric(x) ('0' <= (x) && '9' >= (x))
#define isWhitespace(x) (' ' == (x) || '\t' == (x))
#define isComment(x) (';' == (x))
#ifdef LUA_DEBUG
#define Dprintf(...) printf(__VA_ARGS__)
#else
#define Dprintf(...)
#endif
#define doParse0(inc,func,str) {\
int temp = func(str + inc);\
if(temp < 0) {\
Dprintf ("%i from %s in String %s\n",temp,#func,str + inc);\
return -1;\
}\
inc += temp; \
}
#define doParse1(inc,func,str,...) {\
int temp = func(str + inc,__VA_ARGS__);\
if(temp < 0) {\
Dprintf ("%i from %s in String %s\n",temp,#func,str + inc);\
return -1;\
}\
inc += temp; \
}
typedef enum {
PARAMETER_A,
PARAMETER_B,
PARAMETER_C,
PARAMETER_Ax,
PARAMETER_Bx,
PARAMETER_sBx
}Parameter;
ut32* current_write_prt;
ut32 current_write_index;
static int findNextWordStart (const char* str);
static int parseParameters (const char* str,OpCode opCode);
static int parseParameter (const char* str,Parameter parameter);
static int parseNextInstruction (const char* str);
static int parseWhitespaces (const char* str);
const char* instruction_names[] = {
"move","loadk","loadkx","loadbool","loadnil","getupval","gettabup","gettable","settabup","setupval","settable","newtable","self","add","sub","mul","mod",
"pow","div","idiv","band","bor","bxor","shl","shr","unm","bnot","not","len","concat","jmp","eq","lt","le",
"test","testset","call","tailcall","return","forloop","forprep","tforcall","tforloop","setlist","closure","vararg","extraarg",0
};
static ut32 getInstruction (const ut8* data){
ut32 instruction = 0;
instruction |= data[3] << 24;
instruction |= data[2] << 16;
instruction |= data[1] << 8;
instruction |= data[0] << 0;
return instruction;
}
static void setInstruction (ut32 opcode,ut8* data){
data[3] = opcode >> 24;
data[2] = opcode >> 16;
data[1] = opcode >> 8;
data[0] = opcode >> 0;
}
static int findNextWordStart (const char* str){
int chars_skipped = 0;
char c;
char comment_char;
while(1){
doParse0(chars_skipped,parseWhitespaces,str);
c = str[chars_skipped];
if( isAlpha(c) || isNumeric(c) || c == '-' ){//if alphanumeric character return position
return chars_skipped;
}else if( c == ';' ){//skip comment
do{
++chars_skipped;
if( c == '\0'){
Dprintf ("Invalic Char 0x%02x\n",c);
return -1;
}
comment_char = str[chars_skipped];
}while(comment_char != '\n');//if no newline
}else if( c == '\n' ){//skip comment
++chars_skipped;
continue;
}else if( c == '\0'){
break;
}else{
Dprintf ("Invalic Char 0x%02x\n",c);
return -1;
}
}
Dprintf ("Parsed %i empty Chars\n",chars_skipped);
return chars_skipped;
}
static int parseNextInstruction (const char* str){
int chars_skipped = 0;
doParse0(chars_skipped,findNextWordStart,str);
const char* str_ptr = str + chars_skipped;
int i;
for (i = 0;instruction_names[i] != 0;++i) {//iterate over instruction strings
bool accepted = true;
int j;
for(j = 0;instruction_names[i][j] != '\0';++j){//iterate over characters
if( !((instruction_names[i][j] == str_ptr[j]) || (instruction_names[i][j] == (str_ptr[j] - 'A' + 'a'))) ){//if char or uppercase char does not match
accepted = false;
break;
}
}
if(((isWhitespace(str_ptr[j]) || isComment(str_ptr[j])) && accepted)){//if this is longest match possible
//write operation
chars_skipped += j;
Dprintf ("Opcode %i Instruction %s\n",i,instruction_names[i]);
SET_OPCODE(current_write_prt[current_write_index],i);//sets the opcode
doParse1(chars_skipped,parseParameters,str,i);//Parse parameters
++current_write_index;//finished parsing an instruction so increase index
return chars_skipped;
}
}
Dprintf ("Error\n");
return -1;
}
static int parseWhitespaces (const char* str){
int skipped_whitespace = 0;
char c = str[skipped_whitespace];
while( isWhitespace(c) ){
c = str[++skipped_whitespace];
}
Dprintf ("Parsed %i Whitespaces\n",skipped_whitespace);
return skipped_whitespace;
}
static int parseParameters (const char* str,OpCode opCode){
int chars_skipped = 0;
doParse0(chars_skipped,parseWhitespaces,str);
switch(opCode){
case OP_LOADKX:/* A R(A) := Kst(extra arg) */
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
break;
case OP_MOVE:/* A B R(A) := R(B) */
case OP_LOADNIL:/* A B R(A), R(A+1), ..., R(A+B) := nil */
case OP_GETUPVAL:/* A B R(A) := UpValue[B] */
case OP_SETUPVAL:/* A B UpValue[B] := R(A) */
case OP_UNM:/* A B R(A) := -R(B) */
case OP_BNOT:/* A B R(A) := ~R(B) */
case OP_NOT:/* A B R(A) := not R(B) */
case OP_LEN:/* A B R(A) := length of R(B) */
case OP_RETURN:/* A B return R(A), ... ,R(A+B-2) (see note) */
case OP_VARARG:/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
doParse1(chars_skipped,parseParameter,str,PARAMETER_B);
break;
case OP_TEST:/* A C if not (R(A) <=> C) then pc++ */
case OP_TFORCALL:/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
doParse1(chars_skipped,parseParameter,str,PARAMETER_C);
break;
case OP_LOADK:/* A Bx R(A) := Kst(Bx) */
case OP_CLOSURE:/* A Bx R(A) := closure(KPROTO[Bx]) */
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
doParse1(chars_skipped,parseParameter,str,PARAMETER_Bx);
break;
case OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */
case OP_GETTABUP:/* A B C R(A) := UpValue[B][RK(C)] */
case OP_GETTABLE:/* A B C R(A) := R(B)[RK(C)] */
case OP_SETTABUP:/* A B C UpValue[A][RK(B)] := RK(C) */
case OP_SETTABLE:/* A B C R(A)[RK(B)] := RK(C) */
case OP_NEWTABLE:/* A B C R(A) := {} (size = B,C) */
case OP_SELF:/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
case OP_ADD:/* A B C R(A) := RK(B) + RK(C) */
case OP_SUB:/* A B C R(A) := RK(B) - RK(C) */
case OP_MUL:/* A B C R(A) := RK(B) * RK(C) */
case OP_MOD:/* A B C R(A) := RK(B) % RK(C) */
case OP_POW:/* A B C R(A) := RK(B) ^ RK(C) */
case OP_DIV:/* A B C R(A) := RK(B) / RK(C) */
case OP_IDIV:/* A B C R(A) := RK(B) // RK(C) */
case OP_BAND:/* A B C R(A) := RK(B) & RK(C) */
case OP_BOR:/* A B C R(A) := RK(B) | RK(C) */
case OP_BXOR:/* A B C R(A) := RK(B) ~ RK(C) */
case OP_SHL:/* A B C R(A) := RK(B) << RK(C) */
case OP_SHR:/* A B C R(A) := RK(B) >> RK(C) */
case OP_CONCAT:/* A B C R(A) := R(B).. ... ..R(C) */
case OP_EQ:/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case OP_LT:/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case OP_LE:/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
case OP_TESTSET:/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
case OP_CALL:/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
case OP_TAILCALL:/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
case OP_SETLIST:/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
doParse1(chars_skipped,parseParameter,str,PARAMETER_B);
doParse1(chars_skipped,parseParameter,str,PARAMETER_C);
break;
case OP_JMP:/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
case OP_FORLOOP:/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
case OP_FORPREP:/* A sBx R(A)-=R(A+2); pc+=sBx */
case OP_TFORLOOP:/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
doParse1(chars_skipped,parseParameter,str,PARAMETER_A);
doParse1(chars_skipped,parseParameter,str,PARAMETER_sBx);
break;
case OP_EXTRAARG:/* Ax extra (larger) argument for previous opcode */
doParse1(chars_skipped,parseParameter,str,PARAMETER_Ax);
break;
}
return chars_skipped;
}
static int parseParameter (const char* str,Parameter parameter){
int skipped_chars = findNextWordStart (str);
int resultingNumber = 0;
bool negative = false;
if(str[skipped_chars] == '-'){
negative = true;
++skipped_chars;
}
char c = str[skipped_chars];
if( !isNumeric(c) ){
return -1;
}
while( isNumeric(c) ){
resultingNumber *= 10;
resultingNumber += c - '0';
c = str[++skipped_chars];
}
resultingNumber = negative ? resultingNumber*(-1) : resultingNumber;
Dprintf ("Parsed Parameter %i\n",resultingNumber);
if(parameter != PARAMETER_sBx && resultingNumber < 0){
return -1;
}
switch(parameter){
case PARAMETER_A:
SETARG_A(current_write_prt[current_write_index],resultingNumber);
break;
case PARAMETER_B:
SETARG_B(current_write_prt[current_write_index],resultingNumber);
break;
case PARAMETER_C:
SETARG_C(current_write_prt[current_write_index],resultingNumber);
break;
case PARAMETER_Ax:
SETARG_Ax(current_write_prt[current_write_index],resultingNumber);
break;
case PARAMETER_Bx:
SETARG_Bx(current_write_prt[current_write_index],resultingNumber);
break;
case PARAMETER_sBx:
SETARG_sBx(current_write_prt[current_write_index],resultingNumber);
break;
break;
}
return skipped_chars;
}
int lua53asm (RAsmOp *op, const char *s){
int parsed = 0;
Dprintf ("%s\n",s);
ut32 instruction;
current_write_prt = &instruction;
current_write_index = 0;
doParse0 (parsed,parseNextInstruction,s);
setInstruction (instruction,op->buf);
Dprintf ("%d\n",parsed);
Dprintf ("%08x\n",instruction);
return 4;
}
int lua53dissasm (RAsmOp *op, const ut8 *buf, int len){
ut32 instruction = 0;
if(len < 4)
return 0;
instruction = getInstruction (buf);
OpCode operator = GET_OPCODE (instruction);
Dprintf ("Parse Bytes %08x\n",((ut32*)buf)[0]);
switch(operator){
case OP_LOADKX:/* A R(A) := Kst(extra arg) */
sprintf (op->buf_asm, "%s %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction));
break;
case OP_MOVE:/* A B R(A) := R(B) */
case OP_LOADNIL:/* A B R(A), R(A+1), ..., R(A+B) := nil */
case OP_GETUPVAL:/* A B R(A) := UpValue[B] */
case OP_SETUPVAL:/* A B UpValue[B] := R(A) */
case OP_UNM:/* A B R(A) := -R(B) */
case OP_BNOT:/* A B R(A) := ~R(B) */
case OP_NOT:/* A B R(A) := not R(B) */
case OP_LEN:/* A B R(A) := length of R(B) */
case OP_RETURN:/* A B return R(A), ... ,R(A+B-2) (see note) */
case OP_VARARG:/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
sprintf (op->buf_asm, "%s %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction));
break;
case OP_TEST:/* A C if not (R(A) <=> C) then pc++ */
case OP_TFORCALL:/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
sprintf (op->buf_asm, "%s %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_C(instruction));
break;
case OP_LOADK:/* A Bx R(A) := Kst(Bx) */
sprintf (op->buf_asm, "%s %i Kst(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_Bx(instruction));
break;
case OP_CLOSURE:/* A Bx R(A) := closure(KPROTO[Bx]) */
sprintf (op->buf_asm, "%s %i KPROTO(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_Bx(instruction));
break;
case OP_LOADBOOL:/* A B C R(A) := (Bool)B; if (C) pc++ */
case OP_NEWTABLE:/* A B C R(A) := {} (size = B,C) */
case OP_CONCAT:/* A B C R(A) := R(B).. ... ..R(C) */
case OP_TESTSET:/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
case OP_CALL:/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
case OP_TAILCALL:/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
case OP_SETLIST:/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
sprintf (op->buf_asm, "%s %i %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction),GETARG_C(instruction));
break;
case OP_SELF:/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
case OP_GETTABUP:/* A B C R(A) := UpValue[B][RK(C)] */
case OP_GETTABLE:/* A B C R(A) := R(B)[RK(C)] */
if(GETARG_C(instruction) & 0x100)
sprintf (op->buf_asm, "%s %i %i K(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction),GETARG_C(instruction) & 0xFF);
else
sprintf (op->buf_asm, "%s %i %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction),GETARG_C(instruction));
break;
case OP_SETTABUP:/* A B C UpValue[A][RK(B)] := RK(C) */
case OP_SETTABLE:/* A B C R(A)[RK(B)] := RK(C) */
case OP_ADD:/* A B C R(A) := RK(B) + RK(C) */
case OP_SUB:/* A B C R(A) := RK(B) - RK(C) */
case OP_MUL:/* A B C R(A) := RK(B) * RK(C) */
case OP_MOD:/* A B C R(A) := RK(B) % RK(C) */
case OP_POW:/* A B C R(A) := RK(B) ^ RK(C) */
case OP_DIV:/* A B C R(A) := RK(B) / RK(C) */
case OP_IDIV:/* A B C R(A) := RK(B) // RK(C) */
case OP_BAND:/* A B C R(A) := RK(B) & RK(C) */
case OP_BOR:/* A B C R(A) := RK(B) | RK(C) */
case OP_BXOR:/* A B C R(A) := RK(B) ~ RK(C) */
case OP_SHL:/* A B C R(A) := RK(B) << RK(C) */
case OP_SHR:/* A B C R(A) := RK(B) >> RK(C) */
case OP_EQ:/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
case OP_LT:/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
case OP_LE:/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
if(GETARG_B(instruction) & 0x100){
if(GETARG_C(instruction) & 0x100)
sprintf (op->buf_asm, "%s %i K(%i) K(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction) & 0xFF,GETARG_C(instruction) & 0xFF);
else
sprintf (op->buf_asm, "%s %i K(%i) %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction) & 0xFF,GETARG_C(instruction));
}else{
if(GETARG_C(instruction) & 0x100)
sprintf (op->buf_asm, "%s %i %i K(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction),GETARG_C(instruction) & 0xFF);
else
sprintf (op->buf_asm, "%s %i %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_B(instruction),GETARG_C(instruction));
}
break;
case OP_JMP:/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
case OP_FORLOOP:/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
case OP_FORPREP:/* A sBx R(A)-=R(A+2); pc+=sBx */
case OP_TFORLOOP:/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
sprintf (op->buf_asm, "%s %i %i", instruction_names[GET_OPCODE(instruction)], GETARG_A(instruction),GETARG_sBx(instruction));
break;
case OP_EXTRAARG:/* Ax extra (larger) argument for previous opcode */
sprintf (op->buf_asm, "%s Kst(%i)", instruction_names[GET_OPCODE(instruction)], GETARG_Ax(instruction));
break;
}
return 4;
}
#ifdef MAIN_ASM
int main (int argc, char **argv) {
char *c = "move 1 2\n forprep 13 -2";
int p = 0;
current_write_prt = malloc(8);
current_write_index = 0;
Dprintf ("Parsing String: %s\n",c);
Dprintf ("-----------------------\n");
doParse0(p,parseNextInstruction,c,(int)strlen(c));
Dprintf ("Parsed Characters %i\n",p);
Dprintf ("%d %08x\n", current_write_index, current_write_prt[current_write_index-1]);
Dprintf ("------------\n");
doParse0(p,parseNextInstruction,c,(int)strlen(c));
Dprintf ("Parsed Characters %i\n",p);
Dprintf ("%d %08x\n", current_write_index, current_write_prt[current_write_index-1]);
Dprintf ("------------\n");
RAsmOp* asmOp = (RAsmOp*) malloc(sizeof(RAsmOp));
int advanced = lua53dissasm (asmOp,(const char *)current_write_prt,4);
Dprintf ("%s\n",asmOp->buf_asm);
lua53dissasm (asmOp,(const char *)current_write_prt + advanced,4);
Dprintf ("%s\n",asmOp->buf_asm);
free(current_write_prt);
return 0;
}
#endif //MAIN_ASM

230
libr/asm/arch/lua53/lua53.h Normal file
View File

@ -0,0 +1,230 @@
/*
** $Id: lopcodes.h,v 1.149 2016/07/19 17:12:21 roberto Exp $
** Opcodes for Lua virtual machine
*/
/******************************************************************************
* Copyright (C) 1994-2017 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#ifndef lopcodes_h
#define lopcodes_h
#include <limits.h>
#include <stddef.h>
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
'A' : 8 bits
'B' : 9 bits
'C' : 9 bits
'Ax' : 26 bits ('A', 'B', and 'C' together)
'Bx' : 18 bits ('B' and 'C' together)
'sBx' : signed Bx
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
===========================================================================*/
enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
#define cast(x,y) ((x)y)
/*
** size and position of opcode arguments.
*/
#define SIZE_C 9
#define SIZE_B 9
#define SIZE_Bx (SIZE_C + SIZE_B)
#define SIZE_A 8
#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A)
#define SIZE_OP 6
#define POS_OP 0
#define POS_A (POS_OP + SIZE_OP)
#define POS_C (POS_A + SIZE_A)
#define POS_B (POS_C + SIZE_C)
#define POS_Bx POS_C
#define POS_Ax POS_A
#define MAX_INT INT_MAX /* maximum value of an int */
#define LUAI_BITSINT 32
/*
** limits for opcode arguments.
** we use (signed) int to manipulate most arguments,
** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)
*/
#if SIZE_Bx < LUAI_BITSINT-1
#define MAXARG_Bx ((1<<SIZE_Bx)-1)
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
#else
#define MAXARG_Bx MAX_INT
#define MAXARG_sBx MAX_INT
#endif
#if SIZE_Ax < LUAI_BITSINT-1
#define MAXARG_Ax ((1<<SIZE_Ax)-1)
#else
#define MAXARG_Ax MAX_INT
#endif
#define MAXARG_A ((1<<SIZE_A)-1)
#define MAXARG_B ((1<<SIZE_B)-1)
#define MAXARG_C ((1<<SIZE_C)-1)
/* creates a mask with 'n' 1 bits at position 'p' */
#define MASK1(n,p) ((~((~0)<<(n)))<<(p))
/* creates a mask with 'n' 0 bits at position 'p' */
#define MASK0(n,p) (~MASK1(n,p))
static ut32 getInstruction(const ut8* data);
static void setInstruction(ut32 opcode, ut8* data);
/*
** the following macros help to manipulate instructions
*/
#define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))
#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \
((cast(ut32, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))
#define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0)))
#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \
((cast(ut32, v)<<pos)&MASK1(size,pos))))
#define GETARG_A(i) getarg(i, POS_A, SIZE_A)
#define SETARG_A(i,v) setarg(i, v, POS_A, SIZE_A)
#define GETARG_B(i) getarg(i, POS_B, SIZE_B)
#define SETARG_B(i,v) setarg(i, v, POS_B, SIZE_B)
#define GETARG_C(i) getarg(i, POS_C, SIZE_C)
#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
#define GETARG_Bx(i) getarg(i, POS_Bx, SIZE_Bx)
#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
#define GETARG_Ax(i) getarg(i, POS_Ax, SIZE_Ax)
#define SETARG_Ax(i,v) setarg(i, v, POS_Ax, SIZE_Ax)
#define GETARG_sBx(i) (GETARG_Bx(i)-MAXARG_sBx)
#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
#define CREATE_ABC(o,a,b,c) ((cast(ut32, o)<<POS_OP) \
| (cast(ut32, a)<<POS_A) \
| (cast(ut32, b)<<POS_B) \
| (cast(ut32, c)<<POS_C))
#define CREATE_ABx(o,a,bc) ((cast(ut32, o)<<POS_OP) \
| (cast(ut32, a)<<POS_A) \
| (cast(ut32, bc)<<POS_Bx))
#define CREATE_Ax(o,a) ((cast(ut32)<<POS_OP) \
| (cast(ut32, a)<<POS_Ax))
typedef enum {
/*----------------------------------------------------------------------
name args description
------------------------------------------------------------------------*/
OP_MOVE,/* A B R(A) := R(B) */
OP_LOADK,/* A Bx R(A) := Kst(Bx) */
OP_LOADKX,/* A R(A) := Kst(extra arg) */
OP_LOADBOOL,/* A B C R(A) := (Bool)B; if (C) pc++ */
OP_LOADNIL,/* A B R(A), R(A+1), ..., R(A+B) := nil */
OP_GETUPVAL,/* A B R(A) := UpValue[B] */
OP_GETTABUP,/* A B C R(A) := UpValue[B][RK(C)] */
OP_GETTABLE,/* A B C R(A) := R(B)[RK(C)] */
OP_SETTABUP,/* A B C UpValue[A][RK(B)] := RK(C) */
OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */
OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
OP_ADD,/* A B C R(A) := RK(B) + RK(C) */
OP_SUB,/* A B C R(A) := RK(B) - RK(C) */
OP_MUL,/* A B C R(A) := RK(B) * RK(C) */
OP_MOD,/* A B C R(A) := RK(B) % RK(C) */
OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */
OP_DIV,/* A B C R(A) := RK(B) / RK(C) */
OP_IDIV,/* A B C R(A) := RK(B) // RK(C) */
OP_BAND,/* A B C R(A) := RK(B) & RK(C) */
OP_BOR,/* A B C R(A) := RK(B) | RK(C) */
OP_BXOR,/* A B C R(A) := RK(B) ~ RK(C) */
OP_SHL,/* A B C R(A) := RK(B) << RK(C) */
OP_SHR,/* A B C R(A) := RK(B) >> RK(C) */
OP_UNM,/* A B R(A) := -R(B) */
OP_BNOT,/* A B R(A) := ~R(B) */
OP_NOT,/* A B R(A) := not R(B) */
OP_LEN,/* A B R(A) := length of R(B) */
OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
OP_TEST,/* A C if not (R(A) <=> C) then pc++ */
OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */
OP_FORLOOP,/* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
OP_FORPREP,/* A sBx R(A)-=R(A+2); pc+=sBx */
OP_TFORCALL,/* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
OP_TFORLOOP,/* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx }*/
OP_SETLIST,/* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx]) */
OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
} OpCode;
#endif

47
libr/asm/d/lua53 Normal file
View File

@ -0,0 +1,47 @@
move=moves value from a register to a registers
loadk=loads a constant value
loadkx=loads an extended constant value
loadbool=loads a bool value
loadnil=loads nil
getupval=gets an upvalue
gettabup=gets a value from a tabular upvalue
gettable=gets a value from a table
setupval=sets an upvalue
settabup=sets a value from a tabular upvalue
settable=sets a value from a table
newtable=creates a new table
self=gets a value from the table and saves the table
add=adds two registers
sub=subtracts two registers
mul=multiplies two register
mod=modulo of two registers
pow=exponentiates two registers
div=division of two registers
idiv=integer division of two registers
band=boolean and of two registers
bor=boolean or of two registers
bxor=boolean xor of two registers
shl=shift left of two registers
shr=shift right of two registers
unm=negates a register
bnot=boolean not of a registers
not=not of a registers
len=length of a registers
concat=concat of multiple registers
jmp=relative jump
eq=skip if not equals
lt=skip if lower than
le=skip if lower equals
test=skip if register equals to value
testset=set if register equal to value
call=calls a function
tailcall=calls a function and returns
return=return of a function
forloop=for loop header
forprep=prepares a for loop
tforcall=calls an iterator function
tforloop=generic for loop head
setlist=sets multiple consecutive fields of a table
closure=creates an instance of a function
vararg=copies a variable number of arguments into registers
extraarg=an extra large argument for loadk

View File

@ -17,7 +17,7 @@ ARCHS+=x86_as.mk x86_nz.mk cris_gnu.mk vax.mk
ARCHS+=ppc_gnu.mk ppc_cs.mk x86_udis.mk xap.mk x86_nasm.mk avr.mk
ARCHS+=sh.mk arm_winedbg.mk tms320.mk gb.mk snes.mk ebc.mk malbolge.mk ws.mk
ARCHS+=6502.mk h8300.mk cr16.mk v850.mk spc700.mk propeller.mk msp430.mk i4004.mk
ARCHS+=lh5801.mk v810.mk mcs96.mk lm32.mk
ARCHS+=lh5801.mk v810.mk mcs96.mk lm32.mk lua53.mk
ARCHS+=riscv.mk rsp.mk
include $(ARCHS)

35
libr/asm/p/asm_lua53.c Normal file
View File

@ -0,0 +1,35 @@
/* radare - LGPL - Copyright 2012-2013 - pancake */
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_asm.h>
#include "../arch/lua53/lua53.c"
static int do_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
return op->size = lua53dissasm (op, buf, len);
}
static int do_assemble(RAsm *a, RAsmOp *op, const char *buf) {
return op->size = lua53asm (op, buf);
}
RAsmPlugin r_asm_plugin_lua53 = {
.name = "lua53",
.desc = "Lua 5.3 VM assembly plugin",
.license = "MIT",
.arch = "lua53",
.bits = 32,
.endian = R_SYS_ENDIAN_LITTLE,
.disassemble = &do_disassemble,
.assemble = &do_assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_lua53,
.version = R2_VERSION
};
#endif

11
libr/asm/p/lua53.mk Normal file
View File

@ -0,0 +1,11 @@
OBJ_LUA53=asm_lua53.o
STATIC_OBJ+=${OBJ_LUA53}
TARGET_LUA53=asm_lua53.${EXT_SO}
ifeq ($(WITHPIC),1)
ALL_TARGETS+=${TARGET_LUA53}
${TARGET_LUA53}: ${OBJ_LUA53}
${CC} $(call libname,asm_lua53) ${LDFLAGS} ${CFLAGS} -o ${TARGET_LUA53} ${OBJ_LUA53}
endif

View File

@ -14,7 +14,7 @@ FORMATS=any.mk elf.mk elf64.mk pe.mk pe64.mk te.mk mach0.mk
FORMATS+=bios.mk mach064.mk fatmach0.mk dyldcache.mk java.mk
FORMATS+=dex.mk fs.mk ningb.mk coff.mk ningba.mk xbe.mk zimg.mk
FORMATS+=omf.mk cgc.mk dol.mk nes.mk mbn.mk psxexe.mk spc700.mk
FORMATS+=vsf.mk nin3ds.mk xtr_dyldcache.mk bflt.mk
FORMATS+=vsf.mk nin3ds.mk xtr_dyldcache.mk bflt.mk lua53.mk
include $(FORMATS)
all: ${ALL_TARGETS}

329
libr/bin/p/bin_lua53.c Normal file
View File

@ -0,0 +1,329 @@
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>
#include "../../anal/arch/lua53/lua53_parser.c"
static bool check_bytes(const ut8 *buf, ut64 length);
static int init(void *user) {
Dprintf ("Init\n");
return 0;
}
static int finit(void *user) {
Dprintf ("FInit\n");
if(lua53_data.functionList){
r_list_free (lua53_data.functionList);
lua53_data.functionList = 0;
}
return 0;
}
static bool load(RBinFile *arch){
Dprintf ("Load\n");
const ut8 *bytes = arch? r_buf_buffer (arch->buf): NULL;
ut64 sz = arch? r_buf_size (arch->buf): 0;
return check_bytes (bytes, sz);
}
static bool check(RBinFile *arch) {
Dprintf ("Check\n");
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
return check_bytes (bytes, sz);
}
static bool check_bytes(const ut8 *buf, ut64 length) {
ParseStruct parseStruct;
ut64 parsedbytes = lua53parseHeader (buf,0,length,&parseStruct);
if(parsedbytes)
Dprintf ( "It is a Lua Binary!!!\n");
return parsedbytes != 0;
}
static void addSection (RList *list, const char *name, ut64 addr, ut32 size, bool isFunc) {
RBinSection *binSection = R_NEW0 (RBinSection);
if (!binSection) return;
strcpy (binSection->name, name);
binSection->vaddr = binSection->paddr = addr;
binSection->size = binSection->vsize = size;
binSection->add = true;
binSection->is_data = false;
binSection->bits = isFunc ? 8*lua53_data.instructionSize : 8;
binSection->has_strings = !isFunc;
binSection->arch = strdup("lua53");
if(isFunc){
binSection->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP;
}else
binSection->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_MAP;
r_list_append (list, binSection);
}
static void addSections (LuaFunction* func, ParseStruct* parseStruct){
char* string;
if(func->name_size == 0 || func->name_ptr == 0){
string = malloc (11);
sprintf (string,"0x%"PFMT64x,func->offset);
}else{
string = malloc (func->name_size + 1);
memcpy(string,func->name_ptr,func->name_size);
string[func->name_size] = '\0';
}
char string_buffer[R_BIN_SIZEOF_STRINGS + 1];
sprintf (string_buffer,"header.%s",string);
addSection (parseStruct->data,string_buffer,func->offset,func->code_offset - func->offset, false);
sprintf (string_buffer,"code.%s",string);
addSection (parseStruct->data,string_buffer,func->code_offset,func->const_offset - func->code_offset, true);//code section also holds codesize
sprintf (string_buffer,"consts.%s",string);
addSection (parseStruct->data,string_buffer,func->const_offset,func->upvalue_offset - func->const_offset, false);
sprintf (string_buffer,"upvalues.%s",string);
addSection (parseStruct->data,string_buffer,func->upvalue_offset,func->protos_offset - func->upvalue_offset, false);
sprintf (string_buffer,"debuginfo.%s",string);
addSection (parseStruct->data,string_buffer,func->debug_offset,func->offset + func->size - func->debug_offset, false);
r_str_free (string);
}
static RList* sections (RBinFile *arch) {
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
Dprintf ("Sections\n");
ParseStruct parseStruct;
memset (&parseStruct,0,sizeof(parseStruct));
parseStruct.onFunction = addSections;
parseStruct.data = r_list_newf ((RListFree)free);
if(!parseStruct.data)
return NULL;
ut64 headersize = 4 + 1 + 1 + 6 + 5 + bytes[15] + bytes[16] + 1;//header + version + format + stringterminators + sizes + integer + number + upvalues
addSection (parseStruct.data,"lua-header",0,headersize, false);
//parse functions
lua53parseFunction (bytes,headersize,sz,0,&parseStruct);
Dprintf ("End Section\n");
return parseStruct.data;
}
static void addString(const ut8 *buf, ut64 offset, ut64 length,ParseStruct* parseStruct){
RBinString* binstring = R_NEW0 (RBinString);
if(binstring == NULL)
return;
binstring->string = r_str_newlen ((char*)buf + offset,length);
binstring->vaddr = binstring->paddr = offset;
binstring->ordinal = 0;
binstring->size = length;
binstring->length = length;
r_list_append (parseStruct->data, binstring);
}
static void addSymbol (RList *list, char *name, ut64 addr, ut32 size, const char* type) {
RBinSymbol* binSymbol = R_NEW0 (RBinSymbol);
if(binSymbol == NULL)
return;
binSymbol->name = strdup (name);
binSymbol->vaddr = binSymbol->paddr = addr;
binSymbol->size = size;
binSymbol->ordinal = 0;
binSymbol->type = type;
r_list_append (list, binSymbol);
}
static void handleFuncSymbol (LuaFunction* func, ParseStruct* parseStruct){
RBinSymbol* binSymbol = R_NEW0 (RBinSymbol);
if(binSymbol == NULL)
return;
char* string;
if(!func->name_ptr || !func->name_size){
string = malloc (11);
sprintf (string,"0x%"PFMT64x,func->offset);
}else{
string = malloc (func->name_size + 1);
memcpy(string,func->name_ptr,func->name_size);
int i;
for(i = 0; i < func->name_size;i++)
if(string[i] == '@')
string[i] = '_';
string[func->name_size] = '\0';
}
char string_buffer[R_BIN_SIZEOF_STRINGS + 1];
sprintf (string_buffer,"lineDefined.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset - 3 - 2*lua53_data.intSize,lua53_data.intSize,"NUM");
sprintf (string_buffer,"lastLineDefined.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset - 3 - lua53_data.intSize,lua53_data.intSize,"NUM");
sprintf (string_buffer,"numParams.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset - 3,1,"NUM");
sprintf (string_buffer,"isVarArg.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset - 2,1,"BOOL");
sprintf (string_buffer,"maxStackSize.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset - 1,1,"BOOL");
sprintf (string_buffer,"codesize.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset,lua53_data.intSize,"NUM");
sprintf (string_buffer,"func.%s",string);
addSymbol (parseStruct->data,string_buffer,func->code_offset + lua53_data.intSize,lua53_data.instructionSize*func->code_size,"FUNC");
sprintf (string_buffer,"constsize.%s",string);
addSymbol (parseStruct->data,string_buffer,func->const_offset,lua53_data.intSize,"NUM");
sprintf (string_buffer,"upvaluesize.%s",string);
addSymbol (parseStruct->data,string_buffer,func->upvalue_offset,lua53_data.intSize,"NUM");
sprintf (string_buffer,"prototypesize.%s",string);
addSymbol (parseStruct->data,string_buffer,func->protos_offset,lua53_data.intSize,"NUM");
r_str_free (string);
}
static RList* strings(RBinFile *arch) {
Dprintf ("Strings\n");
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
ut64 headersize = 4 + 1 + 1 + 6 + 5 + bytes[15] + bytes[16] + 1;//header + version + format + stringterminators + sizes + integer + number + upvalues
ParseStruct parseStruct;
memset (&parseStruct,0,sizeof (parseStruct));
parseStruct.onString = addString;
parseStruct.data = r_list_new ();
if(!parseStruct.data)
return NULL;
lua53parseFunction (bytes,headersize,sz,0,&parseStruct);
Dprintf ("End Strings\n");
return parseStruct.data;
}
static RList* symbols(RBinFile *arch) {
Dprintf ("Symbols\n");
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
ut64 headersize = 4 + 1 + 1 + 6 + 5 + bytes[15] + bytes[16] + 1;//header + version + format + stringterminators + sizes + integer + number + upvalues
ParseStruct parseStruct;
memset (&parseStruct,0,sizeof(parseStruct));
parseStruct.onFunction = handleFuncSymbol;
parseStruct.data = NULL;
parseStruct.data = r_list_new ();
if(!parseStruct.data)
return NULL;
addSymbol (parseStruct.data,"lua-header",0,4,"NOTYPE");
addSymbol (parseStruct.data,"lua-version",4,1,"NOTYPE");
addSymbol (parseStruct.data,"lua-format",5,1,"NOTYPE");
addSymbol (parseStruct.data,"stringterminators",6,6,"NOTYPE");
addSymbol (parseStruct.data,"int-size",12,1,"NUM");
addSymbol (parseStruct.data,"size-size",13,1,"NUM");
addSymbol (parseStruct.data,"instruction-size",14,1,"NUM");
addSymbol (parseStruct.data,"lua-int-size",15,1,"NUM");
addSymbol (parseStruct.data,"lua-number-size",16,1,"NUM");
addSymbol (parseStruct.data,"check-int",17,bytes[15],"NUM");
addSymbol (parseStruct.data,"check-number",17 + bytes[15],bytes[16],"FLOAT");
addSymbol (parseStruct.data,"upvalues",17 + bytes[15] + bytes[16],1,"NUM");
lua53parseFunction (bytes,headersize,sz,0,&parseStruct);
Dprintf ("End Symbols\n");
return parseStruct.data;
}
static RBinInfo* info(RBinFile *arch) {
RBinInfo *ret = NULL;
if (!(ret = R_NEW0 (RBinInfo)))
return NULL;
ret->file = strdup (arch->file);
ret->type = strdup ("lua53");
ret->os = strdup ("any");
ret->machine = strdup ("LUA 5.3 VM");
ret->arch = strdup ("lua53");
ret->bits = lua53_data.instructionSize * 8;
ret->has_va = 1;
ret->big_endian = 0;
return ret;
}
static void addEntry (LuaFunction* func, ParseStruct* parseStruct){
if(func->parent_func == NULL){
RBinAddr *ptr = NULL;
if ((ptr = R_NEW0 (RBinAddr))) {
ptr->paddr = ptr->vaddr = func->code_offset + lua53_data.intSize;
r_list_append (parseStruct->data, ptr);
}
}
}
static RList* entries(RBinFile *arch) {
Dprintf ("Entries\n");
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
ut64 sz = arch ? r_buf_size (arch->buf): 0;
ut64 headersize = 4 + 1 + 1 + 6 + 5 + bytes[15] + bytes[16] + 1;//header + version + format + stringterminators + sizes + integer + number + upvalues
ParseStruct parseStruct;
memset (&parseStruct,0,sizeof(parseStruct));
parseStruct.onFunction = addEntry;
parseStruct.data = NULL;
parseStruct.data = r_list_new ();
if(!parseStruct.data)
return NULL;
lua53parseFunction (bytes,headersize,sz,0,&parseStruct);
Dprintf ("End Entries\n");
return parseStruct.data;
}
RBinPlugin r_bin_plugin_lua53 = {
.name = "lua53",
.desc = "LUA 5.3 bin plugin",
.license = "MIT",
.init = &init,
.fini = &finit,
.load = &load,
.sections = &sections,
.check = &check,
.check_bytes = &check_bytes,
.symbols = &symbols,
.strings = &strings,
.info = &info,
.entries = &entries,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_BIN,
.data = &r_bin_plugin_lua53,
.version = R2_VERSION
};
#endif

12
libr/bin/p/lua53.mk Normal file
View File

@ -0,0 +1,12 @@
OBJ_LUA53=bin_lua53.o
STATIC_OBJ+=${OBJ_LUA53}
TARGET_LUA53=bin_lua53.${EXT_SO}
ifeq (${WITHPIC},1)
ALL_TARGETS+=${TARGET_LUA53}
${TARGET_LUA53}: ${OBJ_LUA53}
-${CC} $(call libname,bin_lua53) -shared ${CFLAGS} \
$(OBJ_LUA53) $(LINK) $(LDFLAGS)
endif

View File

@ -1625,6 +1625,7 @@ extern RAnalPlugin r_anal_plugin_i4004;
extern RAnalPlugin r_anal_plugin_xtensa;
extern RAnalPlugin r_anal_plugin_pic18c;
extern RAnalPlugin r_anal_plugin_rsp;
extern RAnalPlugin r_anal_plugin_lua53;
#ifdef __cplusplus
}
#endif

View File

@ -246,6 +246,7 @@ extern RAsmPlugin r_asm_plugin_tricore;
extern RAsmPlugin r_asm_plugin_pic18c;
extern RAsmPlugin r_asm_plugin_rsp;
extern RAsmPlugin r_asm_plugin_wasm;
extern RAsmPlugin r_asm_plugin_lua53;
#endif

View File

@ -358,7 +358,7 @@ typedef struct r_bin_section_t {
int bits;
bool has_strings;
bool add; // indicates when you want to add the section to io `S` command
bool is_data;
bool is_data;
} RBinSection;
typedef struct r_bin_class_t {
@ -677,6 +677,7 @@ extern RBinPlugin r_bin_plugin_dyldcache;
extern RBinPlugin r_bin_plugin_avr;
extern RBinPlugin r_bin_plugin_menuet;
extern RBinPlugin r_bin_plugin_wasm;
extern RBinPlugin r_bin_plugin_lua53;
extern RBinPlugin r_bin_plugin_nro;
#ifdef __cplusplus

View File

@ -13,6 +13,7 @@ anal.gb
anal.h8300
anal.i8080
anal.java
anal.lua53
anal.m68k_cs
anal.xtensa
anal.malbolge
@ -61,6 +62,7 @@ asm.hppa_gnu
asm.i4004
asm.i8080
asm.java
asm.lua53
asm.lm32
asm.tricore
asm.xtensa
@ -116,6 +118,7 @@ bin.elf
bin.elf64
bin.fs
bin.java
bin.lua53
bin.menuet
bin.mach0
bin.mach064