如何在进程的当前栈中获取当前栈中已经压栈了的函数名?
我的问题如下:
现在别人已经有了一个程序,然后我在别人程序里面的任意一个函数中调用我的函数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函数中采用内嵌汇编,看是否可以获取到当前的调用关系链,但是我现在还没有找到具体可行的方案, 希望有高人指点!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
函数名字不入栈吧?在汇编中call funtion 只是一句伪代码,跑的时候就会把funtion的地址替换
谢谢你的回帖~~
是的,压入栈的只是函数的地址!其实并不一定需要准确的知道函数名,只要能知道唯一标识这条链的东西就是可以的。
回复 1# SCU_Snowkey
试试 __builtin_return_address吧。
楼主说的是backtrace吧?
man backtrace
vxworks中的tt命令就是干这事的。
我猜大概原理是:在你的栈中,向高地址找 pushl %ebp ; movl %esp, %ebp 这样的opcode,如果找到,则说明是在进行函数调用,那么这两条opcode的再往上一条地址就是调用你的函数的时压栈的返回值,通过找这个返回值在符号表中的位置就能找到对应的函数符号,也就是调用你的函数的名字。
这个问题已经差不多解决了,也给大家分享下我所知道的,不对的请大家指正。
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)以后我们可以得到当前栈的信息。
楼主可以读取符号文件的话,就可以找到main的虚拟地址吧。 Back Trace顺次找到函数返回的地址,应该能找到离main比较近的那个地址,就可以找到main的栈帧了吧。 如果不查找符号文件的话,找到离地址0x08048000最近的那个返回地址也差不多可以定位到main的栈帧吧。