Detecting / avoiding g++ symbol collisions - c++

Is there a way to detect and avoid if two shared libraries both expose the same global scope symbols? We recently ran into a situation where we had libA.so that exported the SuperCoolMethod() and libB.so that also exposed the SuperCoolMethod() which would clobber the previous copy of said method. This is on Linux using g++ 4.0 and later. So in isolation if you link against libA.so everything would work as expected, but once libB.so was added to the picture the wrong method was called and the call would fail causing the executing thread to abort without notifying us of the potential problem. Through exhausting trial and error we eventually found the SuperCoolMethod() getting clobbered and notified the vendor of libB.so so that the __attribute__((visibility("hidden"))) can be applied to their copy of the method.

As this is C++ the libraries each ought to be in their own namespace so collisions do no occur.

dynamically loading the library and attaching the symbols via dlopen and dlsym would work. You would have to write code to do it but if you were really truly stuck it would be a solution

As a work-around, if you only use one of the two methods, the order in which they appear on the link command line determines which version of the function you end up with in the final executable.
This isn't just an artifact, it's defined behavior, so you can depend on it (until the vendor fixes it).

Related

create "no-op" version of a dll?

Suppose I have an application app.exe which does a load-time link to d.dll, which in turn does a load-time link to dangerous.dll. Suppose that dangerous.dll is considered to have various security vulnerabilities. Suppose also that none of the functionality in dangerous.dll is needed by app.exe, and app.exe does not make any calls to d.dll that require it to use any functions in dangerous.dll.
I want to distribute the app without dangerous.dll, and ideally with minimal or no modifications to app.exe or d.dll. If I just remove dangerous.dll, I get a loading error when starting app.exe because it loads d.ll and d.dll tries to load dangerous.dll, which fails.
Option 1
I could make a "no-op" version of dangerous.dll, that provided all the same export function signatures as dangerous.dll, but had no-op code for all the exported functions themselves. That might not be too bad. I wonder if there already exists a tool that can take a .dll file and output another .dll file that has the same export functions, but ones that do nothing? This has the disadvantage that my no-op version of dangerous.dll would still be visible to the user, and it would look like my application still has the vulnerabilities in dangerous.dll.
Option 2
I wonder if there is some way, without building d.dll from source, I could hack d.dll so that it does not attempt a load-time load of dangerous.dll. It would be okay if this caused any calls from d.dll to a dangerous.dll function to fail/crash, since as I say app.exe should not cause d.ll to use any of the functions in dangerous.dll.
If you have the source for d.dll, then just fix it to not load/use dangerous.dll.
If you don't have the source, just build a dangerous.dll with stub implementations for all exported functions.
Case closed. Move on and spend your time on more productive stuff.

Using __gcov_flush within a library doesn't force the other modules to yield .gcda files

Lately I have been trying to use gcc/gcov to undertake code-coverage testing for a C++ project. The project consists of its main module and several .so libraries, which should all be taken into measurement.
I have compiled all the modules with --coverage parameter each with gcc and kept them where they were generated, together with corresponding .gcno tag files. After a normal execution and graceful exit the .gcda files could be properly generated.
The problem is, the program is supposed to be a services without interruption or termination, and it's not allowed to insert any customized code (like a signal handler) into the main module. As the solutions from the web suggest, I wrote a signal handler function in a standalone .so library, which invokes __gcov_flush on receiving SIGUSR1 signal to flush the runtime coverage counters to files.
However, it was observed that, while the __gcov_flush function is guaranteed to be properly invoked, only the .gcda file of the .so library is generated during runtime. It seems to me that __gcov_flush is in charge of flushing the data of the wrapper module but not the others. I wonder if this is how it is supposed to work, or is there some tricks I need to take care of to generate complete results?
I see two problems here.
If your executable loads several shared libraries it is quite hard
to get the functionality needed. The linker adds profiling code from
libgcov.a for every shared library and it is hard to call every
library's __gcov_flush() from one central place like signal handler
defined in yet another shared library.
The function __gcov_flush() function from libgcov.a is declared
with __attribute__ ((__visibility__ ("hidden")))
If you extract _gcov.o from the archive and run
objdump -t _gcov.o
you see something like
_gcov.o: file format elf32-littlearm
SYMBOL TABLE:
000014b4 g F .text 00000016 .hidden __gcov_flush
Linker doesn't export hidden symbols even if you ask it to do that
as it mentioned here or here
So I see two solutions for the second problem.
You may try to edit symbol table for _gcov.o in libgcov.a and
set visibility to "default" instead of "hidden". I didn't take
that way because I didn't find any good elf editor.
If you managed to do that make sure to update your link command so
it links this patched _gcov.o instead of default one from
libgcov.a. Basically, you need to remove --coverage option from
your linker flags for that.
You may create a wrapper for __gcov_flush() declare and export it
as it suggested in the links above. Call this wrapper from your
signal handler in the shared library.
I suggest you not to add profiling for the small signal handler
library - it is really unnecessary.

g++ linking order dependency when linking c code to c++ code

