How to include different versions of same static library in an application? - linker

I have an application which includes AA.so. AA.so internally includes CC.a version 1.
Now I have to include BB.so to the same application for some other feature. BB.so also includes CC.a version 2.
I don't have source code of any of these libraries.
My question is -
How to make sure that function calls from AA.so go to CC.a version 1 and calls from BB.so go to CC.a version 2?

How to make sure that function calls from AA.so go to CC.a version 1 and calls from BB.so go to CC.a version 2?
You can't: making sure involves building AA.so and BB.so in a self-contained manner, and you can't rebuild them.
What you can do is try to make this work by loading the libraries at runtime using dlopen("AA.so", RTLD_LAZY|RTLD_LOCAL) and same for BB.so, and hope that the libraries don't step on each other.
In theory that (RTLD_LOCAL is the important bit) should work. In practice, there are many ways this could still break; you are venturing into very dangerous ground.
It could also work today, but break when either shared library is updated. You really should work with your library suppliers to get out of this multiple incompatible version mess.
Update:
I believe shared objects do not depend on anything else and in that sense they are self-contained.
The "not depend on anything else" part is necessary, but not sufficient.
Normally, a shared library exports all global functions and data linked into it. Suppose CC.a contains a global function foo; suppose that versions 1 and 2 of this function are not compatible, and that foo is exported from both AA.so and BB.so. In that case, whichever library is loaded first will win. If AA.so is loaded first, then a call from BB.so to foo will get resolved to the definition inside AA.so, and your program will either corrupt its state, or crash.
To verify that this is not the case, you should run nm -D on AA.so and BB.so, and confirm that the intersection of symbols exported from these libraries is empty. If it is not empty, you have to verify that the two definitions are compatible.

Related

Go/Cgo: produce static library without definitions of Go runtime functions

