LLVM解释器在哪里寻找外部函数(库?)

时间:2017-03-02 19:43:31

标签: assembly llvm system-calls llvm-ir

我正在使用LLVM IR,我无法解决(在google和doc的帮助下)LLVM解释器lli正在寻找外部(不是明确定义的函数。我的意思是基本的系统功能)。例如,如果我想编写没有依赖项的简单程序,在linux上将在屏幕上写一些内容我可以做类似的事情:

@message = private constant [12 x i8] c"hello world\0A"
define i32 @puts(i8* %s) {
    call i32 asm sideeffect "movl $$0x2, %edi\0Amovl $$0xC, %edx\0Amovl$$1, %eax\0Asyscall\0A", "=A,{si}"(i8* %s) #1
    ret i32 %1
}
define void @exit(i32 %c) {
    call i32 asm sideeffect "movl $$60, %eax\0Asyscall\0A", "=A,{di}"(i32 %c) #1
    ret void
}
define void @main() {
    getelementptr [12 x i8], [12 x i8]* @message, i64 0, i64 0
    call i32 @puts(i8* %1)
    call void @exit(i32 0)
    ret void
}
define void @_start() {
    call void @main()
    ret void
}

main_startldlli具有交叉兼容性。所以上面的代码在两者中都一样。我可以lli这个,代码将从mainllc然后ld开始,它也会起作用,因此代码将从_start开始预期。现在,如果我写代码:

@formatString = private constant [4 x i8] c"%d\0A\00" 
declare i32 @printf(i8*, ...)
define i32 @main() {
    %d = shl i32 2, 3
    %s = getelementptr [4 x i8], [4 x i8]* @formatString, i64 0, i64 0
    %call = call i32 (i8*, ...) @printf(i8* %s, i32 %d)
    ret i32 0
}

它也适用于lli,但我不能ld因为ld不知道对printf的引用,这也是预期的。我可以包含准备ld参数以使代码也能正常工作,或者只使用gcc file.o -o file,但这不是我的观点。我的观点是如何使lli不包含任何外部库(如libc),只运行我的代码,并可能定义我自己的入口点,所以我可以包含任何准备好的libc或任何其他库随意,我知道我可以覆盖函数的名称,这应该有效,但是我不能确定什么是重写的,所以如果使用lli printf lli会引发错误,我会很高兴没有定义的。或许我弄错了,adapter.notifyDataSetChanged()无法在这样的裸露环境中执行。

1 个答案:

答案 0 :(得分:2)

TL; DR:在没有JIT的情况下使用lli并且可能会起作用:

lli -force-interpreter main.bc

更多信息:

通常,它取决于你在引擎盖下使用的JIT引擎的类型(如果有的话)。

我不能谈论MCJIT(-jit-kind=mcjit)因为我不熟悉它,但我可以向你保证,如果你使用ORC JIT(-jit-kind=orc-mcjit或{{1},这是不可能的。 }})。但是,这仅适用于-jit-kind=orc-lazy,如果您决定自己使用ORC,则可以控制此行为。

lli ORC的上下文中,ORC不仅会加载模块/外部对象,还会加载整个程序的地址空间。这意味着您将获得所有libc和整个LLVM本身。

根据您的需要,您可能会尝试将lli真正用作解释器,但由于不再涉及JIT,因此速度会慢一些。

只需添加lli选项,除了少数例外情况,您将会很高兴。这些功能仍将正常执行:

-force-interpreter