2011-05-31 66 views
7

我有一個共享庫(bar.so)鏈接到一個更大的程序(foo)的插件。 foo和bar.so都依賴於相同的第三方庫(baz),但他們需要將baz的實現完全分開。所以當我鏈接foo(使用提供的對象文件和檔案)時,我需要它忽略bar.so中任何對baz的使用,反之亦然。如何限制訪問共享對象中的符號?

現在如果我鏈接foo且--trace-symbol=baz_fun其中baz_fun是有問題的符號,我得到了下面的一個輸出:

bar.so: definition of baz_fun 
foo/src.a(baz.o): reference to baz_fun 

我相信這是告訴我,FOO被引用從bar.so baz_fun(和foo的執行證實了這一點)。

的解決方案,我曾嘗試:

  • 使用objcopy以「本地化」感興趣的符號:objcopy --localize-symbols=local.syms bar.so其中local.syms包含了所有感興趣的符號。我想我可能只是在這裏感到困惑,也許「本地」並不意味着我認爲的意思。無論如何,我從上面的鏈接獲得相同的輸出。我應該注意到,如果我在bar.so上運行nm工具,那麼在使用objcopy之前,所有符號都有T標誌(大寫字母表示全局),並且在objcopy之後,它們有一個t表示它們現在是本地的。所以看來我正確使用objcopy
  • 編譯與-fvisibility=hidden然而,由於一些其他限制,我需要使用GCC 3.3,似乎不支持該功能。我可能可以升級到GCC的較新版本,但希望確認使用此標誌進行編譯將有助於我在前往該道路之前。

其他注意事項:

  • 我沒有訪問foo或巴茲
  • 的源代碼,我寧願讓我所有的插件在一個共享對象( bar.so)。 baz實際上是一個許可證庫,所以我不希望它分開

回答

3

使用dlopen加載您的插件與RTLD_DEEPBIND標誌。

(編輯)

請注意,RTLD_DEEPBIND是Linux特有的和需要的glibc 2.3.4或更高版本。

+0

也許我誤解了,但是如果我沒有訪問加載插件bar.so的foo的源代碼,我該怎麼做? – brady 2011-06-01 13:08:58

+0

好的,如果你只控制欄而不是foo,你可以在兩個庫bar1和bar2中拆分欄。 bar1提供插件接口並將所有呼叫轉發到bar2,而bar2實現所有內容。 bar1應該調用'dlopen(「libbar2.so」,RTLD_NOW | RTLD_DEEPBIND)''和'dlsym'所有需要的函數。或者你可以保留一個欄,並從那裏保存「dlopen(」libbaz.so「,RTLD_NOW | RTLD_DEEPBIND)」和「dlsym」所有你需要的功能。使用任何方法都需要更少的電話到'dlsym'。 – 2011-06-01 13:52:30