C++ code (v5.7) link to C library (v5.8) on SunOS 5.10
Hello,
I have a 3rd party shared library compiled using Sun C v5.8 (on SunOS 5.10). It comes in 2 flavors: shared object and static lib.
I compile my C test code using Sun C++ v5.7 (also on SunOS 5.10). Regardless of whether I link to the shared object or static lib, the result is the same: the program segmentation faults when I run it.
I use sun studio to load the program and core dump and the error message is something I don't understand:
program terminated by signal SEGV (no mapping at the fault address)
0x0811d516: __cplus_fini_at_exit+0x007a:addb%al,(%eax)
If I were to use Sun C v5.7 to compile my C test code and to link to the Sun C v5.8 library, I have no problems with either the static or dynamic library.
I thought it was a compiler incompatibility issue between v5.7 and v5.8. But I was unable to find any of such info in the Sun C/C++ data sheets.
The frustrating thing is if I were to use the C++ compiler to compile my C test code into object code, and THEN use the Sun C v5.7 to link my object code together with either the static or dynamic 3rd library, the program will run fine. I assume that indicates that I also don't have any potential name-mangling problem either.
Using the C v5.7 compiler for production compile-and-link is out of the question as my actual source code is written using C++.
Is there some sort of switch I need to turn on when using the C++ compiler to do this kind of job?
By the way, just to test things, I wrote a C function and generated a dynamic library using Sun C v5.7. Next, I wrote my main function (again in C) to invoke the function in the dynamic library. I compiled my main program to link with the dynamic library using Sun C++ v5.7. IThis test program also ran fine. And I don't have to use any special switches either.
Thanks in advance.
# 1
Hi
Why don't you use CC 5.8 to link your app? That should solve your problems.
Note that if an app uses C++ at all, you should compile and link main() with CC, not cc. Otherwise you may have problems with the creation and destruction of global C++ objects (like standard streams). If you really need a C main, just make a tiny C++ main that simply calls 'extern "C" cmain(int argc char **argv)', and then write your C main as cmain.
Paul
# 2
Dear Paul,
Good point, I missed mentioning that in my post.
I work for a company where our current compiling platform is Sun C++ v5.7. I can't just use CC v5.8 for my project and CC v5.7 for the rest of the code. It's either CC v5.7 or CC v5.8 for everything. And there's alot of code written, which is shared between different departments, different offices and different countries. I don't want to go there unless I have exhaust all alternatives.
The 3rd party library is a C library. All my production code is in C++. Compiling and linking to the 3rd party library using CC v5.7 results in segmentation fault which I have already mentioned.
# 3
Could you, please, list all the compilation (both compile and link stage) flags that you use there?Optimization options etc...regards,__Fedor.
SFVa at 2007-7-12 2:37:14 >

