views:

263

answers:

3

I have an application which can make use of plugins which are loaded at runtime using dlopen. Each of the plugins defines a function toretrieve the plugin information which is defined using a common structure. Something like that:

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;
 }

This works well and plugins can be loaded. Now i want to build a small tool to read these properties without linking the whole application. For doing that I have some code like this:

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);

This works nice for simple plugins. The issue is that many plugins reference further symbols from the application, which are resolved even though RTLD_LAZY was set. (like global variables from the application which are used to initialize plugin-global things) So the dlopen() call fails with an error like fatal: relocation error: file sample_plugin.so: symbol application_some_symbol: referenced symbol not found. As I just want to have access to the single simple structure I was wondering how I can prevent the linker from doing that much of his work.

A: 

How about a dirty hack with 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.      

Nikolai N Fetissov
+1  A: 

According to man dlopen (emphasis is mine)

RTLD_LAZY

Perform lazy binding.
Only resolve symbols as the code that references them is executed. If the symbol is never referenced, then it is never resolved. (Lazy binding is only performed for function references; references to variables are always immediately bound when the library is loaded.)

So you need to add to your tool all the global variables your plugin might use.

qrdl
Yeah, I hoped somebody would have an idea for a work-around :-/
johannes
A: 

If you are using elf binaries you may want to see if your platform has libelf available. Try man elf for more info. This may get you what you need without having to actually link. I have never used it though, so I don't know.

nategoose
Thanks, based on an example from Solaris' gelf(3ELF) man page I created a small tool which, on the fly, generates a .so with all needed symbols, then loads this .so and then dlopen()'s my plugin. a bit hackish but works :-)(probably I might have done that with a shell script paring ldd output, too ... but works for now and I can organize my plugins here)
johannes
Well, you're probably smarter than me to have made that tool. Very interesting. Glad I could be of assistance.
nategoose