[英]ARM LDR instruction with PC register as memory address
我有這個反編譯的 arm 二進制文件。 評論基於此答案...
...
12de3c0: e59f6400 ldr r6, [pc, #1024] ; load into r6 a word from offset 0x12de7c8 (0x12de3c0 + 0x8 + 1024)
12de3c4: e1a0a000 mov sl, r0 ; ignore this
12de3c8: e1a09001 mov r9, r1 ; ignore this
12de3cc: e08f6006 add r6, pc, r6 ; r6 = pc + r6; so r6 = 0x12de3cc + 0x8 + 0x035cbf8f = 0x48AA363 ???
12de3d0: e5d60000 ldrb r0, [r6] ; load a byte into r0 from the obtained address (0x48AA363)
...
12de7c8: 035cbf8f cmpeq ip, #572 ; 0x23c
...
但是,我很困惑 0x48AA363 超過了二進制文件的大小,所以我的假設肯定有誤。 我可能在哪里誤解了代碼?
如果您在具有虛擬內存的操作系統下運行,則將可執行文件映射到從非零虛擬地址開始的內存是正常的。 (因此 NULL 指針 deref 可能會出錯,而不是有效地址!)。 這意味着代碼指針(包括執行時的 PC)通常是大數字,遠大於文件大小。 請注意,即使您已經在反匯編中看到的12de3c0
地址也很大。
鏈接器通常會在部分之間放置間隙(因此數組越界更容易出錯,從而更容易調試,以及其他原因)。 因此,與您的.text
部分相當遠的某個地址的 PC 相對尋址(通過add r6, pc, r6
)很可能是.data
或.bss
。 .rodata
不太可能,因為加載常量字節沒有意義。
您可以使用readelf -a
查看程序頭給出的映射,並找到該地址的位置。 假設您的可執行文件仍然具有節頭,您還可以查看地址所在的節,而不僅僅是來自 ELF 段頭的權限和文件偏移量。
您還可以在此處設置斷點並運行它,以仔細檢查您的數學並查看ldrb
從哪個地址加載。 (並仔細檢查運行時修復(又名文本重定位)或其他什么。盡管在非 PIE 可執行文件中通常不需要。)
我最初將以上內容寫為評論。 在你已經這樣做之后,我發布了這個:
我放置了一個斷點,r6 正好是 0x48AA363。 並且該內存區域包含一個值為 0 的字節,可能是全局/靜態布爾值,因為它后面是
cmp r0, #0
是的,聽起來是一個合理的結論。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.