如何编译cpp然后将其链接到共享库

时间:2016-04-28 09:45:22

标签: c++ compilation dynamic-linking

我想让另一个.cpp文件中定义的函数在另一个模拟工具中可用。

我在这个问题中找到了以下代码:-finstrument-functions doesn't work with dynamically loaded g++ shared objects (.so)

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);
}
通过执行以下操作编译Trace.cpp:

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

请注意,我不需要:MyLib.cppMyLibStub.cpp

而是编译Trace.cpp

g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic Trace.cpp -o libMyLib.so.0.0 

我尝试过的事情:

我希望拥有Trace.cpp的共享对象是:

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

我添加了-L-l

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins -L /home/user/Desktop/test/ -lMyLib -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

得到了:

  

/ usr / bin / ld:找不到-lMyLib

我也尝试过:

opp_makemake -f --deep --no-deep-includes --make-so -I . -o veins /home/user/Desktop/test/libMyLib.so.0.0 -O out -I../../inet/src/util/headerserializers/sctp/headers -L../../inet/src -linet 

编译成功但应用程序崩溃了:

  

启动时出错:无法加载库   &#39; ../../ src // libveins.so&#39;:libMyLib.so.0:无法打开共享对象   file:没有这样的文件或目录。

问题:

  1. 如何正确编译Trace.cpp
  2. 如何将其与其他共享库链接?
  3. 您可能会注意到我对编译,链接和类似方面的经验不足。所以,非常欢迎任何额外的解释!

1 个答案:

答案 0 :(得分:1)

由于@Flexo重申@EmployedRussian在链接问题中所说的内容,重点是在__cyg_profile_func_***提供的libc.so.6之前实现LD_PRELOAD

执行此操作的一种方法是使用LD_PRELOAD环境变量。 Here您可以阅读g++ -shared -fPIC myImp.cc -o myImp.so -ldl 的作用及其运作方式。

要使用LD_PRELOAD trick,您需要将上述功能的实现编译为共享库。

您可以这样做:

.so

获得LD_PRELOAD=<path/to/myImp.so>- ./<myExecutable> 文件后,导航到可执行文件所在的目录并执行:

LD_PRELOAD

对于共享库,使用动态链接。含义:

  

解析一些未定义的符号(推迟),直到程序运行。

通过使用myImp.cc,您可以在链接之前解析您感兴趣的符号。

此处您有__cyg_profile_func_exit的实现,我从中获取了https://groups.google.com/forum/#!topic/gnu.gcc.help/a-hvguqe10I

当前版本缺少#ifdef __cplusplus extern "C" { #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dlfcn.h> 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 static FILE *fp; int call_level=0; void * last_fn; void __cyg_profile_func_enter(void *this_fn, void *call_site) { Dl_info di; if (fp == NULL) fp = fopen( "trace.txt", "w" ); if (fp == NULL) exit(-1); if ( this_fn!=last_fn) ++call_level; for (int i=0;i<=call_level;i++) { fprintf(fp,"\t"); } //fprintf(fp, "entering %p\n", (int *)this_fn); fprintf(fp, "entering %p", (int *)this_fn); if (dladdr(this_fn, &di)) { fprintf(fp, " %s (%s)", di.dli_sname ? di.dli_sname : "<unknown>", di.dli_fname); } fputs("\n", fp); (void)call_site; last_fn = this_fn; } void __cyg_profile_func_exit(void *this_fn, void *call_site) { --call_level; for (int i=0;i<=call_level;i++) fprintf(fp,"\t"); fprintf(fp, "exiting %p\n", (int *)this_fn); (void)call_site; } 的正确实现,我无法对函数名称进行解码。

LD_PRELOAD

使用if (N % 2 == 0 && (N >= 6 && N <= 20)) { /* ... */ } 的函数跟踪的另一个选项在Function Tracing部分由LTTng使用,但我从未使用过它......