lua虚拟机字节码修改_[翻译]Lua 5.2 字节码和虚拟机

Lua 5.2 字节码和虚拟机

by Dirk Laurie

Copyright © 2013. Freely available under the terms of the Lua license.

原文:http://files.catwell.info/misc/mirror/lua-5.2-bytecode-vm-dirk-laurie/lua52vm.html 翻译:阳春

序言

我写此文是因为只有如此我才能理解它。此篇适合给非常熟悉Lua5.2参考手册(LRM5.2),在至少一台机器(Knuth’s MIX就行了)上有一点机器指令经验,并且想要对Lua5.2源码做些修修补补的读者阅读。

感谢:我从Elijah Frederickson的网站上借鉴了许多(https://github.com/mlnlover11/LuaAssemblyTools) (LAT) ,上面不仅有Lua5.1和Lua5.2的汇编工具,还有一份超完整的极其有用的其他人早期工作的集合,特别是,Kein-Hong Man的No-Frills Introduction to Lua5.1 VM Instructions(NFI),虽然是为Lua5.1而写但仍具极大的参考价值。当然,早晚你都得阅读Lus5.2源码的简练而权威的注释。

二进制区块

一个区块可以被存储在文件或者宿主程序的字符串中。为了执行一个区块,Lua首先为一台虚拟机将区块预编译成指令,然后它用一个解释器为虚拟机执行编译后的代码。

区块也可以被预编译成二进制形式,细节请参考luac。程序的源码形式和编译后的形式可以互转,Lua自动检测文件类型并自动执行。——§3.3.2

上面是LRM5.2中唯一提到”虚拟机”字眼的段落。三个标准库函数处理二进制区块:load、loadfile和string.dump.这就是用户能从官方获取的全部信息。对闭源代码来说这也就是用户能知道的全部了。

但是Lua是开源的。它的源代码有很好的注释,同时我们也可以做逆向工程。让我们从luac开始。

$ luac

luac: no input files given

usage: luac [options] [filenames]

Available options are:

-l       list (use -l -l for full listing)

-o name  output to file 'name' (default is "luac.out")

-p       parse only

-s       strip debug information

-v       show version information

--       stop handling options

-        stop handling options and process stdin

嗯,我们会给它一个Hello World程序,略微修改一下让它更为有趣。第二行之后,终端输入停止(我按Control-D)然后luac的输出开始。

$ luac -l -l -v -s -

Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio

local hello = "Hello"

print (hello.." World!")

main <0> (7 instructions at 0x9984970)0>

0+ params, 4 slots, 1 upvalue, 1 local, 3 constants, 0 functions

1   [1] LOADK       0 -1    ; "Hello"

2   [2] GETTABUP    1 0 -2  ; _ENV "print"

3   [2] MOVE        2 0

4   [2] LOADK       3 -3    ; " World!"

5   [2] CONCAT      2 2 3

6   [2] CALL        1 2 1

7   [2] RETURN      0 1

constants (3) for 0x9984970:

1   "Hello"

2   "print"

3   " World!"

locals (1) for 0x9984970:

0   hello   2   8

upvalues (1) for 0x9984970:

0   _ENV    1   0

我们稍后讨论这个输出,在这时候我想要你看到这四个清单:稍微注释过的汇编代码,常数,局部变量,外部局部变量。

现在我们回到Lua本身。load同一区块,dump下来获取其字节码,把它写到文件里。我修改(patched)了我的Lua,用三个空格代替了控制台的>,这样你可以直接剪切粘贴这些代码。

$ lua

Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio

func = load 'local  hello = "Hello" print (hello.." World!")'

chunk = string.dump(func)

io.open("hello.luac","wb"):write(chunk)

luac也可以接受二进制区块。我们可以用它来看看load做了什么。

$ luac -l -l -v hello.luac

Lua 5.2.1  Copyright (C) 1994-2012 Lua.org, PUC-Rio

main  (7 instructions at 0x90d0b50)

0+ params, 4 slots, 1 upvalue, 1 local, 3 constants, 0 functions

1   [1] LOADK       0 -1    ; "Hello"

2   [1] GETTABUP    1 0 -2  ; _ENV "print"

3   [1] MOVE        2 0

4   [1] LOADK       3 -3    ; " World!"

5   [1] CONCAT      2 2 3

6   [1] CALL        1 2 1

7   [1] RETURN      0 1

constants (3) for 0x90d0b50:

1   "Hello"

2   "print"

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值