web-dev-qa-db-ja.com

C ++シンボル名を壊すLinuxユーティリティとは何ですか?

シンボルをデマングルする_c++filt_コマンドがありますが、反対のことを行ってシンボル名をマングルするツールは何ですか?

これは、マングルされたC++関数名でdlsym()を呼び出す場合に役立ちます。新しいコンパイラバージョンや新しいコンパイラブランドが使用されたり、現在複数のプラットフォーム用にコンパイルされているために、時間の経過とともに変更される可能性があるため、コードにマングル化する名前をハードコーディングしないほうがよいでしょう。

コードがコンパイラに依存しないように、実行時にC++関数を表す文字列を取得するプログラム的な方法はありますか?これを行う可能性のある1つの方法は、使用されているコンパイラの名前のマングリングを実行し、適切なマングルされたC++シンボル名をdlsym()が使用する文字列に挿入するユーティリティをコンパイル時に呼び出すことです。

これは私がこのサイトで見つけたソリューションに最も近いものです これは、固定Cスタイル名を使用して、ライブラリで定義されているC++シンボルを間接的に指定することによって達成されますdlsym()、ただし、そのライブラリが提供するものを制御できない場合、これはオプションではありません。

50
WilliamKF

あなたが見ている.soのシンボルテーブルを見るとあなたが望むものを得ることができるかもしれません:誰か他の人がすでにこれに答えました 共有ライブラリのシンボルテーブルを返す

ただし、シンボルが多すぎる場合は...機能しない可能性があります。
これがおかしなアイデアです。買い手責任負担!

可能な解決策は次のとおりです。

  1. 名前が1つだけのスタブを含むファイルを作成します。必要な名前は次のとおりです。void myfunction(){}

  2. そのファイルをコンパイルします(-fPICと-sharedを使用して、動的ライブラリです)。

  3. その特定のファイルでdlopen/dlsymを呼び出す

  4. 記号を反復処理します(必要なものだけに加えて、フィルターできる他の通常のジャンクがあるはずです)。シンボルの繰り返し処理は不便ですが、次のように実行できます。 共有ライブラリシンボルテーブルを返す

  5. それを解放するdlclose()(シンボルからスタブを失う)

  6. Dlopenで必要なファイルを開きます

基本的には、コードからコンパイラーを呼び出し、.soを作成して、調べて、唯一の値を取得し、その.soをアンロードして、必要なものにロードできるようにします。

それはクレイジーです。

3
rts1

これが、g ++が名前をマングルする方法です。これらのマングルルールをプログラムに実装する場合があります。

別の(クレイジーな)解決策は、使用したいライブラリー内のすべてのシンボルをリストし(フォーマットを理解していればそれほど難しくありません)、それらすべてをデマングルし、そのリストで関数の名前を検索することです。このメソッドの利点は、デマングルを行うための関数呼び出しがあるため、デマングルが簡単になることです:abi::__cxa_demangle、cxxabi.hヘッダーから。

5
Dani

名前マングリングは実装固有です。

名前をマングリングするための標準はないので、最善の策はそれを行うコンパイラーを見つけることです。

名前のマングリング

これを手動で行う場合に役立つ表がここにあります

3
otc

最初の投稿よりも簡単な方法。次のような小さなC++プログラムを作成します。

#include <stdlib.h>

extern int doit(const char *toto, bool is);

int main(int argc, char *argv[])
{
  exit(doit (argv[0], true));
}

でそれを構築する

# g++ -S test.cpp

そして、アセンブラソースからシンボル名を抽出します

# cat test.s | grep call | grep doit | awk '{print $2}'

あなたが得る:

rcoscali@srjlx0001:/tmp/TestC++$ cat test.s | grep call | grep doit | awk '{print $2}'
_Z4doitPKcb
rcoscali@srjlx0001:/tmp/TestC++$ 

符号化されたdoit記号は_Z4doitPKcb使用する予定のコンパイラを使用します。これは、各コンパイラに独自の名前変換規則があるためです(あるコンパイラから別のコンパイラでは、これらの規則は変更される可能性があります)。

楽しんで !

1