【问题标题】:LLVM IR to Executable Segfaults after Compilation编译后 LLVM IR 到可执行段错误
【发布时间】:2020-10-22 21:37:34
【问题描述】:

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

问题在于(我认为)链接对象并能够执行它。


main.ll 包含了我能想到的最低限度的 IR:

define void @main() {
  ret void
}

lli main.ll 运行得很好,即它什么也不做。

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

并且链接到不存在的库:ld.lld -o main{,.o}

但是生成的二进制文件会立即出现段错误。我接受了一些教程的建议,这些教程引导我尝试通过 GCC 进行链接,我被告知“在制作 PIE 对象时不能使用 [Relocations]”,维基百科告诉我这是指生成的二进制文件中的位置独立性。

所以我重新编译为对象:llc --filetype=obj --relocation-model=pic main.{o,ll} 并使用 GCC 重新编译,它运行正常,运行输出没有按预期执行。

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

所以,我遇到的第一个问题是:对于这个简单的示例,我在链接对象(假设我链接正确)和二进制文件之间缺少什么步骤?

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


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

任何帮助将不胜感激。

【问题讨论】:

    标签: compilation llvm executable llvm-ir


    【解决方案1】:

    对于发现此问题并试图将.ll 文件转换为可执行文件的其他人:我发现缺少 C 运行时库。默认情况下,gccclang 都包含这些内容,但可悲的是,-v 选项并没有给我太多帮助......

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

    一个示例命令(显然是特定于操作系统的)是:

    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 &lt;object file&gt; 则无效。

    如果有人可以提供澄清,我很乐意接受他们的回答。

    【讨论】:

    • 可执行文件的入口点不是main,而是_start_start 的默认实现将在 crt 内(通常在 crt0 中)调用 main。因此,crt 对象的添加包含了您的入口点,然后调用您的 main.
    猜你喜欢
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-15
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多