David Lefaivre
David Lefaivre

Reputation: 211

unaligned access with memcpy

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>

Upvotes: 4

Views: 9181

Answers (1)

Davide Capodaglio
Davide Capodaglio

Reputation: 143

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

Upvotes: -1

Related Questions