alignment faults in 3.6
Mans Rullgard
mans.rullgard at linaro.org
Fri Oct 5 18:37:40 EDT 2012
On 5 October 2012 17:01, Rob Herring <robherring2 at 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
More information about the linux-arm-kernel
mailing list