2017-10-21 3 views
1

私はdlopendlsymを呼び出すプログラムの動作を調べようとしています。最後の目標は、dlsymで取得した関数に呼び出しを記録する小さな関数を挿入することです。macOSでは、どのようにしてdlsymへの呼び出しを傍受できますか?

通常は、あなたがDYLD_INSERT_LIBRARIESでラップしたいいくつかの機能fooのために、あなたはこのような何か書く:

void (*real_foo)(void); 

void init() __attribute__((constructor)) { 
    real_foo = dlsym(RTLD_NEXT, "foo"); 
} 

void foo(void) { 
    puts("foo was called"); 
    real_foo(); 
} 

を問題は、あなたがdlsymをラップしようとしているとき、あなたはこれで終わるということです。

void* (*real_dlsym)(void* handle, const char* symbol); 

void init() __attribute__((constructor)) { 
    real_dlsym = dlsym(RTLD_NEXT, "dlsym"); 
} 

void* dlsym(void* handle, const char* symbol) { 
    return real_dlsym(handle, symbol); 
} 

initは役に立たないdlsymの独自の実装を呼び出してしまいます。

別のものをエクスポートしているときに「本当の」dlsymを取得するにはどうすればよいですか?あるいは、dlsymへの呼び出しを傍受する良い方法がありますか?

答えて

0

/usr/lib/system/libdyld.dylibには、少なくとも10.12システムでは、dlsymが実際に実装されています。それはdlopen()そのファイルで動作するはずですdlsym()の実装を得るために返されたハンドルでdlsym()を呼び出してください。 RTLD_FIRSTRTLD_LOCALのように、modeのフラグをdlopen()に追加することができます。次のように指定します。

void *libdyld_handle = dlopen("/usr/lib/system/libdyld.dylib", RTLD_LAZY); 
    void *dlsym_funcptr = dlsym(libdyld_handle, "dlsym"); 
+0

dlsymは自分の「実装」と呼ばれるため使用できません。私はそれを他のものと呼ぶことはできません。そうでなければ、本当のdlsymを置き換えることはできません。 – zneak

関連する問題