如何在运行时(通过某个符号或寄存器)找到调用堆栈的地址范围?我正在使用nm
和readelf
来挑选我的符号而我找不到符号。在寄存器的情况下,似乎我只限于当前帧的基本和堆栈指针,而不是起始地址。
我想回避涉及解析/proc/pid/maps
的答案 - 我总是觉得解析系统相关问题的文本很尴尬。我在g++
上使用Linux x86/x86_64
。
编辑:我可以使用x86
段注册SS
进行计算吗?
答案 0 :(得分:2)
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
它。< / em>这可能意味着最好的机制是解析/proc/pid/maps
文件,即使我认为我们都同意它是俗气的。
答案 1 :(得分:1)
当前堆栈指针在esp
寄存器中可用。但是,由于堆栈是在运行时分配的(因为可能有多个线程),因此您必须深入了解运行时库的私有数据,以找出当前堆栈的边界位置。
答案 2 :(得分:1)
你得到的最接近的是/proc/self/maps
,但即使你的程序是多线程的,也不会那么容易。你可能应该接受这不是你可以在C中做的事情。如果我们知道你想要达到什么目标会有所帮助。
答案 3 :(得分:0)
目标文件没有理由包含调用堆栈的地址。在加载可运行文件后,OP已分配调用堆栈。
通常,rsp
(或esp
或您平台中的任何内容)都包含调用堆栈底部的地址。这意味着,当你调用一个函数时(或者甚至当你声明一个变量时)它应该有所不同。