2013-10-03 85 views
1

我的主應用程序靜態鏈接到靜態庫A帶有函數ABC和我的動態庫xyz.dylib也靜態鏈接到具有相同函數ABC的相同靜態庫A.函數ABC使用全局定義的變量。dlopen和dylib:主要應用程序和dylib地址空間

現在,當主應用程序在運行時使用dlopen加載xyz.dylib。初始化程序被調用,在那裏我調用了ABC函數。該函數使用ABC並使用主應用程序地址空間中的全局變量。

+0

我有同樣的問題。我希望我能找到一種方法讓dylib自成一體。這也是一個安全問題 - 因爲它意味着有人可以創建一個你用dlopen打開的dylib,然後在主程序中使用隨機的golbal數據結構。 –

回答

0

在Osx上,內聯dylib鏈接器的函數將使用第一個使用的函數。因此,例如,如果首先在主可執行文件中使用內聯函數,然後在加載的dylib中使用內聯函數,則它將使用主可執行文件中的一個。

這通常很好,除非你的內聯引用了全局符號,在這種情況下,如果你的全局變量是dylib和你的可執行文件,你現在正在使用它。

再次這通常很好,因爲一致地使用相同的版本。

如果您有2個內聯函數引用全局的可執行文件和dylib,並且首先在可執行文件中使用了一個函數,並且首先在dylib中使用了另一個函數,則會出現問題。然後你有一對不匹配的。例如:

class MagicAlloc 
{ 
    void* Alloc()   { return gAlloc.get(); } 
    void Free(void* v) { gAlloc.free(v); } 

    static RealAllocator gAlloc; 
}; 

假設你叫MagicAlloc ::中的Alloc可執行文件,然後調用它在dylib,現在在這兩個您將使用gAlloc在可執行所有分配。然後,第一次調用MagicAlloc :: Free發生在dylib中。然後你將嘗試從dylib的全局變量中釋放二進制文件中分配的東西。

解決辦法有兩個:

  1. 不要使用內聯引用全局/靜態。將全局結構和函數定義移動到相同的翻譯單元(目標文件)中。將全局變量標記爲「靜態」,以便在TLU外部甚至不可見。現在你的函數將在鏈接步驟中靜態解析,並綁定到正確的全局。

  2. 隱藏可執行文件中除插件api外的所有符號。鏈接正常,但連接的二進制文件時本身通過以下的鏈接:

    輪候冊,-exported_symbols_list,export_file

其中,出口文件應導出鏈接的符號列表。例如。你至少需要在該文件中有「_main」。現在當你的dylib運行時,它將不能動態鏈接到錯誤的內聯,因爲它們不會在動態符號表中。第二種解決方案也更安全,因爲惡意插件無法輕鬆訪問全局變量。