簡體   English   中英

以 PC 寄存器作為內存地址的 ARM LDR 指令

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM