Linaro g++ aarch64 编译导致未对齐错误 [英] Linaro g++ aarch64 compilation cause unalignment fault
问题描述
我使用 linaro g++ for ARM arch64 来编译一个简单的 cpp 文件:
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] = "";
}
经过objdump
生成的elf文件,我得到了它的asm代码:
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
在 ARMV8 板上执行此代码之前,sp
被初始化为与 0x1000 对齐的地址.
Before executing this code on an ARMV8 board, sp
is initialized to an address aligned to 0x1000.
此类代码的执行引发了对齐错误异常12a8: a9007c1f stp xzr, xzr, [x0]
The execution of such code raised an alignment fault exception on 12a8: a9007c1f stp xzr, xzr, [x0]
我注意到 x0
是由 0x1
添加的,因此在执行 stp
指令时它与 0x1
对齐.
I noticed x0
was added by 0x1
so it was aligned to 0x1
when stp
instruction was executed.
为什么 g++ 没有让它与 0x10
对齐以避免这种对齐错误异常?
Why g++ didn't make it align to 0x10
to avoid such alignment fault exception?
g++ 版本是:
gcc 4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)
推荐答案
来自 手册:
-munaligned-access
-mno-unaligned-access
启用(或禁用)从非 16 位或 32 位对齐的地址读取和写入 16 位和 32 位值.默认情况下,所有 ARMv6 之前的和所有ARMv6-M 架构,并为所有其他架构启用.如果未启用未对齐访问然后打包数据结构中的字将一次访问一个字节.
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.
ARM 属性 Tag_CPU_unaligned_access 将在生成的目标文件为真或假,取决于此选项的设置.如果启用了未对齐访问,则预处理器符号 __ARM_FEATURE_UNALIGNED 也将被定义.
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 支持开箱即用的未对齐访问,因此 GCC 假定它可用.如果不是这种情况,您可能必须使用上述开关明确禁用它.预发行版"也有可能您使用的版本尚未完成,并且存在各种错误/问题.
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.
编辑
如评论中所述,相应的AArch64 选项是:
As mentioned in the comments, the corresponding AArch64 options are:
-mstrict-align
-mno-strict-align
避免或允许生成可能未在架构规范中描述的自然对象边界上对齐的内存访问.
Avoid or allow generating memory accesses that may not be aligned on a natural object boundary as described in the architecture specification.
顺便说一下,代码的行为是这样的,因为 GCC 从字面上解释了赋值:
By the way, the code behaves like this because GCC interpreted the assignment literally:
- 复制字符串";(所以只有一个零字节)到缓冲区的开头.
- 用零填充缓冲区的其余部分.
我怀疑如果您启用优化,未对齐的访问将消失.或者,如果您使用 char word[80] = {0}
,它应该一次性完成归零.
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屋!