8

独自の非 GNU クロスプラットフォーム C++ 環境を構築しようとして、スタックの巻き戻しの基本を本当に理解していないという事実に直面しました。私が構築した環境は以下の通りです。

libc++libc++abilibunwind(または他のアンワインダー)。

libc++abiある種の libunwind が既に含まれていることがわかりましたが、Linux では使用していません。私が理解したコメントから、それは特別な libunwind: LLVM Stack Unwinder であり、Darwin と ARM のみをサポートし、x86_64 はサポートしていません。CPU アーキテクチャがスタックの巻き戻しプロセスに影響を与えるのはなぜですか?

また、次のスタックアンワインダーについても知っています。

  1. glibc 組み込み。
  2. libc++abi LLVM libunwind.
  3. GNU libunwind (サバンナから)。

質問:

  1. プラットフォームまたは CPU アーキテクチャは、スタックの巻き戻しプロセスにどのように影響しますか?
  2. 1 つだけでなく、多くのスタック アンワインダーを使用する必要があるのはなぜですか?
  3. どのような種類のアンワインダーが存在し、それらの違いは何ですか?

回答からの期待:

各質問の個別のポイントだけでなく、このトピック全体をカバーする回答が得られることを期待しています.

4

1 に答える 1

3

基本的に、スタック レイアウトはコンパイラ次第です。最適と思われる方法でスタックをレイアウトできます。言語標準は、スタックがどのように配置されるかについて何も述べていません。

実際には、異なるコンパイラは異なる方法でスタックをレイアウトし、同じコンパイラでも異なるオプションで実行すると異なる方法でレイアウトすることができます。スタック レイアウトは、ターゲット プラットフォーム上の型のサイズ (特にポインター型のサイズ)、GCC などのコンパイラ オプションによって異なります。-fomit-frame-pointer、プラットフォームの ABI 要件 (たとえば、x64 には定義済みの ABI がありますが、x86 にはありません)。スタックを解釈する方法は、コンパイラが関連情報を格納する方法にも依存します。これは、部分的には実行形式に依存します (おそらく、最近は ELF または COFF のいずれかですが、実際には、OS が実行可能ファイルをロードしてエントリ ポイントを見つけることができる限り、他のすべてはほとんど手に入れることができます)。部分的にはデバッグに依存します。情報形式 - これも、使用中のコンパイラとデバッガの組み合わせに固有です。最終的に、アンワインダーが追従できないような方法でスタックとプログラム フローを操作するインライン アセンブラーを作成することは完全に可能です。一部のコンパイラでは、関数のプロローグとエピローグをカスタマイズできるため、巻き戻しアルゴリズムを混乱させる別の機会が与えられます。

これらすべての最終的な影響は、どこでも機能する単一のスタック巻き戻しアルゴリズムを作成することができないということです。アンワインド アルゴリズムは、コンパイラ、OS、および最も基本的な情報以上のデバッガと一致する必要があります。できる最善の方法は、単純なスタック巻き戻しインターフェイスを作成し、サポートするコンパイラ/OS/デバッガの組み合わせごとに異なる方法で実装することです。

于 2014-08-18T06:31:59.407 に答える