Arm 利纳罗g++;aarch64编译导致未对齐故障

Arm 利纳罗g++;aarch64编译导致未对齐故障,arm,g++,memory-alignment,arm64,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] = ""; } 在生成的elf文件objdump之后,我得到了它的asm代码: 000000000000

我正在使用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]        = "";
}
在生成的elf文件
objdump
之后,我得到了它的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
发件人:

-munalized访问

-mno未对齐访问

启用(或禁用)从非16位或32位对齐的地址读取和写入16位和32位值。 默认情况下,所有ARMv6之前版本和所有 ARMv6-M体系结构,并为所有其他体系结构启用。如果 未启用未对齐访问,则压缩数据结构中的字 每次将访问一个字节

ARM属性标记\u CPU\u未对齐\u访问将在 生成的对象文件为true或false,具体取决于 此选项的设置。如果启用了未对齐访问,则 还将定义未对齐的预处理器符号uuu ARM u FEATURE u

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

编辑

如评论中所述,相应的是:

-mstrict align

-mno严格对齐

避免或允许生成可能不在体系结构规范中描述的自然对象边界上对齐的内存访问

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

  • 将字符串“”复制到缓冲区的开头(因此只有一个零字节)
  • 用零填充缓冲区的其余部分
  • 我怀疑如果启用优化,未对齐的访问将消失。
    或者,如果您使用
    char-word[80]={0}
    ,它应该一次完成调零。

    在对ARMV8体系结构进行了一些研究之后,我对遇到的数据中止异常有了更深的理解

  • 为什么会发生这种对齐故障异常

    正如@IgorSkochinsky所提到的,AArch64/ARMv8支持未对齐的访问。但由于我在一个简单的裸机环境中工作,MMU没有被嵌入,所以在本例中,内存被视为一个设备,设备不支持未对齐的访问。如果启用MMU,则此异常消失

  • 如何强制GCC编译未对齐的免访问elf文件

    在手册中,
    -mno unaligned access
    应该足够了,但对于我的GCC版本:

    gcc 4.8.1 20130506(预释放)(交叉工具NG linaro-1.13.1-4.8-2013.05-linaro GCC 2013.05)

    它说没有这样的选择。在我的例子中,另一个选项
    -mstrict align
    解决了这个问题


  • 谢谢我使用
    munalligned access
    -mno unaligned access
    选项进行了测试,elf文件似乎没有什么不同,仍然具有未对齐的访问权限。但替换为
    char-word[80]={0}确实有效。请注意(如下面的答案中所讨论的),等效的AArch64选项是-mstrict align(),非常感谢您的发现!我在arm64上的U-boot中遇到未对齐访问异常。我想知道内存是否像你说的那样被视为设备。事实证明,我的主板故意通过U-boot配置
    CONFIG\U SYS\U DCACHE\U OFF
    CONFIG\U SYS\U ICACHE\U OFF
    禁用CPU缓存。拆下这些后,对齐故障消失。再次感谢你的帖子。
    gcc  4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)