4

I'm using a netif struct (similar to http://www.nongnu.org/lwip/structnetif.html) and I got a question related to the alignment. I noticed that every int start on an address that is a multiplier of 4 (e.g. 0x20010db0). However, let's take a look at the following :

struct netif {

...

u8_t    hwaddr_len (at address 0x20010db8)

u8_t[8] hwaddr (at address 0x20010db9)

u8_t    mtu (at address 0x20010dc1)

...

}

From what I understand, hwaddr_len is align on 4 bytes, hwaddr is "align" on 1 bytes (because it's a u8_t, this isn't align on 4 bytes (32 bits)) and mtu is "align" on 1 byte. After that, all the other member of the struct are align again on 4 bytes. So, I think this should be good, even if hwaddr is not align on a 4 bytes multipler, but when I try to do a memcpy from "src" to hwaddr, I got a unalign access error.

I'm compiling on arm gcc compiler. Is anyone got an idea why it is failing?

Ps : I don't have much knowledge about ARM alignment issues, sorry if my question may seem obvious.

EDIT :

Version of the compiler : gcc-arm-none-eabi-4_9-2015q3

The section where it is failing :

lpwif_get_slla(struct lpwif *lpwif, void *lla, unsigned char lla_len)
{
WpanDeviceP dev = lpwif->dev->wpan;
unsigned char len = 0;

if (lla_len >= 8) {
    if (lpwif->eui[0] == 0xff) {
        /* Fetch WPAN Device's Long Address. */
        uint64_t addr64;
        memset(&addr64, 0xff, sizeof(addr64));
        WpanGet(dev, WpanPibAttr_macExtendedAddress, &addr64, 8);

        /* Always return address in network-byte order */
        lpwif->eui[0] = (addr64 >> 56) & 0xff;
        lpwif->eui[1] = (addr64 >> 48) & 0xff;
        lpwif->eui[2] = (addr64 >> 40) & 0xff;
        lpwif->eui[3] = (addr64 >> 32) & 0xff;
        lpwif->eui[4] = (addr64 >> 24) & 0xff;
        lpwif->eui[5] = (addr64 >> 16) & 0xff;
        lpwif->eui[6] = (addr64 >>  8) & 0xff;
        lpwif->eui[7] = (addr64 >>  0) & 0xff;
    }
    if (lpwif->eui[0] == 0xff) return 0; /* Device has no EUI-64 address. */
    if (lla) memcpy(lla, lpwif->eui, 8);
}

And this method is called by `lpwif_get_slla(&state->lpwif, netif->hwaddr, 8);

Disassembly:

   if (lpwif->eui[0] == 0xff) return 0; /* Device has no EUI-64 address. */

 10098ac:   6bfb        ldr r3, [r7, #60]   ; 0x3c
 10098ae:   f893 3024   ldrb.w  r3, [r3, #36]   ; 0x24
 10098b2:   2bff        cmp r3, #255    ; 0xff
 10098b4:   d101        bne.n   10098ba <lpwif_get_slla+0x10e>
 10098b6:   2300        movs    r3, #0
 10098b8:   e07f        b.n 10099ba <lpwif_get_slla+0x20e>

   if (lla) memcpy(lla, lpwif->eui, 8);

 10098ba:   6bbb        ldr r3, [r7, #56]   ; 0x38
 10098bc:   2b00        cmp r3, #0
 10098be:   d006        beq.n   10098ce <lpwif_get_slla+0x122>
 10098c0:   6bfb        ldr r3, [r7, #60]   ; 0x3c
 10098c2:   3324        adds    r3, #36 ; 0x24
 10098c4:   6bb8        ldr r0, [r7, #56]   ; 0x38
 10098c6:   4619        mov r1, r3
 10098c8:   2208        movs    r2, #8
 10098ca:   4b3f        ldr r3, [pc, #252]  ; (10099c8 <lpwif_get_slla+0x21c>)
 10098cc:   4798        blx r3

    return 8;

 10098ce:   2308        movs    r3, #8
 10098d0:   e073        b.n 10099ba <lpwif_get_slla+0x20e>
artless noise
  • 21,212
  • 6
  • 68
  • 105
David Lefaivre
  • 191
  • 3
  • 14
  • 3
    The `memcpy` will take care of alignment for you. Some ARM cpus have the ability to do unaligned accesses. Are you sure you do not have a conflict between your build and run systems? Can you give 'C' code snippet in use and an assembler list where the un-aligned exception occurs. These details would help someone answer. If you 'lie' about alignment through casting, then the compile might generate code that will cause an 'unaligned' exception. – artless noise Nov 12 '15 at 16:41
  • Can you post the code that it is failing on? – Bobby Sacamano Nov 12 '15 at 16:43
  • What is `src`, and how exactly are you calling `memcpy` (i.e. are there any undefined-behaviour-inducing pointer casts in the code not shown here)? Also, what actual version of GCC are you using? (I believe the ARM backend in some very old versions could sometimes emit incorrect instructions for unaligned loads/stores) – Notlikethat Nov 12 '15 at 16:45
  • It'd be nice to see the instruction address which is causing the fault, plus the read address that's causing the fault, but I'm guessing that which is calling `lpwif_get_slla()` is passing in a casted pointer (that is some non-word aligned buffer) for `lpwif`, and when it's getting `lpwif->eui`, it's trying to do an ldr on a non-word aligned address and barfing. – Russ Schultz Nov 14 '15 at 04:57
  • Hmm, a relatively up-to-date GCC 4.9 could well be configured to target ARMv7 by default. As the first comment alludes to, if you're inadvertently letting the compiler believe that potentially unaligned single-word loads/stores are fine, but then trying to run on something like an ARM9 or Cortex-M0 where that isn't the case, that's likely to cause problems even if the code itself is 100% correct. – Notlikethat Nov 14 '15 at 13:31

1 Answers1

0

Try to replace the memcpy with a copy with a simple for loop. The compiler is probabily optimizing it, assuming it is memory aligned.