Link C++-Library dynamically with gcc crosscompiler

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
hrniels
Member
Member
Posts: 53
Joined: Wed Nov 05, 2008 5:18 am
Location: Marburg, Germany

Link C++-Library dynamically with gcc crosscompiler

Post by hrniels »

Hi!

I'm trying to link my small C++-"standard"-library dynamically to my C++-user-applications. I have a working gcc crosscompiler and use libgcc and libsupc++ of it. When I link statically everything works.
Its not easy for me to describe the problem because there are many, depending on how I do things. But I'll try :)
So, gcc provides the crtbegin.o and crtend.o for me with .init and .fini, __do_global_ctors_aux, frame_dummy etc.. I provide the crt0.o with the _start symbol and some additional os-specific stuff. To build a real function in .init and .fini I provide a crt1.o and crtn.0 as well. They simply add the function-prolog and -eiplog to the calls of frame_dummy, __do_global_ctors_aux and __do_global_dtors_aux. To achieve that I tell gcc about the files in my gcc-config:

Code: Select all

#undef	STARTFILE_SPEC
#define STARTFILE_SPEC "%{shared|pie:crt0S.o%s;:crt0.o%s} %{shared:crt1S.o%s;:crt1.o%s} %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"

#undef	ENDFILE_SPEC
#define ENDFILE_SPEC "%{shared|pie:crtendS.o%s;:crtend.o%s} %{shared:crtnS.o%s;:crtn.o%s}"
(Inspired by the linux-way of doing it)
So far, so good. As you can see, I want to use different files (crt*S.o) when building a shared library (like linux does). There's the first problem: who should provide crtbeginS.o and crtendS.o? Since gcc gives me crtbegin.o and crtend.o, I guess, gcc should give me that files, too. But how do I tell that gcc?

At the moment I have created a symlink from crtbeginS.o to crtbegin.o and the same for crtend. But that can't really work in the end. But anyway, perhaps there are other problems as well; therefore I'll tell you how I build the libstdc++.so and so on:

Code: Select all

i586-elf-escape-g++ -nodefaultlibs -shared -Wl,-soname,libstdc++.so -o libstdc++.so <many objectfiles> -lc -lsupc++ -lgcc -L../../build/dist/lib
(the object files are created with -fPIC)
I.e. since I don't specify -nostartfiles the crt*S.o are put into it, too. If I specify that flag ld complains about that __dso_handle is missing. When I look into the libstdc++.so of linux, there seem to be no startfiles except the stuff in .init and .fini. But I don't know how they achieve that; or in other words: why are there no references of __dso_handle? (they are put into my lib because I have some static objects for which the constructor is called at startup. This constructor has a call to atexit with __dso_handle as argument)
In this way it "works" so far. But I get a warning-message:

Code: Select all

/home/hrniels/escape/source/build/dist/bin/../lib/gcc/i586-elf-escape/4.4.3/../../../../i586-elf-escape/bin/ld: warning: cannot find entry symbol _start; defaulting to 00002820
Thats correct, because I skip that symbol for shared libraries. When I don't skip it, the linker complains about "multiple definitions" when I try to link a userapp to libstdc++.so. There are some similar issues even without _start. If I try to link a userapp with the following:

Code: Select all

i586-elf-escape-g++ -o user_cpptest.bin cppmain.o
I get:

Code: Select all

