2010-04-10 22 views
1

我有一個應用程序可以利用在運行時使用dlopen加載的插件。每個插件定義一個函數來檢索使用通用結構定義的插件信息。類似的東西:dlopen/dlsym儘可能少鏈接

struct plugin { 
    char *name; 
    char *app_version; 
    int app_verion_id; 
    char *plugin_version; 
    int plugin_version_id; 
    /* ... */ 
}; 

struct plugin p = { "sample plugin",APP_VERION,APP_VERSION_ID,"1.2.3",10203 }; 

struct plugin *get_plugin() { 
    return &p; 
} 

這很好,插件可以加載。現在我想構建一個小工具來讀取這些屬性,而無需鏈接整個應用程序。爲了做到這一點,我有這樣的代碼:

void *handle; 
struct plugin *plugin; 
struct plugin *(get_plugin*)(); 

handle = dlopen(filename, RTLD_LAZY); 
if (!handle) { /*...return; ...*/ } 

get_plugin = dlym(handle, "get_plugin"); 
if (!get_plugin) { /*...return; ...*/ } 

plugin = get_plugin(); 
printf("Plugin: %s\n", plugin->name); 

這對於簡單的插件很好。問題在於許多插件引用了來自應用程序的更多符號,即使設置了RTLD_LAZY,也可以解析這些符號。 (如應用程序中用於初始化插件全局事物的全局變量)因此,dlopen()調用失敗,並出現如fatal: relocation error: file sample_plugin.so: symbol application_some_symbol: referenced symbol not found這樣的錯誤。因爲我只想訪問單個簡單結構,所以我想知道如何阻止鏈接器完成他的大部分工作。

+0

構建插件時使用了哪些鏈接選項? – 2010-04-10 17:40:16

回答

1

如果您使用的是精靈二進制文件,您可能想查看您的平臺是否有libelf可用。 嘗試man elf瞭解更多信息。這可能會讓你得到你所需要的,而不必實際鏈接。我從來沒有用過它,所以我不知道。

+0

謝謝,基於Solaris的gelf(3ELF)手冊頁的一個例子,我創建了一個小工具,它在運行時生成一個.so,所有需要的符號,然後加載這個.so,然後dlopen()是我的插件。有點hackish,但工作:-) (可能我可能已經做了一個shell腳本配對ldd輸出,也...現在可以工作,我可以在這裏組織我的插件) – johannes 2010-04-16 15:28:40

+0

嗯,你可能比我更聰明已經制作了該工具。很有意思。很高興我可以提供幫助。 – nategoose 2010-04-20 23:25:46

0

怎麼樣一個骯髒的黑客與objdump

~$ objdump -s -j .rodata plugin.so 

plugin.so:  file format elf32-i386 

Contents of section .rodata: 
20000000 73616d70 6c652070 6c756769 6e00332e sample plugin.3. 
20000010 322e3100 312e322e 3300    2.1.1.2.3.  

1

根據man dlopen(重點是我的)

RTLD_LAZY

執行延遲綁定。
僅當 引用它們的代碼被執行時才解析符號。如果 符號從未被引用,那麼它將永遠不會被解析。 (懶惰綁定 僅供功能 引用執行;引用 加載 庫時,總是會立即綁定變量。)

所以,你需要添加到您的工具所有的全局變量,你的插件可能會使用。

+0

是的,我希望有人會有一個變通的想法: -/ – johannes 2010-04-10 18:51:58

相關問題