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.