53

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

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

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

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

4

4 に答える 4

7

これが、g++ が名前をマングルする方法です。これらのマングリング ルールをプログラムに実装することもできます。

もう 1 つの (クレイジーな) 解決策は、使用するライブラリ内のすべてのシンボルを一覧表示し (形式を理解していればそれほど難しくありません)、それらをすべてデマングルし、その一覧で関数の名前を検索することです。この方法の利点は、abi::__cxa_demanglecxxabi.h ヘッダーからの関数呼び出しがあるため、デマングリングが簡単になることです。

于 2015-08-23T03:37:45.367 に答える
5

あなたが見ている.soのシンボルテーブルを見ることで、あなたが望むものを得ることができるかもしれません :

ただし、シンボルが多すぎると...うまくいかない場合があります。
だからここにクレイジーなアイデアがあります。買い手責任負担!

潜在的な解決策は次のとおりです。

  1. ちょうど 1 つの名前のスタブを持つファイルを作成します: 必要な名前: void myfunction() { }

  2. そのファイルをコンパイルします (-fPIC および -shared を使用して動的ライブラリにする)

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

  4. シンボルを反復処理します (必要なものと、フィルターできる他の通常のジャンクのみが存在する必要があります)。シンボルを繰り返し処理するのは面倒ですが、それは可能です: 共有ライブラリ シンボル テーブルを返す

  5. dlclose() で解放します (シンボルからスタブを失います)

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

基本的に、コードからコンパイラを呼び出すと、.so が作成され、参照して唯一の値を取得し、その .so をアンロードして、必要な値をロードできます。

それはクレイジーです。

于 2015-08-21T21:29:52.417 に答える
1

最初に投稿された方法よりも簡単な方法。次のような小さな 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

楽しむ !

于 2016-06-25T12:51:37.127 に答える