On 5 October 2012 17:01, Rob Herring <robherri...@gmail.com> wrote: > Here's a testcase. Compiled on ubuntu precise with > "arm-linux-gnueabihf-gcc -O2 -marm -march=armv7-a test.c". > > typedef unsigned short u16; > typedef unsigned short __sum16; > typedef unsigned int __u32; > typedef unsigned char __u8; > typedef __u32 __be32; > typedef u16 __be16; > > struct iphdr { > __u8 ihl:4, > version:4; > __u8 tos; > __be16 tot_len; > __be16 id; > __be16 frag_off; > __u8 ttl; > __u8 protocol; > __sum16 check; > __be32 saddr; > __be32 daddr; > /*The options start here. */ > }; > > #define ntohl(x) __swab32((__u32)(__be32)(x)) > #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ > > static inline __attribute__((const)) __u32 __swab32(__u32 x) > { > __asm__ ("rev %0, %1" : "=r" (x) : "r" (x)); > return x; > } > > int main(void * buffer, unsigned int *p_id) > { > unsigned int id; > int flush = 1; > const struct iphdr *iph = buffer; > __u32 len = *p_id; > > id = ntohl(*(__be32 *)&iph->id); > flush = (u16)((ntohl(*(__be32 *)iph) ^ len) | (id ^ IP_DF)); > id >>= 16; > > *p_id = id; > return flush; > }
The problem is the (__be32 *) casts. This is a normal pointer to a 32-bit, which is assumed to be aligned, and the cast overrides the packed attribute from the struct. Dereferencing these cast expressions must be done with the macros from asm/unaligned.h -- Mans Rullgard / mru _______________________________________________ linaro-toolchain mailing list linaro-toolchain@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-toolchain