LuaJit分析(三)luajit字节码文件格式

Luajit字节码文件格式的完整信息如上图所示,包括文件头Header和原型Proto,一个原型可以对应lua源码中的一个函数或源文件。
一、文件头
文件标志: 占用三个字节,始终是0x1B4C4A,表示这是一个luajit文件
版本: 占用一个字节,最新版2.1.0-beta3显示为2
**Flags标志:**占用一个字节,官方定义为:

cpp 复制代码
#define BCDUMP_F_BE   0x01
#define BCDUMP_F_STRIP    0x02
#define BCDUMP_F_FFI    0x04
#define BCDUMP_F_FR2    0x08

BE表示是否大端对齐,默认0表示小端对齐

STRIP表示是否去除调试信息,0表示没去除,包含调试信息

FFI表示是否有调用外部C函数库

FR2表示是否使用开启了FR2,64位模式编译时FR2 = 1
文件名大小(STRIP=0) :源文件名占用的字节大小
**文件名(STRIP=0):**源文件名

二、原型
1、原型头
原型大小: uleb128类型,表示整个原型占用字节大小,为0标志结束
**原型flags标志:**定义如下:

cpp 复制代码
#define PROTO_CHILD   0x01  /* Has child prototypes. */
#define PROTO_VARARG    0x02  /* Vararg function. */
#define PROTO_FFI   0x04  /* Uses BC_KCDATA for FFI datatypes. */
#define PROTO_NOJIT   0x08  /* JIT disabled for this function. */
#define PROTO_ILOOP   0x10  /* Patched bytecode with ILOOP etc. */

第一位proto_child定义是否是一个子函数,即闭包

第二位proto_vararg 函数是否返回多个值

第三位 proto_ffi 是否使用了扩展

第四位proto_nojit标志是否禁用了jit模式

第五位 proto_iloop标志是否有iloop循环指令
参数个数: 函数有几个参数
Frame大小: 使用栈帧的大小
upvalue个数: 使用外部函数中变量的个数
复杂常量个数:
数值常量个数:
指令个数:
调试信息大小(STRIP=0): 后面调试信息占用字节的大小
起始行(STRIP=0): 原型的在文件中的起始行
行数(STRIP=0): 原型占用的总行数
2、原型体
指令: 原型的字节码指令,每条指令占四个字节,默认对齐时,第一个字节为opcode,

个数为原型头中的指令个数
Upvalues: upvalue,uint16,个数为原型头中指定的个数
**复杂常量:**保存了多种类型的常量,定义如下:

cpp 复制代码
typedef struct {
uleb128 tp;
MSize constant_type = uleb128_value(tp);
if (constant_type >= BCDUMP_KGC_STR) {
int32 len = constant_type - BCDUMP_KGC_STR;
char str[len]
} else if (constant_type == BCDUMP_KGC_TAB) {
Table t;
} else if (constant_type != BCDUMP_KGC_CHILD) {
TNumber num;
if constant_type == BCDUMP_KGC_COMPLEX:
            Tnumber num;
} else {
prototype val = prototypes.pop();
}
}ComplexConstant

第一个uleb128表示这个复杂常量的类型,如下:

cpp 复制代码
enum {
BCDUMP_KGC_CHILD = 0,
BCDUMP_KGC_TAB = 1,
BCDUMP_KGC_I64 = 2,
BCDUMP_KGC_U64 = 3,
BCDUMP_KGC_COMPLEX = 4,
BCDUMP_KGC_STR = 5
};

主要包括了字符串,数值,table 和 child (prototype自身)

Table定义如下:

cpp 复制代码
typedef struct {
uleb128 array_items_count;
uleb128 hash_items_count;
local int32 array_items_count_ = uleb128_value(array_items_count);
local int32 hash_items_count_ = uleb128_value(hash_items_count);
while (array_items_count_-- > 0) {
ArrayItem array_item;
}
while (hash_items_count_-- > 0) {
HashItem hash_item;
}
} Table;

HashItem定义如下:

cpp 复制代码
typedef struct {
ComplexConstant key;
ComplexConstant value;
} HashItem;

**数值常量:**保存数值类型的常量,可以表示整数和浮点数,定义如下:

cpp 复制代码
typedef struct {
uleb128_33 lo;
if (lo.val[0] & 0x1)
uleb128 hi;
} NumericConstant;

**调试信息(STRIP=0):**包括三个部分,定义如下:

cpp 复制代码
typedef struct{
if (debuginfo_size > 0) {
LineInfo lineinfo(lines_count, instructions_count);
if (upvalues_count > 0)
UpValueNames upvalue_names(upvalues_count);
VarInfos varinfos;
}
} DebugInfo

Lineinfo记录了每条指令所在的行,upvalue_names记录了upvalue的字符串信息,varinfos记录了每个变量的字符串,定义如下:

cpp 复制代码
typedef struct(uchar tp) {
local uchar tp_ = tp;
if (tp >= VARNAME__MAX) {
string str;
} else {
VARNAME_TYPE vartype;
}
if (tp != VARNAME_END) {
uleb128 start_addr;
uleb128 end_addr;
}
} VarInfo;

Varinfo记录了变量的类型,以及变量作用域的起始行和结束行

相关推荐
海哥20191 天前
原创Lua脚本压缩HTML网页源码,节省60%流量和带宽,找老板加薪
lua
geekmice1 天前
thymeleaf处理参数传递问题
开发语言·lua
geekmice1 天前
Thymeleaf传递复杂对象参数解决思路
开发语言·lua
星空露珠2 天前
lua获取随机颜色rgb转换hex
数据结构·数据库·算法·游戏·lua
杀死那个蝈坦2 天前
监听 Canal
java·前端·eclipse·kotlin·bootstrap·html·lua
杀死那个蝈坦3 天前
Lua核心认知
开发语言·lua
杀死那个蝈坦3 天前
Redis 缓存预热
java·开发语言·青少年编程·kotlin·lua
FAREWELL000753 天前
Lua学习记录(6) --- Lua中的元表相关内容
开发语言·学习·lua
FAREWELL000753 天前
Lua学习记录(4) --- Lua中多文件调用 以及 关于位运算符的零碎知识点
开发语言·学习·lua
测试涛叔3 天前
高频Postman软件测试面试题
测试工具·lua·postman