In GCC, if I compile something into a shared library with GCC with g++ -shared func.cpp -o libfunc.so -fPIC, internal function calls to global symbols go through GOT in this generated shared library file. But if I compile with g++ func.cpp -o libfunc.so -mcmodel=large, it will not generate GOT but instead relocate by patching with R_X86_64_64 style relocation directly.
I want this behavior for executables as well. If I compile an executable with g++ main.cpp libfunc.so -o a.out, GCC will generate GOT for any function call from main.cpp to one defined in libfunc.so. I don't want this behavior. I want R_X86_64_64 style relocation. How can I achieve that?
Executables are compiled with -fPIE by default in modern distros for security reasons. To get old behavior add -no-pie to CFLAGS/CXXFLAGS.
Related
I am trying to compile a multi threaded application to WebAssembly. The application uses OpenMP for multithreading.
To compile I am using the Emscripten framework.
I have already downloaded the source files for OpenMP and compiled it for my host machine using make. With the following command I can get it to link with a simple demo application on my machine:
g++ -Wall -Werror -pedantic main.o -o main.x /$PATH_TO_OPENMP/build/runtime/src/libgomp.a -pthread -lstdc++ -Wl,--no-as-needed -ldl
I then tried to compile OpenMP to the llvm bytecode format used by Emscripten. To do so I tried to run 'emmake make', so that the emscripten framework executes the OpenMP makefiles with a suitable compiler. As emscripten does not like shared object files I compiled it to static library .a files.
This works and actually gives me object files to which I can link.
I then wanted to link my demo application with the following command
em++ -Wall -Werror -pedantic main.o -o main.html /home/main/data/Programming/openMP/openmp_web/build/runtime/src/libgomp.a -pthread -lstdc++ -Wl,--no-as-needed -ldl
But I get these warnings, that it couldn't link to OpenMP files:
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents/kmp_atomic.cpp.o is not a valid object file for emscripten, cannot link
.
.
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents/kmp_str.cpp.o is not a valid object file for emscripten, cannot link
shared:WARNING: object /tmp/emscripten_temp_ONa0eU_archive_contents
So I figured I must have compiled OpenMP with the wrong compiler. I then tried to change the compiler when building the library by using the following commands:
cmake -DCMAKE_C_COMPILER=emcc -DCMAKE_CXX_COMPILER=em++ -DLIBOMP_LIB_TYPE=normal -DLIBOMP_ENABLE_SHARED=OFF -DCMAKE_BUILD_TYPE=Release -DLIBOMP_ARCH=x86_64 OPENMP_STANDALONE_BUILD=1 ..
emmake make
But this just gives strange errors on some missing system variables
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_platform.h:82:2: error: Unknown OS
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_platform.h:203:2: error: Unknown or unsupported architecture
In file included from /home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_alloc.cpp:13:
In file included from /home/main/data/Programming/openMP/openmp_web/runtime/src/kmp.h:77:
/home/main/data/Programming/openMP/openmp_web/runtime/src/kmp_os.h:171:2: error: "Can't determine size_t printf format specifier."
Does anyone have an idea on what I could do differently?
Consider the following scenario:
Shared Library libA.so ,with no dependencies.
Shared Library libB.so, with libA.so as its dependency.
I want to compile a binary file that links with the libB.
Should I link the binary with libB only or with libA either?
Is there any way to link only with the direct dependencies, letting the resolution of unresolved symbols from the dependencies for runtime?
I'm worried about the fact that the library libB implementation may change in the future, introducing other dependencies (libC, libD, libE for instance). Am I going to have problems with that?
In other words:
libA files: a.cpp a.h
libB files: b.cpp b.h
main program files: main.cpp
Of course, b.cpp includes a.h and main.cpp includes b.h.
Compilation commands:
g++ -fPIC a.cpp -c
g++ -shared -o libA.so a.o
g++ -fPIC b.cpp -c -I.
g++ -shared -o libB.so b.o -L. -lA
Which of the bellow options should I use?
g++ main.cpp -o main -I. -L. -lB
or
g++ main.cpp -o main -I. -L. -lB -lA
I couldn't use the first option. The linker complains about the unresolved symbols from the library libA. But it sound a little strange to me.
Thanks very much.
-- Updated comments:
When I link the binary, the linker will try to resolve all symbols from the main and the libB. However, libB has undefined symbols from the libA. That's why the linker complains about that.
That's why I need to link with the libA too.
However I found a way to ignore unresolved symbols from shared libraries.
Looks like I should use the following command line to do that:
g++ main.cpp -o main -I. -L. -lB -Wl,-unresolved-symbols=ignore-in-shared-libs
Looks like it is still possible to use the -rpath option.
However I need to understand it a little better.
Does anyone knows any possible pitfalls when using the -Wl,-unresolved-symbols=ignore-in-shared-libs option?
-- Updated comments 2:
-rpath should not be used for this purpose. It is useful to force a library to be found in a given directory. The -unresolved-symbol approach looks much better.
Thanks again.
It looks like you are most of the way there already. Well done with your investigation. Let's see if I can help clear up the 'why' behind it.
Here's what the linker is doing. When you link your executable ('main' above) it has some symbols (functions and other things) that are unresolved. It will look down the list of libraries that follow, trying to resolve unresolved symbols. Along the way, it finds that some of the symbols are provided by libB.so, so it notes that they are now resolved by this library.
However, it also discovers that some of those symbols use other symbols that are not yet resolved in your executable, so it now needs to resolve those as well. Without linking against libA.so, your application would be incomplete. Once it links against libA.so, all symbols are resolved and linking is complete.
As you saw, the use of -unresolved-symbols-in-shared-libs, doesn't fix the problem. It just defers it so that those symbols are resolved at run time. That's what -rpath is for: to specify the libraries to be searched at run time. If those symbols can't be resolved then, your app will fail to start.
It's not an easy thing to figure out library dependencies because a symbol could be provided by more than one library and be satisfied by linking against any one of them.
There is another description of this process here: Why does the order in which libraries are linked sometimes cause errors in GCC?
For dynamic linking only with direct dependencies you can use -Wl,--as-needed with adding the libs after -Wl,--as-needed:
gcc main.c -o main -I. -L. -Wl,--as-needed -lB -lA
For checking the direct dependencies you should use readelf instead of ldd because ldd also shows the indirect dependencies.
$ readelf -d main | grep library
0x0000000000000001 (NEEDED) Shared library: [libB.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
ldd also shows the indirect dependencies:
$ LD_LIBRARY_PATH=. ldd ./main
linux-vdso.so.1 (0x00007fff13717000)
libB.so => ./libB.so (0x00007fb6738ed000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb6734ea000)
libA.so => ./libA.so (0x00007fb6732e8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb673af0000)
If you use cmake, you can add the following lines to include only direct dependencies:
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed ${CMAKE_SHARED_LINKER_FLAGS}")
Another option is to use libtool
If you change the g++ call to libtool --mode=compile g++ to compile the source code and then libtool --mode=link g++ to create the application off of libB, then libA will be linked automatically.
This is an interesting post - I was banging my head with this as well, but I think you miss a point here..
The idea is as follows, right ?
main.cpp =(depends)=> libB.so =(depends)=> libA.so
Let's further consider that ..
In a.cpp (and only there) you define a class / variable, let's call it "symA"
In b.cpp (and only there) you define a class / variable, let's call it "symB".
symB uses symA
main.cpp uses symB
Now, libB.so and libA.so have been compiled as you described above. After that, your first option should work, i.e.:
g++ main.cpp -o main -I. -L. -lB
I guess that your problem originates from the fact that
in main.cpp you also refer to symA
Am I correct?
If you use a symbol in your code, then that symbol must be found in an .so file
The whole idea of inter-referencing shared libraries (i.e. creating APIs), is that the symbols in the deeper layers are hidden (think of peeling onions) and not used.
.. i.e. don't refer to symA in your main.cpp, but only to symB instead (and let symB to refer symA only).
using gcc 4.5.1 in a 64bit x86 machine,I first create a.o as following:
g++ -fPIC -c a.cc -o a.o
then try to create liba.so as following:
g++ -static-libstdc++ -shared -W1,-soname,liba.so -o liba.so.1.0.0 a.o
but failed, with the following information:
relocation R_X86_64_32S against `vtable for __gnu_cxx::stdio_filebuf >' can not be used when making a shared object; recompile with -fPIC
I try to recompile libstdc++ library,with -fPIC added,but it failed anyway
I would expect that the static libstdc++ library was not build with -fPIC, and therefore can't be linked into a shared library.
Theoretically you could put non-PIC compiled code into a dynamic library, but it wouldn't be sharable (each program using it would have to have its own copy) so it's often not implemented.
You're going to need to link against the shared C++ library, make your own library a static library, or else rebuild libstdc++ yourself and grab the .o files from the build directory.
There is a similar question about this topic on stackoverflow, which refers to an external site about static linking of libstdc++.
I've been trying to find the proper .a's and related flags for statically linking an app or SO under Linux. I know -static exists, but I can't use it as there's one specific SO I must link to.
To put it another way, I'm looking for the appropriate flags to statically link everything, except for a specific SO.
Thanks.
At my workplace we use -Bstatic and -Bdynamic but they are options to the linker ld. You can specify them with gcc using the -Wl option.
g++ -o app -Wl,-Bstatic -llib1 -llib2 -llib3 -Wl,-Bdynamic -llib4 app.o
Above shows command line for linking with lib1, lib2, and lib3 as static libraries and lib4 as a shared object library.
I'm currently trying to compile a dynamically linked library (for a plugin system) using Windows and MinGW.
I compile each objects using this command line :
mingw-g++ -fPIC test.cpp
And the library using this line:
mingw-g++ -rdynamic -shared -Wl,-soname,test.so.1 -o test.so test.o
It doesn't work at all (using GCC with Linux, a similar line works though) : fPIC and rdynamic are ignored for some reason.
And while trying to make the library, it fails because the compiler try to link it with objects that are supposed to be resolved as I dynamically link it with the main binary.
So how do you compile this using MinGW?
Thanks :) !
-fPIC and -rdynamic are ignored because they are unused for Windows.
Also, .so is not the correct output extension for libraries on Windows.
To make a shared library for/on windows with GCC:
mingw-g++ -c file.cpp -o file.o
mingw-g++ -shared -Wl,--out-implib,libfile.a -o file.dll file.o
No more, no less.
And, documentation is always lovely to have: http://www.mingw.org/wiki/sampleDLL