[uClinux-dev] Nasty compiler bug when using shared libraries

Paul McGougan paul.mcgougan at braintree.com.au
Thu Oct 13 03:46:34 EDT 2005


Hiya All,

We've found what looks to be a nasty compiler bug using the
m68k-elf-20030314 toolchain from uClinux.org compiling for Coldfire 5272.

I've included some test code produced by one of the guys here that shows the
fault and his analysis of it.

His code has comparisons between examples that both work and don't work, and
includes the disassembly where you can clearly see what is wrong.

Has anyone seen this before; know any fixes; or any advice?

-- Start Included Text --

The problem actually seems to be caused by a "throw()" declaration in a
constructor, not the templates as I originally thought (it just happens that
the place that's used is by the STL templates).

My test file:

class nothrow
{
public:
   nothrow() throw();

   int *p;
};

nothrow::nothrow() throw() : p(0)
{
}


class throws
{
public:
   throws();

   int *p;
};

throws::throws() : p(0)
{
}

Compiled with g++ 2.95.3:
m68k-elf-g++ -mid-shared-library -mshared-library-id=1 -fomit-frame-pointer 
-Os -g -c test.cpp

00000000 <__7nothrow>:
   0:   2a6d fff8       moveal %a5@(-8),%a5 <- changes a5 without saving!
   4:   206f 0008       moveal %sp@(8),%a0 <- tries to get this ptr from
wrong place on stack!
   8:   4290            clrl %a0@
   a:   2008            movel %a0,%d0
   c:   4e75            rts

0000000e <__6throws>:
   e:   206f 0004       moveal %sp@(4),%a0
  12:   4290            clrl %a0@
  14:   2008            movel %a0,%d0
  16:   4e75            rts
  18:   4e71            nop

However when compiled with g++ 3.4.0:
m68k-elf-g++ -mid-shared-library -mshared-library-id=1 -fomit-frame-pointer 
-Os -g -c test.cpp

00000000 <_ZN7nothrowC2Ev>:
   0:   206f 0004       moveal %sp@(4),%a0
   4:   4290            clrl %a0@
   6:   4e75            rts

00000008 <_ZN7nothrowC1Ev>:
   8:   206f 0004       moveal %sp@(4),%a0
   c:   4290            clrl %a0@
   e:   4e75            rts

00000010 <_ZN6throwsC2Ev>:
  10:   206f 0004       moveal %sp@(4),%a0
  14:   4290            clrl %a0@
  16:   4e75            rts

00000018 <_ZN6throwsC1Ev>:
  18:   206f 0004       moveal %sp@(4),%a0
  1c:   4290            clrl %a0@
  1e:   4e75            rts

As you can see, both versions are identical, so the bug appears to be fixed.
As a side note, I have no idea why it creates two symbols for each
constructor?

As a reference, 2.95.3 produced identical code for both constructors when
using -msep-data rather than -mid-shared-library:

00000000 <__7nothrow>:
   0:   206f 0004       moveal %sp@(4),%a0
   4:   4290            clrl %a0@
   6:   2008            movel %a0,%d0
   8:   4e75            rts
   a:   4e71            nop

0000000c <__6throws>:
   c:   206f 0004       moveal %sp@(4),%a0
  10:   4290            clrl %a0@
  12:   2008            movel %a0,%d0
  14:   4e75            rts
  16:   4e71            nop

So it appears that the bug is strictly caused by the nothrow() spec
and -mid-shared-library. To test this conclusion, I tried just a normal
function with a throw() specification and -mid-shared-library:

void testfn(int *a) throw()
{
   *a = 0;
}

00000000 <testfn__FPi>:
   0:   2a6d fff8       moveal %a5@(-8),%a5 <- again, clobbers a5
   4:   206f 0008       moveal %sp@(8),%a0 <- again, gets arg from wrong
place
   8:   4290            clrl %a0@
   a:   4e75            rts

And to prove templates work properly:

template <typename T>
class templ
{
public:
   templ() : p(0) {}

   T *p;
};

class inherit : public templ<int>
{
public:
   inherit();
};

inherit::inherit()
{
}

00000000 <__7inherit>:
   0:   206f 0004       moveal %sp@(4),%a0
   4:   4290            clrl %a0@
   6:   2008            movel %a0,%d0
   8:   4e75            rts
   a:   4e71            nop

Conclusion:

The throw() specification in combination with -mid-shared-library is
completely broken in 2.95.3 but fixed in 3.4.0. This affects us when
inheriting from std::vector as the constructor for allocator is marked as
throw() when exceptions are disabled (and of course we are disabling
exceptions).

The fact the work around we have (call an empty function in our constructor
body) works in this scenario is a mystery to me. When I tried it in other
scenarios the outputted code was seriously broken, far worse than the
original. It looks like we just lucked out.
-- End Included Text --

Thoughts?

Paul McGougan
Technology Development Manager
Braintree Communications Pty Ltd
--
This information together with any attachments is for the use of the
intended recipient(s) only and may contain confidential and/or privileged
information and is subject to copyright. If you have received this email in
error please inform the sender as quickly as possible and delete this email
and any copies of this information from your computer system network. If you
are not the intended recipient of this email, you must not copy, distribute
or take any action(s) that relies on this information. Any form of
disclosure, modification, distribution and/or publication of this email is
strictly prohibited.




More information about the uClinux-dev mailing list