2016-11-22 8 views
1

C++を使用しているSolaris 10の現在の実行可能ファイルから関数のアドレスを知る必要があります(私はGNU g ++ 4.9.2を使用しています)。たとえば、void doSomething(const char * p)という関数があります。これは、現在の実行可能ファイルで定義されている場合と定義されていない場合があります。だから、私は、現在の実行可能ファイル内の関数を検索したい場合は、存在する場合は、他のいくつかのデフォルトの操作を行う呼び出してください。それ、どうやったら出来るの? dlsymは助けますか? 構文と変更された名前で私を助けてください。現在の実行可能ファイルから関数アドレスを取得する方法は?

+0

はい、それはまさにdlsymの目的です。関数のポインタ(つまりアドレス)を(mangled)名前で返します。 – Cameron

+0

@Cameron使用する引数(現在の実行可能ファイルから検索する)と変更された名前を手助けしてください –

答えて

3

nm execを実行すると、実行可能ファイルにシンボルの一覧が表示されます。共有ライブラリからシンボルを取得しようとしている場合は、nmシンボルのライブラリも使用できます。あなたが欲しいものを選んで、何かのようにそれを読み込む...

void* handle = dlopen(NULL, RTLD_LAZY); 
void* ptr = dlsym(handle, "mangled_name_you_got_from_nm"); 

あなたはおそらくあなたがに(当然、変化するようなものを経由してロードされている関数の関数ポインタ型にキャストしたいと思うでしょうけど適切な関数ポインタ型)...

void* handle = dlopen(NULL, RTLD_LAZY); 
auto ptr = reinterpret_cast<int(*)(int)>(dlsym(handle, "mangled_name_you_got_from_nm")); 
+0

Solaris 10にはnmと同等のものはありますか?それは私が手口の名前を取得するのに役立ちます –

+0

[elfdump -S](https://docs.oracle.com/cd/E26502_01/html/E29030/elfdump-1.html#REFMAN1elfdump-1) – yugr

+0

これで行くことができますこれは答えには2つの欠点があります。(1)コンパイラ間で、または同じコンパイラの異なるバージョン間でも名前の変更が変わる可能性があります。 (2)メインの実行可能ファイルが '-rdynamic'(または同等のもの)とリンクされていない限り、関数は動的シンボルテーブルにエクスポートされず、' dlsym'は 'NULL'を返します。 –

0

「が定義されていればfoo()を呼び出し、それがない場合は、何もしない」のライブラリにはかなり一般的である必要があります。

一般的な例の1つは、プログラムがスレッドとリンクされている場合はpthread_mutex_lockpthread_mutex_unlockを呼び出し、それ以外の場合はロックを行わないことです。

弱い未解決シンボルは完璧な解決策です。

extern void foo() __attribute__((weak)); 

void MaybeCallFoo() 
{ 
    if (&foo == NULL) { printf("foo is not defined\n"); return; } 
    foo(); // It is defined, call it. 
} 
関連する問題