2012-02-13 73 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中做的事情。如果我們知道你想達到什麼,這將會有所幫助。