This is the mail archive of the ecos-devel@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Strange __cxa_pure_virtual problem


>>>>> "John" == John Dallaway <john@dallaway.org.uk> writes:

    John> Hi Uwe (and Bart)

    <snip>

    John> Bart, do you have any ideas why your implementation of
    John> __cxa_pure_virtual() in CYGPKG_INFRA might be ignored?

It is not necessarily being ignored. The eCos version of
__cxa_pure_virtual() ends up in libtarget.a, which is part of the same
linker script GROUP() as libsupc++.a. So strictly speaking the linker
is perfectly at liberty to choose one or the other. Normally I would
expect it to pick whichever it came across first while reading in the
library archives, which would mean the eCos libtarget.a one. I have no
idea why changing the compiler optimization level would affect the
linker behaviour.

A couple of points:

1) __cxa_pure_virtual() is actually pretty useless, except possibly as
a debugging tool. It is intend to catch the case where application
code calls a virtual function for an object that is still being
constructed, Ideally its use could be suppressed at compile-time, but
even if we submitted a compiler patch for this it would not help any
time soon.

2) it might be possible to fix the problem in the linker by making the
library search order more deterministic. If the linker is not going to
be deterministic about this then it should probably issue a warning
about ambiguous duplicate definitions in libraries. Again that is not
going to help anytime soon.

3) arguably __cxa_pure_virtual() should have been removed from libsupc++
in the prebuilt toolchains. But we don't want to respin toolchains for
this, and anyway that would not help with the synthetic target where
we want people to be able to use the existing Linux toolchain whenever
possible.

4) since __cxa_pure_virtual() should never get called in correctly
written code we could have a dummy symbol definition at an invalid
location. That is what -Wl,--defsym -Wl,__cxa_pure_virtual=0 achieves,
it tells the linker that __cxa_pure_virtual() can be found at location
0x0. The same could be achieved in the linker script. But 0x0 may not
always be a sensible NULL location, some targets may have real code
there. Plus, we don't want to start messing about with the linker
flags for all targets, nor the linker scripts for all architectures
and possibly all targets.

So, I think there is one solution (untested) that may work:

----------------------------------------------------------------------------
2009-08-07  Bart Veer  <bartv@ecoscentric.com>

	* cdl/infra.cdl: move __cxa_pure_virtual() into extras.o to
	prevent linker ambiguity with the libsupc++ version.

Index: cdl/infra.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/infra/current/cdl/infra.cdl,v
retrieving revision 1.18
diff -u -p -r1.18 infra.cdl
--- cdl/infra.cdl	29 Jan 2009 17:49:44 -0000	1.18
+++ cdl/infra.cdl	7 Aug 2009 13:30:03 -0000
@@ -59,7 +59,8 @@ cdl_package CYGPKG_INFRA {
     compile startup.cxx prestart.cxx pkgstart.cxx userstart.cxx      \
             dummyxxmain.cxx null.cxx simple.cxx fancy.cxx buffer.cxx \
             diag.cxx tcdiag.cxx memcpy.c memset.c delete.cxx eprintf.c \
-	    pure.cxx gccsupport.cxx
+            gccsupport.cxx
+    compile -library=libextras.a pure.cxx
 
 
     # ====================================================================
----------------------------------------------------------------------------

Basically this moves pure.cxx from libtarget.a to
libextras.a/extras.o. That means the eCos version will be part of a .o
file so will automatically be part of the executable with no need for
searching libraries, so the libsupc++ version will never be
considered. If __cxa_pure_virtual() is never used then linker garbage
collection should take care of it.

The disadvantage is that any dependencies of __cxa_pure_virtual() will
get resolved before linker garbage collection takes place, so if any
of those dependencies involve C++ static constructors or anything else
covered by a linker script KEEP() then we have added bloat to the
system. Looking at the current implementation:

----------------------------------------------------------------------------
extern "C" void
__cxa_pure_virtual(void)
{
    CYG_FAIL("attempt to use a virtual function before object has been constructed");
    for ( ; ; );
}
----------------------------------------------------------------------------

in a production build (CYGDBG_USE_ASSERTS disabled) CYG_FAIL() maps to
CYG_EMPTY_STATEMENT so no problem there. In a debug build we are
likely to pull in cyg_assert_msg() and cyg_assert_fail(), which means
all of diag_printf() and its dependencies. That is not actually too
serious. For anything except a minimal configuration there should be
other asserts in the system so those functions will get pulled in
anyway. However, for a minimal debug configuration we may have bloated
the system. We need to consider whether that is acceptable, or whether
we should remove the CYG_FAIL() line from the function - given that
__cxa_pure_virtual() serves little purpose anyway.

This assumes moving pure.cxx to libextras.a fixes the problem.
Hopefully somebody will try this in the near future.

Bart

-- 
Bart Veer                                   eCos Configuration Architect
eCosCentric Limited    The eCos experts      http://www.ecoscentric.com/
Barnwell House, Barnwell Drive, Cambridge, UK.      Tel: +44 1223 245571
Registered in England and Wales: Reg No 4422071.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]