GCC/G++ 符號導出控制
我們知道,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 <iostream>
#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<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, 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<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
由此可見,只有 globalDump1() 和 classDump1() 被導出,globalDump2() 和 classDump2() 被隱藏,可以通過編寫個可執行文件來測試。
TAG:程序員小新人學習 |