I think I understand why I need LD_PRELOAD set when loading a multithreaded applicatoin that loads a single threaded library that loads libcl.2 but I was wondering if I could use some linker setting to avoid this. Any help appreciated.
Update:
Perl loads
dynamic /usr/lib/libc.2
Perl loads DB2.sl
DB2 Attempts to load
dynamic /usr/lib/libcl.2
Could it be the fact that something with that shared object name is already loaded it then fails.
/usr/lib>pwd
/usr/lib
/usr/lib>ls -lt | grep libcl.2
-r-xr-xr-x 1 bin bin 1261568 Feb 14 2003 libcl.2
lrwxr-xr-x 1 root sys 9 Nov 21 2002 libcl.sl -> ./libcl.2
Now the reason refuses to go looking for something of this same name might be explained by the chattr output:
Both have the disable fields set so they won't look in the environment nor use the alternate name
chatr on perl
perl:
shared executable
shared library dynamic path search:
SHLIB_PATH disabled second
embedded path disabled first Not Defined
shared library list:
dynamic /usr/lib/libnsl.1
dynamic /usr/lib/libnm.sl
dynamic /usr/lib/libdld.2
dynamic /usr/lib/libm.2
dynamic /usr/lib/libsec.2
dynamic /usr/lib/libpthread.1
dynamic /usr/lib/libc.2
chatr on DB2.sl
DB2.sl:
shared library
shared library dynamic path search:
SHLIB_PATH disabled second
embedded path disabled first Not Defined
shared library list:
dynamic /opt/IBM/db2/V8.1/lib/libdb2.sl
dynamic /usr/lib/libcl.2
Could maybe the chatr settings of one of the libraries be adjusted?
Update: why not just make them use the same name for the library.
Depending on your compiler/linker (thinking of the HPUX machines I logged onto more than a decade ago makes me shudder), --rpath might help: from what I understand, in your case the rtld is looking in the wrong place first, so that's why you want to preload some other version of the lib, right? In that case, rpath will embed an additional search location into the compiled binary, which you can use to point it to the directory where your preferred version is coming from.
Hope this helps. -V
I wrote an article about shared libraries on HP-UX and tried to make it clear and comprehensive. I found myself having to debug why programs couldn't find their libraries and so I documented it.
The three main locations that will affect the library search are 1) /etc/SHLIBPATH; 2) environment variables; and 3) the embedded library search path.
Unfortunately, this is a drastic oversimplification: the best reference I have to offer is that article that brings everything together (in my opinion, any way).
There are not linker flags to avoid this.
Related
I have a BB 10/QNX app in which I need to use more recent version of SQLite than is default on BB 10. I thought I could do that by linking my own SQLite code with my app. I realized that in my qmake-generated Makefile the option -lsqlite3 is passed to qcc. In the library location (/opt/bbndk/target_10_2_0_1155/qnx6/armle-v7/usr/lib) I found the following files:
size filename
559386 libsqlite3.a
560662 libsqlite3S.a
15 libsqlite3.so -> libsqlite3.so.1
496503 libsqlite3.so.1
I thought that I can replace libsqlite3.a with my own file compiled from latest sqlite3.c (amalgamation). What confuses me is that the size of my application executable is just 180 kB, so the code from libsqlite3.a doesn't seem to be present in it. If SQLite is dynamically linked, I'd expect the application archive (.bar) to contain libsqlite3.so, which also isn't true, because the archive is just 130 kB big. How is it possible that the application uses SQLite (via Qt database classes), but SQLite code never makes it to the application archive?
Static version
When linking an executable to a static library, the compiler know you're building a "finished product": nothing will depend on your executable. It allows the compiler to not include unused code. Let's say you're using only one function from the library, which itself is not using anything else from the library. The compiler will pick only the machine code corresponding to this specific function and gently ignore the rest.
Dynamic version
Regarding the size of the bar archive and the dynamic library, it goes down to what really is a bar archive. It's simply a zip archive (maybe with some metadata added, don't know in details). Two possibilities: either the .so file is greatly compressed, or the compiler relies on the system library and doesn't bundle it in the bar archive.
gcc c89
I am just looking to link against the below shared library.
I am wondering why the programmer has created so many soft-links. The programmer has left the company and I am just wondering what is the purpose.
lrwxrwxrwx. 1 24 Jan 11 11:23 libsofia-sip-ua.so -> libsofia-sip-ua.so.0.6.0
lrwxrwxrwx. 1 24 Jan 11 11:23 libsofia-sip-ua.so.0 -> libsofia-sip-ua.so.0.6.0
-rwxrwxr-x. 1 4728304 Jan 11 11:19 libsofia-sip-ua.so.0.6.0
For what I can understand if the library was to get updated to a newer version you could just soft-link it with the updated version.
But why create libsofia-sip.so.0?
Many thanks for any suggestions,
The filename ending in .so is the one used by the linker (not dynamic linker) when you use the -l option to specify a library you want to search/link. The linker is unaware of other suffixes and won't find them. When the linker opens this file, it finds a different name in the DT_SONAME field of the library's header, usually the name with a single-number suffix. This is the name it will store in the DT_NEEDED field of the new program's dynamic linking header.
The filename ending in .so.N (e.g. N=0 in your case) is the one corresponding to the DT_SONAME in the library file, and it represents a series of library versions which all have a compatible ABI.
The filename ending in .so.N.X.Y is the actual file for the currently installed library version. It's possible for more than one of these to exist, and normally the other symlinks will be setup to point to the most recent version. But old versions are not automatically overwritten this way, so you could manually load an old one with LD_PRELOAD or replace the symlinks if there's a reason you need to downgrade.
Most likely, the library's "real name" is libsofia-sip-ua.so.0. This is encoded into the shared object. The libsofia-sip-ua.0.6.0 name is probably just a name it was installed under.
It was probably the ldconfig program that made the links. I believe it always makes a link for the embedded name if the library file has some other name.
So it probably was not the programmer who wanted these extra links. He, or his library build tool, named the library file a different name than what is embedded inside the library file.
In my SConscript I have the following line:
Program("xtest", Split("main.cpp"), LIBS="mylib fltk Xft Xinerama Xext X11 m")
How do I get scons to use mylib.a instead of mylib.so, while linking dynamically with the other libraries?
EDIT: Looking to use as few platform specific hacks as possible.
Passing the full filepath wrapped in a File node will force static linking. For example:
lib = File('/usr/lib/libfoo.a')
Program('bar', 'main.c', LIBS = [lib])
Will produce the following linker command line
g++ -o bar main.o /usr/lib/libfoo.a
Notice how the "-l" flag is not passed to the linker for this LIBS entry. This effectively forces static linking. The alternative is to modify LINKFLAGS to get what you want with the caveat that you are bypassing the library dependency scanner -- the status of the library will not be checked for rebuilds.
To make this platform independent you append the env['SHLIBSUFFIX'] onto the library you want to use. env['SHLIBSUFFIX'] gives you this environments suffix for shared libraries.
You also have the ['SHLIBPREFIX'], ['LIBPREFIX'], ['LIBSUFFIX'] and ['PROGSUFFIX'], all useful for situations like this.
Edit:
I obviously haven't made myself understood, so I will clarify.
The return value of these lookups are strings to the pre/suffixes that platform uses. In that way you can refer to the file you need on each platform. Note that you cannot use it as a pure string, it has to be embedded as a file node as BennyG suggests. Working with nodes are anyway the best solution as file nodes are much more versatile than a string.
Hope this helps.
I am working on Linux environment. I have two 'C' source packages train and test_train.
train package when compiled generates libtrain.so
test_train links to libtrain.so and generates executable train-test
Now I want to generate a call graph using gprof which shows calling sequence of functions in main program as well as those inside libtrain.so
I am compiling and linking both packages with -pg option and debugging level is o0.
After I do ./train-test , gmon.out is generated. Then I do:
$ gprof -q ./train-test gmon.out
Here, output shows call graph of functions in train-test but not in libtrain.so
What could be the problem ?
gprof won't work, you need to use sprof instead. I found these links helpful:
How to use sprof?
http://greg-n-blog.blogspot.com/2010/01/profiling-shared-library-on-linux-using.html
Summary from the 2nd link:
Compile your shared library (libmylib.so) in debug (-g) mode. No -pg.
export LD_PROFILE_OUTPUT=`pwd`
export LD_PROFILE=libmylib.so
rm -f $LD_PROFILE.profile
execute your program that loads libmylib.so
sprof PATH-TO-LIB/$LD_PROFILE $LD_PROFILE.profile -p >log
See the log.
I found that in step 2, it needs to be an existing directory -- otherwise you get a helpful warning. And in step 3, you might need to specify the library as libmylib.so.X (maybe even .X.Y, not sure) -- otherwise you get no warning whatsoever.
I'm loading my library from Python and didn't have any luck with sprof. Instead, I used oprofile, which was in the Fedora repositories, at least:
operf --callgraph /path/to/mybinary
Wait for your application to finish or do Ctl-c to stop profiling. Now let's generate a profile summary:
opreport --callgraph --symbols
See the documentation to interpret it. It's kind of a mess. In the generated report, each symbol is listed in a block of its own. The block's main symbol is the one that's not indented. The items above it are functions that call that function, and the ones below it are the things that get called by it. The percentages in the below section are the relative amount of time it spent in those callees.
If you're not on Linux (like me on Solaris) you simply out of luck as there is no sprof there.
If you have the sources of your library you can solve your problem by linking a static library and making your profiling binary with that one instead.
Another way I manage to trace calls to shared libraries, is by using truss. With the option -u [!]lib,...:[:][!]func, ... one can get a good picture of the call history of a run. It's not completely the same as profiling but can be very usefull in some scenarios.
I'm integrating .NET support into our C++ application.
It's an old-school MFC application, with 1 extra file compiled with the "/clr" option that references a CWinFormsControl.
I'm not allowed to remove the linker flag "/NODEFAULTLIB".
(We have our own build management system, not Visual Studio's.)
This means I have to specify all necessary libraries: VC runtime and MFC.
Other compiler options include "/MD"
Next to that: I can't use the linker flag "/FORCE:MULTIPLE" and just add everything:
I'm looking for a non-overlapping set of libraries.
As a bare minimum:
mscoree.lib
MSVCRT.lib
mfc90.lib (adjust version appropriately)
And iterate from there.
Use the AppWizard to create a bare-bones MFC app in your style (SDI / MDI / dialog ) and then put on your depends.
How I solved it:
link with "/FORCE:MULTIPLE /verbose" (that links ok) and set the output aside.
link with "/NODEFAULTIB /verbose" and trace all unresolveds in the output of the previous step and add the libraries 1 by 1.
This resulted in doubles: "AAA.lib: XXX already defined in BBB.lib"
Then I finally got it:
Recompiled managed AND unmanaged units with /MD
and link to (among others):
mscoree.lib
msvcmrt.lib
mfcm80d.lib
Mixing /MT (unmanaged) and /MD (managed) turned out to be the bad idea:
different(overlapping) libraries are needed.
#ajryan: Dependcy Walker only tells me what dll's are used, not what libraries are linked to when linking.
(e.g. msvcmrt.lib ?)
I think.
Thanks for the answers!
Jan