2

I need to call an exported symbol from my own application - therefore I need to know if it's safe to call dlopen / LoadLibrary on "yourself".

An example would be:

LoadLibrary("test.exe");

inside a program called test.exe.

I tested it and it seems to work, but I'm not quite sure if it is actually supported behavior.

4

3 回答 3

5

From the MSDN documentation here...

The system maintains a per-process reference count on all loaded modules. Calling LoadLibrary increments the reference count. Calling the FreeLibrary or FreeLibraryAndExitThread function decrements the reference count. The system unloads a module when its reference count reaches zero or when the process terminates (regardless of the reference count).

It will work, just remember to clean-up after yourself by calling FreeLibrary, as stated above.

What you may have really wanted instead is GetModuleHandle.

Retrieves a module handle for the specified module. The module must have been loaded by the calling process.

In fact, what you're trying to do is even a special case.

lpModuleName [in, optional]

...

If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).

So, trying this...

#include <stdio.h>
#include <windows.h>

__declspec(dllexport) void print(void) {
  puts("OK");
}

main() {
  HMODULE mod = GetModuleHandle(0);
  FARPROC proc = GetProcAddress(mod, "print");
  proc();
  return 0;
}

... appears to work:

C:\dev\scrap>gcc -oprint print.c

C:\dev\scrap>print
OK

For dlopen, it appears very similar.

If filename is a NULL pointer, then the returned handle is for the main program. When given to dlsym(), this handle causes a search for a symbol in the main program, followed by all shared libraries loaded at program startup, and then all shared libraries loaded by dlopen() with the flag RTLD_GLOBAL.

于 2012-07-31T15:43:44.697 回答
2

A quick test on Windows:

#include <windows.h>
#include <stdio.h>

__declspec(dllexport) FARPROC Test() { 
    printf("It worked");
}

int main(int argc, char **argv) {
    HMODULE m = LoadLibrary(argv[0]);
    FARPROC test = GetProcAddress(m, "Test");
    test();
    return 0;
}

produced the following output:

It worked

I suppose in theory that doesn't guarantee that it might not break on some other version of Windows, but I consider that rather doubtful.

于 2012-07-31T14:05:09.840 回答
2

You can do this trivially with dlopen() - there's a pseudo handle given as a GNU extension, RTLD_DEFAULT which acts like a handle to yourself, so you can simply skip the dlopen() call and write:

dlsym(RTLD_DEFAULT, "entry_func");

For example:

#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
#include <assert.h>

void print(void) {
  puts("OK");
}

int main() {
  void (*proc)(void) = dlsym(RTLD_DEFAULT, "print");
  assert(proc);
  proc();
  return 0;
}

Note that you'll need to compile with -rdynamic for this to work.

According to the manpage on a recent Solaris machine RTLD_DEFAULT is available there too.

于 2012-07-31T15:56:37.723 回答