8

どのLLVM IRコードが前に実行されるかについての一般的なルールを知っている人はいますmainか?

Clang++ 3.6 を使用すると、オブジェクト ファイルの「.text.startup」セクションの関数を介してグローバル クラス変数のコンストラクターが呼び出されるようです。例えば:

define internal void @__cxx_global_var_init() section ".text.startup" {
  call void @_ZN7MyClassC2Ev(%class.MyClass* @M)
  ret void
}

この例から、 を指定する IR 関数定義を正確に探す必要があると思いますsection ".text.startup"

私の理論が正しいと疑う理由は 2 つあります。

  • LLVM IR ファイルには他に何も表示されません ( .ll)LLVM が「__cxx_global_var_init」のような C++ 固有の関数名をスニッフィングしていないと仮定する場合、グローバル オブジェクト コンストラクターを最初に実行する必要があることを示唆しています。したがってsection ".text.startup"、唯一の明白な手段はmain()しかし、それが正しいとしても、関数を の前に実行させるための十分な条件を特定しましたがそれmain()が LLVM IR で関数を の前に実行させる唯一の方法であることを示していませんmain()

  • Gnu リンカは、場合によっては、セクションの最初の命令を.textプログラムのエントリ ポイントとして使用します。 Raspberry Pi プログラミングに関するこの記事では、コードを最初に実行する手段として、.text.startupコンテンツをプログラムのセクションに表示される最初のコード本体にする方法について説明しています。.text.text.startup

残念ながら、私の理論を裏付けるものは他にあまり見つかりません。

  • 文字列「.startup」の LLVM 3.6 ソース コードを grep すると、LLVM コードの CLang 固有の部分でしか見つかりません。私の理論が正しいとすれば、LLVM コードの他の部分でもその文字列が見つかったはずです。特に、C++ フロントエンド以外の部分です。

  • C++ でのデータ初期化に関するこの記事は、".text.startup" に特別な役割があることを暗示しているようですが、Linux プログラム ローダーが実際にその名前のセクションを探すとは言えません。あったとしても、プラットフォームに中立な LLVM IR で特別な意味を持つ Linux 固有の可能性のあるセクション名を見つけたら驚くでしょう。

  • Linux 3.13.0 のソース コードには文字列 ".startup" が含まれていないようです。これは、プログラム ローダーが ".text.startup" という名前のセクションをスニッフィングしていないことを示唆しています。

4

1 に答える 1

6

答えは簡単です。LLVM は裏で何も実行していません。main() を実行する前に必要なすべての準備を行うのは、Cランタイム(CRT) の仕事です。これには、静的な ctor や類似のものも含まれます (ただし、これらに限定されません)。ランタイムは、通常、特別なセクション (.init_array や .ctors など) で生成されるコンストラクターのアドレスを介して、これらのオブジェクトについて通知されます。詳細については、たとえばhttp://wiki.osdev.org/Calling_Global_Constructorsを参照してください。

于 2015-06-19T14:58:45.843 に答える