2014-04-24 16 views
1

我用Linaro的G ++中針對ARM arch64編譯一個簡單的cpp文件:Linaro的G ++ aarch64編譯原因unalignment故障

int main() 
{ 
    char *helloMain  = "main module (crm.c)"; 
    long faculty, num = 12; 
    int stop,mainLoop = 1; 
    char word[80]  = ""; 
} 

objdump後生成的ELF文件時,我得到了它的彙編代碼:

0000000000001270 <main>: 
int main() 
{ 
    1270: d101c3ff sub sp, sp, #0x70 
    char *helloMain  = "main module (crm.c)"; 
    1274: 90000020 adrp x0, 5000 <_malloc_trim_r+0x160> 
    1278: 9111c000 add x0, x0, #0x470 
    127c: f90003e0 str x0, [sp] 
    long faculty, num = 12; 
    1280: d2800180 movz x0, #0xc 
    1284: f90007e0 str x0, [sp,#8] 
    int stop,mainLoop = 1; 
    1288: 52800020 movz w0, #0x1 
    128c: b90013e0 str w0, [sp,#16] 
    char word[80]  = ""; 
    1290: 910063e0 add x0, sp, #0x18 
    1294: 90000021 adrp x1, 5000 <_malloc_trim_r+0x160> 
    1298: 91122021 add x1, x1, #0x488 
    129c: 39400021 ldrb w1, [x1] 
    12a0: 39000001 strb w1, [x0] 
    12a4: 91000400 add x0, x0, #0x1 
    12a8: a9007c1f stp xzr, xzr, [x0] 
    12ac: a9017c1f stp xzr, xzr, [x0,#16] 
    12b0: a9027c1f stp xzr, xzr, [x0,#32] 
    12b4: a9037c1f stp xzr, xzr, [x0,#48] 
    12b8: f900201f str xzr, [x0,#64] 
    12bc: b900481f str wzr, [x0,#72] 
    12c0: 7900981f strh wzr, [x0,#76] 
    12c4: 3901381f strb wzr, [x0,#78] 
} 
    12c8: 52800000 movz w0, #0x0 
    12cc: 9101c3ff add sp, sp, #0x70 
    12d0: d65f03c0 ret 

在ARMV8開發板上執行此代碼之前,sp被初始化爲與0x1000對齊的地址。

這樣的代碼的執行上 12a8而升高的對準錯誤異常:a9007c1f STP XZR,XZR,[X0]

我注意到x0通過0x1加入,使它在被執行stp指令被對準以0x1

爲什麼g ++沒有使它與0x10對齊以避免這種對齊錯誤異常?

的克++版本是:

gcc 4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05) 

回答

2

the manual

-munaligned-access
-mno-unaligned-access

啓用(或禁用)讀取和16-寫入和從32位值不是16位或32位對齊的地址。 默認情況下,對於所有其他體系結構,對於所有ARMv6之前的版本和所有 ARMv6-M體系結構禁用未對齊的訪問,並且啓用。如果 未對齊訪問未啓用,則打包數據結構 中的字將一次訪問一個字節。

ARM屬性Tag_CPU_unaligned_access將在 生成的目標文件中設置爲true或false,具體取決於此選項的 設置。如果啓用了未對齊訪問,那麼 預處理器符號__ARM_FEATURE_UNALIGNED也將被定義。

AArch64/ARMv8支持開箱即用的未對齊訪問,所以GCC認爲它可用。如果情況並非如此,則可能必須使用上述開關明確禁用它。您使用的「預發佈」版本還可能尚未完成,並且存在各種錯誤/問題。

順便提一下,代碼的行爲就像是因爲GCC解釋字面的分配:到緩衝區的開始

  1. 複製字符串「」(所以只是一個零字節)。
  2. 用零填充緩衝區的其餘部分。

我懷疑如果啓用優化,未對齊的訪問將會消失。 或者,如果您使用char word[80] = {0},則應該一次完成調零。

+0

謝謝。我使用'munaligned-access'和'-mno-unaligned-access'選項進行了測試,這些elf文件似乎沒有什麼不同,仍然沒有對齊訪問。但用'char word [80] = {0}替換;'確實有效。 –

+2

請注意,(如下面的答案中所討論的)等效的AArch64選項是-mstrict-align(https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html) –

2

經過對ARMV8架構的一些研究之後,我對我遇到的數據異常異常有了更深入的瞭解。

  1. 爲什麼這樣對齊故障異常會發生?

    正如@IgorSkochinsky所提到的,AArch64/ARMv8支持非對齊訪問。但是當我在一個簡單的裸機環境中工作時,MMU沒有啓用,所以在這種情況下,內存被認爲是一個設備,而設備不支持未對齊的訪問。如果啓用MMU,則此異常消失。

  2. 如何強制GCC編譯未對齊訪問的免費精靈文件?

    從手動,-mno-unaligned-access應該是足夠了,但對於我的GCC版本:

    GCC 4.8.1 20130506(搶鮮)(crosstool的-NG Linaro的-1.13.1-4.8-2013.05 - Linaro的GCC 2013.05)

    它說沒有這樣的選擇。在我的情況下,另一個選項-mstrict-align解決了這個問題。

+0

非常感謝您的發現!我在arm64上的U-boot中遇到了未對齊的訪問異常。正如你所說,我想知道內存是否被視爲設備。 –

+0

事實證明,我的主板通過U-boot配置'CONFIG_SYS_DCACHE_OFF'和'CONFIG_SYS_ICACHE_OFF'故意取消CPU緩存。去除這些後,對齊錯誤消失。再次感謝您的信息。 –