Prior to today I had always believed that the order that objects and libraries were passed to g++ during the linking stage was unimportant. Then, today, I tried to link from c++ code to c code. I wrapped all the C headers in an extern "C" block but the linker still had difficulties finding symbols which I knew were in the C object archives.
Perplexed, I created a relatively simple example to isolate the linking error but much to my surprise, the simpler example linked without any problems.
After a little trial and error, I found that by emulating the linking pattern used in the simple example, I could get the main code to link OK. The pattern was object code first, object archives second eg:
g++ -o serverCpp serverCpp.o algoC.o libcrypto.a
Can anyone shed some light on why this might be so?. I've never seen this problem when linking ordinary c++ code.
The order you specify object files and libraries is VERY important in GCC - if you haven't been bitten by this before you have lead a charmed life. The linker searches symbols in the order that they appear, so if you have a source file that contains a call to a library function, you need to put it before the library, or the linker won't know that it has to resolve it. Complex use of libraries can mean that you have to specify the library more than once, which is a royal pain to get right.
The library order pass to gcc/g++ does actually matter. If A depends on B, A must be listed first. The reason is that it optimizes out symbols that aren't referenced, so if it sees library B first, and no one has referenced it at that point then it won't link in anything from it at all.
A static library is a collection of object files grouped into an archive. When linking against it, the linker only chooses the objects it needs to resolve any currently undefined symbols. Since the objects are linked in order given on the command line, objects from the library will only be included if the library comes after all the objects that depend on it.
So the link order is very important; if you're going to use static libraries, then you need to be careful to keep track of dependencies, and don't introduce cyclic dependencies between libraries.
You can use --start-group archives --end-group
and write the 2 dependent libraries instead of archives:
gcc main.o -L. -Wl,--start-group -lobj_A -lobj_b -Wl,--end-group

How to detect unresolved symbol when creating a library?

Under Solaris 10, I'm creating a library A.so that calls a function f() which is defined in library B.so. To compile the library A.so, I declare in my code f() as extern.
Unfortunately, I "forgot" to declare in A's makefile that it has to link with B.
However, "make A" causes no warning, no error, and the library A.so is created.
Of course, when executing A's code, the call of f() crashes because it is undefined.
Is there a way (linker option, code trick...) to make the compilation of library A fail ?
How can I be sure that all symbols refered to in library A are defined at compile time ?
Thanks for any suggestions.
Simplest way: add a "test_lib" target in the makefile, that will produce a binary using all the symbols expored from libraryA. (doesn't have to be anything meaningful... just take the address, no need to call the function or anything, it just needs to be referenced).
Tanks
I think I found something interesting and even simpler in the linker's manual (d'ho)
The -z defs option and the --no-undefined option force a fatal error if any undefined symbols remain at the end of the link. This mode is the default when an executable is built. For historic reasons, this mode is not the default when building a shared object. Use of the -z defs option is recommended, as this mode assures the object being built is self-contained. A self-contained object has all symbolic references resolved internally, or to the object's immediate dependencies.

Trouble compiling dll that accesses another dll

So, I have an interesting issue. I am working with a proprietary set of dlls that I ,obviously, don't have the source for. The goal is to write an intermediate dll that groups together a large series of funnction calls from the proprietary dlls. The problem I am having, when compiling with g++, is that I get errors for the original dlls along the lines of:
cannot export libname_NULL_THUNK_DATA. Symbol not found.
If I add a main and just compile to an executable everything works as expected. I'm using mingw for compilation. Thanks for any help.
In response to the first reply: Either I'm confused about what you're saying or I didn't word my question very well. I'm not explicitly trying to export anything from my wrapper I am just calling functions from their dlls. The problem is that I get errors that it can't export these specific symbols from the dll to my wrapper. The issue is that I'm not even entirely sure what these _NULL_THUNK_DATA symbols are for. I did a search and read somewhere that they shouldn't be exported because they're internal symbols that windows uses. I have tried using the --exclude-symbols directive to the linker but it didn't seem to do anything. I apologize if I'm completely misunderstanding what you're trying to say.
So, I think my issue was related to this. When just compiling a standard executable that uses a dll I was able to include the headers and directly call the functions for example:
#include :3rdparty.h
int main(){
dostuff(); // a function in the 3rdparty.dll
}
this would compile and run fine. I just needed to link the libraries in the g++ command.
When linking with the -shared flag I would get these errors (with main removed of course). I think it has something to do with the fact that by default g++ attempts to import all symbols from the dll. What I didn't understand is why this happens in the dll vs in an executable. I will try doing it using GetProcAddress(). Thank you!
it should be as easy as you think it should be.
eg:
your dll code needs:
void doStuff()
{
3rdparty.login();
3rdparty.dostuff();
3rdparty.logoff();
};
so far - so good, you've included the right headers .... (if you have them, if you don't then you need to import the library using LoadLibrary(), then create a function pointer to each exported dll entrypoint using GetProcAddress() and then call that function pointer)
You then link with the 3rd party lib and that's it. Occasionally you will have to wrap the definitions with 'extern "C"' in order to get the linkage name mangling correct.
As you say you're using g++, you can't be getting confused with __declspec(dllimport) which is a MS VC extension.
"Compiling" tells me that you're approaching this from the wrong end. Your DLL should not export its own wrapper functions, but directly refer to exports from other DLLs.
E.g. in a Windows Kernel32.DEF file, the following forward exists:
EXPORTS
...
HeapAlloc = NTDLL.RtlAllocHeap
There's no code for the HeapAlloc function.