编译后 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 库。 gcc
和 clang
默认包含这些,但是 -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>
行不通。
如果有人能提供说明,我很乐意接受他们的回答。
我目前正在为一种玩具语言编写编译器而苦恼;这对我来说是一个新领域。我正在使用 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 库。 gcc
和 clang
默认包含这些,但是 -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>
行不通。
如果有人能提供说明,我很乐意接受他们的回答。