I am using different versions of libm.a. One that I am playing with is fdlibm's libm.a (from Sun).
The problem is that I feel that my program does not call the functions in fdlibm's libm.a, but calls those of the system's glibc's libm.a.
#include "fdlibm.h"
int main(){
double x = sin(3);
}
The program is compiled C++ programs(because it has to be linked with other c++ programs):
g++ prog.cpp libm.a
where libm.a is the fdlibm's. (From Sun, http://www.netlib.org/fdlibm/readme)
Question 1
How can I know what does sin actually invoke at run-time? I heard about various tools like objdump, gdb... Which one can be used for my case and how?
Question 2
How can I enforce fdlibm's libm.a be used?
Thanks.
Question 1. I heard about various tools like objdump, gdb.
As with gdb.
Create file trace_sin.gdb
$ cat trace_sin.gdb
set confirm off
b sin
commands
bt
c
end
r
quit
And run your program:
$ gdb -q -x trace_sin.gdb ./a.out Reading symbols from ./a.out...(no
debugging symbols found)...done. Breakpoint 1 at 0x400498
Breakpoint 1, 0x000000314941c760 in sin () from /lib64/libm.so.6
#0 0x000000314941c760 in sin () from /lib64/libm.so.6
#1 0x0000000000400629 in main ()
As you see in my case sin comes from libm
Question 2. How can I enforce fdlibm's libm.a be used?
Just make sure than sin from fdlibm comes before libm's sin
I grew tired of linking/deferred loading of the .so version of a library, and somewhere I found that you can achieve a link to a specific libary, by specifying path to the library.
Perhaps this can help with your challenge.
example - I can change this command (and link to SDL2 .so)
$(CC) $(CC_FLAGS) $< -o $# -L../../bag -lbag_i686 -lSDL2
and achive the same with
$(CC) $(CC_FLAGS) $< -o $# -L../../bag -lbag_i686 /usr/local/lib/libSDL2.so
Explicitly identifying which lib to use.
On ubuntu, I can use 'locate' to find the full path of a file. It turns out that SDL2 (.so) lands in both /usr/local/lib and /usr/lib/x86_64-linux-gnu. I suppose the x86_64 is more appropriate for my system, and it also links.
I have used the following simple technique to 'gently specify' (not explicit) a library needed for link. This technique might be appropriate for you.
I had already created several libraries which I had to use, and they were all in one specific path: "/home//cvs-tools/lib1". )
When it came time to use the 1 boost lib I needed, I simply copied the latest libboost_chrono.a into "/home//cvs-tools/lib1". No .so in the way.
And touched my make files so that when I updated boost, rather than me trying to remember all implications, I simply added to my make file the copy of chrono.a to my lib1, and my normal build then updated lib1's copy.
So, by 'gently specific', I mean that a) my make file copied the b) specific COTS library (boost) into c) my lib1 directory, and thus picked up by the same -L.
Related
In my program I need to load a shared library dynamically with dlopen(). Both the program and the shared library are successfully cross-compiled for an ARM architecture with the cross-compiler installed on my x86. However, whenever the program tries to load the library at run time on ARM, it fails giving this error:
undefined symbol: _dl_hwcap
I cannot find the culprit of this error.
Let me give details on how the shared library (libmyplugin.so) is built on x86 first. I use the g++ cross-compiler as below:
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module1.o module1.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module2.o module2.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -o dist/libmyplugin.so build/module1.o build/module2.o --sysroot /home/me/arm/sysroot/ -Wl,--no-as-needed -ldl -lX11 -lXext /home/me/arm/libstatic.a -shared -s -fPIC
Please pay attention to the following notes:
module1.cpp and module2.cpp are my source code files.
libstatic.a is a big archive of object .o files implementing the stuff directly invoked/referenced by module1.cpp and module2.cpp. These object files have been compiled by others for the same ARM architecture as mine, with the same compiler flags, but using a slightly more updated g++ compiler (v4.9 instead of my v4.8.3). Unfortunately, I have no control on the building of these objects.
--sysroot /home/me/arm/sysroot/ represents the remote filesystem of my ARM OS from which the local g++ cross-compiler can take the native libraries while linking.
-Wl,--no-as-needed -ldl -lX11 -lXext: these flags are required to force the dynamic loader to load the X11 libraries present on the system when my shared library is loaded by the program. In particular, --no-as-needed is required because the X11 libraries are NOT directly referenced by module1.o and module2.o; on the contrary the X11 libraries are referenced by the static library only.
Note that all the above setup works on x86. It's just that I don't understand what is the reason of the _dl_hwcap symbol not resolved when the program tried to load the library on ARM.
Do you have any idea how to investigate this issue?
There are a myriad of things that could be problematic, but here are four avenues of exploration. I am concentrating on the -shared in your link line, but the last item addresses that as well.
(A nice HOWTO on shared libraries is here:
http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
a) Check your environment variable LD_LIBRARY_PATH. Since you aren't using RPATH to the linker (RPATH embeds a full path to the .so so you can find it at runtime), then the only way the linker can find your code is to search the LD_LIBRARY_PATH.
Make sure the .so or .0 you want is in the path.
b) Use the UNIX utility 'nm' to search .so (shared objects) and .a files for that symbol. For example, 'nm -D /usr/lib64/libpython2.6.so' will show all dynamic symbols
in the libpython.so, and you can look for symbols of interest:
For example, Is 'initgc' defined or used in libpython?
% nm -D /usr/lib64/libpython2.6.so | grep initgc
000003404300cf0 T initgc
The 'T' means TEXT or, yes, it is defined there. See if you can find the symbol in the module of interest using grep and nm. (A 'U' means undefined, which means it is defined in another module).
c) Another useful tool is 'ldd'. It shows all dynamic libraries that the library you are looking on depends on. For example:
% ldd /usr/lib64/libpython2.6.so
linux-vdso.so.1 => (0x00007fffa49ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033f0200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000033f0600000)
libutil.so.1 => /lib64/libutil.so.1 (0x00000033fea00000)
libm.so.6 => /lib64/libm.so.6 (0x00000033f0a00000)
libc.so.6 => /lib64/libc.so.6 (0x00000033efe00000)
/lib64/ld-linux-x86-64.so.2 (0x00000033efa00000)
If it can't find a library (because it's not on the LD_LIBRARY_PATH or wasn't specified in the RPATH), the library will turn up empty.
d) I am a little worried from your link line of seeing a '.a' file with a -shared option. Some compilers/linkers cannot use a '.a' (archive) file to create a '.so' file. '.so' files usually have to made from other '.so' files or '.o' files that have been compiled with -fPIC.
I would recommend (if you can), recompile /home/me/arm/libstatic.a so that it's a .so. If you can't do, you might have to make your final output a '.a' file as well. (In other words, get rid of the -shared command line option).
In summary: Check your LD_LIBRARY_PATH, use nm and ldd to look around at your .a and .so files, but I think the end result is that you may not be able to combine .so and .a files.
I hope this helps.
I think this symbol may be in the "ld-lsb" library needed by "Xext". On my system the library is a symlink "/lib64/ld-lsb-x86-64.so -> ld-linux-x86-64.so.2", but I am sure that is not the same on the arm. Maybe give it a whirl on your linker line?
We created a custom shared library from some C++ code using
g++ -c -fPIC customTest.cpp
g++ -shared -o libcustomTest.so customTest.o
And we put it in the project directory and in our makefile we have the default target being
main: main.o
nvcc $^ -o main -lcustomTest -L.
And this works just fine.
The problem is, we'd like to move our library to /usr/lib/ or any arbitrary folder and still have the program locate it and use it but this hasn't been happening as we want it to.
We have a folder in our root that we created called libTest and in that folder we put our library customTest.so.0.1. Then we edited ld.so.conf in /etc/ to had /libTest in it.
Then we went to the directory of our program files and ran
ldconfig -v
which looked like this but larger
libpanel.so.5 -> libpanel.so.5.9
libt1.so.5 -> libt1.so.5.1.2
libbluetooth.so.3 -> libbluetooth.so.3.11.4
libgck-1.so.0 -> libgck-1.so.0.0.0
libdca.so.0 -> libdca.so.0.0.0
a lot of links are created and what not, but libcustomTest.so is not one of them. Not surprisingly, when we run make the custom library can't be located.
Can anyone point us in the right direction with what we are doing wrong? By the way we are on Ubuntu 11.10
g++ -shared -o libcustomTest.so customTest.o
This will create a shared library with SONAME not set.
We have a folder in our root that we created called libTest and in that folder we put our library customTest.so.0.1
Don't do that. Just copy libcustomTest.so into /libTest, and be done with it.
a lot of links are created and what not, but libcustomTest.so is not one of them.
That's expected result. ldconfig creates symlinks from SONAME to actual implementation binary. Since you didn't set SONAME, no symlink for you.
Unless you understand what SONAME is for, don't bother setting it (via -Wl,--soname=... flag) either. On Linux, SONAME and external library versioning is usually the wrong answer, as symbol versioning provides much better approach anyway.
Is the STD library a shared library or what is it ? out of curiosity .
Are there any books describe in detail the shared , static libraries development ?
Are there any tutorial ?
p.s (i'm using netbeans , eclipse, anjuta) and the tutorials aren't useful as I'm trying to understand what's actually going on.
On my platform (Ubuntu Maverick) it is:
g++ test.cpp
ldd a.out
linux-vdso.so.1 => (0x00007fffee1ff000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f18755fd000)
libm.so.6 => /lib/libm.so.6 (0x00007f187537a000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007f1875163000)
libc.so.6 => /lib/libc.so.6 (0x00007f1874de0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1875920000)
Note libstdc++.so.6 above.
With cmake creating a shared library is very easy.
1.
Install cmake 2.6 or later.
2.
Create a file test.cpp with the code for your library.
3.
Create a file CMakeLists.txt:
cmake_minimum_required(VERSION 2.6)
project(TEST)
add_library(test SHARED test.cpp)
4.
Run cmake to create a makefile:
cmake -G "Unix Makefiles"
5.
Run make to build your shared library.
With CMake you can also generate an Eclipse CDT project using the following command
cmake -G "Eclipse CDT4 - Unix Makefiles"
You can also find an interesting article on the topic with further references here.
1.) Is the STD library a shared library or what is it?
I have no idea. Could be either. Probably both. Does it matter? Unless you are dealing with something really exotic like a stand-alone statically linked binary for system rebuilding, as long as the compiler/system knows how to link it in, you are unlikely to be concerned with it.
In a nutshell, code can be in static libraries, in which case it's linked into the final (compiled/generated) executable and those binaries can become quite large. Or it can be in a shared library, in which case the library is dynamically loaded and multiple applications can (theoretically) share one common memory image. Unless you are doing something that is quite large, and that will be shared across multiple applications, I'd question the wisdom of going with shared libraries. The additional headaches, especially debugging headaches, are rarely worth it. And without multiple concurrently running applications, there's no savings...
To make a static library, I'd compile a bunch of files into object files... Than use ar and randlib. E.g.:
g++ -c foo1.C -o foo1.o
g++ -c foo2.C -o foo2.o
ar -rv libfoo.a foo1.o foo2.o
ranlib libfoo.a
Subsequently, I'd just link that library in:
g++ testfoo.C -o testfoo -L. -lfoo
Note that if you are using multiple libraries, the ordering of -lbar1 -lbar2 on that (g++ testfoo.C) command line is important! It determines which libraries can call functions/methods in other libraries. Circular dependencies are BAD!
With respect to foo1.o foo2.o files to ar, the ordering makes no difference.
Dynamic libraries...
Some time ago, under an ancient fedora core 3 system, I was playing around with shared libraries under linux. Back then, I would compile my shared library, say fooLibrary.c, with:
g++ -shared -Wl,-soname,libfooLibrary.so.1 -o libfooLibrary.so.1.0 -fPIC fooLibrary.c -ldl
At that time I was playing with LD_PRELOAD, so I had a little script to run my program that did:
export LD_PRELOAD=libfooLibrary.so ; export LD_LIBRARY_PATH=. ; ./myTestProgram
(Note that I did NOT want LD_PRELOAD set when running commands like g++, ls, cd, etc as I was intercepting system calls.)
(FYI: strace is also fun to play with... You should also check out ldd and nm.)
You may want to look at things like dlopen() and dlsym() -- for manually accessing dynamic libraries...
Oh, and the environment variable LD_LIBRARY_PATH adds directories to the default searchpath for dynamic libraries...
(With respect to debugging, let me just mention that when I intercepted malloc(), I found that somewhere inside dlopen()/dlsym() were calls to malloc(). Meaning that I needed to use malloc() before I could manually load the library that provided the real malloc(). Fun times debugging that one...)
PS One more thought: You may want to review the command-line options to gcc/g++. There's a lot of useful info in there...
http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/index.html#toc_Invoking-GCC
I built libbz2 (static variant) using MinGW (GCC 4.5.0) compilation system and now try to import this library into my MSVS2008 project.
I've done these things already and everything worked fine, for example, with zlib (which means that created C libraries are actually interchangeable).
However, when doing the same with libbz2, I face some unknown troubles - when I compile my MSVS2008-project I receive the following error on linking stage:
unresolved external symbol ___chkstk referenced in function _bzopen_or_bzdopen
I don't know why this happens (I think it's because some basic C runtimes are not fully compatible), but maybe someone knows how to fix this kind of error?
Maybe there is a manual way to somehow merge the implementation of MinGW-based ___chkstk into libbz2 static library?
Thank you.
I read your answer, but I think there's an easier (automatic) way of doing the manual merging of object files: use the CFLAG -static-libgcc, which will link in the necessary functions (what you are describing and doing manually).
Thanks everyone, I found the answer.
Basically, you can simply link to libgcc.a / libgcc.lib which was used when building the library.
The more convenient way that deals with the ___chkstk problem only means doing something like ar x libgcc.a (which produces many .o files) and then merging your libbz2 object files with __chkstk.o file.
I think it should be in linker options e.g. LDFLAGS=-static, while LDFLAGS=-static-libgcc still gives dynamically linked binaries...with any test.c:
gcc -c test.c
gcc -static-libgcc test.o
ldd a.out
libc.so.6 => /lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
gcc -c test.c
gcc -static test.o
ldd a.out
not a dynamic executable
For librarian, simply use ar
ar q libtest.a <path>/libgcc.a
EDIT: I suppose I should clarify, in case it matters. I am on a AIX Unix box, so I am using VAC compilers - no gnu compilers.
End edit
I am pretty rusty in C/C++, so forgive me if this is a simple question.
I would like to take common functions out of a few of my C programs and put them in shared libraries or shared objects. If I was doing this in perl I would put my subs in a perl module and use that module when needed.
For the sake of an example, let's say I have this function:
int giveInteger()
{
return 1034;
}
Obviously this is not a real world example, but if I wanted to share that function, how would I proceed?
I'm pretty sure I have 2 options:
Put my shared function in a file, and have it compile with my main program at compile time. If I ever make changes to my shared function, I would have to recompile my main program.
Put my shared function in a file, and compile it as a shared library (if I have my terms correct), and have my main program link to that shared library. Any changes I make to my shared library (after compiling it) would be integrated into my main program at runtime without re-compiling my main program.
Am I correct on that thinking?
If so, how can I complish either/both of those methods? I've searched a lot and I seem to find information how how I could have my own program link to someone else's shared library, but not how to create my own shared functions and compile them in a way I can use them in my own program.
Thanks so much!
Brian
EDIT: Conclusion
Thanks everyone for your help! I thought I would add to this post what is working for me (for dynamic shared libraries on AIX) so that others can benefit:
I compile my shared functions:
xlc -c sharedFunctions.c -o sharedFunctions.o
Then make it a shared object:
xlc -qmkshrobj -qexpfile=exportlist sharedFunctions.o
xlc -G -o libsharedFunctions.so sharedFunctions.o -bE:exportlist
Then link it another program:
xlc -brtl -o mainProgram mainProgram.c -L. -lsharedFunctions
And another comment helped me find this link, which also helped:
http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/proguide/ref/compile_library.htm
Thanks again to all who helped me out!
Yeah you are correct. The first is called a static library, while the second is called a shared library, because the code is not bound to the executable at compile time, but everytime again when your program is loaded.
Static library
Compile your library's code as follows:
gcc -c *.c
The -c tells the program not to link the object file, but just leaves you with object files for each .c file that was compiled. Now, archive them into one static library:
ar rcs libmystuff.a *.o
man ar will tell you what the rcs options mean. Now, libmystuff.a is a archive file (you can open it with some zip-file viewers) which contain those object files, together with an index of symbols for each object file. You can link it to your program:
gcc *.c libmystuff.a -o myprogram
Now, your program is ready. Note that the order of where the static libraries appear in the command matter. See my Link order answer.
Shared library
For a shared library, you will create your library with
gcc -shared -o libmystuff.so *.c
That's all it takes, libmystuff.so is now a shared object file. If you want to link a program to it, you have to put it into a directory that is listed in the /etc/ld.so.conf file, or that is given by the -L switch to GCC, or listed in the LD_LIBRARY_PATH variable. When linking, you cut the lib prefix and .so suffix from the library name you tell gcc.
gcc -L. -lmystuff *.c -o myprogram
Internally, gcc will just pass your arguments to the GNU linker. You can see what arguments it pass using the -### option: Gcc will print the exact arguments given to each sub process.
For details about the linking process (how some stuff is done internally), view my Linux GCC linker answer.
You've got a third option. In general, your C++ compiler should be able to link C routines. The necessary options may vary from compiler to compiler, so R your fine M, but basically, you should be able to compile with g++ as here:
$ g++ -o myapp myapp.cpp myfunc.c giveint.c
... or compile separately
$ gcc -c myfunc.c
$ gcc -c giveint.c
$ g++ -c myapp.cpp
$ g++ -o myapp myapp.o myfunc.o
You also need to include your declaration of the functions; you do that in C++ as
extern "C" {
int myfunc(int,int);
int giveInterger(void);
}
You need to distinguish between recompiling and relinking.
If you put giveInteger() into a separate (archive) library, and then modify it later, you'll (obviously) need to recompile the source file in which it is defined, and relink all programs that use it; but you will not need to recompile such programs [1].
For a shared library, you'll need to recompile and relink the library; but you will not have to relink or recompile any of the programs which use it.
Building C++ shared libraries on AIX used to be complicated; you needed to use makeC++SharedLib shell script. But with VAC 5.0 and 6.0 it became quite easy. I believe all you need to do is [2]:
xlC -G -o shr.o giveInteger.cc
xlC -o myapp main.cc shr.o
[1] If you write correct Makefile (which is recommended practice), all of this will happen automatically when you type make.
[2] There is a certain feature of AIX which may complicate matters: by default shared libraries are loaded into memory, and "stick" there until subsequent reboot. So you may rebuild the shr.o, rerun the program, and observe "old" version of the library being executed. To prevent this, a common practice is to make shr.o world-unreadable:
chmod 0750 shr.o