/home/hrniels/escape/source/build/dist/bin/../lib/gcc/i586-elf-escape/4.4.3/crtend.o:(.dtors+0x0): multiple definition of `__DTOR_END__'
/home/hrniels/escape/source/build/dist/bin/../lib/gcc/i586-elf-escape/4.4.3/../../../../i586-elf-escape/lib/libstdc++.so:/home/hrniels/escape/source/cross/src/gcc/libgcc/../gcc/unwind-dw2-fde.c:228: first defined here
/home/hrniels/escape/source/build/dist/bin/../lib/gcc/i586-elf-escape/4.4.3/../../../../i586-elf-escape/bin/ld: error in /home/hrniels/escape/source/build/dist/bin/../lib/gcc/i586-elf-escape/4.4.3/../../../../i586-elf-escape/lib/libstdc++.so(.eh_frame); no .eh_frame_hdr table will be created.
/home/hrniels/escape/source/build/debug/user/cpp/cpptest/./cppmain.o: In function `main':
/home/hrniels/escape/source/user/cpp/cpptest/cppmain.cpp:67: undefined reference to `__dynamic_cast'
/home/hrniels/escape/source/user/cpp/cpptest/cppmain.cpp:77: undefined reference to `__dynamic_cast'
/home/hrniels/escape/source/user/cpp/cpptest/cppmain.cpp:157: undefined reference to `typeinfo for int'
/home/hrniels/escape/source/user/cpp/cpptest/cppmain.cpp:66: undefined reference to `typeinfo for int'
collect2: ld returned 1 exit status
I'm not sure whats correct and whats wrong here.

I hope I've described the problem well enough. If not, feel free to ask :)
Thanks in advance!
hrniels
hrniels
Member
Member
Posts: 53
Joined: Wed Nov 05, 2008 5:18 am
Location: Marburg, Germany

Re: Link C++-Library dynamically with gcc crosscompiler

Post by hrniels »

After working on other things, I tried to solve this problem again. And I managed to solve it :)
To be honest, I can't explain every problem I had before and why its gone now. But heres how I do it now:
Link the libstdc++.so via:

Code: Select all

i586-elf-escape-ld -shared -soname libstdc++.so -o libstdc++.so <objectfiles> -lc
Additionally I supply the symbol __dso_handle in this library:

Code: Select all

void *__dso_handle;
Finally I can link user-apps with:

Code: Select all

i586-elf-escape-g++ -o user_cpptest.bin cppmain.o -lstdc++ -L../../build/dist/lib/ -lsupc++
Note that I explicitly specify libstdc++ here. Otherwise I get undefined references to operator new and delete (this problem occurrs when I link statically, too). I haven't figured out why this happens (since libstdc++ is linked implicitly anyway), but I guess it has something to do with the order of libstdc++ and libsupc++.

Some words to the start-files: Shared libraries of course don't need __do_global_ctors_aux, frame_dummy and so on anyway (and no start-symbol either). And I don't need a shared-version of crtbegin.o and crtend.o because all thats happening in there is linked statically to the app (libsupc++-stuff, constructors in the app itself, ...). Constructors of shared-libraries are called by my dynamic linker via the .ctors-section.
Unfortunatly it still doesn't work when building libstdc++.so with g++. Same problems as before. It always expects a start-symbol. My guess is that my gcc is perhaps configured in the wrong way, so that -shared doesn't really work or something like that?

Anyway, in the end its really simple, as you can see. But wasn't easy to get there :)
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Link C++-Library dynamically with gcc crosscompiler

Post by pcmattman »

I haven't figured out why this happens (since libstdc++ is linked implicitly anyway), but I guess it has something to do with the order of libstdc++ and libsupc++.
In your "gcc-config" you define start files and end files, but did you know you also specify implicit library selection as well? This allows you to take parameters on the command line and add extra libraries without requiring user intervention. I've seen it used in Linux in order to implicitly choose a debug libc if -g[1..n] is passed, and this is also used for things like the "-pthread" parameter to point to the right system pthreads library.

Might be worth looking into in the future.
hrniels
Member
Member
Posts: 53
Joined: Wed Nov 05, 2008 5:18 am
Location: Marburg, Germany

Re: Link C++-Library dynamically with gcc crosscompiler

Post by hrniels »

pcmattman wrote:In your "gcc-config" you define start files and end files, but did you know you also specify implicit library selection as well? This allows you to take parameters on the command line and add extra libraries without requiring user intervention. I've seen it used in Linux in order to implicitly choose a debug libc if -g[1..n] is passed, and this is also used for things like the "-pthread" parameter to point to the right system pthreads library.
No, didn't know that. I will take a look at it. Thanks!
Post Reply