質問はどのように共有ライブラリ(UNIX/LINUX)から関数アドレスを取得できますか?共有ライブラリからの関数ポインタの取得の違い
私はUbuntu 10.04(amd64)とFreeBSD-8.2(amd64)でコンパイルして実行するCでいくつかのテストケースを書きました(下記参照)。私は何の違いも感じなかったが、私は起こりうるトラブルについてもっと知りたい。ここで
彼らは以下のとおりです。
- テスト1
lib.c
char* f0(void) {
return "Hello, World!";
}
main.cの
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void *hlib, *addr;
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if (!(hlib = dlopen("./lib.so", RTLD_LAZY)))
return 1;
if (!(addr = foo = dlsym(hlib, "f0")))
return 2;
s = foo();
printf("%p => %s\n", addr, s);
return 0;
}
今
それを構築:
gcc -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so -shared -nostartfiles lib.o
gcc -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
これは、ライブラリ関数f0()のアドレスと実行結果を出力します。
- 試験2
lib.h(ここで、動的リンクライブラリの標準インタフェースを規定する)
#ifndef __LIB_H__
#define __LIB_H__
typedef struct __syminfo {
char* name; // function name
void* addr; // function address
} syminfo_t;
typedef struct __libinfo {
int num; // number of exported functions
syminfo_t sym[1]; // vector of exported function information
} libinfo_t;
extern int (*__getinfo)(libinfo_t**);
#endif
/* __LIB_H__
*/
lib.c(ライブラリ自体)
#include <stdlib.h>
#include <lib.h>
static libinfo_t* li;
char* foo(void);
__attribute__((constructor)) void __init() {
if ((li = calloc(1, sizeof(libinfo_t)))) {
li->num = 1;
li->sym[0].name = "foo";
li->sym[0].addr = &foo;
}
}
__attribute__((destructor)) void __free() {
if (li)
free(li);
}
int getinfo(libinfo_t** inf) {
if (!inf)
return -1;
*inf = li;
return 0;
}
char* foo(void) {
return "Hello, World!";
}
main.c
今#include <stdio.h>
#include <dlfcn.h>
#include <lib.h>
libinfo_t* inf;
void* hlib;
int (*__getinfo)(libinfo_t**);
char* (*foo)(void);
char* s;
int main(int argc, char** argv) {
if (!(hlib = dlopen("./lib.so", RTLD_LAZY)))
return 1;
if (!(__getinfo = dlsym(hlib, "getinfo")))
return 2;
if (__getinfo(&inf))
return 3;
if (!(foo = inf->sym[0].addr))
return 4;
s = foo();
printf("%p => %s\n", inf->sym[0].addr, s);
return 0;
}
(-nostartfilesなし)でコンパイル:
gcc -I. -o lib.o -c lib.c -Wall -Werror -O3 -fPIC
gcc -o lib.so lib.o -shared
gcc -I. -o main.o -c main.c -Wall -Werror -O3
gcc -o prog main.o -ldl
このprintf関数を試験1と同じ:ライブラリ関数fooのアドレス()とその実行結果。
私はどのように共有ライブラリ関数のアドレスを取得することができますが、私は2番目のテストで正しいですか?私はそれにいくつかの問題がありますか?
注:FreeBSD-8.2では、-ldl引数を使用する必要はありません。すべてのdlfcn.hルーチンはlibcライブラリにあります。
説明のためにそれぞれ対応しています。
ありがとうございました。私には有益な情報がありました=) – user2168737