プログラムの main(…) 関数を見つけるにはどうすればよいですか?
質問
私は現在、数百のコード ファイルといくつかのサードパーティ ライブラリへの依存関係を含むプロジェクトを Mac OS に移植しています。ようやく、プログラムが警告やエラーなしでコンパイルされるところまで到達しましたが、独自の main 関数が実行されないようです。
代わりに、サードパーティに属すると思われる他のメイン関数を実行しているようです。この関数は、診断用のデータをコンソールに書き込み、その後終了します。
(gdb) continue
Current language: auto; currently c++
//
// This is an automatically generated file.
// Do not edit.
//
const unsigned short expTable[] =
{
0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
...
0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
};
Debugger stopped.
Program exited with status value:0.
スタック トレースは有効に見えますが、gdb は各スタック エントリの正しい行番号とファイル名を表示しないため、デバッガを使用してこの main 関数が存在する場所を見つけることはできません (「 この未解決の疑問 詳細については)。
検索が完了するまでに数分かかりましたが、結果は返されませんでした。
私のプロジェクトは他のライブラリの中で SDL を使用していますが、SDL_Main() とその根本的な問題を解決し、完璧に機能する SDL プロジェクト テンプレートの上にプロジェクトを構築しました。したがって、私自身の main 関数が有効であると確信しています。
何が問題になっているのかわかりますか?現在、不正な main 関数を見つけて削除する方法がわかりません。
ありがとう、
エイドリアン
編集: 今気づいたのですが、「これは自動生成されたものです」という文字列でファイルを検索する際に間違えてしまいました。同じ文字列を持つ数十のファイルを見つけました。それらはすべて、私が使用しているサードパーティ ライブラリの 1 つである FreeImage に属しています。したがって、問題は FreeImage に関連しているようですが、同梱の MacOs makefile を使用して Freeimage をライブラリとしてコンパイルし、ライブラリのみを含めたので、どうすればよいかまだわかりません。新しいバージョンの FreeImage を再構築して、問題が解決したかどうかを確認してみます。
解決
main() が呼び出される前に失敗する静的オブジェクトの初期化子ではないでしょうか?
他のヒント
バイナリにメインがいくつかありますか?使ってみてください nm
その上で。 (それは不可能であるはずです ld
重複したものにはリンクしませんが、動的ライブラリに移動して、 _main
そこには)
nm a.out | grep -5 _main
これにより、前後に 5 行が表示されます。 _main
バイナリで見つかりました a.out
複数ある場合は、周囲の記号を参照して、それらがどの部分にあるかを確認してください。
次のステップでは、使用される各動的ライブラリで同じことを行うことができます。使用されている動的ライブラリのリストを取得するには、次を使用します。otool
otool -L a.out
もう 1 つのエントリ ポイントを見つける方法はわかりませんが、独自のエントリ ポイントを明示的に指定して、もう 1 つのエントリ ポイントを未使用にすることができます。GNUリンカーを使用できます LD -e オプションでエントリ ポイントを設定します。
-e エントリ
--entry=エントリ
デフォルトのエントリポイントではなく、プログラムの実行を開始するための明示的なシンボルとしてエントリを使用します。symbolという名前のエントリがない場合、リンカーはエントリを数字として解析し、エントリアドレスとして使用しようとします(数値はベース10で解釈されます。ベース16にリーディング0x、またはベース8にリーディング0を使用できます。
Windows でこの問題が発生した場合の今後の読者のために。同等のリンカー オプションは次のとおりです。 /エントリ.
実行可能ファイルを実行してみましたか nm
?何かヒントを与えてくれるかもしれません。という名前のグローバルに表示される関数を複数持つプログラムをリンクすることが可能だとは思いません。 main()
, 、どのようにしてそれが起こるのかわかりません。
インクルードするヘッダー ファイルに目を通し、再マップする定義がないか確認してください。 main
何か他のものに。これは、セットアップを行うためにライブラリの main 関数が最初に呼び出されるようにするための古いトリックです。通常、最終的には再定義された値を参照して main 関数を呼び出します。
簡単なハック:
readelf -s -w my_bin_file > temp.txt
Open Temp.txt、Main(1つの列にFUNCを使用)を検索すると、最初のファイル列が見つかるまで上がります。これはリンクされたメインのファイルです。
編集: これは、GNU Unix フレーバーとそのフレンドでのみ機能します。OS X は ELF ではなく Mach-O 形式を使用します。
C では、main 関数の前に別のエントリポイントを呼び出すことができることは知っていますが、それはアイデアかもしれません。通常、コードは次のようになります。
void __attribute__ ((constructor)) my_main(void);
コード内でそのようなものを検索できるかもしれません。
C では、main 関数をキャッチして「実際の」main の後に呼び出すさまざまな方法もあります。一部のスレッド ライブラリには、環境やスケジューラーなどを「準備」するためにこの種のハックが含まれています。
これはあまり役に立ちませんが、メインがまったく呼び出されない理由がこれで説明される可能性があります。
お役に立てれば!
もう一つメモ。
WxWidget は独自の定義も行います main
から ここ
すべてのプログラムと同様に、「main」関数が必要です。wxWidgets では、main はこのマクロを使用して実装され、アプリケーション インスタンスを作成してプログラムを開始します。
IMPLEMENT_APP(MyApp)
マップファイルを生成します。ほとんどのプログラムは実際には main から開始されません。GCC のマップファイルには __start または __executable_start のアドレスが示されており、これに侵入してステップ実行して、プログラムが終了する原因を確認できます。