2011-10-17 49 views
1

沒有修改和重新編譯gnu gcc和stdC++庫構建,我需要能夠使用不同的嵌入式soname重現這些庫的動態加載版本。如何重新包裝gnu gcc標準庫stdC++,gcc和gcc_eh?

我以爲我會聰明,利用現有的靜態版本,並像這樣的東西重新包裝: ld -E -shared -static "-lstdc++" -lgcc -lgcc_eh -o librepackaged_standard.so

librepacked_standard.so被創建,沒有警告或錯誤,但LDD報告它不是一個動態庫, readelf報告只有這些基本符號:

Symbol table '.symtab' contains 4 entries: 
    Num: Value   Size Type Bind Vis  Ndx Name 
    0: 0000000000000000  0 NOTYPE LOCAL DEFAULT UND 
    1: 0000000000201000  0 NOTYPE GLOBAL DEFAULT ABS __bss_start 
    2: 0000000000201000  0 NOTYPE GLOBAL DEFAULT ABS _edata 
    3: 0000000000201000  0 NOTYPE GLOBAL DEFAULT ABS _end 

我不確定爲什麼LD是不是在所有靜態定義符號的帶來。我也不知道是否有任何其他特殊參數需要它才能起作用。

另一種選擇是,如果有一個專門跨平臺的方式來簡單地改變嵌入到原始精靈庫的soname。我目前只關心精靈格式的二進制文件。我不想寫我自己的工具來更改現有二進制文件中的.soname。

更新: 沒有符號被編譯的原因是因爲ld處理靜態二進制文件的方式與.o文件不同。默認情況下,它不會從.a文件中導入任何符號,除非鏈接線上的另一個庫需要它們。我通過提供--whole-archive選項來解決這個問題。

然而,讓我另一個錯誤,relocation R_X86_64_32S against _ZSt12_S_first_one」創建共享對象時,不能使用;使用-fPIC and重新編譯無法讀取符號:錯誤值它們都來自bitset.o歸檔中的libstdC++。a。所以我不能只將.a's重新編譯爲動態庫,因爲默認情況下,GNU GCC編譯不會使用PIC選項編譯用於靜態庫的對象文件。

這使得我發現一個小精靈工具或修改其生成重新編譯GNU GCC。

如前所述由其中一個答案,許可問題可以與任何這些方法的關注。我最好的答案是,我們需要改變我們的需求,找到一種不以任何方式改變或重新包裝GCC標準庫的解決方案。

回答

2

沒有符號被編譯到共享庫的原因是因爲ld處理靜態二進制文件與.o文件不同。默認情況下,它不會從.a文件中導入任何符號,除非鏈接線上的另一個庫需要它們。這個特定問題的答案是使用--whole-archive選項,並直接鏈接.a文件。

然而,對於這個工作的。包含在靜態歸檔中的文件需要在編譯時使用-fPIC選項進行編譯。但是,用於靜態庫的對象文件不會在可用的靜態庫中使用該選項進行編譯。

因此,更改SONAME的解決方案是使用ELF二進制實用程序或重新構建GNU GCC以修改其使用不同的SONAME。

由於在這種情況下存在許可問題,因此任何解決方案都不適用於該項目,因爲它不是開源的,我們也不希望爲我們的所有平臺重新分配GNU GCC的源代碼版本。

1
  1. -static可能會破壞-shared
  2. 經典,你會從靜態庫中提取的目標文件,然後打包這些目標文件到共享庫 - 依託普遍使用PIC(位置無關的代碼),以便在靜態庫可以安全的對象被轉換成共享庫。你也許能夠在沒有提取步驟的情況下做到,但我對此表示懷疑。
  3. 您可能想要考慮您是否符合許可條款和條件。
+0

ld手冊頁聲明爲-static:不要鏈接到共享庫。 您可以在命令行上多次使用此選項:它會影響庫搜索後面的-l選項。 該選項可與-shared一起使用。這樣做意味着正在創建共享庫,但是必須通過從靜態庫中提取條目來解決庫的所有外部引用。 – James

+0

關於許可,這是給予我要求的人的一個好點。我試圖說服他們,最好的選擇是要求在支持的平臺上安裝最小版本的stdC++庫軟件包,AFAIK是軟件的常見做法。 – James