當前位置:
首頁 > 知識 > GCC/G++ 符號導出控制

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() 被隱藏,可以通過編寫個可執行文件來測試。

GCC/G++ 符號導出控制

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

dubbo同名方法的問題及思考
前端測試之用戶體驗測試

TAG:程序員小新人學習 |