问题
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)
回答1:
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:
- Copy the string "" (so just a single zero byte) to the start of the buffer.
- 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.
回答2:
After some study on ARMV8 architecture, I got deeper understandings about the data abort exception that I met.
Why did this align fault exception occur?
As @IgorSkochinsky has mentioned, AArch64/ARMv8 supports unaligned access. But as I'm working on a simple bare-metal environment, MMU wasn't enbaled, so in this case, memory is regarded as a device, and device doesn't support unaligned access. If MMU is enabled, this exception is gone.
How to force GCC to compile an unaligned-access free elf file?
From the manual,
-mno-unaligned-access
should be enough, but for my GCC version:gcc 4.8.1 20130506 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2013.05 - Linaro GCC 2013.05)
it says there's no such option. In my case, another option
-mstrict-align
solved this problem.
来源:https://stackoverflow.com/questions/23266411/linaro-g-aarch64-compilation-cause-unalignment-fault