Linaro g ++ aarch64编译会导致未对齐错误 [英] Linaro g++ aarch64 compilation cause unalignment fault

查看:926
本文介绍了Linaro g ++ aarch64编译会导致未对齐错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Linaro g ++来编译一个简单的cpp文件:

  int main()
{
char * helloMain =主模块(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 添加的,因此它与 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)


解决方案

From 手册


-munaligned -access

-mno-unaligned-access



启用(或禁用)从非16位或32位对齐的地址读取和写入16位和32位值。
默认情况下,对于所有ARMv6之前的版本和所有
ARMv6-M体系结构,禁用未对齐访问,并对所有其他体系结构启用。如果未启用
未对齐访问,则打包数据结构
中的字将一次访问一个字节。
$ b ARM属性Tag_CPU_unaligned_access将在
生成的目标文件中设置为true或false,具体取决于此选项的
设置。如果启用了未对齐访问,那么还会定义
预处理器符号__ARM_FEATURE_UNALIGNED。


AArch64 / ARMv8支持未对齐访问框,所以GCC认为它可用。如果情况并非如此,则可能必须使用上述开关明确禁用它。还有可能您使用的预发布版本还没有完成,并且存在各种错误/问题。

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


  1. 将字符串(只是一个零字节)复制到缓冲区的开头。 / li>

  2. 我怀疑如果启用优化,未对齐的访问将消失。
    或者,如果您使用字符单词[80] = {0} ,它应该一次完成调零。


    I'm using linaro g++ for ARM arch64 to compile a simple cpp file:

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

    After objdump the generated elf file, I got its asm code:

    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
    

    Before executing this code on an ARMV8 board, sp is initialized to an address aligned to 0x1000.

    The execution of such code raised an alignment fault exception on 12a8: a9007c1f stp xzr, xzr, [x0]

    I noticed x0 was added by 0x1 so it was aligned to 0x1 when stp instruction was executed.

    Why g++ didn't make it align to 0x10 to avoid such alignment fault exception?

    The g++ version is:

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

    解决方案

    From the manual:

    -munaligned-access
    -mno-unaligned-access

    Enables (or disables) reading and writing of 16- and 32- bit values from addresses that are not 16- or 32- bit aligned. By default unaligned access is disabled for all pre-ARMv6 and all ARMv6-M architectures, and enabled for all other architectures. If unaligned access is not enabled then words in packed data structures will be accessed a byte at a time.

    The ARM attribute Tag_CPU_unaligned_access will be set in the generated object file to either true or false, depending upon the setting of this option. If unaligned access is enabled then the preprocessor symbol __ARM_FEATURE_UNALIGNED will also be defined.

    AArch64/ARMv8 supports unaligned access out of box, so GCC assumes it's available. If this is not the case, you may have to disable it explicitly with the above switch. It's also possible that the "prerelease" version you're using is not quite finished yet and various bugs/issues are present.

    By the way, the code behaves like this because GCC interpreted the assignment literally:

    1. Copy the string "" (so just a single zero byte) to the start of the buffer.
    2. Fill the rest of the buffer with zeroes.

    I suspect that if you enable optimizations, the unaligned access will be gone. Or, if you use char word[80] = {0}, it should do the zeroing in one go.

    这篇关于Linaro g ++ aarch64编译会导致未对齐错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