avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Re: C aliasing rules


From: Lars Noschinski
Subject: Re: [avr-gcc-list] Re: C aliasing rules
Date: Wed, 19 May 2010 14:10:13 +0200
User-agent: Mutt/1.5.20 (2009-06-14)

Hello!

* David Brown <address@hidden> [10-05-18 21:01]:

Thanks for your answer, David.

> Lars Noschinski wrote:
> >I'm trying to debug a strange problem, which depends on whether a
> >function is inlined (then it's broken) or not (then it's ok). Can
> >someone tell me if the following code snippet violates the C aliasing
> >rules for b1 (declared as uint8_t*, written as uint32_t* by
> >xteaDecrypt)?
[...]
> It's not impossible that this is a bug when inlining such complex
> code (and 32-bit code like this is complex on an 8-bit micro).  It's
> difficult to tell without a compilable code snippet, and some
> indication of the expected results.  If you can, you should look at
> the generated assembly to see if you can figure out what is going
> wrong.  Also try to simplify or remove parts of the code until you
> have a minimal example of the problem.
> 
> While it would be useful to find out about the problem (especially
> if it is a bug that is not already known), code like this does not
> benefit much from being inlined.  It's too complex, and requires too
> many registers - the function call overhead is therefore minimal.
> You could improve the results somewhat by manual restructuring
> (perhaps eliminating the memcpy calls), but unless XTEA_ROUNDS is
> very small, the loop there will dominate everything.

XTEA_ROUNDS is 32 and this code is far from being performance critical,
but code breaking with optimization always makes me nervous ;)

Reading more about strict aliasing issues, especially

    
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
    http://davmac.wordpress.com/2010/02/26/c99-revisited/

I'm fairly sure, that accessing a uint8_t[] via a uint32_t* constitutes
undefined behaviour; the same holds for converting the pointer by use of an
union { uint32_t[2]; uint8_t[8] }; by the gcc (4.3.4) documentation for
-fstrict-aliasing:

|     Similarly, access by taking the address, casting the resulting
|     pointer and dereferencing the result has undefined behavior, even
|     if the cast uses a union type, e.g.:
|          int f() {
|            double d = 3.0;
|            return ((union a_union *) &d)->i;
|          }

So it seems the only correct way is either changing the declaration of
xteaDecryptCbc (i.e. use uint32_t from the beginning) or using memcpy.
Or maybe some playing around with __attribute__((may_alias)).

OTOH, this problem also occurs with -fno-strict-aliasing, so maybe there
is some real bug down there in the compiler. I'll try analyising it
later.

> >If I read http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html
> >correctly, it should violate the rules?
> >
> >// 
> >---------------------------------------------------------------------------
> >void xteaDecrypt(uint32_t v[2], uint32_t const k[4]) {
> >    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*XTEA_ROUNDS;
> >    for (uint8_t i=0; i < XTEA_ROUNDS; i++) {
> >        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]);
> >        sum -= delta;
> >        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]);
> >    }
> >    v[0]=v0; v[1]=v1;
> >}
> >
> >void xteaDecryptCbc(uint8_t v[8], uint8_t cb[8], uint8_t const k[16]) {
> >    static uint8_t tmpbuf[8];
> >    memcpy(tmpbuf, v, 8);
> >    xteaDecrypt((uint32_t*)v, (uint32_t*)k);
> >    for (uint8_t i=0; i < 8; i++)
> >        v[i] ^= cb[i];
> >    memcpy(cb, tmpbuf, 8);
> >}
> >
> >int main(void) {
> >    uint8_t b1[8], b2[8], b3[16];
> >    xteaDecryptCbc(b1, b2 b3);
> >}
> >// 
> >---------------------------------------------------------------------------

  -- Lars



reply via email to

[Prev in Thread] Current Thread [Next in Thread]