| Summary: | binutils break C++ in GCC 2.95.x and GCC-current | ||
|---|---|---|---|
| Product: | Base System | Reporter: | pfeifer <pfeifer> |
| Component: | gnu | Assignee: | David E. O'Brien <obrien> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | CC: | pfeifer |
| Priority: | Normal | ||
| Version: | 4.1-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Responsible Changed From-To: freebsd-bugs->obrien Over to maintainer. I've been asked for some clarifications (as the original report was a bit confusing): Both stock FSF/GCC 2.95.2 and current CVS sources of GCC (both without any additional FreeBSD-specific modifications) build fine on FreeBSD 4.1-RELEASE. However, unlike the base FreeBSD 4.1-RELEASE compiler, which is also labeled GCC 2.95.2, both of these unpatched stock versions of GCC generate broken C++ binaries. (Simple C++ code does work, but static constructors, as in the example in this PR do not work properly.) I have not tested any of the versions in our ports collection in any way. Gerald Gerald, as far as I can tell, the breakage occured because FreeBSD is now using architecture-independent crtbegin.c file. As a side effect to this change, crtn.S and crtn.S files are now empty. Consequently, .fini and .init sections in elf output file never get corresponding _init of _fini label and required __asm(ret) instruction never gets appended to it. I am not sure what is the best srategy to use in order to make GCC snapshots to work out of the box on FreeBSD again. I suggest that FreeBSD just should remove it's custom _init and _fini functions from crtbegin.c altogether and use code from GCC stock crtbegin.c file. If I am not mistaken, David O'Brien has this change on his todo list already. For the time being, you may want to check versions 1.3 and 1.2 of crti.S and crtn.o recpectively, compile them and place resulting .o files into your /usr/local/lib/gcc-lib/i386-portbld-freebsd5.0/2.97 directory (or whatever directory is correct for the version of gcc you are using). This will at least will get you going for the time being. If you prefer, I will send you these object files. On Sun, Oct 15, 2000 at 08:30:02AM -0700, Alexander N. Kabaev wrote: > as far as I can tell, the breakage occured because FreeBSD is now using > architecture-independent crtbegin.c file. As a side effect to this change, > crtn.S and crtn.S files are now empty. I tought GCC (as built from FSF sources) provided all the crt foo it needed. I see now, it only provides its own crt{begin,end}.o. -- -- David (obrien@FreeBSD.org) The problem is that our crt foo is incompatable with g++'s constructor
and thread mechanism. In order to get g++ working at yahoo, we had
to back out to the old crt{i,n}.o and use gcc's crt{begin,end}.o
so that the frame hooks etc were called in the right places.
See glibc's own crtbegin/end etc for how to do an elf-specific set
of crt files that remain gcc/g++ compatable.
According to my recollection of the original AT&T/USL manuals that I
have (in Australia) that cover ELF, toolchain, linking, abi's, etc, I
still believe our crt{i,n}.o are broken. We have replaced the extensible
"linker set"-like mechanism that was part of the ELF linking defintion
with a static _init() and _fini() function. Other systems, notably
g++, depend on the original system working. Anyway, I will be checking
out the details in about 2 weeks when I get back to .au and look it up.
-Peter
> The problem is that our crt foo is incompatable with g++'s constructor > and thread mechanism. In order to get g++ working at yahoo, we had > to back out to the old crt{i,n}.o and use gcc's crt{begin,end}.o > so that the frame hooks etc were called in the right places. I disagree. Our custom crtbegin.c was and is indeed incompatible with DWARF2 exception unwinding method GCC is using by default, but our crt1.c, crti.S and crtn.S were working just fine until FreeBSD started to use architecture independent crtbegin.c implementation. Since non-system GCC versions do not use FreeBSD crtbegin.c at all, this incompatibility does not prevent them from working correctly. > According to my recollection of the original AT&T/USL manuals that I > have (in Australia) that cover ELF, toolchain, linking, abi's, etc, I > still believe our crt{i,n}.o are broken. We have replaced the extensible > "linker set"-like mechanism that was part of the ELF linking defintion > with a static _init() and _fini() function. All that previous versions of crti.S and crtn.S files were doing is they were providing function prologue (function name label) and epilogue (ret instruction) for compiler generated .init and .fini sections. The way compiler generates .init and .fini sections is indeed similar to linker sets. Our startup files were working OK with any version of GCC as long as GCC .init|.fini section with all initialization calls it needs. The new platform independent implementation does not use these sections anymore and implements it's own _init and _fini functions instead. That is IMHO wrong not only because it breaks GCC but also because crtbegin.o will require modification each time GCC developers add feature which requires non-trivial initialization at startup time. Presenting .init and .fini sections as functions allows us to call them from crt1.c right before and after _main. Alternatively, ld.so dynamic loader could be changed to run contents of these sections at the module load time but that way we will lose the possibility to run some other code (such as profiling related initialization) before constructors are run. Changing dynamic loader is not feasible at this point anyway because it will introduce severe backwards binary compatibility problems without providing any significant advantage. State Changed From-To: open->closed done |
[ This is a resend of 20942 which was forwarded to the mailing list but then lost by the GNATS machinery. Suggested by sheldonh. ] Apparently binutils as of 4.1-RELEASE break static constructors in C++ for GCC 2.95.x and GCC-current. Both work fine (w/o FreeBSD patches) on FreeBSD 3.x and also GCC 2.95.2 as shipped with 4.1-RELEASE is fine. You'll experience the problem only, if you build GCC by yourself. I assume that there is a problem (change) in binutils on 4.1-RELEASE that causes this breakage and that has been fixed (also made) in the imported version of GCC? Fix: 1. Fix (the local copy?) of binutils. 2. If it is a GCC bug (which I don't believe) that has been fixed in the FreeBSD tree, submit the change back to the GCC maintainers. How-To-Repeat: Compile and run the following small C++ program with either GCC 2.95.2 (original GNU version, w/o FreeBSD patches) or GCC-current and you'll get a core dump as the static constructor is not invoked. GCC as shipped with 4.1-RELEASE is not affected. -------- cut -------- #include <map> #include <iostream> struct NAMESTABLE { map<int,int> lookup; NAMESTABLE() : lookup() { cout << "constructor" << endl; } void add(const char *s, const int &item) { cout << s << endl; lookup.insert(pair<int,int>(item,0)); } }; NAMESTABLE q; int main() { NAMESTABLE p; p.add("auto",1); q.add("static",1); }