2016-09-25 65 views
27

In this document on page。 27它說文本段開始於 0x400000。爲什麼選擇這個特定的地址?有沒有 的原因?相同的地址選擇在GNU ldLinux爲什麼選擇地址0x400000作爲x86_64 ABI文本段的開始?

$ ld -verbose | grep -i text-segment 
    PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; 

這是令人驚訝的,因爲這個地址是更大在32位x86可執行文件:

$ ld -verbose | grep -i text-segment 
    PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS; 

我讀this question其中討論了爲什麼選擇0x080xxxxx地址i386的 ,但它不能解釋x86_64中的更改。關於這個問題很難找到任何解釋 。有人有線索嗎?

+0

https://www.uclibc.org/docs/psABI-x86_64.pdf是最新版本(0.99.7),[根據OSDev Wiki](http://wiki.osdev.org/System_V_ABI#文件)。 –

+0

0x400000是4MiB,所以這可能與大頁面支持有關。 3.3.3節只允許頁面大小達到64KiB。 –

+0

@ivan_pozdeev:https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI鏈接到由git HEAD修訂的LaTeX源代碼構建的PDF。 x86-64頁表可以使用2MB的巨大頁面(甚至1GiB),而Linux對匿名內存是透明/機會的,但不支持文件映射。我猜想4MB距離0足夠遠,索引的NULL指針deref通常不會索引到有效頁面。呃,我看到你在你的回答中說了同樣的話。 –

回答

28

底線:amd64在使用大地址時存在一些技術限制,建議將地址空間的低位2GiB專用於代碼和數據以提高效率。因此堆棧已經被重新定位在這個範圍之外。


i386 ABI

  • 疊層位於的代碼之前,從不到0x8048000向下生長。其中「」略多於128 MB 用於堆棧,大約2 GB用於文本和數據「(第3-22頁)。
  • 動態區段在0x80000000(2GiB)開始,
  • 和內核佔據頂部的「保留區」,其規範允許高達1GiB,起始於至少0xC0000000(第3-21)( which is what it typically does)。
  • 主程序不要求與位置無關。
  • 不需要實現來捕獲空指針訪問(p。3-21),但期望128MiB以上的某些棧空間(即288KiB)將被保留用於該目的是合理的。

amd64whose ABI配製爲修訂i386一個(第9頁))具有更爲龐大的(48位)的地址空間,但大多數指令只接受32位的立即操作數(其包括直接地址和跳轉指令中的偏移量),需要更多的工作和更低效的代碼(特別是在考慮指令相互依賴性時)來處理更大的值。作者通過介紹幾種他們推薦使用的「代碼模型」來「解決這些限制」的措施,「允許編譯器生成更好的代碼」。(第33頁)

  • 具體而言,首先將它們的, 「小代碼模型」,表明在範圍使用地址」從0到2 31 -2 -1或從0x000000000x7effffff它允許一些非常有效的相對引用和數組迭代。這是很多程序綽綽有餘的1.98GiB
  • 「中等代碼模型」基於前一個將數據分成上述邊界下的「快速」部分和需要特殊指令訪問的「更慢」剩餘部分。雖然代碼仍在邊界之下。
  • 而只有「大而全」的模式不作任何大小的假設,需要編譯器「在中期 代碼模型使用movabs指令,因爲,即使是處理文本部分內的地址。另外,間接分支當分支到當前指令指針偏移量爲 的地址未知時需要。「他們繼續建議將代碼庫分割爲多個共享庫,因爲這些措施不適用於已知位於邊界內的偏移的相對引用(如「小位置獨立代碼模型」中所述)。

因此,疊層的共享庫空間(0x80000000000128GiB),因爲它的地址是從來沒有立即操作數,總是引用間接或與來自另一參考lea/mov下移動到,因此僅相對偏移限制適用。


上面解釋了爲什麼加載地址被移到了較低的地址。現在,爲什麼它移到0x4000004MiB)?在這裏,我來到空的,所以,總結我在ABI規範讀過,我只能猜測,它認爲「剛剛好」:

  • 這是大到足以捕捉任何可能的不正確結構的偏移,允許更大amd64運行的數據單元,但又足夠小,不會浪費地址空間的大部分有價值的起始地址2GiB
  • 它等於迄今爲止最大的實際頁面大小,是所能想到的所有其他虛擬內存單元大小的倍數。

注意實際的X32 Linux版本已經從這個佈局moremore偏離隨着時間的推移。但是我們在這裏討論的是ABI規範,因爲amd64正式基於它,而不是任何衍生布局(請參閱引用的段落)。

相關問題