注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

如何实现python递归反汇编函数  

2017-07-31 14:51:51|  分类: python |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、问题
有时候(通常是为了测试)为了更详细的了解python的代码内容,希望看下python的反汇编代码,但是默认情况下python都只反汇编第一层代码内容,顶层函数调用的二级函数没有反汇编,而更坑的是抓耳挠腮的看了半天,命名看到代码就在那里,但是没有办法把内容反汇编出来。
例如,这个简单的代码如何将函数L3的内容反汇编出来呢?
tsecer@harry: cat nesty.py 
def L1():
print "in L1"
def L2():
print "in L2"
def L3():
print "in L3"
>>> dis.dis(nesty.L1)
  2           0 LOAD_CONST               1 ('in L1')
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       

  3           5 LOAD_CONST               2 (<code object L2 at 0xb76fe8d8, file "nesty.py", line 3>)
              8 MAKE_FUNCTION            0
             11 STORE_FAST               0 (L2)
             14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        
>>> 

二、函数调用的实现
从函数的反汇编代码中看到,函数的装载通过
LOAD_CONST               0 (<code object L1 at 0xb77a3380, file "nesty.py", line 1>)
指令完成,它也就是通过frame结构的const列表中加载到L1代码的内容,以这个为输入构造函数,
Python-2.2.2\Python\ceval.c
/* Interpreter main loop */

PyObject *
PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
{
……
    co = f->f_code;
    names = co->co_names;
    consts = co->co_consts;

……
        case LOAD_CONST:
            x = GETITEM(consts, oparg);
            Py_INCREF(x);
            PUSH(x);
            goto fast_next_opcode;
……
}

typedef struct _frame {
    PyObject_VAR_HEAD
    struct _frame *f_back; /* previous frame, or NULL */
    PyCodeObject *f_code; /* code segment */
……
} PyFrameObject;

三、PyFrameObject对象的f_code从何而来
从PyFrame_New来看,这个内容就是一个PyCodeObject实例
Python-2.6.6\Objects\frameobject.c
PyFrameObject *
PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
            PyObject *locals)
{
……
        f->f_code = code;
……
}
而这个类型对于我们的例子,可以通过nesty.L1得到:
>>> type(nesty.L1)
<type 'function'>
>>> 

四、如何访问到一个Code对象的co_consts字段
从下面代码中看,可以通过导出的co_consts获得
Python-2.6.6\Objects\codeobject.c
static PyMemberDef code_memberlist[] = {
……
    {"co_code",         T_OBJECT,       OFF(co_code),           READONLY},
    {"co_consts",       T_OBJECT,       OFF(co_consts),         READONLY},
    {"co_names",        T_OBJECT,       OFF(co_names),          READONLY},
……
    {NULL}      /* Sentinel */
};

五、简单效果
由于例子中LOAD_CONST访问的下标是2,所以反汇编也要使用2作为下标
  3           5 LOAD_CONST               2 (<code object L2 at 0xb76fe8d8, file "nesty.py", line 3>)

>>> dis.dis(nesty.L1.func_code.co_consts[2])
  4           0 LOAD_CONST               1 ('in L2')
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       

  5           5 LOAD_CONST               2 (<code object L3 at 0xb76fe770, file "nesty.py", line 5>)
              8 MAKE_FUNCTION            0
             11 STORE_FAST               0 (L3)
             14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        
>>> 

同理,这里看到
  5           5 LOAD_CONST               2 (<code object L3 at 0xb76fe770, file "nesty.py", line 5>)

指令的参数依然是2,所以L3的反汇编代码为
>>> dis.dis(nesty.L1.func_code.co_consts[2].co_consts[2])
  6           0 LOAD_CONST               1 ('in L3')
              3 PRINT_ITEM          
              4 PRINT_NEWLINE       
              5 LOAD_CONST               0 (None)
              8 RETURN_VALUE        
>>> 

六、通用的做法
3.7版本将会合入一个支持递归反汇编的功能,不过暂时(现在是2017.07.31)还没有发布,可以在gitbub的开发分支上看其完成实现不过在github上可以提前看到完整的实现代码
  评论这张
 
阅读(35)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017