Your SlideShare is downloading. ×
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Lua/LuaJIT 字节码浅析
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Lua/LuaJIT 字节码浅析

3,332

Published on

介绍Lua 5.1/LuaJIT 2.0字节码的外部表示格式,以及ngx_lua closure factory代码在字节码级别的实现。ngx_lua的字节码加载功能即通过这里介绍的方法实现。

介绍Lua 5.1/LuaJIT 2.0字节码的外部表示格式,以及ngx_lua closure factory代码在字节码级别的实现。ngx_lua的字节码加载功能即通过这里介绍的方法实现。

Published in: Technology, Education
0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,332
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
116
Comments
0
Likes
19
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Lua/LuaJIT 字节码浅析 清无 2012-05-29Contents1 外部存 格式 1 1.1 Lua 5.1 字节码外部结构 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Lua 5.1 字节码实例分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.3 LuaJIT 2.0 函数原型内存结构 . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.4 LuaJIT 2.0 字节码外部结构 . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.5 LuaJIT 2.0 字节码实例分析 . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Closure Factory 包 代码实现 7 2.1 Lua 5.1 下的实现 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.2 LuaJIT 2.0 下的实现 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 字节码参考 9 3.1 Lua 5.1 字节码种类 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.2 Lua 5.1 字节码列表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.3 LuaJIT 2.0 字节码种类 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.4 LuaJIT 2.0 字节码列表 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 外部存 格式1.1 Lua 5.1 字节码外部结构 参考 luaU_dump@ldump.c • header 结构 1
  • 2. 1.1 Lua 5.1 字节码外部结构 1 外部存 格式 • 基本数据类型外部结构 注意 Lua 5.1 的内部字符串末尾总会自动添加一个 ‘’,在外部表示法中该字符将一并输出。 • 函数外部结构 (即输出 Proto 对象时的结构) 2
  • 3. 1.2 Lua 5.1 字节码实例分析 1 外部存 格式 • luac 同时给定多文件时是打包编译,其处理方式是创建一个新的匿名函数,将每个文 件内的代码作为该函数的一个内部函数处理, 匿名函数顺序调用这些内部函数运行 • 标准 Lua 5.1 的字节码文件不可跨平台使用, 因为其使用了 int/size_t/lua_Number 等不同平台不同编译选项下字长都不一样的类型, 若在不兼容编译的 Lua 中加载将 因为 header 不匹配而报告 “bad header” 错误1.2 Lua 5.1 字节码实例分析 示例代码为:§ ¤ 1 return function() 2 print "hello" 3 end¦ ¥通过 luac 编译后字节码文件内容分析如下: 3
  • 4. 1.2 Lua 5.1 字节码实例分析 1 外部存 格式 字节序列 含 header 1b 4c 75 61 LUA_SIGNATURE: “(esc)Lua” 51 LUAC_VERSION (5.1) 00 LUAC_FORMAT (official binary file) 01 little endian 04 LP64 linux: sizeof(int)==4 08 LP64 linux: sizeof(size_t)==8 04 LP64 linux: sizeof(Instruction)==4 08 lua_Number is double: sizeof(lua_Number)==8 00 lua_Number is some kind of float function 0 begins 08 00 00 00 00 00 00 00 function 0 source str len 40 61 31 2e 6c 75 61 00 function 0 source str: “@a1.lua(nil)” 00 00 00 00 function 0 linedefined 00 00 00 00 function 0 lastlinedefined 00 function 0 upvalues 00 function 0 numparams 02 function 0 is vararg func 02 function 0 maxstacksize 03 00 00 00 function 0 bytecode instruction num function 0 bytecode begins 24 00 00 00 CLOSURE 0 0 1e 00 00 01 RETURN 0 2 1e 00 80 00 RETURN 0 1 00 00 00 00 function 0 referenced consts 01 00 00 00 number of internal functions in function 0 function 1 inserted 00 00 00 00 00 00 00 00 function 1 source str len 01 00 00 00 function 1 linedefined 03 00 00 00 function 1 lastlinedefined 00 function 1 upvalues 00 function 1 numparams 00 function 1 is normal func 02 function 1 maxstacksize 04 00 00 00 function 1 bytecode instruction num function 1 bytecode begins 05 00 00 00 GETGLOBAL 0 0 41 40 00 00 LOADK 1 1 1c 40 00 01 CALL 0 2 1 1e 00 80 00 RETURN 0 1 4
  • 5. 1.3 LuaJIT 2.0 函数原型内存结构 1 外部存 格式 字节序列 含 function 1 consts begins 02 00 00 00 function 1 referenced consts 04 const 0 type: LUA_TSTRING(4) 06 00 00 00 00 00 00 00 const 0 length 70 72 69 6e 74 00 const 0 content: “print(nil)” 04 const 1 type: LUA_TSTRING(4) 06 00 00 00 00 00 00 00 const 1 length 68 65 6c 6c 6f 00 const 1 content: “hello(nil)” 00 00 00 00 number of internal functions in function 1 function 1 debug info begins 04 00 00 00 function 1 lineinfo vector size 02 00 00 00 src lineno of bytecode 0 02 00 00 00 src lineno of bytecode 1 02 00 00 00 src lineno of bytecode 2 03 00 00 00 src lineno of bytecode 3 00 00 00 00 number of local vars in function 1 00 00 00 00 number of upvalues in function 1 function 0 resumed function 0 debug info begins 03 00 00 00 function 0 lineinfo vector size 03 00 00 00 src lineno of bytecode 0 03 00 00 00 src lineno of bytecode 1 03 00 00 00 src lineno of bytecode 2 00 00 00 00 number of local vars in function 0 00 00 00 00 number of upvalues in function 01.3 LuaJIT 2.0 函数原型内存结构1.4 LuaJIT 2.0 字节码外部结构 参考 lj_bcwrite@lj_bcwrite.c • header 结构 5
  • 6. 1.5 LuaJIT 2.0 字节码实例分析 1 外部存 格式 • 函数外部结构 (即输出 GCproto 对象时的结构) • footer 结构:在文件末尾附加单字节 0 • LuaJIT 2.0 字节码文件可跨平台使用, 因为其只使用了字节、 ULEB128 变长序列化方 案和定长整数。但其格式可能在不同 major/minor 版本间变化, 加载不同版本的字节 码时会报告 cannot load incompatible bytecode 错误1.5 LuaJIT 2.0 字节码实例分析 示例代码为:§ ¤ 1 return function() 2 print "hello" 3 end¦ ¥通过 luajit -b 编译后字节码文件内容分析如下: 6
  • 7. 2 CLOSURE FACTORY 包 代码实现 字节序列 含 header 1b 4c 4a BCDUMP_HEAD1/2/3: “(esc)LJ” 01 BCDUMP_VERSION 02 flag: no FFI, stripped, little endian function 0 begins 23 function 0 rest data total length: 35 00 function 0 flag: no ffi, no vararg, no child 00 function 0 parameters 00 function 0 framesize 00 function 0 upvalues number 02 function 0 collectable consts number 00 function 0 lua_number consts number 04 function 0 bytecode number function 0 bytecode begins 34 00 00 00 GGET 0 0 25 01 01 00 KSTR 1 1 3e 00 02 01 CALL 0 1 2 47 00 01 00 RET0 0 1 function 0 gc’able consts begins 0a gc’able const 0 type (type=bcdump_kgc_str(5), len=10-5=5) 68 65 6c 6c 6f gc’able const 0 content: “hello” 0a gc’able const 1 type (type=bcdump_kgc_str(5), len=10-5=5) 70 72 69 6e 74 gc’able const 1 content: “print” function 1 begins 14 function 1 rest data total length: 20 03 function 1 flag: no FFI, vararg, has child 00 function 1 parameters 01 function 1 framesize 00 function 1 upvalues number 01 function 1 collectable consts number 00 function 1 lua_number consts number 03 function 1 bytecode number function 1 bytecode begins 31 00 00 00 FNEW 0 0 30 00 00 80 UCLO 0 0 48 00 02 00 RET1 0 2 function 1 gc’able consts begins 00 gc’able const 0 type (type=BCDUMP_KGC_CHILD(0)) footer 00 bytecode file footer2 Closure Factory 包 代码实现2.1 Lua 5.1 下的实现 对于 Lua 5.1, 需要识别待加载字节码 header 中的 int、 size_t、Instruction 字长,相应构建 closure factory 函数字节码, 并将原用户字节码的函数部分整体作为 closure factory 函数的内部函数插入。例如, 对于 int、size_t、Instruction 字长分别为 4、 4 的 Lua 平台下编译 8、 7
  • 8. 2.2 LuaJIT 2.0 下的实现 2 CLOSURE FACTORY 包 代码实现出的用户字节码,构造 closure factory 的方法为: 1. 读入待加载字节码 header 并原样输出 2. 读取待加载字节码 body 数据中的 8(size_t) 字节长度,按此长度读出后续的 source 字符串内容,并将长度和字符串内容输出 3. 输出 int 字长的空 linedefined 字段: 0x00 0x00 0x00 0x00 4. 输出 int 字长的空 lastlinedefined 字段: 0x00 0x00 0x00 0x00 5. 输出 char 字长的空 nups 字段: 0x00 6. 输出 char 字长的空 numparams 字段: 0x00 7. 输出 char 字长的 is_vararg 字段值 2 表示 main chunk 为变参函数: 0x02 8. 输出 char 字长的 maxstacksize 默认值 2: 0x02 9. 输出 int 字长的 closure factory 函数字节码长度 3: 0x03 0x00 0x00 0x00 10. 输出 Instruction 字长的 3 条 closure factory 函数字节码: 0x24 0x00 0x00 0x00 0x1e 0x00 0x00 0x01 0x1e 0x00 0x80 0x00 11. 输出 int 字长的空 sizek 字段: 0x00 0x00 0x00 0x00 12. 输出 int 字长的 sizep 字段值 1, 以便将原用户字节码作为 closure factory 的内部函数 处理: 0x01 0x00 0x00 0x00 13. 插入待加载字节码 body 数据 14. 输出 int 字长的空 sizelineinfo 字段:0x00 0x00 0x00 0x00 15. 输出 int 字长的空 sizelocvars 字段:0x00 0x00 0x00 0x00 16. 输出 int 字长的空 sizeupvalues 字段:0x00 0x00 0x00 0x00 17. 完成!2.2 LuaJIT 2.0 下的实现 LuaJIT 2.0 的字节码是平台无关的, 且父函数总在其子函数之后输出,故添加 closurefactory 时比 Lua 5.1 简单的多,方法为: 1. 读入全部待加载字节码数据,截去末尾 footer 的 1 字节后原样输出 2. 输出 ULEB128 编码方式的 closure factory 函数剩余数据长度 20: 0x14 3. 输出 closure factory 函数标志字节 (no ffi, vararg, has child): 0x03 4. 输出 char 字长的空 numparams 字段:0x00 5. 输出 char 字长的默认 framesize 字段:0x01 6. 输出 char 字长的空 nups 字段:0x00 7. 输出 ULEB128 编码方式的可回收常量计数 1,因为 closure factory 仅引用目标字节 码这一常量:0x01 8
  • 9. 3 字节码参考 8. 输出 ULEB128 编码方式的数值常量计数 0:0x00 9. 输出 ULEB128 编码方式的 closure factory 字节码数量 3:0x0310. 输出 int32_t 字长的 3 条 closure factory 字节码:0x31 0x00 0x00 0x00 0x30 0x00 0x00 0x80 0x48 0x00 0x02 0x0011. 输出含有目标字节码占位空间的可回收常量区:0x0012. 输出末尾 footer:0x0013. 完成!3 字节码参考3.1 Lua 5.1 字节码种类 参考 lopcodes.h3.2 Lua 5.1 字节码列表 符 OPCODE 参数 式 能 LOADK 0x01 iABx GETGLOBAL 0x05 iABx CALL 0x1c iABC RETURN 0x1e iABC CLOSURE 0x24 iABx3.3 LuaJIT 2.0 字节码种类 参考 lj_bc.h 9
  • 10. 3.4 LuaJIT 2.0 字节码列表 3 字节码参考3.4 LuaJIT 2.0 字节码列表 符 OPCODE 参数 式 能 KSTR 0x25 AD UCLO 0x30 AD FNEW 0x31 AD GGET 0x34 AD CALL 0x3e ABC RET0 0x47 AD RET1 0x48 AD 10

×