2011-09-13 17 views
7

Sto usando alcuni strumenti GNU, cioè il compilatore GNU C++ (g ++) e il GNU Linker (ld) per creare un file di libreria condivisa (.so) così come un file eseguibile binario.Problema con il GNU linker (ld) per esportare un simbolo

Il file eseguibile binario utilizza la funzione dlopen per caricare dinamicamente il file di libreria condivisa in fase di runtime. Oltre a ciò, il file di libreria condivisa deve richiamare un particolare metodo di classe (chiamato ToolboxManager::registerToolbox) definito all'interno dell'eseguibile binario. Ciò è consentito forzando l'eseguibile binario per esportare il metodo di classe, che a sua volta viene eseguito al momento del collegamento collegando l'eseguibile binario con le seguenti opzioni della riga di comando;

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt 

dove il file ${top_srcdir}/dynamic_symbol_table.txt contiene il seguente contenuto;

{ 
    extern "C++" 
    { 
    "ToolboxManager::registerToolbox*"; 
    }; 
}; 

Nota l'uso del asterisco (*) nel file per forzare il linker di esportare tutti i simboli che iniziano con ToolboxManager::registerToolbox.

Quando si esegue l'utilità GNU nm (nm -C -g ./a.out) nell'eseguibile eseguibile binario, vengono visualizzate le seguenti informazioni sul metodo di classe sopra menzionato;

08053da0 T ToolboxManager::registerToolbox 
      ( 
      std::string&, 
      std::string&, 
      std::map 
      < 
      std::string, 
      Factory_DSPB_Base*, 
      std::less 
      < 
       std::string 
      >, 
      std::allocator 
      < 
       std::pair 
       < 
       std::string const, 
       Factory_DSPB_Base* 
       > 
      > 
      >& 
      ) 

o, se l'utilità nm viene richiamato come sopra, ma questa volta senza l'utilizzo della riga di comando -C;

08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE 

Finora, questo sembra buono. La "T" davanti alla definizione del metodo di classe ToolboxManager::registerToolbox, denota che il metodo risiede nella sezione Testo/Codice del file.

Analogamente, se eseguo l'utilità nm (nm -C -g ./toolbox.so) sul file di libreria condivisa, visualizza le seguenti informazioni sullo stesso metodo della classe summenzionata;

U ToolboxManager::registerToolbox 
    (
    std::string&, 
    std::string&, 
    std::map 
    < 
    std::string, 
    Factory_DSPB_Base*, 
    std::less 
    < 
    std::string 
    >, 
    std::allocator 
    < 
    std::pair 
    < 
     std::string const, 
     Factory_DSPB_Base* 
    > 
    > 
    >& 
) 

Anche questo sembra buono. La "U" davanti alla definizione del metodo di classe ToolboxManager::registerToolbox, denota che il metodo non è definito nel file di libreria condivisa.

Tuttavia, si verifica un problema quando eseguo il binario eseguibile dalla riga di comando e questo problema provoca la visualizzazione del seguente messaggio di errore;

./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE 

La classe nome del metodo mutilato che appare in questo messaggio runtime seguito è mostrata, come la prima delle due linee. A scopo di confronto, il nome del metodo di classe mutilato da sopra (e che è stato generato utilizzando il comando nm -g) è mostrato di seguito come la seconda delle due linee;

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE 

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE 

Come si può vedere, i due nomi storti sono identici. Pertanto, non riesco a capire perché il simbolo non definito non può essere risolto in fase di esecuzione.

Ho quindi ricollegato l'eseguibile binario, tuttavia questa volta ho sostituito il seguente comando del linker;

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt 

con questo;

-Wl,--export-dynamic 

L'opzione del linker --export-dynamic istruisce la GNU Linker per aggiungere tutti i simboli della tabella dei simboli dinamica.

Se quindi è stato eseguito di nuovo l'eseguibile binario. Questa volta ha eseguito correttamente e la chiamata alla funzione dlopen non ha provocato un errore di simbolo non definito. Questo mi ha completamente perplesso, poiché sembra che il simbolo venga esportato correttamente nella versione iniziale dell'eseguibile binario. Qualcuno è in grado di vedere il problema qui? Qualsiasi aiuto sarebbe immensamente apprezzato.

Grazie in anticipo.

risposta

3

Sono riuscito a risolvere questo problema. Ho trovato che se rimuovo le virgolette dalla seguente riga;

"ToolboxManager::registerToolbox*" 

all'interno del file ${top_srcdir}/dynamic_symbol_table.txt e quindi ricollegare il binario eseguibile, allora funziona. Cioè, la funzione dlopen non fallirà più.

Non posso fare a meno di chiedermi se sarebbe stato più appropriato porre questa domanda sulla mailing list GNU binutils che qui su questo sito web.

Problemi correlati