Linaro g ++ aarch64编译导致不对齐错误

时间:2014-04-24 10:34:24

标签: arm g++ memory-alignment arm64

我正在使用linaro g ++ for ARM arch64来编译一个简单的cpp文件:

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

objdump生成的elf文件之后,我得到了它的asm代码:

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,因此在执行0x1指令时它与stp对齐。

为什么g ++没有与0x10对齐以避免这种对齐错误异常?

g ++版本是:

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

2 个答案:

答案 0 :(得分:2)

来自the manual

  

-munaligned-access
  -mno-unaligned-access

     

启用(或禁用)从非16位或32位对齐的地址读取和写入16位和32位值。   默认情况下,对所有pre-ARMv6及所有ARMv6禁用未对齐访问   ARMv6-M架构,并为所有其他架构启用 。如果   未打开未对齐的访问权限,然后打包数据结构中的单词   将一次访问一个字节。

     

将在中设置ARM属性Tag_CPU_unaligned_access   生成的对象文件为true或false,具体取决于   设置此选项。如果启用了未对齐访问,则启用   预定义符号__ARM_FEATURE_UNALIGNED也将被定义。

AArch64 / ARMv8支持开箱即用的未对齐访问,因此GCC认为它可用。如果不是这种情况,您可能必须使用上述开关明确禁用它。你正在使用的“预发布”版本也可能尚未完成,并且存在各种错误/问题。

顺便说一下,代码的行为是这样的,因为GCC按字面解释了赋值:

  1. 将字符串“”(只有一个零字节)复制到缓冲区的开头。
  2. 用零填充缓冲区的其余部分。
  3. 我怀疑如果你启用了优化,那么未对齐的访问将会消失。 或者,如果您使用char word[80] = {0},它应该一次性进行归零。

答案 1 :(得分: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解决了这个问题。