2016-04-28 18 views
0

別のシミュレーションツールで別の.cppファイルに定義されている機能を使用可能にしたいと考えています。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.cppおよびMyLibStub.cpp

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

を私が試した何:

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 
:私はTrace.cppを持ちたい

共有オブジェクトをすることによって得られる代わりにTrace.cppがやってコンパイル

私はを追加しましたと-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は:

コンパイル
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 

:私も試した-lmylib

を見つけることができません正常に終了しましたが、アプリケーションがクラッシュしました:

起動時に

エラー:ライブラリ を読み込むことができません「../../src//libveins.so」:libMyLib.so.0は:そのようなファイルやディレクトリはありません:共有オブジェクト ファイルを開くことができません。


質問:

  1. 正しくTrace.cppをコンパイルする方法は?
  2. 他の共有ライブラリとリンクするにはどうすればいいですか?

あなたが気づいているように、私はコンパイルやリンクなどの経験はあまりありません。だから、余分な説明は大歓迎です!

+0

あなたが他の場所でコメントで尋ねた質問への答えあなたがリンクしている質問には、「あなたは自分の__cyg_profile_func_enterをlibc.so.6のどこかに置く必要があります。それを実行する一つの方法は、あなたのメインの実行可能ファイルにリンクすることです。あなたの実行可能ファイルに直接リンクされています(つまり、dlopen()ではありません)。 "それ以外のこの質問は、一般的な "どのようにリンクするのですか?"これは選択したビルドツールのドキュメントでカバーされています。 – Flexo

+0

ええと、それは私が今把握しようとしているものです。トリッキーな部分は、私が使っているツールが最終的に3つのシミュレーションツールを一緒に "マージ"するスクリプトを使ってmakefileを生成することです。最終的なmakeは次のようなものです:http://pastebin.com/EiXGiHbK ... so本当の疑問は、 'libc.so.6'の実装の前に私の実装をどうやって置くのですか? :/ – cross

答えて

1

@Flexoは@EmployedRussianがリンクされた質問に述べたことを述べているので、主な点はlibc.so.6で提供される前に__cyg_profile_func_***の実装を得ることです。

これを行う1つの方法は、LD_PRELOAD環境変数を使用することです。 Hereは、LD_PRELOADの機能とその動作を読み取ることができます。

LD_PRELOAD trickを使用するには、上記の関数の実装を共有ライブラリとしてコンパイルする必要があります。

次の操作を行うことにより、これを行うことができます:あなたは.soファイルを取得したら

g++ -shared -fPIC myImp.cc -o myImp.so -ldl 

は、あなたの実行ファイルがあるディレクトリに移動し、実行します。

共有ライブラリの
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を使用する関数トレースするためのもう1つのオプションは、セクションFunction Tracingで、LTTngによって使用されますが、私はそれを使用したことがない...

関連する問題