2012-12-11 43 views
3

我的應用程序使用靜態初始化代碼構建了一個庫。所有其他庫都是這樣做的,並且之前加載得很好,但是當從另一個庫調用函數時,它會死亡。這有點像:調用@plt函數時在dlopen/static init上共享庫SIGSEGV

0x12311 <-- bad address 
_static_initialization_0 <-- function call 
.... 
dlopen 

現在,在拆卸函數調用看起來像

call [email protected] 

不過,這種呼叫結束調用無效地址0x12311,即PLT條目得到了錯誤的地址。

問題是很有可能的問題庫是種第三方之一,即二進制預構建形式,即使它依賴於其他庫。上週我們進行了大量優化,並更改了很多頭文件等等。 PLT錯誤的函數MyFunc位於我們的(另一個)庫中,它獲得了大量的優化更改。

這怎麼可能?確切的問題是:

  1. 什麼是導致PLT不匹配
  2. 的機制是有辦法解決它不接觸預編譯庫 - 可選的,因爲我能得到重建的版本,但我仍然好奇爲什麼它崩潰

此外,同樣的應用程序工作正常編譯時使用-O2優化,這就是我所說的奇怪(二進制庫在這兩種情況下是相同的)。

P.S. Ubuntu的12.04 x86_64,但應用程序是i386。

UPDATE:在註釋中的建議(因爲某些原因被刪除),以檢查LD_DEBUG還是不錯的,在LD_DEBUG =綁定我看到這個應用程序的「崩潰」的版本:

10272: /media/EXT/work/build32/bin/libMyLib.so: error: 
    symbol lookup error: undefined symbol: omp_set_num_threads (fatal) 

然後停止綁定libMyLib.so符號,而在非失敗版本中,它保持綁定其他符號。但我不明白爲什麼它會繼續執行並嘗試加載父庫。實際上,方案如下:

libA -> libB -> libMyLib 

的libmylib失敗(如通過LD_DEBUG輸出上面所指出的),所以它完全跳過它,並且還libB和具有結合LIBA符號繼續(!)。非失敗版本完全加載libMyLib符號,然後繼續使用libB符號,然後使用libA符號。

坦白地說,它看起來像ld bug。

至於爲什麼優化版本的工作原理,我認爲omp_方法並不是真的需要,並且被鏈接器優化拋出,因此它不會在運行時找到它。

這是我在LD_DEBUG看到=所有日誌OMP_符號後未找到的libC:

19225: symbol=omp_set_num_threads; lookup in file=/usr/lib/i386-linux-gnu/libXdmcp.so.6 [0] 
19225: /media/EXT/Work/libC.so: error: symbol lookup error: undefined symbol: omp_set_num_threads (fatal) 
19225: 
19225: file=/media/EXT/libA.so [0]; destroying link map 
19225: 
19225: file=/media/EXT/libA.so [0]; dynamically loaded by /media/EXT/libX.so [0] 
19225: file=/media/EXT/libA.so [0]; generating link map 
19225: dynamic: 0xf2fdb764 base: 0xf2f81000 size: 0x00064a28 
19225: entry: 0xf2f8ffd0 phdr: 0xf2f81034 phnum: 7 
19225: 
19225: checking for version `GCC_3.0' in file /lib/i386-linux-gnu/libgcc_s.so.1 [0] required by file /media/EXT/libA.so [0] 
... few more checking 
19225: object=/media/EXT/libA.so [0] 
19225: scope 0: bin/mainapp /lib/i386-linux-gnu/libpthread.so.0 /media/EXT/libX.so ... 
19225: scope 1:... 
19225: 
19225: 
19225: relocation processing: /media/EXT/libA.so 
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=bin/mainapp [0] 
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=/lib/i386-linux-gnu/libpthread.so.0 [0] 
19225: symbol=_ZTVN10__cxxabiv117__class_type_infoE; lookup in file=/media/EXT/libX.so [0] 
19225: binding file /media/EXT/libA.so [0] to /media/EXT/libX.so [0]: normal symbol `_ZTVN10__cxxabiv117__class_type_infoE' 

... here it continues to bind libA symbols, and after finishing that 

19225: 
19225: 
19225: calling init: /media/EXT/libC.so 
19225: 

它要求對未初始化libC.so模塊初始化。

(只是提及libX.so是調用dlopen的基本模塊,也包含所有其他庫使用的基本方法。)

銷燬libA的鏈接映射後,日誌顯示它再次生成,我只是不明白裝載器是否繼續加載libA,或者這次從頭開始而不打擾libB/libC。那麼,在任何情況下,它都會忽略libB/libC,直到調用libC的init爲止。

+0

使用'納米-C -D'到還原函數的名稱。 –

+0

我使用C++ filt,但我確實知道函數和它在哪裏。 – queen3

回答

0

omp_set_num_threads與GCC內部的OpenMP support有關。

您可能應該將-fopenmp標誌傳遞給gcc編譯&鏈接時間(即使您只是dlopen-使用OpenMP的庫)。

也許原來的圖書館提供者忘記了。

(OpenMP是改變編譯過程的整個行爲)

+0

是的,但這是一個不同的問題。 – queen3

+0

不,我認爲應該在使用OpenMP的'dlopen'庫時儘快用'-fopenmp'構建應用程序。 –

+1

當然,但這不是問題的關鍵(正如我提到的,我已經得到了重建版本),我試圖找出PLT問題的原因,也就是說我不認爲可以初始化一個庫並非所有的PLT都已建立。 – queen3