2012-02-13 43 views
2

如何在运行时(通过某个符号或寄存器)找到调用堆栈的地址范围?我使用nmreadelf来挑选我的符号,但我没有找到。在寄存器的情况下,似乎我只限于当前帧的基址和堆栈指针,而不是起始地址。哪里(正好)是调用堆栈?

我想避开涉及解析的答案/proc/pid/maps - 我总是觉得与系统相关的问题难以解析文本。我在Linux x86/x86_64上使用g++

编辑:我可以使用x86段寄存器SS来计算它吗?

+0

Hrm,我现在看到你在追求与大多数提问人不同的东西(通常是好奇心或家庭作业:) - 你是在用户空间还是内核空间中运行?正在修改ELF loader公平游戏?这是一个自我检查或外部过程进行检查的过程吗? – sarnold 2012-02-13 09:33:28

+0

嘿,是的。我正在嘲笑SDSM系统。我在用户空间中运行,能够修改ELF加载器,并让主进程使用'Dyninst'或全局符号检查自己。 – sholsapp 2012-02-13 17:51:21

+1

哈;有了这些新信息,我开始寻找eglibc的来源,试图找到装载机的来源,我认为这些来源会建立堆栈。我在'dl-execstack.c'中发现了以下注释:_没有可移植的方法来知道初始线程堆栈的边界以便“保护”它。这听起来不太好。 :( – sarnold 2012-02-13 23:23:10

回答

2

/proc/pid/maps文件在Linux上提供了一个进程的内存映射的一些信息:

$ 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文件,尽管我认为我们都认为它很俗气。

+0

已接受有关问题的意见! – sholsapp 2012-02-28 17:22:14

1

当前堆栈指针可在esp寄存器中使用。但是,由于堆栈是在运行时分配的(因为可能有多个线程),您将不得不深入运行时库的私有数据以找出当前堆栈的边界位置。

+0

当我需要执行这个代码时,只有一个过程。我想要堆栈的底部地址(而不是'esp')。如果我可以知道'.init'代码被调用之前'esp'是什么,那就行了! =) – sholsapp 2012-02-13 02:28:53

+0

由于堆栈向下,'esp'是底部地址(但你想要顶部)。为什么你需要堆栈的界限? – asaelr 2012-02-13 02:32:19

+0

@asaelr:流程迁移实验。我需要将地址空间复制到'n'进程。一次只有一个进程*运行*,但在同步点处进程状态是同步的。现在,我正在使用启发式检测栈边界。 – sholsapp 2012-02-13 02:36:22

0

没有理由让对象文件包含调用堆栈的地址。调用堆栈在加载可运行文件后由OP分配。

通常,rsp(或esp或您在平台中拥有的任何东西)包含调用堆栈底部的地址。这意味着,当你调用一个函数时(甚至当你声明一个变量时)它应该会有所不同。

1

最接近的是/proc/self/maps,但即使这样也不会让您的程序变得简单,如果您的程序是多线程的。你可能应该接受,这不是你可以在C中做的事情。如果我们知道你想达到什么,这将会有所帮助。