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

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

问题描述

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

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.

这是在i*86上使用了很长时间的机制,并且仍然在许多RISC机器上使用.它使堆栈展开变得容易且非常快,但在寄存器匮乏的机器上效率不高,例如 i*x86 和较低程度的 x86_64,因为该帧寄存器可以在其他地方更好地使用.

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.

解决方案是创建增强数据,它描述了如何在给定当前寄存器组和内存内容的情况下找到当前帧(例如,当前帧位于 $rsp",或在 $rbp 的偏移量 MM",前一帧与当前帧的偏移量 J"等)

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.)

这实际上就是 .eh_frame 的含义.将其从您的二进制文件中删除,就不可能进行堆栈展开.

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天全站免登陆