glibc backtrace()如何确定返回地址是哪个堆栈内存? [英] How does glibc backtrace() determine which stack memory are the return addresses?

查看:272
本文介绍了glibc backtrace()如何确定返回地址是哪个堆栈内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就程序而言,堆栈只是一堆内存. backtrace函数如何确定哪些堆栈字节是指令指针的返回地址,而不是那些仅是函数参数的地址,等等?

解决方案

就程序而言,堆栈只是一堆内存.

那是正确的.如果您对程序的结构一无所知,则将无法解开其堆栈.

最容易用于展开的结构是其中单个帧指针"被展开的结构.保留寄存器以始终指向当前帧,并且该帧在已知偏移处包含上一个帧指针.

这是在i*86上使用了很长时间的机制,并且仍然在许多RISC计算机上使用.它使堆栈退卷变得容易且非常快速,但是在缺少寄存器的计算机(例如i*x86和较低范围的x86_64)上效率不高,因为该帧寄存器可以在其他地方更好地使用.

解决方案是创建扩充数据,其描述如何在给定寄存器和存储器内容的当前集合的情况下找到当前帧(例如,当前帧位于距$rsp的偏移NN处"). ,或与$rbp处于MM偏移",先前的帧位于与当前帧的偏移J处",等等)

这实际上是.eh_frame的含义.从二进制文件中删除它,将无法展开堆栈.

此机制也比简单的帧指针遍历慢得多,需要复杂的代码,并且容易出错(不保证编译器会发出正确的展开描述符,并且手工编码的汇编程序可能根本没有它们). /p>

还有其他解决方案,这些解决方案可以快速,轻松地进行放松,但它们需要一个不同的调用约定.

As far as a program is concerned, a stack is just a bunch of memory. How does the backtrace function determine which stack bytes are instruction pointer return addresses as opposed to which are just function arguments, etc?

解决方案

As far as a program is concerned, a stack is just a bunch of memory.

That is correct. If you knew nothing about the structure of the program, you wouldn't be able to unwind its stack.

The easiest structure to use for unwinding is one where a single "frame pointer" register is reserved to always point to the current frame, and the frame contains previous frame pointer at a known offset.

That is the mechanism that was used for a long time on i*86, and is still used on many RISC machines. It makes stack unwinding easy and very fast, but it is not efficient on register-starved machines, such as i*x86 and to lower extent x86_64, because that frame register can be put to better use elsewhere.

The solution is to create augmentation data, which describes how to find the current frame given current set of registers and memory contents (e.g. "current frame is at offset NN from $rsp", or "at offset MM from $rbp", "previous frame is at offset J from current frame", etc.)

That is effectively what .eh_frame is. Remove it from your binary, and no stack unwinding will be possible.

This mechanism is also significantly slower than a simple frame pointer walk, requires complicated code, and is error-prone (compilers are not guaranteed to emit correct unwind descriptors, and hand-coded assembly may not have them at all).

There are other solutions which make unwinding fast and easy, but they require a different calling convention.

这篇关于glibc backtrace()如何确定返回地址是哪个堆栈内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