Strange symbols while linking shared library g++ - linux

I have a file with the void initGui() function in it. It does stuff.
I also have a .so shared library made with that file.
The problem is, when I try to launch a dlsym(..., "initGui"), dlerror() tells me that it didn't found the symbol (of course, I used dlopen to open it). So I tried to nm my shared lib. I "understood" that _Z7initGuiiii might be what I'm looking for. So I tried to dlsym it ... And it worked.
Please can someone tell me how to have clean symbols in my shared object library ?
I compile with g++ -Wall -Wextra -Werror -c -fPIC.

The usual practice when dlsym-ing inside some dlopen-ed shared library coded in C++ is to have the convention that those seeked symbols (those that you are dlsym-ing) are declared extern "C". Then their name is easily visible with dlsym. So you need to declare
extern "C" void initGui(void);
and then to do
typedef void initguiroutine_sig_t(void);
initguiroutine_sig_t* initguiptr = dlsym(dlhandle,"initGui");
if (!initguiptr) {
fprintf(stderr, "initGui not found: %s\n", dlerror());
exit (EXIT_FAILURE);
};
// later, call initguiptr like
(*initguiptr) ();
I don't recommend understanding in great details how your C++ name mangling works, it is not very well defined, and details depend upon particular version of the C++ libraries (notably the standard C++ library) and of the compiler version.

Related

Enumerating shared libraries loaded via dlopen(RTLD_GLOBAL)

Is there a way to determine at runtime which shared libraries have been loaded into the global symbol namespace of the current process? I'm primarily interested in anything that was loaded as a result of a dlopen() call that used the RTLD_GLOBAL flag.
I'm wanting to do this for auditing purposes -- it's important for an application I work on that dynamically-loaded shared libraries are loaded with dlopen's RTLD_LOCAL wherever possible so as not to conflict with third-party code; anything that's loaded into the global symbol namespace needs to be tightly controlled.
I've looked at the dl_iterate_phdr() API, but it doesn't seem to include this information.
You can try with
#define _GNU_SOURCE
#include <dlfcn.h>
typedef void *(*orig_dl)(const char *file, int mode);
void *dlopen(const char *file, int mode)
{
orig_dl o_dlopen;
o_dlopen = (orig_dl)dlsym(RTLD_NEXT, "dlopen");
return o_dlopen(file, mode);
}
Compile it using gcc -shared -fPIC dlo.c -o dlo.so -ldl
add LD_PRELOAD=dlo.so and here you go. You can log/trace/print any dlopen usage with specific mode
I think the suggestion to replace dlopen() using LD_PRELOAD is only a partial solution -- you won't catch dependencies of a library loaded with dlopen() that way.
In the end, I couldn't see any way of doing this without scraping the internal state of the dynamic linker itself. It found that there's a _rtld_global symbol exported from ld.so that has the information, but that you have to use private Glibc headers to interpret it.
The following is a Python snippet that will (assuming my reading of the Glibc sources is correct) print all the shared libraries in the global namespace in the order that they will be searched. Libraries loaded with RTLD_LOCAL will not be printed.
The fact that it relies on implementation details of Glibc means this approach is fraught with peril, but for my testing/auditing purposes I think it'll do nicely.
import ctypes
# Abridged type declarations pillaged from Glibc. See:
# - https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/generic/ldsodefs.h
# - https://sourceware.org/git/?p=glibc.git;a=blob;f=include/link.h
class link_map(ctypes.Structure):
_fields_ = [
("l_addr", ctypes.c_size_t),
("l_name", ctypes.c_char_p),
]
class r_scope_elem(ctypes.Structure):
_fields_ = [
("r_list", ctypes.POINTER(ctypes.POINTER(link_map))),
("r_nlist", ctypes.c_uint),
]
class rtld_global(ctypes.Structure):
_fields_ = [
("_ns_loaded", ctypes.POINTER(link_map)),
("_ns_nloaded", ctypes.c_uint),
("_ns_main_searchlist", ctypes.POINTER(r_scope_elem)),
]
_rtld_global = rtld_global.in_dll(ctypes.CDLL(None), "_rtld_global")
searchlist = _rtld_global._ns_main_searchlist[0]
print [searchlist.r_list[n][0].l_name for n in xrange(searchlist.r_nlist)]
On my CentOS 7 system, this prints:
['', '/lib64/libpython2.7.so.1.0', '/lib64/libpthread.so.0', '/lib64/libdl.so.2',
'/lib64/libutil.so.1', '/lib64/libm.so.6', '/lib64/libc.so.6',
'/lib64/ld-linux-x86-64.so.2']

