免费注册 查看新帖 |

Chinaunix

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

如何在进程的当前栈中获取当前栈中已经压栈了的函数名? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-04-27 11:08 |只看该作者 |倒序浏览
我的问题如下:
现在别人已经有了一个程序,然后我在别人程序里面的任意一个函数中调用我的函数myfunciton,在myfunction中我要能获取到最近三层或者四层的调用关系。
比如别人程序中有如下调用关系的2个函数function1,fucntion2,然后在其中function2中调用myfunction函数,在myfunction函数中需要获取到函数的调用关系。
void function1()
{
  function2();
}

void function2()
{
  myfunction();
}

void myfunction()
{
   
}
  我需要在myfunction函数中获取到调用链的关系,即如何在myfunction中唯一标识function1--function2--myfunction这
一条调用链,也可以说是在myfucntion函数中获取到function1和function2的函数名。

  我的想法是在myfunction函数中采用内嵌汇编,看是否可以获取到当前的调用关系链,但是我现在还没有找到具体可行的方案,  希望有高人指点!

论坛徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16赛季CBA联赛之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金鸡报晓
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年纪念徽章
日期:2016-11-09 13:19:1015-16赛季CBA联赛之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序设计版块每日发帖之星
日期:2015-12-03 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-09 06:20:002015亚冠之吉达阿赫利
日期:2015-07-03 08:39:42
2 [报告]
发表于 2011-04-27 11:13 |只看该作者
函数名字不入栈吧?在汇编中call funtion 只是一句伪代码,跑的时候就会把funtion的地址替换

论坛徽章:
0
3 [报告]
发表于 2011-04-27 11:20 |只看该作者
谢谢你的回帖~~

是的,压入栈的只是函数的地址!其实并不一定需要准确的知道函数名,只要能知道唯一标识这条链的东西就是可以的。

论坛徽章:
0
4 [报告]
发表于 2011-04-27 13:00 |只看该作者
回复 1# SCU_Snowkey


试试   __builtin_return_address吧。

论坛徽章:
5
摩羯座
日期:2014-07-22 09:03:552015元宵节徽章
日期:2015-03-06 15:50:392015亚冠之大阪钢巴
日期:2015-06-12 16:01:352015年中国系统架构师大会
日期:2015-06-29 16:11:2815-16赛季CBA联赛之四川
日期:2018-12-17 14:10:21
5 [报告]
发表于 2011-04-27 15:57 |只看该作者
楼主说的是backtrace吧?
man backtrace

论坛徽章:
0
6 [报告]
发表于 2011-04-27 16:21 |只看该作者
vxworks中的tt命令就是干这事的。

我猜大概原理是:在你的栈中,向高地址找 pushl %ebp ; movl %esp, %ebp 这样的opcode,如果找到,则说明是在进行函数调用,那么这两条opcode的再往上一条地址就是调用你的函数的时压栈的返回值,通过找这个返回值在符号表中的位置就能找到对应的函数符号,也就是调用你的函数的名字。

论坛徽章:
0
7 [报告]
发表于 2011-05-05 10:32 |只看该作者
这个问题已经差不多解决了,也给大家分享下我所知道的,不对的请大家指正。

4楼的朋友说的很对啊,使用__builtin_return_address是可以获取到函数返回地址的,这里所说的返回地址并不是函数的地址,是我们使用call function以后要压栈的下一条指令的地址,但是根据此地址查找符号文件找到距此地址最近的函数名称。我在gdb调试中发现,当__builtin_return_address的参数为零的时候返回值实际上是调用它的函数(caller)中的地址,所以我理解这里参数为零是在当前函数栈中存储的返回地址,依次类推。

另外我也用汇编实现了下类似__builtin_return_address的功能,也请大家指正!
int get_return_address(int iLevel)
{
        __asm__("pushl %%ebx\n\t"
                "movl %%ebp,%%eax\n\t"
                "movl 12(%%esp),%%ebx\n\n"
                "__next:\n\t"
                "test %%ebx,%%ebx\n\t"
                "je __break\n\t"
                "dec %%ebx\n\t"
                "movl (%%eax),%%eax\n\t"
                "jmp __next\n\n"
                "__break:\n\t"
                "movl 4(%%eax),%%eax\n\t"
                "pop %%ebx\n\t"
                ::
        );
}

小弟还有个问题,希望有高人能指点下!
在我们程序运行的当前栈中,如何定位到main函数,因为我们c程序执行都是从main函数开始执行的,我们通过在栈中找上一层函数的地址,如何判断哪一层已经是main函数的栈了呢?就像gdb里面一样,使用bt(backtrace)以后我们可以得到当前栈的信息。

评分

参与人数 1可用积分 +2 收起 理由
amarant + 2 精品文章

查看全部评分

论坛徽章:
0
8 [报告]
发表于 2011-05-05 12:05 |只看该作者
楼主可以读取符号文件的话,就可以找到main的虚拟地址吧。 Back Trace顺次找到函数返回的地址,应该能找到离main比较近的那个地址,就可以找到main的栈帧了吧。 如果不查找符号文件的话,找到离地址0x08048000最近的那个返回地址也差不多可以定位到main的栈帧吧。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP