2
votes

Target: ARM Cortex-A9
GCC Version: 4.9.2

Hello everyone,

I have a problem with GCC producing core that causes data aborts because of unaligned accesses. I isolated a piece of code that shows the problem. I don't know how to make GCC to handle this correctly. Help would be appreciated!

struct B
{
    char c1;
    char c2;
    char c3;
    char c4;
};

struct A
{
    char c;
    struct B b;
    char c2;
};

int main(int argc, char** argv)
{
    struct A a;
    a.c2 = 42;    // Works fine
    a.b.c1 = 42   // Works fine, too
    struct B b;
    b = a.b;      // Crashes because of unaligned access
    return 0;
}

The memory layout looks like this:

a           struct A    48  S:0x3FFFFFE0    R/W
  c         char        8   S:0x3FFFFFE0    R/W
  b         struct B    32  S:0x3FFFFFE1    R/W
    c1      char        8   S:0x3FFFFFE1    R/W
    c2      char        8   S:0x3FFFFFE2    R/W
    c3      char        8   S:0x3FFFFFE3    R/W
    c4      char        8   S:0x3FFFFFE4    R/W
  c2        char        8   S:0x3FFFFFE5    R/W

Now for the first two assignments commands like

a.c2 = 42;     : STRB     r3,[r11,#-7]       with r11 = 0x3FFFFFEC

are produced and they work fine.

However, for the last assignment,

b = a.b;       : LDR      r0,[r2,#0]         with r2 = 0x3FFFFFE1

is produced what results in a data abort because of unaligned access. GCC issues no warnings or anything about that.

Does anyone know how to fix that?

Btw., alignment attributes in all struct declarations is not an option in my project.

1
Seems to work ideone.com/vr3Szyimreal
What particular build/configuration of GCC are you using, with what invocation options, and under what circumstances have you got the SCTLR.A bit set, or are accessing something other than normal memory, to cause an unaligned LDR to fault at all (given that it's a v7 core)?Notlikethat
The program itself is perfectly valid C++, so there shouldn't be any warnings.eerorika
I see this as a bug in GCC. A work around is to force B to word-aligned.user3528438
@Keith It's not a bug, GCC will just optimise a 4-byte memcpy into a single pair of 32-bit load/store instructions when it believes it's targeting a v7 core operating on normal memory such that alignment doesn't matter (just as it would on x86). The real question is what aspect of the OP's system caused that assumption to be false.Notlikethat

1 Answers

3
votes

If you use -mno-unaligned-access you get the correct result.

It was a surprise to me that it didn't do this by default as it's so oftenly wrong to do unaligned memory access on arm.