簡體   English   中英

ARM未對齊的內存訪問解決方法

[英]ARM unaligned memory access workaround

我必須將源代碼移植到運行Linux的ARM平台。 不幸的是,我遇到了未對齊的內存訪問問題。 源使用指針強制轉換和訪問。

像下面這樣的代碼像病毒一樣遍布代碼庫。 由於gcc -Wcast-align命令行選項,我可以查明有問題的位置,但是有超過一千個實例要經歷。

u = (IEC_BOOL);
(((*(IEC_LINT*)pSP).H < b.H) 
   || (((*(IEC_LINT*)pSP).H == b.H) && ((*(IEC_LINT*)pSP).L < b.L) )) ? 1 : 0);
*(IEC_DWORD OS_SPTR *)pSP = 
    (IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP >> u);  
*(IEC_DWORD OS_SPTR *)pSP = 
    (IEC_DWORD)(*(IEC_DWORD OS_SPTR *)pSP << -u);  
u = (IEC_BYTE)((*(IEC_DINT*)pSP != b) ? 1 : 0);  
*(IEC_DWORD*)pSP = (IEC_DWORD)(*(IEC_DWORD*)pSP & w);  
(*(IEC_ULINT*)pSP).H += u.H;   
(((*(IEC_ULINT OS_SPTR *)pSP).H == b.H) 
    && ((*(IEC_ULINT OS_SPTR *)pSP).L > b.L))) ? 1 : 0);
u = (IEC_BYTE)((*(IEC_REAL*)pSP >= b) ? 1 : 0);

使用echo 2 > /proc/cpu/alignment on會使Linux內核修復問題,但應用程序的性能會降低到不再可接受的程度。

我在網上搜索了類似於GCC(v4.4.1)編譯器的__unaligned__packed關鍵字,但截至目前為止空了。

我認為很多問題的代碼行可以通過一個或多或少復雜的正則表達式/替換來修復,但是現在,經過一段時間的努力,我看到,這種方法也將需要大量繁瑣的工作。

你們有什么建議如何完成這項工作? 我認為一個gcc 4.5編譯器插件會有點矯枉過正但是有沒有比正則表達式好的東西? 您能提出哪些其他建議? 不一定所有問題實例都必須修復,因為我仍然可以依賴內核來處理一些罕見的情況。

__attribute__((__packed__))這可能在某些情況下有所幫助,但我真的認為這段代碼應該比以后更早清理,因為你可能會花更多的時間解決問題而不是修復它一勞永逸。

哇,這是一個不聖潔的混亂。 擺弄編譯器不會讓你到處都是。 代碼在所有體系結構上都是非法的,但恰好在某些體系結構上工作(例如x86)。 我會修復代碼本身。

可悲的是,沒有辦法做到這一點。 但是,您可以通過一長串搜索和替換獲得很長的路要走,然后手動修復其余部分。 我首先刪除這些數據類型的聲明,所以如果你編譯錯過的任何代碼,那就錯了。 然后,搜索和替換“*(IEC_DWORD OS_SPTR *)pSP =”“set_dword(pSP,” 。)使用內聯函數“set_dword”來做正確的事情。繼續執行盡可能多的易於更換的代碼段。你可以想象。仍然有大量的手工修理。

我能想到的唯一另一種方法就是編譯器插件,正如你的建議,並使整個編譯單元中的每個指針都有對齊1.編譯器然后將字節加載/存儲所有內容。 它最終可能不僅僅是你想要的代碼。 這可能不像聽起來那么容易實現。

我們可以假設問題源於ARM是32位機器而Linux盒子以64位模式運行的事實,或者代碼可以假設它是在16位機器上運行。

一種方法是查看訪問的底層結構。 成員“H”和“L”可能是32位類型,可以像64位一樣進行訪問。

嘗試修改L和H的類型以使代碼表現得更好。

(不可否認,這是一個空洞,因為代碼片段沒有透露應用程序的細節,也沒有透露底層結構。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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