Question

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)
Was it helpful?

Solution

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.

EDIT

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.

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.

OTHER TIPS

After some study on ARMV8 architecture, I got deeper understandings about the data abort exception that I met.

  1. 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.

  2. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top