免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6829 | 回复: 19
打印 上一主题 下一主题

反汇编 [复制链接]

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-18 11:38 |只看该作者 |倒序浏览
30可用积分
  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/kernel.h>


  4. static int __init test_init(void){
  5.         int *pgd_pa = NULL;
  6.         __asm__ __volatile__("movl %%cr3, %0":"=r"(pgd_pa));
  7.         printk("cr3 is %p\n", pgd_pa);
  8.         return 0;
  9. }

  10. static void __exit test_exit(void){
  11.        
  12. }

  13. module_init(test_init);
  14. module_exit(test_exit);

  15. MODULE_LICENSE("GPL");
复制代码


谁能帮我把这个反汇编注释一下,反汇编出血者。

最佳答案

查看完整内容

回复 1# embeddedlwp 其实我并不是专门研究kernel的。只是偶尔会碰上一些讨论恰好与kernel有关,比如这帖。 所以分析中带有许多猜测……1. module_init/module_exit 应该是宏C语言是不允许top level中调用函数的2. module_init与module_exit展开后的代码编译后得到的应该分别是 init_module/cleanup_module源代码里 __asm__ __volatile__("movl %%cr3, %0":"=r"(pgd_pa)) 是出现在 test_init 里反汇编得到的mov %cr3,%eaxmov %eax, ...

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
2 [报告]
发表于 2011-10-18 11:38 |只看该作者
回复 1# embeddedlwp

其实我并不是专门研究kernel的。只是偶尔会碰上一些讨论恰好与kernel有关,比如这帖。 所以分析中带有许多猜测……

1. module_init/module_exit 应该是宏
C语言是不允许top level中调用函数的

2. module_init与module_exit展开后的代码编译后得到的应该分别是 init_module/cleanup_module
源代码里 __asm__ __volatile__("movl %%cr3, %0":"=r"(pgd_pa)) 是出现在 test_init 里

反汇编得到的
mov %cr3,%eax
mov %eax,0x4(%esp)
在 init_module 里

3. cleanup_module
我不明白空函数 test_exit 经过 module_exit 展开后为什么会产生一个函数调用。
但抛开 test_exit/module_exit与 cleanup_mode 之间的关联,仅仅分析 cleanup_module还是很容易的。
这就是最普通的函数,调用了另一个函数。

push %ebp
mov %esp,%ebp ; 这两句是prologue,会在栈上保存一个完整的调用链。
call 4 ; 这是一个函数调用,操作数fc ff ff ff只是一个桩,重定位节中会记录链接时此4字节应该被修正为什么 —— 即被调用函数
; 只从反汇编是看不出被调用函数的。
; 若想了解究竟调用了哪个函数, 如ls所说,要看 rel 节
pop %ebp ; 与上面的prologue对应,将调用链的末尾出栈
ret ; 返回

4. init_module

4.1 先把 prologue/epilogue 去掉
push %ebp
mov %esp,%ebp
...
leave
ret

余下的代码与 test_init 的对应关系就很清楚了

4.2 sub $0x8,%esp
这8字节将作为 printk 的参数

4.3 __asm__ __volatile__("movl %%cr3, %0":"=r"(pgd_pa));

mov %cr3,%eax

没有为pgd_pa变量分配内存,而是使用eax。
初值 int*pgd_pa=NULL; 被优化,没有先赋值为0,而是直接获取 cr3 的值。

4.4 printk("cr3 is %p\n", pgd_pa);

mov %eax,0x4(%esp) ; 传递pgd_pa的值
movl $0x0,(%esp) ; 传递 "cr3 is %p\n" 的地址
call 15 ; 调用 printk

后面两条指令中的操作数都是桩。
重定位节中会有相应的数据,使得链接器可以在链接时将操作数修正为 "cr3 is %p\n" 的地址 与 printk 的偏移。

4.5 return 0;
xor %eax,%eax

论坛徽章:
0
3 [报告]
发表于 2011-10-18 11:46 |只看该作者
有源代码你要反汇编干什么?

论坛徽章:
0
4 [报告]
发表于 2011-10-18 11:54 |只看该作者
本帖最后由 davelv 于 2011-10-18 12:06 编辑

