问题描述
我想让另一个 .cpp
文件中定义的函数在另一个模拟工具中可用。
我在这个问题中发现了以下代码:
Trace.cpp
#include< stdio.h>
#ifdef __cplusplus
externC
{
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(输入%p \\\
(int *)this_fn);
}
void __cyg_profile_func_exit(void * this_fn,void * call_site)
{
printf(exiting%p\\\
,(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.cpp
和 MyLibStub.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
并获得:
我也试过:
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 -inet
已成功编译但应用程序崩溃:
strong>
- 如何正确编译
Trace.cpp
? b $ b - 如何将其与共享库的其余部分链接?
您可能注意到我不是很经验与编译,链接和类似。
解决方案由于@Flexo重述@EmployedRussian在链接问题中说的主要观点是在 libc.so.6
提供的实现之前实现 __ cyg_profile_func _ ***
。
一个方法是使用 LD_PRELOAD
环境变量。 ,您可以阅读 LD_PRELOAD
的功能及其工作原理。
a href =http://stackoverflow.com/questions/426230/what-is-the-ld-preload-trick> LD_PRELOAD
小提示需要将上述函数的实现编译为共享库。
您可以这样做:
g ++ -shared -fPIC myImp.cc -o myImp.so -ldl
b $ b
一旦你得到 .so
文件,导航到可执行文件所在的目录并执行:
LD_PRELOAD =< path / to / myImp.so> - ./<myExecutable>
对于共享库,使用动态链接。含义:
解析一些未定义的符号(被推迟),直到程序运行。
通过使用 LD_PRELOAD
,您可以在链接之前解析符号。
这里你有一个 myImp.cc
的实现,我从
当前版本缺少 __ cyg_profile_func_exit
的正确实现,我无法解析函数名称。
#ifdef __cplusplus
externC
{
#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 {
fprintf(fp,\t);
}
// fprintf(fp,entered%p\\\
,(int *)this_fn);
fprintf(fp,entered%p,(int *)this_fn);
if(dladdr(this_fn,& di)){
fprintf(fp,%s(%s),di.dli_sname?di.dli_sname:< unknown>,di。 dli_fname);
}
fputs(\\\
,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 fprintf(fp,exiting%p \\\
,(int *)this_fn);
(void)call_site;
}
在,但我从来没有使用过...
I want to have the functions which are defined in another .cpp
file become available in another simulation tool.
I found the following code in this question: -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 is compiled by doing:
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
Note that I don't need: MyLib.cpp
and MyLibStub.cpp
.
Instead compiled Trace.cpp
doing:
g++ -g -finstrument-functions -Wall -Wl,-soname,libMyLib.so.0 -shared -fPIC -rdynamic Trace.cpp -o libMyLib.so.0.0
What I've tried:
The shared object where I want to have Trace.cpp
is obtained by:
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
I added -L
and -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
and got:
I also tried:
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
which compiled successfully but the application crashed:
Question:
- How to compile
Trace.cpp
correctly? - How to link it with the rest of the shared library?
As you might notice I am not very experienced with compiling, linking and similar. So, any extra explanation is very welcome!
解决方案 As @Flexo restates what @EmployedRussian said in the linked question, the main point is to get your implementation of __cyg_profile_func_***
before the one provided by libc.so.6
.
One method to do this, is to use the LD_PRELOAD
environment variable. Here you can read what LD_PRELOAD
does and how it works.
To use the LD_PRELOAD
trick you will need to compile your implementation of the above-mentioned functions as a shared library.
You can do this by doing:
g++ -shared -fPIC myImp.cc -o myImp.so -ldl
Once you get the .so
file, navigate to the directory where your executable is located and do:
LD_PRELOAD=<path/to/myImp.so>- ./<myExecutable>
For shared libraries, dynamic linking is used. Meaning:
By using LD_PRELOAD
you resolve the symbols of your interest before letting the linked do that.
Here you have an implementation of myImp.cc
, which I took from: https://groups.google.com/forum/#!topic/gnu.gcc.help/a-hvguqe10I
The current version lacks proper implementation for __cyg_profile_func_exit
, and I have not been able to demangle the function names.
#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;
}
Another option for function tracing which uses LD_PRELOAD
is used by LTTng, in the section Function Tracing, but I have never used it...
这篇关于如何编译cpp,然后将其链接到共享库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!