我目前正努力为玩具语言编写编译器;这对我来说是一个新领域。我正在使用 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对象时无法使用[[重定位]”,而Wikipedia告诉我这是指结果二进制文件中的位置独立性。 / p>
所以我用llc --filetype=obj --relocation-model=pic main.{o,ll}
重新编译为对象,并用GCC重新编译,并且它起作用了,运行输出并没有达到预期的效果。
但是再次运行ld.lld
命令并再次尝试运行该二进制文件,则会立即出现段错误。
所以,我的第一个问题是:在这个简单的示例中,链接对象(假设我正确链接)和二进制文件之间缺少什么步骤?
我是否缺少ld
标志,即使我没有特别使用某个标志,也缺少一些必需的库?
当我尝试链接到libc以在IR中使用printf
时,甚至还有GCC方法的更多问题,但我认为在攻击之前,我需要对这个简单的示例有更好的了解。
任何帮助将不胜感激。
答案 0 :(得分:0)
对于其他找到此文件并尝试将.ll
文件制成可执行文件的人:我发现C运行时库丢失了。 gcc
和clang
都默认包含这些选项,但是-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
除了猜测之外,我不确定该问题的“原因”是什么,但这种方法行之有效,而您的标准ld -L... -lc <object file>
并不可行。
如果有人可以提供说明,我会很乐意接受他们的回答。