`

LUA源码分析五:元表

    博客分类:
  • LUA
阅读更多

 

版本整理日期:2011/4/21

 

元表其实就是可以让你HOOK掉一些操作的一张表。

表的定义在ltm.h/c的文件里。对元表的调用在lvm文件里。

来看看是怎么hook的。首先定义了一堆的枚举

 

typedef enum {
  TM_INDEX,
  TM_NEWINDEX,
  TM_GC,
  TM_MODE,
  TM_EQ,  /* last tag method with `fast' access */
  TM_ADD,
  TM_SUB,
  TM_MUL,
  TM_DIV,
  TM_MOD,
  TM_POW,
  TM_UNM,
  TM_LEN,
  TM_LT,
  TM_LE,
  TM_CONCAT,
  TM_CALL,
  TM_N		/* number of elements in the enum */
}

 

 

除了TM_INDEXTM_NEWINDEX外,其他的都是实现定义好的操作符。也就是说如果你要改变s1+s2这样的行为,只要直接设置TM_ADD的函数即可。TM_INDEXTM_NEWINDEX表示读取和等于。比如s[s’]=x[‘x’’]中,左边的[s’]如果没有这个字段则从TM_NEWINDEX中读取,右边的同理。

元表可以存在于这些对象上:

 

 

const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
  Table *mt;
  switch (ttype(o)) {
    case LUA_TTABLE:         //表
      mt = hvalue(o)->metatable;
      break;
    case LUA_TUSERDATA:      //自定义对象
      mt = uvalue(o)->metatable;
      break;
    default:                 //全局
      mt = G(L)->mt[ttype(o)];
  }
  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);
}

 

 

lua源码里,对元表的访问其实也是很简单的:

我们直接从虚拟机代码开始跟起,通过元表存在的对象类型上,会从OP_GETTABLE上跳转,代码如下

 

case OP_GETTABLE: {
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
        continue;
      }

 

 

luaV_gettable中,会先扫描是否有RKC(i)的值。即上文提到的s[s’]=x[‘x’’]中的[s’]。如果有则返回,直接读取;否则扫描TM_INDEX字段,然后判断里面是否函数,如果是则进入调用。代码如下:

 

 

void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
  int loop;
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
    const TValue *tm;
    if (ttistable(t)) {  /* `t' is a table? */
      Table *h = hvalue(t);
      const TValue *res = luaH_get(h, key); /* do a primitive get */
      if (!ttisnil(res) ||  /* result is no nil? */
          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
        setobj2s(L, val, res);
        return;
      }
      /* else will try the tag method */
    }
    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
      luaG_typeerror(L, t, "index");
if (ttisfunction(tm)) {
  //这里是我们的跳转点
      callTMres(L, val, tm, t, key);
      return;
    }
    t = tm;  /* else repeat with `tm' */ 
  }
  luaG_runerror(L, "loop in gettable");
}

 callTMres(L, val, tm, t, key);往下跟,先把要调用的函数(tm)压入,接着是lua固用的调用代码流程(如果你熟悉前篇的话),最后又来到虚拟机的OP_CALL处,代码如下。

 

     case OP_CALL: {
        int b = GETARG_B(i);
        int nresults = GETARG_C(i) - 1;
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
        L->savedpc = pc;
      //这里是我们的进入点
        switch (luaD_precall(L, ra, nresults)) {

 

 

在熟悉的luaD_precall,来到我们设定的C++函数处。代码如下:

 

int luaD_precall (lua_State *L, StkId func, int nresults) {
    n = (*curr_func(L)->c.f)(L);  /* do the actual call */
}

 元表虽然给我们提供了一种hook的手法,但是一切还是以实际需求来进行选择运用。不一定一切非要元表的思维来实现

 

 

1
3
分享到:
评论

相关推荐

    Lua源码分析

    Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析Lua源码分析

    lua源码分析

    这个是lua的源码分析,lua的源码写的非常好,整个设计的结构非常巧妙,不管是对于学习lua本身还是c语言的数据结构都非常有帮助。

    云风-lua源码欣赏-lua-5.21

    第一章概览由甮由源文件划分 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮 甮

    lua 源码剖析

    里面有风云 大神写的对lua 的源码剖析。还有lua5.2源码。

    lua源码欣赏

    lua源码欣赏 lua源代码分析,来之云风!

    lua-5.3.4源码

    lua5.3.4源码,导入VS2015可以直接编译,想学习分析Lua源码的可以下载,研究。

    Lua源码剖析,Lua虚拟机的机制分析,硕士论文

    Lua源码剖析,Lua虚拟机的机制分析,硕士论文

    CodeLearn_Lua:Lua源码分析

    CodeLearn_Lua:Lua源码分析

    Lua源码剖析21

    Lua源码剖析(二):词法分析、语法分析、代码生成词法分析lua对与每一个文件(chunk)建立一个 LexState 来做词法分析的词法分析根据语法分析的需求

    Lua源码剖析

    一篇详尽的Lua源码分析文档,适合初学者阅读

    lua 源码分析

    lua分源,lua的性能不用说了吧,想深一步了解的可以看看

    Lua源代码分析顺序

    Lua源代码分析顺序

    Lua 源码剖析.rar

    本PDF是云风大神对Lua的源代码进行了详尽地分析,对想深入学习Lua编程的人来说无疑是一大利器!

    毕业设计论文范文源码-nginx-lua-module-zh-wiki:https://github.com/openresty/lua-ng

    毕业设计论文范文源码 Name ngx_http_lua_module - 嵌入强有力的 Lua 到 Nginx HTTP 服务中。 该模块不是随着 Nginx 源码发行。 更多请看 。 Table of Contents Status 生产版本可用 Version 该文档描述的 ngx_lua ...

    Lua-5.1.5-部分源码注释

    前段时间阅读lua5.1.5,并把部分源码写了注释,包括Object,string table,state,部分词法分析,现在改看lua5.2了,详细可加Q群讨论3-0-1-5-4-8-7-4-8(lua技术交流)

    bstree:Lua 源代码混淆器

    它分析源代码中的 Lua 文件并输出编码器和解码器。 BS 代表 Bit Stream 或 Bull Shit,取决于你的心情。 用法 $ lua bstree.lua &lt;input.lua&gt;+ 此命令将分析所有给定的 Lua 文件并输出两个文件: bsenc.lua...

    lua 源码鉴赏 readinglua 云风.zip

    云风此人,我从未见过,但是游戏界,他的传闻还是很多的,这个是他对于lua这个脚本语言的一个原理分析,我受益良多。

Global site tag (gtag.js) - Google Analytics