在以前的GCC版本中,objdump
報告的符號偏移量與實際執行代碼時使用的符號偏移量相匹配。例如:objdump報告的符號偏移量不再匹配運行時偏移量
$ cat example.c
#include <stdio.h>
int g_someGlobal = 0;
int main()
{
printf("%d\n", g_someGlobal);
return 0;
}
$ gcc-6 -v
...
gcc version 6.1.1 20160802 (Debian 6.1.1-11)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
...
080496f4 g O .bss 00000004 g_someGlobal
...
的確,運行二進制時,在執行期間所使用的符號的實際地址是相同的一個作爲通過objdump的報道:
$ gdb ./example
...
(gdb) start
Temporary breakpoint 1, main() at example.c:10
10 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80496f4
不幸的是,重複相同的序列在最近發佈的Debian拉伸命令,出現這種情況,而不是:
$ gcc-6 -v
...
gcc version 6.3.0 20170415 (Debian 6.3.0-14)
$ gcc-6 -O0 -g -o example example.c
$ objdump -x example | grep Global
00002020 g O .bss 00000004 g_someGlobal
符號現在偏移似乎是一個更小的值 - 這...
$ gdb ./example
...
(gdb) start
...
Temporary breakpoint 1, main() at example.c:7
7 printf("%d\n", g_someGlobal);
(gdb) p/x &g_someGlobal
$1 = 0x80002020
...不再在運行時使用的一個相匹配。
我在這裏犯了一個錯誤嗎?在此期間工具的使用是否改變了?如果不是,這個改變背後的推理是什麼?
無論如何 - 理論上必須有一種方法來獲得承載變量的.bss段的「預期運行時偏移量」(objdump
確實報告將放置哪個段,因此最終運行時位置可以通過加上.bss
偏移量來計算)。在我的初步嘗試這樣做,我還沒有找到一種方式來獲得這一點,雖然:
$ readelf --sections example | grep bss
[26] .bss NOBITS 0000201c 00101c 000008 00 WA 0 0 4
這似乎並沒有上報,似乎發生在.bss
-hosted變量中的0x80000000的「轉移」這個例子。 ?
(即使這是一個「神奇常數」這個新的執行環境,是否適用於.data
變量,也和說實話,我討厭魔法值 - 此前,無論出來的objdump -x
準確,無論符號在哪裏...)
任何信息來解決這個最受歡迎。理想情況下,我想重現objdump -x
的舊行爲 - 即靜態地(不是在運行時)從承載它的ELF中獲取符號的運行時地址的值。
UPDATE:我做了GCC7.1.0的自定義編譯(來源),這不再可重現。也許這是在GCC 6.3(打包在Debian的拉伸版)迴歸...
現在不在KB中輸入答案,但原因是Debian的gcc軟件包是用'--enable-default-pie'構建的。添加'-no-pie'來連接命令行以獲得鏈接時間確定的地址。 –
@R ..的確,經過驗證!如果您將評論添加爲答案,我會接受它。你有沒有關於爲什麼Debian選擇這樣做的背景? – ttsiodras
沒關係,我讀了關於PIE並理解 - 安全相關的事情。再次感謝! – ttsiodras