Linux library calls ambiguously named function in executable - is this possible?

I have a problem with an embedded linux C++ application I've written that consists of an executable and a dynamically linked library. The executable calls a function that is one of the entry points in the library, but that function misbehaves. I've investigated using gdb, and find that the library function, which is supposed to make a call to another function xyz() within the library, actually calls a function of the same name xyz()within the executable.
I'm very surprised this can happen, so maybe I'm doing something stupid. Isn't the library linked within itself without reference to the executable? If the executable wrongly made a call to abc() in the library instead of abc() in the executable that would make slightly more sense, because it is at least linked with the library, although in that case would the linker spot the dual definition? Or prioritise the local function?
I could just rename my functions so none of them have matching names, but I'd like to understand what is going on. I don't have much experience in this area, or with the gcc tools. Firstly, is what I think is happening in the above scenario even possible?
Both the executable and the library make calls to another library.
The link command for the library I'm using is:
powerpc-unknown-linux-gnuspe-g++-4.9.3 aaa.o bbb.o [etc] -shared -o libmylibary.so -L ../otherlibpath -Wl,-rpath-link,../otherlibpath -lotherlibname
That is way how the dynamic linker works. The symbols in executable have higher priority then symbols in dynamic libraries. Dynamic library designer must be aware about it. She must do measures to avoid unwanted symbol mismatch. Most libraries use:
In case of C++ use namespaces. All symbols exported from library should be in a library namespace.
In case of C use a name prefix or suffix for all exported symbol. For example OpenSSL library uses the prefix SSL_ and the public functions have names like SSL_set_mode() so the unwanted symbol collision is avoided.
Do not export symbols from the library that are supposed to be private. If the symbol is not exported from the library then the dynamic linker use the local symbol in the library. #pragma visibility is your friend. See https://gcc.gnu.org/wiki/Visibility
If the library with duplicate symbols is a 3rd party library and its author does not follow the recommendations above then you have to rename your function or perhaps ask the author for a library update.
EDIT
Export/do not export may be controlled by #pragma visibility directive (gcc specific extension):
void exported_function1(int);
void exported_function2(int);
#pragma GCC visibility push(hidden)
void private_function1(int);
void private_function2(int);
#pragma GCC visibility pop
Detail at the link above.

Shared object in Linux without symbol interposition, -fno-semantic-interposition error

