我目前正在为玩具语言编写编译器;这对我来说是一个新的领域。我正在使用LLVMC++API生成LLVMIR,并从中生成一个对象。
问题来了(我认为(链接对象和能够执行它
我有main.ll
,由我能想到的绝对最小IR组成:
define void @main() {
ret void
}
这与lli main.ll
运行得很好,即它什么都不做。
我用:llc --filetype=obj -o main.{o,ll}
把它编译成对象格式。
并链接到没有现有库:ld.lld -o main{,.o}
但是生成的二进制文件立即segfoots。我接受了一些教程的建议,这些教程使我尝试通过GCC进行链接,我被告知";在制作PIE对象"时不能使用[重新定位];维基百科告诉我的是在结果二进制中的位置独立性。
因此,我用:llc --filetype=obj --relocation-model=pic main.{o,ll}
重新编译了对象,并用GCC重新编译了它,它起到了作用,运行输出并没有起到预期的作用。
但是,再次运行ld.lld
命令并尝试再次运行该二进制文件,会立即segfault。
所以,我的第一个问题是:对于这个简单的例子,在链接对象(假设我链接正确(和二进制之间,我缺少了什么步骤
是否有我缺少的ld
标志,一些必需的库,即使我没有特别使用任何一个?
当我试图链接到libc以在IR中使用printf
时,即使GCC方法也会出现更多问题,但我认为在攻击它之前,我需要更好地理解这个简单的例子。
如有任何帮助,我们将不胜感激。
对于其他发现并试图将.ll
文件制作成可执行文件的人来说:我发现缺少了C运行库。默认情况下,gcc
和clang
都包含这些选项,但遗憾的是,-v
选项并没有给我太多内容。。。
使用PIC_
的LLVM下的重定位模型,并将生成的对象与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>
则不然。
如果有人能澄清,我很乐意接受他们的回答。