當(dāng)ARM為其架構(gòu)引入64位支持時(shí),它旨在與以前的32位軟件兼容。但對(duì)于Linux程序員來(lái)說(shuō),仍然存在一些可能影響代碼行為的重大差異。以下是我們發(fā)現(xiàn)的一些內(nèi)容以及我們?yōu)樗麄冮_(kāi)發(fā)的解決方法。
我本來(lái)打算將這篇文章稱(chēng)為“ARMv8 for Linux程序員的新功能?”然而,我認(rèn)為“有什么不同”更為貼切。而且,僅僅為了記錄,“ARMv8-A”是指AArch64,帶有A64指令集,也稱(chēng)為arm64或ARM64。我在示例中使用了AArch64寄存器,但我所描述的許多問(wèn)題也發(fā)生在ARMv8-A 32位執(zhí)行狀態(tài)。
為了幫助構(gòu)建此處討論的問(wèn)題,讓我開(kāi)始通過(guò)給出一些我們?cè)诔蜂N(xiāo)時(shí)所擁有的代碼庫(kù)的背景知識(shí)。我們的核心技術(shù)是記錄和重放引擎,它通過(guò)將所有非確定性輸入記錄到程序并使用即時(shí)編譯(JIT)來(lái)跟蹤程序狀態(tài)來(lái)工作。我們的技術(shù)始于x86(32和64)當(dāng)我們開(kāi)始調(diào)整它以適應(yīng)AArch64時(shí),我已經(jīng)在ARM 32位上獲得了相當(dāng)完整,成熟的支持。幾乎所有的低懸的水果都被抓住了之后我加入了公司(以及很多相當(dāng)高的樹(shù),為了公平)我們?cè)谵D(zhuǎn)向ARMv8時(shí)遇到了一些棘手的問(wèn)題。
這讓我想到了我的第一個(gè)簡(jiǎn)單但可能有用的觀察結(jié)果:ARM64與ARM 32位(又名AArch32)相比,與x86更相似。 ARM64仍然非常RISC(盡管加密加速指令確實(shí)導(dǎo)致RISC架構(gòu)中的眉毛抬起)。所以我不打算試圖涵蓋x86和ARM版本之間的許多差異。我也不想重新審視AArch32和AArch64之間的差異 - 已經(jīng)有很好的資源來(lái)探索這些差異。
此外,許多ARM與ARM64資源都集中在指令集和架構(gòu)差異上。這些差異與大多數(shù)Linux用戶空間應(yīng)用程序開(kāi)發(fā)人員并不十分相關(guān),超出了非常明顯的范圍,例如“你的指針更大?!钡?,正如我們發(fā)現(xiàn)的那樣,對(duì)于Linux用戶空間開(kāi)發(fā)人員來(lái)說(shuō)存在重要差異,其中四個(gè)我將會(huì)在這里討論。這些差異分為幾類(lèi),一些屬于多個(gè)類(lèi)別。類(lèi)別是:
由于遷移使用相當(dāng)新的內(nèi)核版本而產(chǎn)生的差異。
由于體系結(jié)構(gòu)和指令集(這與用戶空間程序員有關(guān))的差異。
Ptrace 差異。我們經(jīng)常使用 ptrace ,所以這對(duì)我們來(lái)說(shuō)非常重要。
我將在下一節(jié)中嘗試使用以下格式:
該區(qū)域的簡(jiǎn)要說(shuō)明。
有什么不同?為什么會(huì)有所不同?(有時(shí)通過(guò)查看一些裝配說(shuō)明比通過(guò)羅嗦的描述更容易理解行為的變化,所以我會(huì)提供那段代碼。)
我們是如何遇到它的?
我們是如何克服它的?
在哪里可以找到更多信息。
1。對(duì) ptrace 的更改
ptrace 為用戶空間程序提供了進(jìn)程跟蹤功能。
有一個(gè)編號(hào)對(duì) ptrace()接受的請(qǐng)求的更改。這些更改產(chǎn)生了最令人愉快的所有不兼容性:編譯錯(cuò)誤。我們的錯(cuò)誤報(bào)告是針對(duì)未定義的符號(hào)PTRACE_GETREGS(對(duì)于通用寄存器),PTRACE_GETFPREGS(對(duì)于浮點(diǎn)和SIMD寄存器),以及PTRACE_GETHBPREGS(對(duì)于硬件斷點(diǎn)寄存器),以及這些請(qǐng)求的SET版本。
ptrace 的 man 頁(yè)面在解決方面毫無(wú)幫助這些錯(cuò)誤,所以我們挖得更深。我們看了一下內(nèi)核源代碼,結(jié)果發(fā)現(xiàn)通常存在獨(dú)立于體系結(jié)構(gòu)的 ptrace 代碼路徑(kernel/ptrace.c中的ptrace_request()),以及獨(dú)立的體系結(jié)構(gòu)依賴路徑(例如arch/arm/kernel/ptrace.c中的arch_ptrace()。雖然arm64版本有一個(gè)用于AArch32應(yīng)用程序的compat_arch_ptrace,但arm64 arch_ptrace()直接調(diào)用ptrace_request()并且不添加任何其他 ptrace 請(qǐng)求類(lèi)型。
解決方案是使用PTRACE_GETREGSET和PTRACE_SETREGSET具有各種不同的參數(shù)來(lái)讀取這些寄存器。
這是GETREGS樣式請(qǐng)求和最接近的等效GETREGSET請(qǐng)求的表。通過(guò) addr ptrace()參數(shù)的不同參數(shù)獲取不同的REGSET。
ARM 32位 | AArch64 |
GETREGS | NT_PRSTATUS |
GETFPREGS | NT_PRFREG |
GETHPBREGS |
NT_ARM_HW_BREAK NT_ARM_HW_WATCH |
表1. ARM 32位和最接近的等效AArch64 ptrace請(qǐng)求。
請(qǐng)注意,NT_ARM_HW_BREAK和NT_ARM_HW_WATCH在GETREGSET請(qǐng)求中的行為相同。
使用GETREGSET并不像使用GETREGS那么簡(jiǎn)單。對(duì)于像這樣的GETREGS請(qǐng)求:
ptrace(PTRACE_GETREGS,0,0,regs);
GETREGSET看起來(lái)像這樣:
struct {void * buf; size_t len;} my_iovec = {regs,sizeof(* regs)};
ptrace(PTRACE_GETREGSET,0,(void *)NT_PRSTATUS,& my_iovec);
注意也是我已經(jīng)說(shuō)過(guò)“最接近的等效GETREGSET請(qǐng)求。”當(dāng)然,AArch64寄存器組與ARM 32位寄存器不同,但兩者之外的寄存器組之間存在更多差異。
圖圖1示出了從ARM 32位GETREGS和AArch64 GETREGSET指令返回的寄存器的圖。
圖1. GETREGS和GETREGSET。
熟悉AArch64的人可能會(huì)注意到GETREGSET我們已經(jīng)獲得了“cpsr”注冊(cè),但硬件架構(gòu)沒(méi)有。 GETREGSET返回的內(nèi)容已經(jīng)從AArch64上可單獨(dú)訪問(wèn)的字段合成為類(lèi)似cpsr的布局。
兩者之間更顯著的差異是GETREGSET缺少orig_r0(或orig_x0)。這種缺乏與系統(tǒng)調(diào)用有關(guān)。在ARM 32位上,系統(tǒng)調(diào)用編號(hào)放在r7中,并且系統(tǒng)調(diào)用參數(shù)在系統(tǒng)調(diào)用(SVC)指令之前放在參數(shù)寄存器r0-r3中。從系統(tǒng)調(diào)用返回的值位于r0(根據(jù)通常的APCS,在特殊情況下為r7)。內(nèi)核從 syscall 返回后,orig_r0將原始的第一個(gè)參數(shù)提供給 syscall (已被返回值覆蓋)。
I實(shí)際上不知道“正常”應(yīng)用程序應(yīng)該使用什么用于這個(gè)原始的第一個(gè)參數(shù)。我們使用它來(lái)支持 restart_syscall ,其中返回值為ERESTART_RESTARTBLOCK。
不幸的是,缺乏orig_x0對(duì)我們來(lái)說(shuō)是個(gè)問(wèn)題,我們還沒(méi)有在任何情況下解決。如果我們已經(jīng)記錄了系統(tǒng)調(diào)用的條目,那么我們就擁有了所需的所有信息。但是,如果我們?cè)?restart_syscall 期間附加了,那么我們就不知道x0的原始值。我們唯一的選擇是允許內(nèi)核重新啟動(dòng) syscall ,但這次重啟對(duì)我們來(lái)說(shuō)是低效的,因?yàn)槲覀儫o(wú)法優(yōu)化系統(tǒng)調(diào)用的錄制。
回到GETREGS與GETREGSET的主題:GETHBPREGS和NT_ARM_HW_BREAK也有很大不同。對(duì)于GETHBPREGS請(qǐng)求,使用 ptrace 調(diào)用中的 addr 字段來(lái)請(qǐng)求特定的硬件斷點(diǎn)寄存器。 NT_ARM_HW_BREAK返回所有硬件斷點(diǎn)寄存器。
-
ARM
+關(guān)注
關(guān)注
134文章
9346瀏覽量
376866 -
PCB打樣
+關(guān)注
關(guān)注
17文章
2977瀏覽量
22513 -
華強(qiáng)PCB
+關(guān)注
關(guān)注
8文章
1831瀏覽量
28565 -
華強(qiáng)pcb線路板打樣
+關(guān)注
關(guān)注
5文章
14629瀏覽量
43872
發(fā)布評(píng)論請(qǐng)先 登錄
ARM總共有幾種架構(gòu)?ARM各架構(gòu)之間的區(qū)別在哪?
請(qǐng)教一下大神arm64硬件斷點(diǎn)和arm有哪些區(qū)別?
微軟推出首個(gè)可用于ARM64設(shè)備的x64仿真
ARM64 Linux內(nèi)核頁(yè)表的塊映射

Core 3399Pro JD4文件系統(tǒng)Linux根文件系統(tǒng)鏡像(arm64&arm32)

Core 3399 JD4文件系統(tǒng)Linux根文件系統(tǒng)鏡像(arm64&arm32)

Core 3399KJ Linux根文件系統(tǒng)鏡像(arm64/arm32)

Core 3399J Linux根文件系統(tǒng)鏡像(arm64/arm32)

Core 3399 JD4 V2文件系統(tǒng)Linux根文件系統(tǒng)鏡像(arm64/arm32)

ROC RK3399 PC Pro文件系統(tǒng)Linux根文件系統(tǒng)鏡像(arm64/arm32)

AIO 3399ProC Linux根文件系統(tǒng)鏡像(arm64/arm32)

評(píng)論