ldd does not show the dependency which make then needs - c++

I have the program which needs v2xmvtest.so. When i try to build it via make i get undefined reference to *
Seems like that function from libssl1.0. (If i install it, it's built fine)
But i do not see the place where these function are used. More than that, when i try ldd v2xmvtest.so it does show only libvssl1.1 dependency.
Summary:
Is there a way to find out where those finctions from libvssl1.0 are used in the program ? (i have source code of the v2xmvtest.so and try to search, but there no any of these)
I need a description why ldd does not show me libssl1.0 dependency, but during linkning it's needed
Thank you!

Libraries are not required to fully define used symbols. For instance you can have lib.cpp:
int foo();
int bar(int x)
{
return x + foo();
}
and it compiles even foo is actually not defined yet:
g++ lib.cpp -shared -o lib.so
Then you can have main.cpp:
#include <iostream>
int bar(int);
int foo()
{
return 10;
}
int main()
{
std::cout << bar(42) << std::endl;
}
which defines foo and compiles successfully with lib.so:
g++ main.cpp lib.so -o main
The foo function in lib.so is expected just to be provided when the application is linked and is not specified where exactly from, even not necessary from a library.
You can check for undefined symbols in a library using nm tool:
nm -C -u lib.so
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U foo()
w __cxa_finalize##GLIBC_2.17
w __gmon_start__
And finally you can force gcc to ensure no undefined symbols are used by the object files by compiling with -Wl,-z,defs linker flag:
g++ lib.cpp -shared -Wl,-z,defs -o lib.so
...
lib.cpp:(.text+0x24): undefined reference to `foo()'

Related

Find static library unresolved dependencies before linking executable

So let's say we have static library mylib.a, which contains compiled cpp files.
file1.cpp:
int do_stuff();
int func_unres()
{
int a = do_stuff();
return a;
}
file2.cpp:
int do_other_stuff();
int func_res()
{
int a = do_other_stuff();
return a;
}
file3.cpp:
int do_other_stuff()
{
return 42;
}
So, as we can see here, no file contains definition of do_stuff function.
Library created this way:
g++ -c file1.cpp -o file1.o
g++ -c file2.cpp -o file2.o
g++ -c file3.cpp -o file3.o
ar r mylib.a file1.o file2.o file3.o
Now we try to make some binary with this library. Simple example main file:
#include <iostream>
int func_res();
int main()
{
std::cout << func_res() << std::endl;
}
Compiling:
g++ main.cpp mylib.a -o my_bin
Everything works just fine.
Now consider case of main file like this:
#include <iostream>
int func_unres();
int main()
{
std::cout << func_unres() << std::endl;
}
In this case binary won't link, cause func_unres requires function do_stuff to be defined.
Is there a way to find out that static library requires symbol which no object file in the library contains before linking it with executable, which uses such symbol?
EDIT:
The question is not how to simple list such symbols, but to get an output with linker like error.
Like if i linked this library with executable using all of symbols it should contain.
It seems that as pointed in comments and in How to force gcc to link an unused static library, linker option --whole-archive is enough to force resolve all symbols and output linker error for all unresolved symbols in static library. So referring the question examples, compiling and linking this way first main file, which doesn't refer undefined symbol, will output linker error anyway:
g++ main.cpp -Wl,--whole-archive mylib.a -Wl,--no-whole-archive
Linking fails despite main doesn't use func_unres:
mylib.a(file1.o): In function func_unres(): file1.cpp:(.text+0x9):
undefined reference to do_stuff()
Second option --no-whole-archive is used so the rest of required libraries' symbols will not be force resolved like this.

C++ - What would happen if two library uses same source code for build

I have doubt is it possible if I built lib1.so using source file common.cppand lib2.so using same source file common.cpp again. Now I want to build my application APP using this two library ,
My question are
is it possible Or it will give me error ?
If it will successfully built then how naming gets resolved?
F.e. let say foo is class in common.cpp. foo_v1 is object of foo in lib1.so and foo_v2 is object of foo in lib2.so. Now during bulid of APP what would happen? Also is it possible to create object of foo in APP application ?
Naturally one would suggest you consider building the common functionality shared
by lib1.so and lib2.so into a distinct shared library, libcommon.so.
But if you want nevertheless to statically link the common functionality
identically1
into both lib1.so and lib2.so, you can link these two shared libraries with
your program. The linker will have no problem with that. Here is an
illustration:
common.h
#ifndef COMMON_H
#define COMMON_H
#include <string>
struct common
{
void print1(std::string const & s) const;
void print2(std::string const & s) const;
static unsigned count;
};
common.cpp
#include <iostream>
#include "common.h"
unsigned common::count = 0;
void common::print1(std::string const & s) const
{
std::cout << s << ". (count = " << count++ << ")" << std::endl;
}
void common::print2(std::string const & s) const
{
std::cout << s << ". (count = " << count++ << ")" << std::endl;
}
foo.h
#ifndef FOO_H
#define FOO_H
#include "common.h"
struct foo
{
void i_am() const;
private:
common _c;
};
#endif
foo.cpp
#include "foo.h"
void foo::i_am() const
{
_c.print1(__PRETTY_FUNCTION__);
}
bar.h
#ifndef BAR_H
#define BAR_H
#include "common.h"
struct bar
{
void i_am() const;
private:
common _c;
};
#endif
bar.cpp
#include "bar.h"
void bar::i_am() const
{
_c.print2(__PRETTY_FUNCTION__);
}
Now we'll make two shared libraries, libfoo.so and libbar.so. The
source files we need are foo.cpp, bar.cpp and common.cpp. First
compile them all to PIC (Position Independent Code
object files:
$ g++ -Wall -Wextra -fPIC -c foo.cpp bar.cpp common.cpp
And here are the object files we just made:
$ ls *.o
bar.o common.o foo.o
Now link libfoo.so using foo.o and common.o:
$ g++ -shared -o libfoo.so foo.o common.o
Then link libbar.so using bar.o and (again) common.o
$ g++ -shared -o libbar.so bar.o common.o
We can see that common::... symbols are defined and exported by libfoo.so:
$ nm -DC libfoo.so | grep common
0000000000202094 B common::count
0000000000000e7e T common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
0000000000000efa T common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
(T means defined in the code section, B means defined in the uinitialized data section). And exactly the same is true about libbar.so
$ nm -DC libbar.so | grep common
0000000000202094 B common::count
0000000000000e7e T common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
0000000000000efa T common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
Now we'll make a program linked with these libraries:
main.cpp
#include "foo.h"
#include "bar.h"
int main()
{
foo f;
bar b;
common c;
f.i_am();
b.i_am();
c.print1(__PRETTY_FUNCTION__);
return 0;
}
It calls foo; it calls bar,
and it calls common::print1.
$ g++ -Wall -Wextra -c main.cpp
$ g++ -o prog main.o -L. -lfoo -lbar -Wl,-rpath=$PWD
It runs like:
$ ./prog
void foo::i_am() const. (count = 0)
void bar::i_am() const. (count = 1)
int main(). (count = 2)
Which is just fine. You might perhaps have worried that two copies of the static class variable
common::count would end up in the program - one from libfoo.so and another from libbar.so,
and that foo would increment one copy and bar would increment the other. But that didn't happen.
How did the linker resolve the common::... symbols? Well to see that we need to find their mangled forms,
as the linker sees them:
$ nm common.o | grep common
0000000000000140 t _GLOBAL__sub_I_common.cpp
0000000000000000 B _ZN6common5countE
0000000000000000 T _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
000000000000007c T _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
There they all are and we can tell which one is which with c++filt:
$ c++filt _ZN6common5countE
common::count
$ c++filt _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
common::print1(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
$ c++filt _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
common::print2(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const
Now we can re-do the linkage of prog, this time asking the linker to tell us the names of the
input files in which these common::... symbols were defined or referenced. This diagnostic
linkage is a bit of a mouthful, so I'll \-split it:
$ g++ -o prog main.o -L. -lfoo -lbar -Wl,-rpath=$PWD \
-Wl,-trace-symbol=_ZN6common5countE \
-Wl,-trace-symbol=_ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE \
-Wl,-trace-symbol=_ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
main.o: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: definition of _ZN6common5countE
./libfoo.so: definition of _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: definition of _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: reference to _ZN6common5countE
./libbar.so: reference to _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
So the linker tells us that it linked the definition of common::count from ./libfoo.so. Likewise the
definition of common::print1. Likewise the definition of common::print2. It linked all the
common::... symbol definitions from libfoo.so.
It tells us that the reference(s) to common::print1 in main.o was resolved to the definition in libfoo.so. Likewise
the reference(s) to common::count in libbar.so. Likewise the reference(s) to common::print1 and
common::print2 in libbar.so. All the common::... symbol references in the program were resolved to the
definitions provided by libfoo.so.
So there were no multiple definition errors, and there is no uncertainty about which "copies" or "versions" of the common::... symbols are used
by the program: it just uses the definitions from libfoo.so.
Why? Simply because libfoo.so was the first library in the linkage that provided definitions
for the common::...symbols. If we relink prog with the order of -lfoo and -lbar reversed:
$ g++ -o prog main.o -L. -lbar -lfoo -Wl,-rpath=$PWD \
-Wl,-trace-symbol=_ZN6common5countE \
-Wl,-trace-symbol=_ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE \
-Wl,-trace-symbol=_ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
main.o: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: definition of _ZN6common5countE
./libbar.so: definition of _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libbar.so: definition of _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: reference to _ZN6common5countE
./libfoo.so: reference to _ZNK6common6print2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
./libfoo.so: reference to _ZNK6common6print1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
then we get exactly the opposite answers. All the common::... symbol references in the program
are now resolved to the definitions provided by libbar.so. Because libbar.so provided them first.
There is still no uncertainty, and it makes no difference to the program, because both libfoo.so
and libbar.so linked the common::... definitions from the same object file, common.o.
The linker does not try to find multiple definitions of symbols. Once it has found a
definition of a symbol S, in an input object file or shared library, it binds references to
S to the definition it has found and is done with resolving S. It does
not care if a shared library it finds later can provide another definition of S, the same or different,
even if that later shared library resolves symbols other than S.
The only way in which you can cause a multiple definition error is by compelling the linker
to statically link multiple definitions, i.e. compel it to physically merge into the output binary
two object files obj1.o and obj2.o both of which contain a definition S.
If you do that, the competing static definitions have exactly the same status, and only
one definition can be used by the program, so the linker has to fail you. But it does not need to take any notice of a
dynamic symbol definition of S provided by a shared library if it has already resolved S, and it does not do so.
[1] Of course, if you compile and link lib1 and lib2 with different preprocessor, compiler or linkage options, you can sabotage the "common" functionality to an arbitary extent.

Find an optional symbol from statically linked file with gcc?

I'd like to support some accelerated AVX/SSE functionality, but I'd like to be able to optionally include it. I could use dlsym() along with a shared object, but I'm trying to avoid shared linkage if at all possible in the interest of more portable binaries.
Is there a mechanism I can use to use a static symbol if it's succesfully linked in, and otherwise fall back to a generic function?
You can use a weak symbol, marked with __attribute__ ((weak)), declared like this:
void avx_function (void) __attribute__ ((weak));
And then you check for NULL before calling the function:
if (avx_function != NULL)
avx_function ();
else
fallback_implementation ();
But this doesn't really work for alternative implementations, only for optional functionality which is linked in by other means: You need a mechanism to actually pull in avx_function because the weak symbol will not do that.
But compile-time or link-time feature selection won't get you portable binaries. You are likely better off with run-time checks and indirection through function pointers (for complex feature selection) if you need portable binaries.
If understand correctly, you have some linkage such as:
gcc -o prog main.o ...
in which some avx_func is called, and you'd like it to be so that
if ... does not statically link the genuine definition of avx_func then it will statically link a generic surrogate.
If that's right, you can simply exploit the fact that the linker will resolve
a symbol to the first definition it finds in the linkage sequence, and will not
link any other definition unless it is forced to (in which case a multiple-definition
error is the usual result). So e.g.
main.cpp
extern void avx_func();
int main()
{
avx_func();
return 0;
}
avx_or_not.cpp
#ifdef HAVE_REAL_AVX
#include <iostream>
void avx_func()
{
std::cout << "The real " << __PRETTY_FUNCTION__ << std::endl;
}
#endif
avx_fallback.cpp
#include <iostream>
void avx_func()
{
std::cout << "The fallback " << __PRETTY_FUNCTION__ << std::endl;
}
Make a static library libavxfallback.a:
$ g++ -Wall -Wextra -c avx_fallback.cpp
$ ar rcs libavxfallback.a avx_fallback.o
Compile the other source, assuming real AVX:
$ g++ -Wall -Wextra -DHAVE_REAL_AVX -c avx_or_not.cpp main.cpp
Link a program:
$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback
Run:
$ ./prog
The real void avx_func()
Again compile the other source, this time assuming no real AVX:
$ g++ -Wall -Wextra -c avx_or_not.cpp main.cpp
Relink and rerun:
$ g++ -o prog main.o avx_or_not.o -L. -lavxfallback
$ ./prog
The fallback void avx_func()
At linktime, you do not need to know whether there is anything in the
linkage before -lavxfallback that calls avx_func(), or defines avx_func():
you still know that if it is called, the first definition in the linkage will
be linked, and it will be the one in libavxfallback if there is no earlier one.

Is it possible to merge weak symbols like vtables/typeinfo across RTLD_LOCAL'ly loaded libraries?

For context: I have a Java project that is partially implemented with two JNI libraries. For the sake of example, libbar.so depends on libfoo.so. If these were system libraries,
System.loadLibrary("bar");
would do the trick. But since they're custom libraries I'm shipping with my JAR, I have to do something like
System.load("/path/to/libfoo.so");
System.load("/path/to/libbar.so");
libfoo needs to go first because otherwise libbar can't find it, as it's not in the system library search path.
This has been working well for a while, but I've now run into an issue where std::any_cast is throwing std::bad_any_cast despite the types being correct. I tracked it down to the fact that both libraries have a different definition of the typeinfo for that type, and they're not being merged at runtime. This seems to be because System.load() ends up invoking dlopen() with RTLD_LOCAL rather than RTLD_GLOBAL.
I wrote this to demonstrate the behaviour without needing JNI:
foo.hpp
class foo { };
extern "C" const void* libfoo_foo_typeinfo();
foo.cpp
#include "foo.hpp"
#include <typeinfo>
extern "C" const void* libfoo_foo_typeinfo()
{
return &typeid(foo);
}
bar.cpp
#include "foo.hpp"
#include <typeinfo>
extern "C" const void* libbar_foo_typeinfo()
{
return &typeid(foo);
}
main.cpp
#include <iostream>
#include <typeinfo>
#include <dlfcn.h>
int main() {
void* libfoo = dlopen("./libfoo.so", RTLD_NOW | RTLD_LOCAL);
void* libbar = dlopen("./libbar.so", RTLD_NOW | RTLD_LOCAL);
auto libfoo_fn = reinterpret_cast<const void* (*)()>(
dlsym(libfoo, "libfoo_foo_typeinfo"));
auto libbar_fn = reinterpret_cast<const void* (*)()>(
dlsym(libbar, "libbar_foo_typeinfo"));
auto libfoo_ti = static_cast<const std::type_info*>(libfoo_fn());
auto libbar_ti = static_cast<const std::type_info*>(libbar_fn());
std::cout << std::boolalpha
<< (libfoo_ti == libbar_ti) << "\n"
<< (*libfoo_ti == *libbar_ti) << "\n";
return 0;
}
Makefile
all: libfoo.so libbar.so main
libfoo.so: foo.cpp
$(CXX) -fpic -shared -Wl,-soname=$# $^ -o $#
libbar.so: bar.cpp
$(CXX) -fpic -shared -Wl,-soname=$# $^ -L. -lfoo -o $#
main: main.cpp
$(CXX) $^ -ldl -o $#
On my system, I get
$ make
...
$ ./main
false
true
This is because even though the typeinfo addresses are different, GCC's libstdc++ uses the mangled names for equality. On LLVM's libc++, for example, equality is based on the typeinfo address itself, so I get:
$ make CXX="clang++ -stdlib=libc++"
$ ./main
false
false
If I pass RTLD_GLOBAL instead, I see
true
true
And if I edit main.cpp to load libbar.so first, it also works, provided I tell it where it can find libfoo.so:
$ LD_LIBRARY_PATH=. ./main
true
true
But for the reasons described at the top of this post, neither of these is a practical workaround.
This is very similar to https://github.com/android-ndk/ndk/issues/533 but with non-dynamic types, so there's no way to add a "key function" to force the typeinfo to be a strong symbol. I happened to reproduce the problem on Android first, but it isn't Android-specific.
No, that is not possible. RTLD_LOCAL seeks to prevent exactly that, and unfortunately must be used for System.loadLibrary since otherwise bad things will happen if you System.loadLibrary two libraries that each define different foo classes.

Compile shared object library, which call function from so too

I have got a f2.cpp file
// f2.cpp
#include <iostream>
void f2()
{
std::cout << "It's a call of f2 function" << std::endl;
}
I use cygwin with crosstool compiler gcc.
g++ -fPIC -c f2.cpp
g++ -shared -o libf2.so f2.o
I have got a libf2.so file. Now I want to call f2 function in f1 library (shared object too) libf1.so.
It's a f1.cpp and i want take f1.so
// f1.cpp
#include <iostream>
void f1()
{
std::cout << "f1 function is calling f2()..." << std::endl;
f2();
}
How i must compile f1.cpp? I don't want to use dlclose, dlerror, dlopen, dlsym...
Аt last i want to use f1.so in main.cpp as a shared object library too... without using use dlclose, dlerror, dlopen, dlsym. How I must compile main.cpp, when i will have a f1.so ?
// main.cpp
#include <iostream>
int main()
{
f1();
return 0;
}
declare f2() in a header file. and compile libf1.so similar to libf2.
Now compile main linking against f1 and f2.
It should look something like this
g++ -lf2 -lf1 -L /path/to/libs main.o
You can simply link them together (if f2 is compiled into libf2.so, you pass -lf2 to the linker). The linker will take care of connecting calls from f1 to f2. Naturally, at runtime f1 will expect to find f2 in the SO load path and the dynamic loader will load it.
Here's a more complete sample, taken from a portion of a Makefile I found lying around. Here, mylib stands for your f2, and main_linked is f1:
mylib: mylib.c mylib.h
gcc $(CFLAGS) -fpic -c mylib.c
gcc -shared -o libmylib.so mylib.o
main_linked: main_linked.c mylib.h mylib.c
gcc $(CFLAGS) -L. -lmylib main_linked.c -o main_linked
Note:
mylib is compiled into a shared library with -shared
main_linked is then built with a single gcc call passing -lmylib to specify the library to link and -L. to say where to find it (in this case - current dir)
Check the -L and -l flags to g++.