Is there a way to produce a C static library from Go code, but without Go runtime function definitions?
Rationale:
Project A creates a C static library with go build -buildmode=c-archive, libA.a .
Works well: project B uses pure C and is able to easily create an executable, statically linking with libA.a, all is fine.
Problem 1: project C happens to also use Go, but would like to use libA.a as a regular C library. Now it has a link problem: the Go runtime functions such as e.g. _cgo_panic are now defined both in project C runtime (as it uses Go) and in libA.a.
Problem 2: project D uses pure C, same as B. Yet it wants to use two different libraries from project A, e.g. libA.a and some libA2.a. Sadly, it does not link either, because Go runtime functions are now defined in both libA.a and libA2.a.
The problems faced by project C and project D could be easily resolved if project A could produce its libraries without the Go runtime definitions inside. Project C could just link with libA.a. Project D would link with libA.a, libA2.a and some libGo.a that would contain definitions of all the Go runtime stuff.
What I tried:
Using linker flags at 'project C' level, such as -Wl,--allow-multiple-definition. Now its build fails with a cryptic message 'function symbol table not sorted by program counter'.
Manually removing go.o from 'libA.a' (as it's just an "ar" archive): didn't work as 'go.o' also contained implementations of my exported functions, so I've removed too much.
Using go build -buildmode=c-shared. As expected, it produces a dynamic library which uses another format, so I could not directly use it as a static library.
Any solution at the client side (such as finding a proper way to ignore duplicate definitions at the link stage for project C) would be also considered a valid answer.
I can also accept a negative answer (no solution) if it provides enough evidence.
Update: see a related question Is there a way to include multiple c-archive packages in a single binary
With the current implementation it's not going to work to use -buildmode=c-archive multiple times and put the results into multiple shared libraries, as you've discovered. The essential problem is that there has to be only one Go runtime, but you have multiple runtimes. When using -buildmode=c-archive there's no way to isolate the different runtimes.
The -buildmode=c-shared libraries differ from buildmode=c-archive in that they are built with -Bsymbolic which forces all their local references to be local. The effect is that we have multiple Go runtimes, but they don't refer to each other so there is no confusion.
You could try adding -Wl,-Bsymbolic to build each shared library that includes Go code in c-archive if your C code doesn't mind being linked with -Bsymbolic.
I wish you luck.

How to circumvent dlopen() caching?

According to its man page, dlopen() will not load the same library twice:
If the same shared object is loaded again with dlopen(), the same
object handle is returned. The dynamic linker maintains reference
counts for object handles, so a dynamically loaded shared object is
not deallocated until dlclose() has been called on it as many times
as dlopen() has succeeded on it. Any initialization returns (see
below) are called just once. However, a subsequent dlopen() call
that loads the same shared object with RTLD_NOW may force symbol
resolution for a shared object earlier loaded with RTLD_LAZY.
(emphasis mine).
But what actually determines the identity of shared objects? I tried to look into the code, but did not come very far. Is it:
some form of normalized path name (e.g. realpath?)
the inode ?
the contents of the libray?
I am pretty sure that I can rule out this last point, since an actual filesystem copy yields two different handles.
To explain the motivation behind this question: I am working with some code that has static global variables. I need multiple instances of that code to run in a thread-safe manner. My current approach is to compile and link said code into a dynamic library and load that library multiple times. With some linker magic, it appears to create several copies of the globals and resolve access in each library to its own copies. The only problem is that my prototype copies the generated library n times for n concurrent uses. This is not only somewhat ugly but I also suspect that it might break on a different platform.
So what is the exact behaviour of dlopen() according to the POSIX standard?
edit: Because it came up in a comment and an answer, no refactoring the code is definitely not an option. It would involve months or even years of work and potentially sacrifice all benefits of using the code in the first place. There exists an ongoing research project that might solve this problem in a much cleaner way, but it is actual research and might fail. I need a solution now.
edit2: Because people still seem to not believe the usecase is actually valid. I am working on a pure functional language, that shall be embedded into a larger C/C++ application. Because I need a prototype with a garbage collector, a proven typechecker, and reasonable performance ASAP, I used OCaml as intermediate code. Right now, I am compiling a source module into an OCaml module, link the generated object code (including startup etc.) into a shared library with the OCaml runtime and dlopen() that shared library. Every .so has its own copy of the runtime, including several global variabels (e.g. the pointer to the young generation) and that is, or rather should be, totally fine. The library exposes exactly two functions: An initializer and a single export that does whatever the original module is intended to do. No symbols of the OCaml runtime are exported/shared. when I load the library, its internal symbols are relocated as expected, the only issue I have right now is that I actually need to copy the .so file for each instance of the job at runtime.
Regarding thread-local-storage: That is actually an interesting idea, as the modification to the runtime is indeed rather simple. But the problem is the machine code generated by the OCaml compiler, as it cannot emit loading instructions for tls symbols (yet?).
POSIX says:
Only a single copy of an object file is brought into the address space, even if dlopen() is invoked multiple times in reference to the file, and even if different pathnames are used to reference the file.
So the answer is "inode". Copying the library file "should work", but hard links won't. Except. Since they will expose the same global symbols and when that happens all (portability) bets are off. You're in the middle of weakly defined behavior that has evolved through bug fixes rather than good design.
Don't dig deeper when you're in a hole. The approach to add additional horrible hacks to make a fundamentally broken library work just leads to additional breakage. Just spend a few hours to fix the library to not use globals instead of spending days to hack around dynamic linking (which will be unportable at best).

Two main functions in a C application

I'm actually put in a big project. My first step to understand the code was to search the main function so that I have a vision of the architecture.
What I discovered is that there is more than one main function. It's true that they are in different folders, but I don't understand how this application succeed to build. What I know is that the linker expects one main function (Entry point).
I believe it's too hard to understand the build process of the application, so I'm asking because for sure some of you have encountered this.
1 - Should I have theoretical background to understand this? If so, please suggest me articles, books, what ever you want.
2 - When do we have to use several main functions in one application?
You can't have multiple main functions for a single executable. There are several possibilities.
If doing a build builds only a single application, then only one of the main functions will be compiled. (Or none, if there's an option to build a library rather than an executable.) There are probably options that determine which one to build, depending on which variant of the application you want, the target system, or something else.
Or perhaps the application consists of multiple executables, with one main function for each one.
If running the build doesn't take too long, a trick I've used to determine which of several source files is actually compiled is to temporarily add #error directives, like:
#error "TEMPORARY: This is /full/path/to/source.cpp"
The resulting error message will tell you which source file was actually compiled. (You can also use #warning directives if your compiler supports them.)
Should i have theorical background to undestand this, suggest me articles book what ever you want
You need to have some understanding of what a build means but, more importantly, you have to understand the build process in your specific environment. You need to have an understanding of:
The list of build targets (executables and shared libraries)
The compiler settings used by them (you could be building DLLs for VS 2010 as well as VS 2012).
When do we have to use several main functions in one application?
When your build system builds multiple executables, you will need multiple main functions.
When your build system chooses file1.c or file2.c for building an executable depending on some settings, you might find main functions in file1.c as well file2.c. This will be a rather poor way to organize code but it is possible.
Trying to link an executable with multiple definitions for the same identifier (aka main in this case) will fail as the linker cannot select one or the other.
There's one possibility, though that allows you to have multiple main entry points, but assuring you only select one in the building process.
I'll illustrate this with a simple example: suppose you have a library (a .a static library) that has a module that includes a main definition. As library modules are selected at link time depending on the actual need of the identifiers at the time the library is linked, you can have a main definition in a module to supply when you don't have one, or that module is not linked in case you have a proper definition of it. This is exploited in some standard libraries like -ll (flex has a definition of main that calls the yylex() function), -ly (bison has a main definition that call the yyparse() routine) These modules are included if you don't have done it before.
But beware, as if you link your main function after the library -ll, for example, it will be included (as main was not resolved at the time he library was included, and then you included the second, duplicated entry, making the ld linker to complaint)

Is it possible to do hot code swapping in C?

this
en.wikipedia.org/wiki/Hot_swapping#cite_note-1
says that VS can do it with the help of its debugger. Does gdb provide a similar functionality ?
this is the closest i could find, but doesn't seem to be ready to be used:
http://www.aitdspace.gr/xmlui/handle/123456789/219
dlopen/dlsym/dlclose are also close, but will not work for -lmylib referenced libraries (reference count never gets to 0).
alternatives i've considered:
1) using -Wl,-wrap,foo and on __wrap_foo() { func = dlopen(); func(); }
2) making libfoo.so a shared library and when we need to hotswap we dlopen(RTLD_GLOBAL) to load the new code and provide updated symbols to the next call to foo();
1) doesn't work very well because it requires me to enumerate all the functions i want to hotswap, which are all of them.
2) doesn't work very well because when foo() is called, the new code is loaded, but foo has forever the reference to that symbol. calling dlopen multiple times make foo to be re evaluated.
You may be interested in Ksplice. It's a technology that came out of MIT that allows software patches to be applied to the Linux kernel without rebooting. This is most relevant for applying security updates:
http://www.ksplice.com/paper
You could certainly hack yourself a system where you store a list of function pointers and can change these pointers to point to whatever library you have dlopen()'d at the time.
You're right, there isn't any easy way to intercept calls to routines with fixed linkage. You can always clobber the start of the routine with an assembly jump to another routine, but that can be dangerous (and isn't C).
Maybe a symbol which is weak in your code and strong in a dlopen()'d library would work?
In any of these cases, you have to deal with the situation where the old code is currently running. That isn't easy either, unless you have points in your program where you know no thread is in the library you want to swap.
the closest i have found is solari dbx which comes with oracle developer studio,however dev studio uses dbx in both linux and solaris,only solaris version supports "edit-and-continue" or "hot code swap"

Change library load order at run time (like LD_PRELOAD but during execution)

How do I change the library a function loads from during run time?
For example, say I want to replace the standard printf function with something new, I can write my own version and compile it into a shared library, then put "LD_PRELOAD=/my/library.so" in the environment before running my executable.
But let's say that instead, I want to change that linkage from within the program itself. Surely that must be possible... right?
EDIT
And no, the following doesn't work (but if you can tell me how to MAKE it work, then that would be sufficient).
void* mylib = dlopen("/path/to/library.so",RTLD_NOW);
printf = dlsym(mylib,"printf");
AFAIK, that is not possible. The general rule is that if the same symbol appears in two libraries, ld.so will favor the library that was loaded first. LD_PRELOAD works by making sure the specified libraries are loaded before any implicitly loaded libraries.
So once execution has started, all implicitly loaded libraries will have been loaded and therefore it's too late to load your library before them.
There is no clean solution but it is possible. I see two options:
Overwrite printf function prolog with jump to your replacement function.
It is quite popular solution for function hooking in MS Windows. You can find examples of function hooking by code rewriting in Google.
Rewrite ELF relocation/linkage tables.
See this article on codeproject that does almost exactly what you are asking but only in a scope of dlopen()'ed modules. In your case you want to also edit your main (typically non-PIC) module. I didn't try it, but maybe its as simple as calling provided code with:
void* handle = dlopen(NULL, RTLD_LAZY);
void* original;
original = elf_hook(argv[0], LIBRARY_ADDRESS_BY_HANDLE(handle), printf, my_printf);
If that fails you'll have to read source of your dynamic linker to figure out what needs to be adapted.
It should be said that trying to replace functions from the libc in your application has undefined behavior as per ISO C/POSIX, regardless of whether you do it statically or dynamically. It may work (and largely will work on GNU/Linux), but it's unwise to rely on it working. If you just want to use the name "printf" but have it do something nonstandard in your program, the best way to do this is to #undef printf and #define printf my_printf AFTER including any system headers. This way you don't interfere with any internal use of the function by libraries you're using...and your implementation of my_printf can even call the system printf if/when it needs to.
On the other hand, if your goal is to interfere with what libraries are doing, somewhere down the line you're probably going to run into compatibility issues. A better approach would probably be figuring out why the library won't do what you want without redefining the functions it uses, patching it, and submitting patches upstream if they're appropriate.
You can't change that. In general *NIX linking concept (or rather lack of concept) symbol is picked from first object where it is found. (Except for oddball AIX which works more like OS/2 by default.)
Programmatically you can always try dlsym(RTLD_DEFAULT) and dlsym(RTLD_NEXT). man dlsym for more. Though it gets out of hand quite quickly. Why is rarely used.
there is an environment variable LD_LIBRARY_PATH where the linker searches for shred libraries, prepend your path to LD_LIBRARY_PATH, i hope that would work
Store the dlsym() result in a lookup table (array, hash table, etc). Then #undef print and #define print to use your lookup table version.

Resources