Home > other >  C hide all function symbols except for what I specify in a shared library
C hide all function symbols except for what I specify in a shared library

Time:01-30

In my example code:

main.cpp

#include <iostream>

#if defined(_WIN32) || defined(__WIN32__)
    #define EXPORT extern "C" __declspec(dllexport)
#elif defined(linux) || defined(__linux)
    #define EXPORT __attribute__((visibility("default"))) 
#endif


EXPORT void hello()
{
    std::cout<<"Hello world!"<<std::endl;
}


/* not exported */ void goodbye()
{
    std::cout<<"Goodbye!"<<std::endl;
}

compiled via options as followed:

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.9)

project(my_test)


add_library(output SHARED
    main.cpp
)

set(CMAKE_CXX_COMPILER "g  ")
set(CMAKE_CXX_FLAGS    "${CMAKE_CXX_FLAGS} -s -Wall -Wextra -std=c  17 -fvisibility=hidden -fvisibility-inlines-hidden")
#set(CMAKE_CXX_FLAGS    "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections")
#set (CMAKE_SHARED_LINKER_FLAGS "-Wl,--gc-sections  -Wl,--strip-all")

I see symbols rather than the hello function:

nm -D liboutput.so

The result:

                 U __cxa_atexit
                 w __cxa_finalize
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000001179 T _Z5hellov
                 U _ZNSolsEPFRSoS_E
                 U _ZNSt8ios_base4InitC1Ev
                 U _ZNSt8ios_base4InitD1Ev
                 U _ZSt4cout
                 U _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
                 U _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc

I do not want the functions such as _ZSt4cout be visible from outside. My problem is not solved even if I enable the last two lines of the cmake recipe.

How can I achieve that?

CodePudding user response:

Your approach is correct but your program contains some undefined symbols which need to be imported from libstdc at startup (e.g. std::cout). Linker has to insert such symbols in your library's symbol table, otherwise loader won't know that they need to be imported.

You can link against static version of STL (via -static-libstdc ) and apply a version script to prevent linker from exporting STL symbols from your shared library:

$ cat foo.map
{
  global:
    _Z3foov;  # Export only foo
  local: *;  # Hide everything else
};
$ g   tmp.o -fPIC -shared -static-libstdc   -Wl,--version-script=foo.map

Note that linking STL statically will cause code bloat.

  •  Tags:  
  • Related