汗,居然是图片。。
第一个函数
//栈帧寄存器ebp保护
//用ebp保存esp,这个是方便操作esp,进行函数内部变量引用
//调用函数入口+4的地方
//恢复ebp
//返回
第二个函数
//栈帧寄存器ebp保护
//用ebp保存esp
//把esp-=8 指向函数第一个参数,在这个函数里有2个4byte的参数
//保存cr3内容到eax
//把eax的数据压入esp+4,也就是后面调用函数的第二个参数
//把数据0压入esp,是后面调用函数的第一个参数
//调用函数入口+15的地方
//清空eax,这里就是把eax返回值,好return 0
//清栈,恢复ebp
//返回

论坛徽章:
0
5 [报告]
发表于 2011-10-18 11:55 |只看该作者
本帖最后由 davelv 于 2011-10-18 12:07 编辑

话说这个汇编和楼主给的程序完全2个东西。
而且这个汇编里面的递归调用是个死循环。

——————————————————
上面说的无效,自己大意了

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
6 [报告]
发表于 2011-10-18 11:59 |只看该作者
回复 2# btdm123


    经常程序有问题需要反汇编查看,求教mov %eax, 0x4(%esp) 为 mov %eax [0x4+%esp],这个是把%eax的放到内存中还是堆栈中阿,还有问什么section .exit.test和section .init.test都push %ebp,将%ebp的值压入内核栈中。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
7 [报告]
发表于 2011-10-18 12:00 |只看该作者
本帖最后由 embeddedlwp 于 2011-10-18 12:01 编辑

回复 4# davelv


    兄弟,不可能阿,这个反汇编确实是这个程序的,不过这个是个.ko

论坛徽章:
0
8 [报告]
发表于 2011-10-18 12:03 |只看该作者
回复 6# embeddedlwp

大概是内联汇编把函数给优化掉了。
esp和ebp基本都是操作栈的,除非你自己没事用它处理堆。

论坛徽章:
17
水瓶座
日期:2013-08-29 12:09:27白羊座
日期:2014-08-07 12:36:42丑牛
日期:2014-07-24 12:44:41寅虎
日期:2014-04-16 16:15:33寅虎
日期:2014-03-12 09:28:43摩羯座
日期:2014-03-06 13:22:04技术图书徽章
日期:2014-03-06 11:34:50天蝎座
日期:2014-01-09 11:31:44寅虎
日期:2013-12-27 17:01:44双子座
日期:2013-12-27 12:32:29双子座
日期:2013-12-25 09:03:33丑牛
日期:2013-12-24 16:18:44
9 [报告]
发表于 2011-10-18 12:03 |只看该作者
本帖最后由 asuka2001 于 2011-10-18 12:07 编辑

1. %ebp是每个函数被调用时的栈顶。所以每次进去都会先保存上一个函数的%ebp,也就是第一条指令push %ebp;然后把本函数的栈顶保存到%ebp,即第二条指令movl %esp, %ebp。

2. 内核模块因为没有装入内核空间,所以函数地址还未决定,所以call这条指令所调用的地址都是按照函数头的偏移量来的。。。这个我不确定,只是从汇编代码上猜的。

3. pop %ebp就是对应push %ebp的保存与恢复了,接下来就是函数返回ret

4. init_module里相同的部分就不重复了:

sub $0x8, %esp,这个是将%esp减小8,x86的栈向下增长,其实就是栈顶往下移动8字节,栈上就空出8个字节,用于局部变量。
mov %cr3, %eax, 将%cr3特殊寄存器里的值复制到%eax寄存器。
mov %eax, 4(%esp), 4(%esp)代表的是栈顶向上4个字节。栈上空出8个字节,这里是使用[%esp+4, %esp + 8 )这一段保存%eax的值。推测是pgd_pa这个局部变量!
mov $0, (%esp), 将0保存到[%esp, %esp + 4)这一段,感觉这里的$0应该等模块装入内核空间后,会是"cr3 is %p\n"这个字符串的地址,其实这2条指令是在传参。可以推测出下面条call是在调用printk


xor %eax, %eax, xor为异或指令,其实就是将%eax清0,然后ret,返回0

论坛徽章:
4
戌狗
日期:2013-08-15 18:22:43技术图书徽章
日期:2013-08-21 13:48:45巨蟹座
日期:2013-09-26 17:06:39处女座
日期:2013-12-25 11:26:10
10 [报告]
发表于 2011-10-18 13:26 |只看该作者
LZ可以看一下这个文件的rel节,应该可以找到重定位这两个call指令,以及那个$0的地方。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP