About shared library in Linux, is there a way to select export functions in a library? - c++

I read the tutorial here:
http://www.techytalk.info/c-cplusplus-library-programming-on-linux-part-two-dynamic-libraries/
It looks to me there is no functionality like dllexport of DLL in Windows platform.
Is there some way to select certain functions within the library as export function and make the rest functions in the library remain invisible to external call?

You may want to use the visibility function attribute of GCC.
See GCC visibility wikipage and read Drepper's paper How To Write Shared Libraries

There are multiple ways to do this.
Either use the visibility function attribute as mentioned in Basiles answer or use a linker version script to do the job.
In a linker script you list all the functions that you want to export. Here is an example:
File: MyLinkerScript.exp
{
global:
myExportedFunction1;
myExportedFunction2;
myExportedFunction3;
local: *;
};
During the link step of your shared library you just pass the following extra parameters to gcc:
-Wl,--version-script=MyLinkerScript.exp
Afterwards all symbols in the shared library will be private except for those listed in the global section of your version script.

Related

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.

Workaround for when -whole-library is not available

I'm trying to compile on an environment where the -Wl,-whole-library flag is not supported (emscripten). How can I trick to force the compiler to include the exported symbols ? The solution should met as many of these properties as possible :
Could be applied on a single library (I don't want to include unused symbols from other libraries)
Could be automatically generated (for example by fetching the exported symbol table with nm?)
Would work with functions & member functions
I thought about computing a file with something like :
int x = (int)(&func_a)+(int)(&func_b)+...;
But it doesn't work with member functions, which cannot be casted to int (and can be private).
Do you have any idea ?
Ideas:
Use --whole-library flag before linking the lib you want and just
after add -no-whole-library before listing other libs so that only
the one you need To be wholly linked is and try add --export-dynamic flag using a linker that supports it.
Then dig the nm/objdump/exportmap road http://accu.org/index.php/journals/1372 to export/build link info and for using link info http://runtimecompiledcplusplus.blogspot.fr/ for using exported maps and code so that you can mimic the -Wl in your code.

Can a Visual Studio produced static library, be stripped of symbols?

I'll divide this questions in 3 parts:
I would like to produce a static library and strip off its symbols. (Debug info is already not included)
Similar to the strip command in linux. Can it be done?
Is there an equivalent tool in windows env, to the nm tool in linux?
When creating a static library using VS2008. Is it possible to define a script that will exclude some of the produced .obj files out of the build and out of the static lib?
Can it be dynamic? I mean I'd define a compilation mode in the script and this would result in specific object files being excluded from the build
If anything is visible that you feel should not be, try declaring it with the "static" keyword. This tells the compiler that it is accessible only to the current module.
There are cases where it would be convenient to be able to strip out all but a small number of "exported" public symbols, but it's not really feasible.
A static library is little more than a collection of .obj files. The internal dependencies haven't been resolved yet, and they won't be resolved until link time.
For example, if your .lib consists of foo.obj and bar.obj, and there's a call in foo.obj to a function defined in bar.obj, then that symbol must be available at link time, even if nothing outside of the library should be able to see it.
For that reason, you cannot strip the symbols (with the possible exception of file-scope static symbols). Even class methods that are protected or private (in the C++-sense) will exist in the symbol table, since the enforcement of the visibility is a compile-time issue, not a link-time one.
In contrast, a dynamic library is a standalone binary that has already been linked. References from foo.obj to bar.obj have already been resolved. Thus a DLL can be stripped of symbols except for the ones that must be exported (and even those can be renamed or replaced by ordinals).
If your DLL exposes a simple C API, then you're all set. But if you want to expose a C++ class, you're probably going to end up exporting all of its methods, even the protected and private ones (since inlining in the external application might result in direct calls to private methods).
No, how do you think the users of the static library would link to it without knowing where are the symbols they use defined?
Yes, try the DUMPBIN utility.
Well, yes. You can run the LIB utility with /REMOVE:foo.
That said, I think you are doing something that either is not worth doing or could be done a lot simpler than with removing library members.
I kept finding the names of certain (but not all) static functions in .obj files produced by VS2010. Interestingly, they were visible in my Release .obj files but not the Debug .obj files. I just used cygwin strings to perform the search:
$ strings myObjectFile.obj | grep myStaticFunctionName
I tracked it down to the "Whole Program Optimization = Yes" setting ("/GL"). When I switched this to "No" the function names no longer appear.
Update: As a followup test I opened the "cleansed" myObjectFile.obj in vim and I can still find them (with either :set encoding=utf-8 or :set encoding=latin1). I'm not sure why strings was missing the matches. Oh well.

Is there a .def file equivalent on Linux for controlling exported function names in a shared library?

I am building a shared library on Ubuntu 9.10. I want to export only a subset of my functions from the library. On the Windows platform, this would be done using a module definition (.def) file which would contain a list of the external and internal names of the functions exported from the library.
I have the following questions:
How can I restrict the exported functions of a shared library to those I want (i.e. a .def file equivalent)
Using .def files as an example, you can give a function an external name that is different from its internal name (useful for prevent name collisions and also redecorating mangled names etc)
On windows I can use the EXPORT command (IIRC) to check the list of exported functions and addresses, what is the equivalent way to do this on Linux?
The most common way to only make certain symbols visible in a shared object on linux is to pass the -fvisibility=hidden to gcc and then decorate the symbols that you want to be visible with __attribute__((visibility("default"))).
If your looking for an export file like solution you might want to look at the linker option --retain-symbols-file=FILENAME which may do what you are looking for.
I don't know an easy way of exporting a function with a different name from its function name, but it is probably possible with an elf editor. Edit: I think you can use a linker script (have a look at the man page for ld) to assign values to symbols in the link step, hence giving an alternative name to a given function. Note, I haven't ever actually tried this.
To view the visible symbols in a shared object you can use the readelf command. readelf -Ds if I remember correctly.
How can I restrict the exported functions of a shared library to those I want (i.e. a .def file equivalent)
Perhaps you're looking for GNU Export Maps or Symbol Versioning
g++ -shared spaceship.cpp -o libspaceship.so.1
-Wl,-soname=libspaceship.so.1 -Wl,
--version-script=spaceship.expmap
gcc also supports the VC syntax of __declspec(dllexport). See this.
Another option is to use the strip command with this way:
strip --keep-symbol=symbol_to_export1 --keep-symbol=symbol_to_export2 ... \
libtotrip.so -o libout.so

C++ shared library shows internal symbols

I have built a shared library (.dll, .so) with VC++2008 and GCC.
The problem is that inside both libs it shows the names of private symbols (classes, functions) and they weren't exported.
I don't want my app to display the name of classes/functions that weren't exported.
Is any way i can do that?
In GCC i did:
Compiled with -fvisibility=hidden and then made public with attribute ((visibility("default")))
In VC++:
__declspec(dllexport)
Thanks!
For GNU tool chains you can use th strip command to remove symbols from object files. It takes various command options to control its behavior. It may do what you want.
You can create a header file to obfuscate the internal function and method names you want to be hidden. Ie something like below (need some include guard too)
#define someFunctionName1 sJkahe28273jwknd
#define someFunctionName2 lSKlajdwe98
#define someMethodName1 ksdKLJLKJl22fss
#define someMethodName2 lsk89hHHuhu7g
...and include this in the header files where the real definitions live.
The private keyword when used for access specification only
effectively works at compile time and is intended as an aid to programmers, not a security feature - as you have found out the "privacy" is implemented
using lexical means .
It's easy to see that this must be so - if you implement two private functions with dependencies between each other in two separate .cpp files, the linker has to find the private names in the resulting object (or library) files.
Bottom line - C++ has no code security features - if you give someone the object code of your program, they will always be able to examine it.