2017-03-02 18 views
2

私はLLVM IRで少し遊んでいますが、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_startldlliとの相互互換性のためです。上のコードは両方で同じように動作します。私は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 
} 

ldも期待されているprintfへの参照を知らないので、それはまたlliで動作しますが、私はそれldできません。私はそのコードを動作させるために、ldのパラメータを準備することもできますし、単にgcc file.o -o fileを使用することもできますが、これは私の問題ではありません。私のポイントは、lliに外部ライブラリ(libcなど)を含めずに自分のコードだけを実行し、独自のエントリポイントを定義する方法です。用意されたlibcや他のライブラリを自由に組み込むことができます。関数の名前を上書きして動作するはずですが、何が書き換えられたのか分からないので、printfが使われていても定義されていなければ、lliがエラーをスローすると私はうれしいでしょう。あるいは、私は何かが間違っているとlliそのような裸の環境では実行できません。

+1

私は 'lli -entry-function = _start file.ll 'を使ってエントリポイントを選択できます。しかし、プリロードされたコードのインタプリタを削除する方法はまだ分かりません。 '-extra-object = 'オプションがありますが、デフォルトでロードされるすべてのオブジェクトを無効にするオプションが見つかりません。 – mucka

答えて

2

TL; DR:JITなしlli使用し、おそらく動作します:

lli -force-interpreter main.bc 

さらに詳しい情報:一般的に

、それは(もしあればあなたはボンネットの下に使用してJITエンジンの種類によって異なります)。

私はそれに慣れていないですので、私はMCJIT(-jit-kind=mcjit)について話すことはできませんが、私はあなたがORC JIT(-jit-kind=orc-mcjitまたは-jit-kind=orc-lazy)を使用する場合はこれが不可能であることを保証することができます。ただし、これはORCを自分で使用する場合はlliにのみ該当し、この動作を制御できます。

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; 
} 
+0

残念ながら、私はすでに試してみましたが、おそらく問題は、正式なgitから新しく 'LLVM version 5.0.0svn'を使っていることでしょう。問題は、インタプリタがプリロードしたすべての関数にアクセスできるということです。とにかく、お返事ありがとう! – mucka

+0

私は 'mcjit-remote-process'を使ってより裸の環境を実現することができるのだろうか"標準的な "リモートプロセス' https://github.com/llvm-mirror/llvm/blob/master/tools/lli/ChildTarget/ChildTarget.cpp'は有望に見えません。 – mucka

+0

カスタムJITスタックをセットアップすることをお勧めします。非常に基本的なカスタムlliはかなり簡単で小さなものです。 [email protected]が必要な場合は、私にラインを落としてください。 – AlexDenisov

関連する問題