-finstrument-functions不适用于dynamic加载的g ++共享对象(.so)

我正在用Ubuntu上的g ++共享对象(.so)文件testing-finstrument函数。 我发现了一个奇怪的行为,即只有库是静态链接的,函数似乎才起作用。 如果我用dlopen / dlsym等链接到库,代码的function仍然有效,但它不会调用__cyg_profile *函数。

这里有一些代码来快速重现问题:

MyLib.h

#ifndef __MYLIB_H__ #define __MYLIB_H__ class MyLib { public: void sayHello(); }; #endif 

MyLib.cpp

 #include "MyLib.h" #include <iostream> using namespace std; void MyLib::sayHello() { cout<<"Hello"<<endl; } 

MyLibStub.cpp(到.so的C接口)

 #include "MyLib.h" extern "C" void LoadMyLib () { MyLib().sayHello(); } 

Trace.cpp

 #include <stdio.h> #ifdef __cplusplus extern "C" { void __cyg_profile_func_enter(void *this_fn, void *call_site) __attribute__((no_instrument_function)); void __cyg_profile_func_exit(void *this_fn, void *call_site) __attribute__((no_instrument_function)); } #endif void __cyg_profile_func_enter(void* this_fn, void* call_site) { printf("entering %p\n", (int*)this_fn); } void __cyg_profile_func_exit(void* this_fn, void* call_site) { printf("exiting %p\n", (int*)this_fn); } 

MainStatic.cpp

 #include <iostream> using namespace std; extern "C" void LoadMyLib (); int main() { LoadMyLib(); return 0; } 

MainDynamic.cpp

 #include <iostream> #include <dlfcn.h> const char* pszLibName = "libMyLib.so.0.0"; const char* pszFuncName = "LoadMyLib"; int main() { void* pLibHandle = dlopen(pszLibName, RTLD_NOW); if(!pLibHandle) { return 1; } void (*pFuncLoad)() = 0; //Resolve the function in MyLibStub.cpp pFuncLoad = (void (*)())dlsym(pLibHandle, pszFuncName); if(!pFuncLoad) { return 1; } pFuncLoad(); dlclose(pLibHandle); return 0; } 

并使用以下命令编译(在Ubuntu 11.10下):

 g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic MyLib.cpp MyLibStub.cpp Trace.cpp -o libMyLib.so.0.0 ln -s libMyLib.so.0.0 libMyLib.so.0 ln -s libMyLib.so.0.0 libMyLib.so g++ MainStatic.cpp -g -Wall -lMyLib -L./ -o MainStatic g++ MainDynamic.cpp -g -Wall -ldl -o MainDynamic 

当用./MainStatic调用时

它给出了这样的东西:

 entering 0xb777693f entering 0xb777689b exiting 0xb777689b exiting 0xb777693f entering 0xb7776998 entering 0xb777680c Hello exiting 0xb777680c exiting 0xb7776998 

然而,当用./MainDynamic

它只给出一个“你好”。

 Hello 

这里有人知道为什么静态和dynamic链接库有这样的区别吗? 是否有任何解决scheme,即使dynamic加载工作? 提前致谢。

Solutions Collecting From Web of "-finstrument-functions不适用于dynamic加载的g ++共享对象(.so)"

这种行为是预期的。

为了理解它,首先需要知道动态加载器使用链接列表搜索符号,以便加载不同的ELF图像。 在这个列表的头部是主要的可执行文件本身,其次是直接链接到它的所有库。 当你dlopen()某个库时,它会被追加到列表的尾部

所以当你刚加载的库中的代码调用__cyg_profile_func_enter ,加载器会在列表中搜索该函数的第一个定义。 第一个定义恰好是libc.so.6提供的缺省定义,它接近列表的末尾,但是位于dlopen() ed库之前。

你可以通过运行来观察所有这些:

 LD_DEBUG=symbols,bindings ./MainDynamic 

并在输出中寻找__cyg_profile_func_enter

那么,为了看到你的仪器,你需要做些什么呢? 你必须 libc.so.6 之前的某处找到自己的__cyg_profile_func_enter 。 一种方法是将其链接到您的主要可执行文件。 或将其链接到直接链接到您的可执行文件(即不是 dlopen() d)的共享库。

一旦你这样做了,你的实现将是列表中的第一个,它会胜过libc.so.6第一个,你会看到它生成的输出。