LLVM解释器在寻找外部函数(库?)
我正在玩LLVM IR,并且我无法解决(在google和doc的帮助下)LLVM解释器lli
正在寻找外部函数(没有明确定义的函数。意味着基本的系统功能)。例如,如果我想写出没有依赖简单的程序,在Linux上,这将写在屏幕上的东西,我可以做这样的事情:LLVM解释器在寻找外部函数(库?)
@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
和_start
是与ld
和lli
交叉兼容性。所以上面的代码在两者中都是一样的我可以lli
这个,并且代码将从main
或llc
然后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
无法在这样的环境中执行。
TL; DR:使用lli
没有JIT的也许可以工作:
lli -force-interpreter main.bc
更多信息:
一般而言,这取决于一个类型,你罩下使用JIT引擎(如果有的话)。
我不能约MCJIT(-jit-kind=mcjit
)说话,因为我不熟悉,但我可以向你保证,如果你使用ORC JIT(-jit-kind=orc-mcjit
或-jit-kind=orc-lazy
),这是不可能的。但是,这仅适用于lli
,如果您决定自行使用ORC,则可以控制此行为。
在lli
的背景下,ORC不仅加载你的模块/外部对象,而且加载整个程序的地址空间。这意味着你得到了所有的libc和整个LLVM本身。
根据您的需要,您可能会尝试使用lli
作为解释器,但由于不再涉及JIT,因此速度会更慢。
只需添加-force-interpreter
选项,除非少数例外,您将很乐意继续。这些功能仍然会正常执行:
void Interpreter::initializeExternalFunctions() {
sys::ScopedLock Writer(*FunctionsLock);
(*FuncNames)["lle_X_atexit"] = lle_X_atexit;
(*FuncNames)["lle_X_exit"] = lle_X_exit;
(*FuncNames)["lle_X_abort"] = lle_X_abort;
(*FuncNames)["lle_X_printf"] = lle_X_printf;
(*FuncNames)["lle_X_sprintf"] = lle_X_sprintf;
(*FuncNames)["lle_X_sscanf"] = lle_X_sscanf;
(*FuncNames)["lle_X_scanf"] = lle_X_scanf;
(*FuncNames)["lle_X_fprintf"] = lle_X_fprintf;
(*FuncNames)["lle_X_memset"] = lle_X_memset;
(*FuncNames)["lle_X_memcpy"] = lle_X_memcpy;
}
不幸的是,我已经尝试过了,也许问题是我正在使用官方git新鲜的'LLVM version 5.0.0svn'。我担心问题是我可以访问解释器为itselt预装的所有功能。无论如何,谢谢你的回答! – mucka
我想知道如果我可以使用'mcjit-remote-process'来实现更多的裸机环境,但是“标准的”远程进程'https://github.com/llvm-mirror/llvm/blob/master/tools/lli/ChildTarget/ChildTarget.cpp'看起来不太有希望。 – mucka
我会建议设置您的自定义JIT堆栈。非常基本的自定义lli是相当容易和小。如果您需要帮助[email protected],请随时联系我 – AlexDenisov
我发现'lli -entry-function = _start file.ll'可以选择任何入口点。但仍不知道如何去除预装代码的解释器。有选项'-extra-object =