[转]lua元表代码分析
http://lin-style.iteye.com/blog/1012138
版本整理日期: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_INDEX和TM_NEWINDEX外,其他的都是实现定义好的操作符。也就是说如果你要改变s1+s2这样的行为,只要直接设置TM_ADD的函数即可。TM_INDEX和TM_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的手法,但是一切还是以实际需求来进行选择运用。不一定一切非要元表的思维来实现
[转]lua元表代码分析的更多相关文章
- lighttpd与fastcgi+cgilua原理、代码分析与安装
原理 http://www.cnblogs.com/skynet/p/4173450.html 快速通用网关接口(Fast Common Gateway Interface/FastCGI)是通用网关 ...
- [转]LUA元表
lua元表和元方法 <lua程序设计> 13章 读书笔记 lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在 ...
- Step By Step(Lua元表与元方法)
Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...
- Android代码分析工具lint学习
1 lint简介 1.1 概述 lint是随Android SDK自带的一个静态代码分析工具.它用来对Android工程的源文件进行检查,找出在正确性.安全.性能.可使用性.可访问性及国际化等方面可能 ...
- pmd静态代码分析
在正式进入测试之前,进行一定的静态代码分析及code review对代码质量及系统提高是有帮助的,以上为数据证明 Pmd 它是一个基于静态规则集的Java源码分析器,它可以识别出潜在的如下问题:– 可 ...
- [Asp.net 5] DependencyInjection项目代码分析-目录
微软DI文章系列如下所示: [Asp.net 5] DependencyInjection项目代码分析 [Asp.net 5] DependencyInjection项目代码分析2-Autofac [ ...
- [Asp.net 5] DependencyInjection项目代码分析4-微软的实现(5)(IEnumerable<>补充)
Asp.net 5的依赖注入注入系列可以参考链接: [Asp.net 5] DependencyInjection项目代码分析-目录 我们在之前讲微软的实现时,对于OpenIEnumerableSer ...
- 完整全面的Java资源库(包括构建、操作、代码分析、编译器、数据库、社区等等)
构建 这里搜集了用来构建应用程序的工具. Apache Maven:Maven使用声明进行构建并进行依赖管理,偏向于使用约定而不是配置进行构建.Maven优于Apache Ant.后者采用了一种过程化 ...
- STM32启动代码分析 IAR 比较好
stm32启动代码分析 (2012-06-12 09:43:31) 转载▼ 最近开始使用ST的stm32w108芯片(也是一款zigbee芯片).开始看他的启动代码看的晕晕呼呼呼的. 还好在c ...
随机推荐
- spring cloud服务发现注解之@EnableDiscoveryClient与@EnableEurekaClient
使用服务发现的时候提到了两种注解,一种为@EnableDiscoveryClient,一种为@EnableEurekaClient,用法上基本一致,今天就来讲下两者,下文是从stackoverflow ...
- Vuejs选项卡案例
css .active { color: red; border-bottom: 1px solid red; } ul li { padding: 0 15px; float: left; list ...
- 浅谈table、form 标签
1.<table> 标签 1.1包含的元素 <caption></caption>:表头信息. <tr></tr> :定义一个表格行: &l ...
- xmanager运行报错:bash: /usr/bin/xterm: No such file or directory
1.原因 xterm没有安装,解决办法是下载然后安装即可. 如果机器可以用yum,则直接使用yum安装xterm即可: yum install -y xterm 如果没有网络,则在某台操作系统大版本相 ...
- 反向代理/负载均衡/session/cookie
正向代理:客户端将流量重定向到burpsuite等软件或连接到VPN再访问服务器而不是直接访问服务器的场景.流量流动方向是真正机器--代理服务器.正向代理又称代理.普通代理. 反向代理:服务器端使用反 ...
- 使用javassist进行动态编程
今天在研究dubbo时,发现一个新的知识点,可以使用javassist包进行动态编程,hibernate也使用该包进行编程.晚上百度了很多资料,将它的特性以代码的形式展现出来. package com ...
- 异步socket处理
服务器端: #include <boost/thread.hpp> #include <boost/asio.hpp> #include <boost/date_time ...
- linux命令--文件查询
ls [ -lahid ] [ /* ] ls -- 默认查询当前目录下的显性文件 -l -- 显示文件的详细信息 -a -- 显示所有文件(包括隐藏文件) -h -- 文件大小显示为 ...
- windows 文本操作
type命令 作用:显示文件类文件内容 (例如:.txt .Java .cpp .c .html 等属于文本类文件 .word excel ppt exe dll 等都不属于文本类文件) fc命令 作 ...
- day27 网络通信协议 tcp/udp区别
今日主要内容: 一.网络通信协议 二.tcp udp协议下的socket 一.网络通信协议 1.1互联网的本质就是一系列的网络协议 本机IP地址('127.0.0.1',xxxx) 互联网连接的电脑互 ...