C++ 隐藏所有函数符号,除了我在共享库中指定的

C++ hide all function symbols except for what I specify in a shared library

在我的示例代码中:

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;
}

通过如下选项编译:

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")

我看到的是符号而不是 hello 函数:

nm -D liboutput.so

结果:

                 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

我不希望 _ZSt4cout 等功能从外部可见。即使我启用了cmake配方的最后两行,我的问题也没有解决。

我怎样才能做到这一点?

您的方法是正确的,但您的程序包含一些未定义的符号,需要在启动时从 libstdc++ 导入(例如 std::cout)。链接器必须在你的库的符号中插入这样的符号 table,否则加载器将不知道它们需要被导入。

您可以 link 针对静态版本的 STL(通过 -static-libstdc++)并应用版本脚本来防止 link 用户从您的共享库中导出 STL 符号:

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

请注意,link静态使用 STL 会导致代码膨胀。