Shared objects (*.so) in Unix-like systems are inefficient because of the symbol interposition: Every access to a global variable inside the .so needs a GOT lookup, and every call from one function to another inside the .so needs a PLT lookup. I was therefore happy to see that gcc version 5.1 has added the option -fno-semantic-interposition. However, when I try to make a .so where one function calls another without using a PLT, I get the error message:
relocation R_X86_64_PC32 against symbol `functionname' can not be used when making a shared object; recompile with -fPIC
I expected the option -fno-semantic-interposition to eliminate this error message, but it doesn't. -mcmodel=large doesn't help either.
The reference to the function is indeed position-independent, which the error message actually confirms (R_X86_64_PC32 means PC-relative 32-bit relocation in 64-bit mode). -fPIC does not really mean position-independent, as the name would imply, it actually means use GOT and PLT.
I cannot use __attribute__((visibility ("hidden"))) because the called function and the caller are compiled in seperate files (caller is in C++, called function is in assembly).
I tried to make an assembly listing to see what the option -fno-semantic-interposition does. I found out that it makes a reference to a local alias when one function calls another in the same file, but it still uses a PLT when calling a function in another file.
(g++ version is 5.2.1 Ubuntu, 64-bit mode).
Is there a way to make the linker accept a cross-reference inside a .so without the GOT/PLT lookup?
Is there a way to make the linker accept a cross-reference inside a .so without the GOT/PLT lookup?
Yes: attribute((visibility("hidden"))) is exactly the way to do it.
I cannot use attribute((visibility ("hidden"))) because the called function and the caller are compiled in seperate files
You are confused: visibility("hidden") means that the symbol will not be exported from the shared library, when it is finally linked. But the symbol is global and visible across multiple translation units before that final link.
Proof:
$ cat t1.c
extern int foo() __attribute__((visibility("hidden")));
int main() { return foo(); }
$ cat t2.c
int foo() __attribute__((visibility("hidden")));
int foo() { return 42; }
$ gcc -c -fPIC t1.c t2.c
$ gcc -shared t1.o t2.o -o t.so
$ nm -D t.so | grep foo
$
I tried to make an assembly listing to see what the option -fno-semantic-interposition does. I found out that it makes a reference to a local alias when one function calls another in the same file, but it still uses a PLT when calling a function in another file.
If you read the discussion in gcc-patches, you'll see that the -fno-semantic-interposition is about allowing inlining of possibly interposable functions, not about the way they are actually called when not inlined.

Static vs. dynamic linking conflicts and duplication

I have a code A that is statically linked against one version of mpich. Now comes library B, which is used by A via dlopen(). B depends on mpich as well, but is linked dynamically against it.
The problem is that now, in order for B to take advantage of mpi distribution, needs to access the communicator currently handled by A. This communicator has been created by A static version of mpich, When B invokes MPI routines, it will use a dynamic version of MPI which is not guarateed to be compatible with the static version attached to A.
This is the overall picture. I think that the only solution is to have mpich dynamically linked for both A and B. What I am not fully understanding is however the following:
how does the linker handle shared objects dependencies when dlopening? Will I have two instances of mpich in VM also with dynamic linking, or is the linker smart enough to realize that the symbols required by the dlopened B are already in the address space and will resolve against those.
Is it possible to tell the linker: when you dlopen this library, don't go fetch the dynamic dependency, but resolve it with the static symbols that are already provided by A
In short: it depends on dlopen options. By default, if a symbol needed by the requested library already exists in the global scope, it will be reused (this is what you want). But you can bypass this behavior with RTLD_DEEPBIND, with this flag, the dependencies won't be reused from the global scope, and will be loaded a second time.
Here is some code to reproduce your situation and demo the effect of this flag.
Let's make a common library that will be used by both lib A and program B. This library will exist in two versions.
$ cat libcommon_v1.c
int common_func(int a)
{
return a+1;
}
$ cat libcommon_v2.c
int common_func(int a)
{
return a+2;
}
Now let's write lib A that uses libcommon_v2:
$ cat liba.c
int common_func(int a);
int a_func(int a)
{
return common_func(a)+1;
}
And finally program B that dynamically links to libcommon_v1 and dlopens lib A:
$ cat progb.c
#include <stdio.h>
#include <dlfcn.h>
int common_func(int a);
int a_func(int a);
int main(int argc, char *argv[])
{
void *dl_handle;
int (*a_ptr)(int);
char c;
/* just make sure common_func is registered in our global scope */
common_func(42);
printf("press 1 for global scope lookup, 2 for deep bind\n");
c = getchar();
if(c == '1')
{
dl_handle = dlopen("./liba.so", RTLD_NOW);
}
else if(c == '2')
{
dl_handle = dlopen("./liba.so", RTLD_NOW | RTLD_DEEPBIND);
}
else
{
printf("wrong choice\n");
return 1;
}
if( ! dl_handle)
{
printf("dlopen failed: %s\n", dlerror());
return 2;
}
a_ptr = dlsym(dl_handle, "a_func");
if( ! a_ptr)
{
printf("dlsym failed: %s\n", dlerror());
return 3;
}
printf("calling a_func(42): %d\n", (*a_ptr)(42));
return 0;
}
Let's build and run all the things:
$ export LD_LIBRARY_PATH=.
$ gcc -o libcommon_v1.so -fPIC -shared libcommon_v1.c
$ gcc -o libcommon_v2.so -fPIC -shared libcommon_v2.c
$ gcc -Wall -g -o progb progb.c -L. -lcommon_v1 -ldl
$ gcc -o liba.so -fPIC -shared liba.c -L. -lcommon_v2
$ ./progb
press 1 for global scope lookup, 2 for deep bind
1
calling a_func(42): 44
$ ./progb
press 1 for global scope lookup, 2 for deep bind
2
calling a_func(42): 45
We can clearly see that with default options, dlopen reuses the symbol common_func that was present in program B and that with RTLD_DEEPBIND, libcommon was loaded again and library A got its own version of common_func.
You did not say which Toolchain (GCC, LLVM, MSC, etc.) you are using, the most helpful answer will depend upon this information.
May I suggest you look at "GCC Exception Frames" http://www.airs.com/blog/archives/166 .
If that is helpful then the Gold Linker, which is available for GCC and LLVM, supports 'Link Time Optimization' and can run in "Make" with DLLTool http://sourceware.org/binutils/docs/binutils/dlltool.html .
Indeed it is possible to have both Static and Dynamic Code call each other, the Computer does not care; it will 'run' anything it is fed -- whether that ends up working exactly the way you want or HCFs depends on correct Code and correct Linker commands.
Using a Debugger will not be fun. It would be best to mangle the names prior to Linking so that when debugging you can see from which module the Code came. Once it is up and running you can undef the Mangle and have the same-named Functions Link (to ensure it still functions).
Compiler / Linker Bugs will not be your friend.
This sort of scenario (Static and Dynamic Linking) occurs more often with MinGW and Cygwin where some of the Libraries are Static yet a Library you download from the Internet is only available in Dynamic form (without Source).
If the Library is from two different Compiler Toolchains then other issues arise, see this StackOverflow Thread: " linking dilemma (undefined reference) between MinGW and MSVC. MinGW fails MSVC works ".
It would be best to simply get the newest version of the Library from the source and compile the whole thing yourself, rather than rely on trying to cobble together bits and pieces from different sources (though it is possible to do that).
You can even load the Dynamic Library and call it (statically) and then reload portions of it later.
How tight are you on Memory and how fast do you want Functions to run, if everything is in Memory your Program can transfer execution to called Functions straight away, if you are swapping a portion of your Code to VM your execution times will really take a hit.
Running a Profiler on your Code will help decide what portions of a Library to load if you want to do 'dynamic dynamic linking' (full control of your dyna-linking by loading a Dynamic Library so it can be used Statically). This is the stuff that headaches and nightmare are made of. GL.

Receive "undefined symbol" error when loading library with dlopen

I'm writing some code that uses dynamic shared libraries as plugins.
My command line for building the shared libraries looks like:
cc -shared -fPIC -o module.so -g -Wall module.c
Within the module, I can call functions that are in any other shared library that has been loaded within the main executable.
However I cannot access (exported) functions that are in the executable itself (I get undefined symbol errors).
My call to dlopen looks like this:
void *handle = dlopen(plugin, RTLD_NOW);
Can anyone please advise how my module can call back to my executable, without having to put all of the executable's utility functions into yet another shared library?
Correct solution is to add -rdynamic to the link command of the main executable. This will add appropriate option to ld (which, when using GNU ld, happens to be --export-dynamic).
Adding --export-dynamic directly is technically incorrect: it's a linker option, and so should be added as -Wl,--export-dynamic, or -Wl,-E. This is also less portable than -rdynamic (other linkers have an equivalent, but the option itself is different).
I've found the answer myself.
I had to add the --export-dynamic flags to the link options for the main executable.
When creating a dynamically linked
executable, add all symbols to the
dynamic symbol table. The dynamic
symbol table is the set of symbols
which are visible from dynamic objects
at run time.
If you do not use this option, the
dynamic symbol table will normally
contain only those symbols which are
referenced by some dynamic object
mentioned in the link.
If you use "dlopen" to load a dynamic
object which needs to refer back to
the symbols defined by the program,
rather than some other dynamic object,
then you will probably need to use
this option when linking the program
itself.
When I encountered the same problem, I just used the following solution. Before loading any plugin, just load the program itself, bringing its symbols to dynamic tables:
dlopen(NULL,RTLD_NOW|RTLD_GLOBAL);
I think the solution is better. The reason is that, it also solves the same problem if you
a) your program (or a trird-party module) is linked (not in runtime) against the shared library, which symbols need to be in dynamic table;
b) can not recompile that module with -rdynamic flag.

Resources