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
}

从这个例子中,我猜我应该寻找那些指定section ".text.startup".

我有两个理由怀疑我的理论是正确的:

  • 我在我的 LLVM IR 文件中看不到任何其他内容(.ll)建议应该首先运行全局对象构造函数,如果我们假设 LLVM 没有嗅探 C++ 特定的函数名称,例如“__cxx_global_var_init”。所以这section ".text.startup"是唯一明显的方法说代码应该在 before 之前运行main()。但即使这是正确的,我们已经确定了导致函数在 before 之前运行的充分条件main(),但还没有证明它是 LLVM IR 中导致函数在 before 之前运行的唯一方法main()

  • 在某些情况下, Gnu 链接器将使用该.text节中的第一条指令作为程序入口点。 这篇关于 Raspberry Pi 编程的文章描述了使.text.startup内容成为程序部分中出现的第一个代码体.text,作为使.text.startup代码首先运行的一种方法。

不幸的是,我没有找到太多其他东西来支持我的理论:

  • 当我 grep 字符串“.startup”的 LLVM 3.6 源代码时,我只能在 LLVM 代码的 CLang 特定部分中找到它。为了使我的理论正确,我希望在 LLVM 代码的其他部分也能找到该字符串;特别是 C++ 前端之外的部分。

  • 这篇关于C++ 中数据初始化的文章似乎暗示“.text.startup”有一个特殊的作用,但它并没有直接说 Linux 程序加载器实际上是在寻找该名称的一部分。即使是这样,我也会惊讶地发现一个可能特定于 Linux 的部分名称在平台中立的 LLVM IR 中具有特殊含义。

  • 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 回答