编译后LLVM IR到可执行分段故障



我目前正在为玩具语言编写编译器;这对我来说是一个新的领域。我正在使用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运行库。默认情况下,gccclang都包含这些选项,但遗憾的是,-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>则不然。

如果有人能澄清,我很乐意接受他们的回答。

最新更新