GCC/G++ 符号导出控制

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

        我们知道,GCC/G++编译出来的二进制文件默认情况下会导出所有的符号表。在实际应用过程中,我们也许出于安全或者其他的原因,不想导出内部所有的符号表,只导出必要的接口给用户使用。此时我们可以利用 GCC/G++ 的 -fvisibility=hidden 选项配合代码的 __attribute__ ((visibility("default"))) 实现。

    (1)默认情况,导出所有符号表:

    示例代码如下:

    test.h:

#ifndef __TEST_H__
#define __TEST_H__

#ifdef __cplusplus
extern "C" {
#endif

void globalDump1();
void globalDump2();

class Dump {
public:
    Dump();
    ~Dump();

    void classDump1();
    void classDump2();
};

#ifdef __cplusplus
}
#endif

#endif
 

    test.cc:

#include
#include "test.h"

void globalDump1() {
    std::cout << "globalDump1" << std::endl;
}

void globalDump2() {
    std::cout << "globalDump2" << std::endl;
}

Dump::Dump() {}

Dump::~Dump() {}

void Dump::classDump1() {
    std::cout << "classDump1" << std::endl;
}

void Dump::classDump2() {
    std::cout << "classDump2" << std::endl;
}
    编译命令如下:$ g++ -v -I. -fPIC -shared -o libtest.so test.cc 

    可以使用 nm 命令查看符号表,如下:

$ nm -CD libtest.so 
0000000000201050 B __bss_start
                 U __cxa_atexit
                 w __cxa_finalize
0000000000201050 D _edata
0000000000201058 B _end
0000000000000bc0 T _fini
0000000000000a86 T globalDump1
0000000000000ab4 T globalDump2
                 w __gmon_start__
0000000000000908 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000000af6 T Dump::classDump1()
0000000000000b2c T Dump::classDump2()
0000000000000ae2 T Dump::Dump()
0000000000000ae2 T Dump::Dump()
0000000000000aec T Dump::~Dump()
0000000000000aec T Dump::~Dump()
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream >& std::endl >(std::basic_ostream >&)
                 U std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*)

    (2)增加 -fvisibility=hidden 选项和 __attribute__(("default")),只导出 globalDump1() 和 classDump1() 两个接口:

    test.h修改如下:

#ifndef __TEST_H__
#define __TEST_H__

#ifdef __cplusplus
extern "C" {
#endif

__attribute__ ((visibility("default"))) void globalDump1();
void globalDump2();

class Dump {
public:
    __attribute__ ((visibility("default"))) Dump();
    __attribute__ ((visibility("default"))) ~Dump();

    __attribute__ ((visibility("default"))) void classDump1();
    void classDump2();
};

#ifdef __cplusplus
}
#endif

#endif
    编译命令修改如下:$ g++ -v -I. -fPIC -shared -fvisibility=hidden -o libtest.so test.cc 

    此时,再次查看编译出来的libtest.so符号表如下:

    $ nm -CD libtest.so 
0000000000201050 B __bss_start
                 U __cxa_atexit
                 w __cxa_finalize
0000000000201050 D _edata
0000000000201058 B _end
0000000000000b50 T _fini
0000000000000a16 T globalDump1
                 w __gmon_start__
00000000000008a0 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
0000000000000a86 T Dump::classDump1()
0000000000000a72 T Dump::Dump()
0000000000000a72 T Dump::Dump()
0000000000000a7c T Dump::~Dump()
0000000000000a7c T Dump::~Dump()
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream >& std::endl >(std::basic_ostream >&)
                 U std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*)
 

    由此可见,只有 globalDump1() 和 classDump1() 被导出,globalDump2() 和 classDump2() 被隐藏,可以通过编写个可执行文件来测试。

转载于:https://my.oschina.net/yepanl/blog/2240240

你可能感兴趣的:(GCC/G++ 符号导出控制)