hidden symbol `xxx' in libxxx.a(xxx.o) is referenced by DSO问题记录

  1. 开启-fvisibility=hidden,编译为静态库,不管函数导不导出,在nm中查看,显示都为T。
    例如:
    头文件common.h中的内容如下:
#define FUNC_EXPORT __attribute__((visibility("default")))

void funa1(void);

FUNC_EXPORT void funa2(void);

FUNC_EXPORT void funb(void);

文件a.c中的内容如下:

#include "common.h"

void funa1(void)
{
}

void funa2(void)
{
}

CMakeLists.txt中的内容如下:

cmake_minimum_required(VERSION 3.15)
project(TestHidden C CXX)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
add_library(suba STATIC a.c)
add_library(suba2 SHARED a.c)

编译后,用nm查看libsuba.a中的函数:


image.png
  1. 编译为动态库,在nm中查看,导出函数显示为T,非导出函数显示为t。
    查看libsuba2.so中的函数:


    image.png
  2. 使用objdump -t查看静态库中的函数,可以看出导出函数和非导出函数的区别。
    非导出函数有.hidden标记。


    image.png
  3. 应用程序可以直接调用静态库中的非导出函数,而不会链接出错。
    例如,main.c中的内容如下:
#include "common.h"

int main(void)
{
    funa1();
    return 0;
}

CMakeLists.txt中增加两行:

add_executable(main main.c)
target_link_libraries(main suba)

编译成功:


image.png
  1. 动态库直接调用静态为中的非导出函数,会报错。
    这种情况通常发生在:应用程序调用动态库中的函数A,A调用静态库中的非导出函数B。
    例如:
    文件b.c中的内容如下:
#include "common.h"

void funb(void)
{
    funa1();
}

文件main.c中的内容如下:

#include "common.h"

int main(void)
{
    funab();
    return 0;
}

修改CMakeLists.txt如下:

add_library(subb SHARED b.c)
add_executable(main main.c)
target_link_libraries(main subb suba)

编译失败:


image.png
  1. 指定动态库依赖静态库,生成动态库时会把所需的符号定义拷贝到自身中,不会链接出错。
    修改CMakeLists.txt如下:
target_link_libraries(subb suba)
target_link_libraries(main subb)

编译成功:


image.png

静态库中的函数拷贝到动态库中后,是外部的还是内部的?

从前面的例子中可以看出,会保持函数原来的可见性。
例如,funa1在静态库中是内部的(带.hidden),那么拷贝到libsubb.so后,是内部的(nm显示为t)。
funa2在静态库中是外部的(不带.hidden),那么拷贝到libsubb.so后,是外部的(nm显示为T)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容