其中(确切地说)是调用堆栈
Where (exactly) is the call stack?
如何在运行时找到调用堆栈的地址边界(通过一些符号或寄存器)?我正在使用nm
和readelf
来挑选我的符号,但我找不到一个。在寄存器的情况下,我似乎只限于当前帧的基指针和堆栈指针,而不是起始地址。
我想回避涉及解析/proc/pid/maps
的答案——我总是觉得为系统相关问题解析文本很尴尬。我在Linux x86/x86_64
上使用g++
。
编辑:我可以使用x86
段寄存器SS
来计算它吗?
Linux上的/proc/pid/maps
文件提供了一些关于进程内存映射的信息:
$ cat /proc/self/maps
00400000-0040b000 r-xp 00000000 08:03 709349 /bin/cat
0060a000-0060b000 r--p 0000a000 08:03 709349 /bin/cat
0060b000-0060c000 rw-p 0000b000 08:03 709349 /bin/cat
00a2d000-00a4e000 rw-p 00000000 00:00 0 [heap]
7f6fdf418000-7f6fdf6bd000 r--p 00000000 08:03 489885 /usr/lib/locale/locale-archive
...
7fff4669e000-7fff466bf000 rw-p 00000000 00:00 0 [stack]
7fff467ff000-7fff46800000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
pmap(1)
命令将这些信息格式化为一个我觉得更令人愉快的显示:
$ pmap $$
11680: bash
0000000000400000 896K r-x-- /bin/bash
...
00007ff31ae2d000 8K rw--- /lib/x86_64-linux-gnu/ld-2.13.so
00007fff66dd2000 132K rw--- [ stack ]
00007fff66dff000 4K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
total 29336K
顺便说一句,在eglibc源文件dl-execstack.c
中,我发现了以下注释:没有一种可移植的方法可以知道初始线程堆栈的边界,以便mprotect
。这可能意味着最好的机制是解析/proc/pid/maps
文件,尽管我认为我们都认为这很俗气。
当前堆栈指针在esp
寄存器中可用。但是,由于堆栈是在运行时分配的(因为可能有多个线程),您将不得不深入到运行时库的私有数据中,以找出当前堆栈的边界在哪里。
最接近的是/proc/self/maps
,但如果您的程序是多线程的,即使这样也不会让它变得容易。你可能应该接受这不是你在C可以做的事情。如果我们知道你想要实现什么,那会有所帮助。
对象文件没有理由包含调用堆栈的地址。调用堆栈是由OP在加载可运行文件后分配的。
通常,rsp
(或esp
,或平台中的任何内容)包含调用堆栈底部的地址。这意味着,当你调用一个函数时(甚至当你声明一个变量时),它应该是不同的。
相关文章:
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- 为什么调用堆栈数组会导致内存泄漏
- 是否可以检查悬挂光纤的调用堆栈?
- MSVC __debugbreak() 与 openGL 错误回调一起使用时不会产生调用堆栈
- 以下代码如何工作以每次为唯一调用堆栈唯一实例化模板函数?
- OpenCV 3 Visual Studio 2017 调试,调用堆栈没有.pdb文件
- C/C++中全局调用堆栈的基础
- 是否可以访问代码中的调用堆栈?
- 调用堆栈显示 SIGBUS,这意味着什么
- 打开C++故障转储不会在调用堆栈中显示正确的行
- 将参数推送到调用堆栈 (C++) 的可移植方法
- 是否可以将功能调用堆栈放在堆上
- 未定义对调用堆栈库的引用出现问题
- 我无法获得由 Clang 构建的优化 NDK 应用程序的调用堆栈
- 调用堆栈中的访问冲突
- GDB正在调试一个缺少特定调用堆栈的符号表的核心转储
- C++按引用传递:如何使用调用堆栈
- 从系统调用内部生成调用堆栈
- 使用 .Net 4.0 时出现堆栈不平衡错误,但在使用 .Net 2.0 时不调用堆栈不平衡错误
- 生成所有可能的调用堆栈的树