Compilation 编译后LLVM IR到可执行SEGFULTS

Compilation 编译后LLVM IR到可执行SEGFULTS,compilation,llvm,executable,llvm-ir,Compilation,Llvm,Executable,Llvm Ir,我目前正在为一种玩具语言编写编译器;这对我来说是一个新的领域。我使用的是 LLVM C++ API生成LLVM Ir >强>,从那里,一个对象.< /P> 问题是(我认为)链接对象并能够执行它 我有main.ll由我能想到的最低IR组成: define void @main() { ret void } 对于lli main.ll,它运行得很好,即它什么也不做 我使用:llc--filetype=obj-omain.{o,ll}将其编译为对象格式 并通过以下链接指向任何现有库:ld.

我目前正在为一种玩具语言编写编译器;这对我来说是一个新的领域。我使用的是<强> LLVM <强> C++ API生成LLVM <强> Ir >强>,从那里,一个对象.< /P> 问题是(我认为)链接对象并能够执行它


我有
main.ll
由我能想到的最低IR组成:

define void @main() {
  ret void
}
对于
lli main.ll
,它运行得很好,即它什么也不做

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

并通过以下链接指向任何现有库:
ld.lld-o main{,.o}

但是,生成的二进制文件立即出现故障。我接受了一些教程的建议,这些教程引导我尝试通过GCC链接,我被告知“[重新定位]在制作饼图对象时不能使用”,Wikipedia告诉我,这指的是结果二进制文件中的位置独立性

因此,我用:
llc--filetype=obj--relocation model=pic main.{o,ll}
重新编译对象,并用GCC重新编译,结果成功了,运行输出并没有达到预期效果

但是再次运行
ld.lld
命令并尝试再次运行该二进制文件会立即导致错误

因此,我的第一个问题是:对于这个简单的例子,在链接对象(假设链接正确)和二进制之间,我缺少了什么步骤?

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


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


任何帮助都将不胜感激。

对于任何发现此文件并试图将
.ll
文件转换为可执行文件的人:我发现C运行时库是缺少的。默认情况下,
gcc
clang
都包含了这些选项,但是
-v
选项并没有给我太多的支持

通过使用
PIC_quot/code>的under LLVM并将生成的对象与C运行时libs动态链接,我成功地使
.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--verbose-L/usr/lib-lc\
-动态链接器\
/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/crt.o\
\
-o\
/usr/lib/crtn.o
除了猜测之外,我不能百分之百确定这个问题的“原因”,但这是可行的,而且您的标准
ld-L-lc
没有


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

可执行文件的入口点不是
main
,而是
\u start
。有一个
\u start
的deafult实现,它将在crt内调用
main
(通常在crt0中)。因此,crt对象的添加为您提供了入口点,该入口点随后调用您的main。