post-build removal of a set of symbols (keeping only a given set) from C++ dynamic library

84 Views Asked by At

i'm building a dynamic library (in C++), which exports a number of symbols.

these exported symbols (obviously) match the API of my library. however, my lib also exports a plethora of additional symbols (that are not mentioned in my public headers at all).

in order to keep the binary interface of my library small (prevent nameclashes; do not clobber the symbol space; prevent consumers of the library to accidentally use a symbol that might go away in the next release), i can make the exported symbols explicit using a version-script, like so (in reality the version script is much more complicated; in any case, it involves C++-demangled symbols and wildcards):

{
        global:
                extern "C++" {
                /* the public API uses the 'MyLib::' namespace */
                 MyLib::*;
                };
                /* g++ version mangling prefixes for 'typeinfo' */
                _ZTI*; _ZTF*; _ZTS*;
                /* g++ version mangling prefixes for 'vtable' */
                 _ZTT*; _ZTV*;
        local:
                *;
};

and then invoke the linker with these additional flags -fvisibility=hidden -Wl,--version-script=mylib.ver

cool.

Now, the library also comes with a testsuite. In order to be able to write concise tests, the unit tests use symbols that are not part of the public API.

Stripping away the non-public symbols from the library will prevent the unit-tests (that link against the library) from finding these symbols. Therefore the testsuite becomes unusable.

One obvious way around this is to only use public symbols in the unit-tests. But this will make the unit-tests much more complicated, and the test results much harder to interpret.

Another possible solution would be to not use the dynamic library for the unit tests but some other library (e.g. a static lib; or a variant of the library that was linked without the version-script). I dislike this, as I would like to test the actual library, not some substitute.

The third solution (which I like most), is to defer the stripping of the non-public symbols until the deployment of the library: the test-suite would use the local library build (with all the symbols), but during make install (or some other explicit post-build step) the unnecessary symbols are stripped away.

Unfortunately I have no idea how to implement this.

  • the version-script is a feature of the linker
  • tools like strip do something different (there's a -N flag to (GNU?) strip that is supposed to remove a symbol, but it doesn't seem to work, even for a plain C-library (without C++ symbol mangling)

So: is there a way to strip away symbols (keeping only a known set) from a library in a post-build step? And if so, how to do that with C++ symbol mangling and using wildcards?

1

There are 1 best solutions below

0
Employed Russian On

is there a way to strip away symbols (keeping only a known set) from a library in a post-build step?

Yes. The (dynamic) symbol names reside in the .dynstr section, and if you overwrite the names there (e.g., overwrite _ZMyLib... with _XMyLib) the dynamic linker will not resolve these symbols.

Iterating over all symbols in the .dynsym (dynamic) symbol table is not hard.

how to do that with C++ symbol mangling and using wildcards?

You would have to call __cxa_demangle on each symbol, then do the wildcard match and decide whether to "zap" the symbol or to leave it alone.