簡體   English   中英

如何告訴MinGW鏈接器不要導出所有符號?

[英]How to tell the MinGW linker not to export all symbols?

我正在使用MinGW工具鏈構建一個Windows動態庫。

為了構建這個庫,我靜態地鏈接到提供API的其他2,我有一個.def文件,在那里我寫了我想要在我的庫中導出的唯一符號。

問題是GCC正在導出所有符號,包括我鏈接到的庫中的符號。 反正告訴鏈接器只是導出def文件中的符號?

我知道有選項--export-all-symbols但似乎沒有相反的選擇。

現在,構建腳本的最后一行具有以下結構:

g++ -shared CXXFLAGS DEFINES INCLUDES -o library.dll library.cpp DEF_FILE \
OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup

編輯:在關於鏈接器的文檔中 ,它表示--export-all-symbols是默認行為,並且如果你提供def文件時沒有明確地使用該選項它被禁用,除非它沒有; 無論如何,第三方庫中的符號正在導出。

編輯:添加選項--exclude-libs LIBS–exclude-symbols SYMBOLS不會阻止導出庫中的符號。

不知道為什么沒有真正的答案,但這對我有用:

  1. 編譯目標文件:

     g++ -O0 -gdwarf-4 dll\\dllmain.cpp -c -o dllmain.o 
  2. 鏈接( -Wl,--exclude-all-symbols很重要):

     g++ -Wl,--enable-auto-import -Wl,--out-implib,libsomelib.a -Wl,--exclude-all-symbols -shared dllmain.o -o somelib.dll 

然后,您可以選擇在DLL的源代碼中直接導出哪些函數:

#include <windows.h>

__declspec(dllexport) void someExportedFunction() {
    MessageBox(NULL, "msgbox", "msgbox", MB_OK);
}

void nonExportedFunction() {
    MessageBox(NULL, "notexported", "notexported", MB_OK);
}

驗證:

C:\libtest>pedump -E somelib.dll

=== EXPORTS ===

# module "somelib.dll"
# flags=0x0  ts="2014-02-20 08:37:48"  version=0.0  ord_base=1
# nFuncs=1  nNames=1

  ORD ENTRY_VA  NAME
    1     1570  _Z20someExportedFunctionv

pedump = http://pedump.me

這是一個經常出現的問題。 以下是SO中的兩個相關問題:

在SO之外:

即,Windows平台上的全局/本地導出不是在鏈接器級別處理,而是提供.def文件以補充.dll

缺乏一個好的答案,我做了一個python腳本,負責從dll導出表中刪除東西,你可以在這里找到它。

您是否在您提供的頁面上閱讀了此內容,如果未明確使用--export-all-symbols,則會顯示行為 - 如果出現以下情況,則禁用自動導出:

任何目標文件中的任何符號都標有__declspec(dllexport)屬性。

您是否嘗試僅顯式導出您感興趣的功能? 在DEF文件中輸入名稱很容易,因為變形,所以這種方法應該更可靠。

如果您的binutils(本機或交叉編譯)的分發提供它,您可以使用dllwrap。

它可以使用DEF文件中的接口生成DLL(在它下面調用gcc,ld和dlltool)。 使用它和直接將DEF文件傳遞給GCC之間的區別在於文件中的定義被區別對待。

例如,如果導出文件中有符號重命名:

_SomeFuntion = _SomeFunction@12

GCC將創建2個導出,一個名稱為_SomeFunction ,另一個名稱為裝飾名稱,而dllwrap只導出_SomeFuntion 因此,如果您只向DEF文件中添加要導出的符號,則最終只能在庫中使用它們。

dllwrap默認使用C編譯器驅動程序,因為它無法另知。 在鏈接C ++代碼時,必須使用選項--driver-name c++來設置驅動程序。 如果你碰巧有帶前綴的MinGW可執行文件,你必須在驅動程序名稱中包含它(例如i686-mingw32-c++而不是c++ ),你也可能需要使用選項--dlltool-name

嘗試使用這兩行而不是您發布的那一行:

g++ -c CXXFLAGS DEFINES INCLUDES -o library.o library.cpp
dllwrap -o library.dll --driver-name c++ --def DEF_FILE OBJECT_FILES LIBS -Wl,--enable-stdcall-fixup

第一個從library.cpp的代碼生成一個目標文件,第二個匯編動態庫。 OBJECT_FILES事物(我假設你以前生成的其他目標文件)也應該有library.o

也就是說,我必須告訴你dllwrap在2006年已經被棄用了,官方的binutils軟件包里沒有關於它的文檔; 獲取一些信息,你可以像往常一樣用--help調用它。 它可以生成導入庫,以備您需要時使用。

您可以使用選項-Wl,--retain-symbols-file=file ,然后列出你想保持(每行一個)中的符號file 這將導致鏈接器丟棄所有其他符號,只保留您想要的符號。

免責聲明:我只在Linux上完成此操作,但AFAIK也適用於Windows

您可以使用-fvisibility=hidden選項; 有關更多信息,請參閱http://gcc.gnu.org/wiki/Visibility

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM