C/C++で関数名(シンボル名)から関数アドレスを取得する方法
関数名(シンボル名)から関数アドレスを取得する方法を紹介します。
1.問題点
関数名(シンボル名)から関数アドレスを取得する処理を実装する必要が生じましたが、実装する方法がわかりません。
ということで、実装方法を紹介します。
2.関数名から関数アドレスを取得する
関数名から関数アドレスを取得するにはdlsym()を利用します。
サンプルを以下に示します。
sample.cc
#include <stdio.h>
#include <dlfcn.h>
int main() {
void *handle;
int (*fptr)(int);
handle = dlopen("/home/foo/a.out", RTLD_LAZY);
fptr = (int (*)(int))dlsym(handle, "main");
printf("function addr: %p\n", fptr);
return 0;
}
実行結果
g++ -ldl -rdynamic sample.cc
% ./a.out
function addr: 0x400880
まず、dlopen()で関数アドレスを取得したい関数が含まれるライブラリを指定します。"RTLD_LAZY"は、ライブラリのコードが実行される際に未定義シンボルを順次解決していくことを示すオプションです。
handle = dlopen("/home/foo/a.out", RTLD_LAZY);
dlsym()の第1パラメータにでライブラリのファイルハンドル、第2パラメータにアドレスを取得したい関数名(シンボル名)を設定します。
fptr = (int (*)(int))dlsym(handle, "main");
その他、ビルド時のポイントとして、"-ldl -rdynamic"が必須パラメータになります。
"-ldl"は動的ロードライブラリへのリンク、"-rdynamic"はすべてのシンボルを動的シンボルテーブルに追加するパラメータです。
"-ldl"を付与せずにビルドすると下記のエラーが発生します。
% g++ -rdynamic sample.cc
/tmp/cc8BV6Dq.o: 関数 `main' 内:
sample.cc:(.text+0x13): `dlopen' に対する定義されていない参照です
sample.cc:(.text+0x28): `dlsym' に対する定義されていない参照です
collect2: エラー: ld はステータス 1 で終了しました
"-rdynamic"を付与せずにビルドすると、ビルドは成功しますがdlsym()で期待する結果が得られません。
% g++ -ldl sample.cc
% ./a.out
function addr: (nil)
3.参考サイト
参考サイトは下記です。ありがとうございました。
- dlsym() -- dlopen() オブジェクトからのシンボルのアドレスの入手
- Manpage of DLOPEN
- [Linux][C/C++]関数の復帰アドレス値と呼び出し元の関数名を取得する方法
Posted by yujiro このページの先頭に戻る
トラックバックURL
コメントする
greeting