编译后 LLVM IR 到可执行段错误

LLVM IR to Executable Segfaults after Compilation

我目前正在为一种玩具语言编写编译器而苦恼;这对我来说是一个新领域。我正在使用 LLVM C++ API 生成 LLVM IR 并从那里生成一个对象。

问题出在(我认为)link对象并能够执行它。


我有 main.ll 由我能想到的最小 IR 组成:

define void @main() {
  ret void
}

这个 运行 与 lli main.ll 没问题,即它什么都不做。

我将其编译为对象格式:llc --filetype=obj -o main.{o,ll}

和 link 没有现有的图书馆:ld.lld -o main{,.o}

然而生成的二进制文件立即出现段错误。我听取了一些教程的建议,这导致我尝试通过 GCC link 并且我被告知“制作 PIE 对象时不能使用 [Relocations]”,维基百科告诉我它指的是位置独立性生成的二进制文件。

所以我重新编译以反对:llc --filetype=obj --relocation-model=pic main.{o,ll} 并使用 GCC 重新编译并且它起作用了,运行 输出没有像预期的那样。

但是 运行再次执行 ld.lld 命令并尝试 运行 该二进制文件,再次立即出现段错误。

所以,我遇到的第一个问题是:我在 linked-object(假设我 linking 正确)和二进制文件之间缺少什么步骤简单的例子?

是否缺少 ld 标记,一些必需的库,即使我没有特别使用任何库?


当我尝试 link 反对 libc 以在 IR 中使用 printf 时,即使使用 GCC 方法也会出现更多问题,但我认为我需要更好地理解这个简单示例在攻击之前。

如有任何帮助,我们将不胜感激。

对于发现此问题并试图将 .ll 文件制作成可执行文件的任何其他人:我发现缺少 C 运行time 库。 gccclang 默认包含这些,但是 -v 选项并没有给我太多可悲的事情......

使用 PIC_ 的 LLVM 下的 relocation model 并将生成的对象与 C 运行time 库动态链接,我设法获得了 .ll 文件定期 运行。

一个示例命令(显然 OS 具体)是:

ld --verbose -L/usr/lib -lc \
  -dynamic-linker \
  /lib64/ld-linux-x86-64.so.2 \
  /usr/lib/Scrt1.o \
  /usr/lib/crti.o \
  /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/crtbeginS.o \
  /usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/crtendS.o  \
  <object file> \
  -o <binary> \
  /usr/lib/crtn.o

除了猜测之外,我不是 100% 确定这件事的“原因”,但这行得通,而您的标准 ld -L... -lc <object file> 行不通。

如果有人能提供说明,我很乐意接受他们的回答。