-finstrument-functions 不适用于动态加载的 g++ 共享对象 (.so)
-finstrument-functions doesn't work with dynamically loaded g++ shared objects (.so)
这些天我正在 Ubuntu 上使用 g++ 共享对象 (.so( 文件测试 -finstrument-functions。我发现了一个奇怪的行为,即 -finstrument-functions 似乎只有在库静态链接时才有效。如果我使用 dlopen/dlsym 等链接到库,代码的功能仍然有效,但它不会调用 __cyg_profile* 函数。
以下是一些代码,可快速重现该问题:
MyLib.h
#ifndef __MYLIB_H__
#define __MYLIB_H__
class MyLib
{
public:
void sayHello();
};
#endif
我的图书馆.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();
}
跟踪.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 %pn", (int*)this_fn);
}
void __cyg_profile_func_exit(void* this_fn, void* call_site)
{
printf("exiting %pn", (int*)this_fn);
}
主静态.cpp
#include <iostream>
using namespace std;
extern "C" void LoadMyLib ();
int main()
{
LoadMyLib();
return 0;
}
主动态.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
这里有人知道为什么静态链接库和动态链接库之间存在如此大的差异吗?有没有任何解决方案可以使它在动态加载时也能工作?提前谢谢。
此行为是预期行为。
为了理解它,您首先需要知道动态加载器使用链表搜索符号,按照加载不同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
中的那个,你会看到它生成的输出。
你可以
dlopen(pszLibName, RTLD_NOW | RTLD_DEEPBIND);
然后,库中定义的符号将优先于全局符号
- 如何从具有移动语义的类对象中生成共享指针
- 使用共享指针的函数调用,其对象应为 const
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- 在共享缓冲区内存中创建 ::std::string 对象
- 如何创建一个共享对象与另一个.所以在Cmake
- 内联函数的函数本地静态对象是否在共享对象文件之间共享?
- 有没有办法列出所有共享内存对象的名称?
- 共享的从属对象
- 在 Android Studio 中使用 C++ 共享对象时出现问题
- 共享对象、符号、C/C++ 库链接和加载
- ./main:加载共享库时出错:libopencv_highgui.so.4.0:无法打开共享对象文件:没有这样的文件或
- 在 win32 上生成 R 包:无法加载共享对象 (.dll)
- C++对象共享属性 - 使用指针或引用
- 如何测试共享对象/共享库已正确编译
- 创建对象共享指针以共享指针为参数
- 限制C++中虚拟基类的对象共享
- 在Ada95中跨共享库/对象共享数据
- 这种线程间对象共享策略是否合理
- 如何更改对象共享指针指向,而它被其他线程占用
- 初始化仅由一组对象共享的静态变量