# 4
Sure! Since only 1 file (apitest.c) needs to be compiled, the following line does both the compilation and linking:
CC -B dynamic -g -I../../../test_root/gen/src -I../../../test_root/momn/src -L../../../test_root/momn/bin -lsocket -loapisun -lssl -lcrypto -o ../../../test_root/momn/bin/apitest ../../../test_root/momn/src/apitest.c
The libsocket.a is from the system. The other libraries (liboapisun.so, libossl.a, libcrypto.a) are provided by the 3rd party.
The compiler version is (CC: Sun C++ 5.7 Patch 117831-07 2006/03/15)
Thanks in advance,
Menger
# 5
Hi people, I found that if I use -library=no%Cstd -library=no%Crun during compilation, then my test program will not crash anymore upon startup.
I understand that no$Cstd means do not use C++ standard library, and no%Crun means do not use C++ runtime library.
Whereas ths is fine for my test code (written in C), it is unacceptable for my production code, which is written in C++. This is because my C++ code uses new/delete, exceptions, iostreams etc all of which are provided by these shared objects. I have tried, and the compiler spews out a whole lot of undefined symbols, e.g. iostream functions, exceptions etc.
Is there any way to get around this? Are there other shared libraries that I can link to that can side step this problem?
Thanks in advance!
# 6
We do not support using an older compiler to link binaries created by a newer compiler. The reason is that newer releases use interfaces unavailable in older releases.
We do support linking old binaries using a newer compiler. We are careful to preserve old interfaces when we update compilers and libraries.
Your options are to ask the 3rd-party library supplier to provide a version compiled with C++ 5.7, or for you to use C++ 5.8 when linking the program. (You don't have to recompile the binaries you created with C++ 5.7.)
# 7
Dear clamage45,
Thanks for your suggestion. I had carried out option 2: using Sun C++ v5.8 to compile the test program and to link to the shared object. The executable still crashes upon start up (error msg in dbx: __cplus_fini_at_exit)
In frustration, I concocted the following test program (apitest.c):
//-- START OF PROGRAM --
#include <iostream>
using namespace::std;
int main()
{
cout << "hello world!" << endl;
return 1;
}
//-- END OF PROGRAM --
And then I compiled and link the program as below:
CC -B dynamic -g -I../../../test_root/gen/src -I../../../test_root/momn/src -L../../../test_root/momn/bin -lsocket -loapisun -lssl -lcrypto -o ../../../test_root/momn/bin/apitest ../../../test_root/momn/src/apitest.c
The program still crashes even though it clearly does not use anything in libsocket, liboapisun, libssl and libcrypto. I used "dbx apitest core" and got the following:
core file header read successfully
Reading ld.so.1
Reading libsocket.so.1
Reading liboapisun.so
Reading libCstd.so.1
Reading libCrun.so.1
Reading libm.so.2
Reading libc.so.1
Reading libnsl.so.1
program terminated by signal SEGV (no mapping at the fault address)
0x08109a56: __cplus_fini_at_exit+0x007a:addb%al,(%eax)
(dbx) where
=>[1] __cplus_fini_at_exit(0x1, 0x8047c64, 0x8047c6c, 0x8109b68, 0xfefd5bfc, 0x0), at 0x8109a56
(Please note this is the same type of error message I encountered when I compile and invoke my normal test code)
Strangely enough, if I don't link to liboapisun, the whole thing will work, i.e. if I do:
CC -B dynamic -g -I../../../omex/gen/src -I../../../omex/omn/src -L../../../omex/omn/bin -lsocket -lssl -lcrypto -o ../../../omex/omn/bin/apitest ../../../omex/omn/src/apitest.c
I got the expected "hello world!" output..
Of course that would defeat the whole purpose because my objective is to find a way for my C++ code to invoke the functions in liboapisun.so (which is compiled by Sun C v5.8).
I had previously thought it might be because I am missing some patches (re:http://forum.java.sun.com/thread.jspa?threadID=5094456&messageID=932519 2&bcsi_scan_024B6B01C62FD143=sm/P0h349gREcm35bsnmTDUAAAC9dmcB&bcsi_scan_ filename=thread.jspa), but I have already installed patch 119964-08 and this problem still persists.
Any ideas and suggestions are welcome.
Thanks in advance.
# 8
It is possible that something is wrong with the way liboapisun.so is built. From your comments, I assume it is C++ code. Please try a few things for me.
1. Run the command
ldd liboapisun.so
The output should show dependencies on /usr/lib/libCrun.so.1 and /usr/lib/libCstd.so.1.
If not, it was not built correctly.
2. To whether the libraries are initialized in the correct order, load the program into dbx, then do this:
stop in `liboapi.so`_init
stop in `libCrun.so`_init
stop in `libCstd.so`_init
run
If the program stops in liboapi.so before either libCrun or libCstd, the library was not built correctly.
Let me know what you find.
# 9
Dear clamage45,
liboapisun.so is a 3rd party library that is C code (compiled using Sun C v5.8).
1. The command "ldd liboapisun.so" returns nothing. I assume this is because it is C library, hence it is not dependent on libCrun.so.1 and libCstd.so.1.
2. I am a newbie dbx user, so I have some difficulty here. I did the following commands:
- stop in `liboapisun.so`_init
- stop in `libCrun.so.1`_init
- stop in `libCstd.so.1`_init
There is no libCrun.so or libCstd.so in /usr/lib, just the .1 versions. Each issued stop command returns:
dbx: warning: '_init' has no debugger info -- will trigger on first instruction
When I start debugging, dbx indicates it stopped at _init. However, it seems to indicate it is `apitest`_init:
Running: apitest
(process id 19038)
stopped in _init at 0xfef741a8
0xfef741a8: _init:pushl%ebp
(dbx) which _init
dbx: warning: unknown language, 'c++' assumed
`apitest`_init
(dbx) where
=>[1] _init(0xfeffa220, 0xfeffc918, 0xfeffa840, 0xfebd0188, 0xfebd0260, 0xfef741a8), at 0xfef741a8
[2] call_init(0xfebd0178, 0x1), at 0xfefd58fc
[3] setup(0x8047be0, 0x8047c24, 0x0, 0x8047fd0, 0x1000, 0xfefca9d7, 0xfeffab18, 0xfefc9000, 0xfefc9000, 0xffffffff, 0x8050034, 0x8047fd6, 0x8047bd8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x2), at 0xfefd4fcc
[4] _setup(0x8047b94, 0xfeffab18, 0x3, 0x8047bd8, 0x4, 0x8047be0), at 0xfefe0734
[5] _rt_boot(0x0, 0x8047cb1, 0x8047cbe, 0x8047e13, 0x8047e27, 0x8047e32), at 0xfefcc0b8
I tried to clear this breakpoint and continue, and I got the following frames stack:
(dbx) where
=>[1] _init(0xfeffa220, 0xfeffc918, 0xfeffa840, 0xfebd018c, 0xfed50dcc, 0xfedc76b8), at 0xfedc76b8
[2] call_init(0xfebd0178, 0x1), at 0xfefd58fc
[3] setup(0x8047be0, 0x8047c24, 0x0, 0x8047fd0, 0x1000, 0xfefca9d7, 0xfeffab18, 0xfefc9000, 0xfefc9000, 0xffffffff, 0x8050034, 0x8047fd6, 0x8047bd8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x2), at 0xfefd4fcc
[4] _setup(0x8047b94, 0xfeffab18, 0x3, 0x8047bd8, 0x4, 0x8047be0), at 0xfefe0734
[5] _rt_boot(0x0, 0x8047cb1, 0x8047cbe, 0x8047e13, 0x8047e27, 0x8047e32), at 0xfefcc0b8
(dbx) clear
cleared (3) stop in _init
(dbx) cont
stopped in _init at 0xfeeec95c
0xfeeec95c: _init:pushl%ebp
(dbx) where
=>[1] _init(0xfeedf164, 0xfef90890, 0xfeffa840, 0xfebd0454, 0xfed50d1c, 0xfeeec95c), at 0xfeeec95c
[2] call_init(0xfebd0450, 0x3), at 0xfefd58fc
[3] is_dep_init(0xfef90890, 0xfef90c90), at 0xfefd5681
[4] elf_bndr(0xfef90c90, 0x238, 0xfedc6341), at 0xfefdf7c5
[5] elf_rtbndr(0x238, 0xfedc6341, 0xfef90c90, 0x14, 0xfedd8ec0, 0xfedd9168), at 0xfefcc1d4
[6] 0xfef90c90(0xfedd9178), at 0xfef90c90
[7] __cplus_fini_at_exit(0xfeffa220, 0xfeffc918, 0xfeffa840, 0xfebd018c, 0xfed50dcc, 0xfedc76b8), at 0xfedc7752
[8] call_init(0xfebd0178, 0x1), at 0xfefd58fc
[9] setup(0x8047be0, 0x8047c24, 0x0, 0x8047fd0, 0x1000, 0xfefca9d7, 0xfeffab18, 0xfefc9000, 0xfefc9000, 0xffffffff, 0x8050034, 0x8047fd6, 0x8047bd8, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0, 0x2), at 0xfefd4fcc
[10] _setup(0x8047b94, 0xfeffab18, 0x3, 0x8047bd8, 0x4, 0x8047be0), at 0xfefe0734
[11] _rt_boot(0x0, 0x8047cb1, 0x8047cbe, 0x8047e13, 0x8047e27, 0x8047e32), at 0xfefcc0b8
If I continue, then it crashes:
(dbx) cont
signal SEGV (no mapping at the fault address) in __cplus_fini_at_exit at 0x810b356
0x0810b356: __cplus_fini_at_exit+0x007a:addb%al,(%eax)
(dbx) where
=>[1] __cplus_fini_at_exit(0x8047b94, 0x8047c24, 0x8047bcc, 0x806f7b5, 0x1, 0x8047bd8), at 0x810b356
By the way, I did a 'which' _init on the subsequent _inits and they all belong to apitest. dbx did stopped at _init, but I don't know why it stopped at apitest_init when I didn't specify that breakpoint.
I don't know why the program seg-faults at _fini() but not at _init(). Overall, did this seg fault occurred because the liboapisun.so is being treated as a C++ shared object when in fact it is in C?
# 10
From previous comments, I thought that liboapisun.so was a C++ library. If I now understand correctly, your program works unless you link it with liboapisun.so, which is C code compiled by a C compiler.
The only explanations I can think of are
1. The liboapisun library does something invalid during its initialization, corrupting the stack or the heap.
2. The library contains symbol definitions that collide with symbols elsewhere in the code, especially a symbol in the C++ runtime libraries.
Let's look for the case when liboapisun defines a global symbol that is the same as a global symbol in libCrun or libCstd.
We can find duplicated symbols by extracting all the global definitions, concatenating them, then using sort and sort -u, comparing the results.
nm /usr/lib/libCrun.so.1 | grep GLOB | grep -v UNDEF | sed -e 's/.*|//' > Crun.txt
nm /usr/lib/libCstd.so.1 | grep GLOB | grep -v UNDEF | sed -e 's/.*|//' > Cstd.txt
nm liboapisun.so | grep GLOB | grep -v UNDEF | sed -e 's/.*|//' > api.txt
sort Crun.txt Cstd.txt api.txt > all.txt
sort -u Crun.txt Cstd.txt api.txt > all-u.txt
diff all-u.txt all.txt
The output of the diff will be any symbols that are defined in more than one of the libraries.
There are some symbols that are defined in both libCrun and libCstd, and some symbols that are artifacts of shared libraries.
You can ignore the following artifacts:
_DYNAMIC
_GLOBAL_OFFSET_TABLE_
_PROCEDURE_LINKAGE_TABLE_
_edata
_end
_etext
_fini
_init
You can also ignore symbols of the form SUNW_1.n where n is a number.
Symbols starting with __1cDstd are from the C++ standard library, and some are common to both libCstd and libCrun. Verify that no such symbols are in liboapisun.
nm liboapisun.so | grep __1cDstd
Any additional symbols that are shown by the diff that appear in liboapisun are likely to cause a problem. Show me what they are, and I may have some suggestions.
If there are none, we'll think of something else to look for.
# 11
Hello, I did all those 'nm' commands, and the differences between all.txt and all-u.txt include the expected following:
SUNW_1.1
SUNW_1.2
SUNW_1.3
SUNW_1.4
_DYNAMIC
_GLOBAL_OFFSET_TABLE_
_PROCEDURE_LINKAGE_TABLE_
_edata
_end
_etext
_fini
_init
I also did get a bunch of __1Dcstd* symbols, but they do not exist inside liboapisun, i.e. the command "nm liboapisun.so | grep __1cDstd" returns nothing.
Based on what you said, all these can be ignored.
At the same time, I also have a static version of the liboapi libary. I performed an "nm ...|grep GLOB | grep -v UNDEF | sed ..." on each of them, then sort each file and compare for differences. I got the following:
_DYNAMIC
_GLOBAL_OFFSET_TABLE_
_PROCEDURE_LINKAGE_TABLE_
_edata
_end
_etext
_fini
_init
_lib_version
These symbols all exist in the liboapisun.so. Again, from your previous thread, they can be ignored. As for the other global and defined symbols, they are common in both dynamic and static versions of liboapisun.
My test program is the 'hello world' program (apitest.cc) that does not invoke any function from the liboapisun as below:
//-- START OF PROGRAM --
#include <iostream>
using namespace::std;
int main()
{
cout << "hello world!" << endl;
return 1;
}
//-- END OF PROGRAM --
The compile line I use is as below:
CC -o apitest apitest.cc -B dynamic -g -I. -L. -loapisun -lsocket -lssl -lcrypto -lnsl
If I use C++ compiler to link against liboapisun.a, the program ran fine. If I link against liboapisun.so, it will crash. However, if I were to link to liboapisun.so but this time, specifying -library=no%Cstd and -library=no%Crun, the program will also run fine.
So, I agree with you liboapisun.so somehow conflicts with libCstd.so libCrun.so, but it does not appear to be multiply defined global symbols.
# 12
Well, this is a mystery. :-(What does liboapisun do? What interface does it present?Do you know what it does when it initializes itself?
# 13
liboapisun has something to do with secured connectivity. It is 3rd party stuff and the documentation is quite vague.
I couldn't figure out why it works with C code and not C++. I admit defeat.
Meanwhile, I am very appreciative of your efforts in helping me throughout all this. Should I make any further progress on this in the future, I will post onto this thread again.
Thanks.
# 14
I have two more suggestions.
1. See if the vendor of liboapisun can help with the problem. If the "sun" in the library name means it is a version for use with Sun products, the vendor should be concerned that a C++ "hello world" program that doesn't use the library still can't link to it. We are happy to work with vendors of libraries to get their code to work with Sun Studio.
2. If you have a service contract with Sun, we can try to find the source of the problem. You would need to send us a copy of liboapisun if the software license allows it.
# 15
Dear clamage45,
Today, I was suddenly inspired to run truss on the program. I used Sun C++ v5.8 to compile the sample code, linking to liboapisun.so. The following is the last part of the truss result:
sigfillset(0xFED3E6E8) = 0
sysi86(SI86FPSTART, 0xFED3ECD8, 0x0000133F, 0x00001F80) = 0x00000001
Incurred fault #6, FLTBOUNDS %pc = 0x0810B2D6
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
Received signal #11, SIGSEGV [default]
siginfo: SIGSEGV SEGV_MAPERR addr=0x00000000
Next, I use the Sun C v5.8 to compile the same sample code, linking to the same liboapisun.so, and again, the following is the last part of the result:
sigfillset(0xFEEBE6E8) = 0
sysi86(SI86FPSTART, 0xFEEBECD8, 0x0000133F, 0x00001F80) = 0x00000001
ioctl(1, TCGETA, 0x08046F04)= 0
fstat64(1, 0x08046E70) = 0
Usage:apitest username password gatewayName gatewayPort
write(1, " U s a g e : a p".., 60)= 60
Example: apitest user1 my_password tnt_gwy1 1234
write(1, " E x a m p l e :a p".., 50)= 50
_exit(1)
I have previously discovered that even if I were to use Sun C++ v5.8 to compile, if I specify -library=no%Cstd -library=no%Crun as part of the compiler options, then it is fine. So, here is the truss command of that build:
sigfillset(0xFEE5E6E8) = 0
sysi86(SI86FPSTART, 0xFEE5ECD8, 0x0000133F, 0x00001F80) = 0x00000001
ioctl(1, TCGETA, 0x08046FA4)= 0
fstat64(1, 0x08046F10) = 0
Usage:apitest username password gatewayName gatewayPort
write(1, " U s a g e : a p".., 60)= 60
Example: apitest user1 my_password tnt_gwy1 1234
write(1, " E x a m p l e :a p".., 50)= 50
_exit(1)
Which seems to be exactly the same as the result from using Sun C v5.8.
So, I suppose there is something weird with this sysi86(SI86FPSTART ...) command. I googled it and the closest thing I could find is this:
http://sunsolve.sun.com/search/document.do?assetkey=1-26-102124-1
The puzzling thing is my machine does not have either patch 118345 or 118565 at all, and it is still crashing, albeit when I run the C++ program (the C version is okay)
Clamage45, is it possible for you to shed some more light on this?
Meantime, I will install the latest versions of both of these patches and see how that will turn out.
Thanks.
# 16
The truss output is not helpful, but I looked at earlier information.
In two places, you show a fault here:
__cplus_fini_at_exit+0x007a: addb %al,(%eax)
Several odd things:
1. address __cplus_fini_at_exit+0x007a is not an instruction boundary
2. the instruction addb %al,(%eax) is not present in routine __cplus_fini_at_exit, which correlates with the offset not being an instruction boundary
3. function __cplus_fini_at_exit is called at program exit, not at program start.
These points suggest a wild jump during initialization, and we must suspect liboapisun.so.
Looking at your entry of May 7 when you ran under dbx, the last stack trace shows a recursive call to call_init, which causes entry to the .init section of a shared library. That means that initialization of shared library A caused an entry into another shared library B before B was initialized. The initialization of A was interrupted while B was initialized, at which point the program crashed, apparently due to a wild jump. Again, we must suspect liboapisun.so, perhaps because it was not built with explicit dependencies on libraries it uses.
Your next step is to report your problem to the vendor of liboapisun. You can point to or quote anything in this thread.
As I said earlier, we can't necessarily support 3rd-party applications for end users, but we are happy to work with software vendors to help them get their applications working.
# 17
I don't think that the problem is fully related to the liboapisun.so , though it may be related to how the api code was compiled.
I managed to link against the "ar" libraries by
... -B static -z allextract -loapisun -z defaultextract -lcrypto -lssl -B dynamic...
The resulting executable crashes the same way.
You can build a blank.c which just has int main(int a, char **c) { int i = 0;} that will SEGV
if you
CC -c blank.c
ld -o blank blank.o
The behavior is not the same as your example but it demonstrates an issue with loading.
The solution to blank is just to do
CC -c blank.c
CC -o blank blank.o
This however does not resolve the original issue.
Tom
# 18
The final solution to the problem was to link against the libssl.so provided in /usr/sfw/libthe liboapisun.so is o.k..Tom
# 19
The 3rd party package came with the following libraries:
liboapisun.so
liboapisun.a
libcrypto.a
libssl.a
The issue in question is the set of libraries libcrypto.a and libssl.a as well as the ones in /usr/sfw/lib (libcrypto.so.0.9.7 and libssl.so.0.9.7)
Using the Sun C compiler to link the test program with either the 3rd party library set, or the library set in /usr/sfw/lib is perfectly fine.
The Sun C++ compiler, the test program will core dump when linked to the 3rd party library set. However, the test program will run fine when linked to the library set in /usr/sfw/lib.
I tried to mix and match, i.e. link to /usr/sfw/lib/libssl.so and 3rd party libcrypto.a using Sun C++. The resultant program core dumps with the expected "cplusplus_fini_at_exit" entry when loaded in the debugger.
I did not bother trying to link to /usr/sfw/libcrypto.so and 3rd party libssl.
Linking to liboapisun.a or liboapisun.so is perfectly fine using C++ compiler.
Statement:: Test program is incompatible with OS when linked with the 3rd party libcrypto.a and libssl.a via the Sun C++ compiler. Program is fine when linked with the system libcrypto.so and libssl.so. Can't really complain since 3rd party has always insist that they only support C programming.
Thanks to clamage45 and tombay for your efforts during this process.
