bic :ACインタープレーターとAPIエクスプローラーこれは、開発者がREPLとしても知られる読み取り評価プリントループを使用してC-APIを探索およびテストできるようにするプロジェクトです。

BICの実行時間依存関係は次のとおりです。
BICを構築するには、次のことが必要です。
BICを構築する前に、これらをインストールしていることを確認してください。次のコマンドは、これらをDebian/ubuntuシステムにインストールする必要があります。
apt-get install build-essentiallibreadline-dev autoconf-archive libgmp-dev flex bison automake m4 libtool pkg-configを期待する
また、次のコマンドを使用して、MacOSシステムにHomeBrewを介して必要な依存関係をインストールすることもできます。
Brew Install Bison Flex GMP Readline Autoconf-Archive
次のコマンドでBICをコンパイルしてインストールできます。
Autoreconf -i ./CONFIGURE -ENABLE DEBUG 作る インストールします
MacOSシステムに基づいて構築するには、構成行を次のように変更する必要があります。
yacc = "$(brew -prefix bison)/bin/bison -y" ./configure - enable -debug
Dockerを使用して、次のコマンドでBICを構築および実行できます。
docker build -t bic https://github.com/hexagonal-sun/bic.git#master
画像がビルドされたら、次のようにBICを実行できます。
docker run -i bic
Arch Linuxを使用している場合は、AURからBICをインストールできます。
yay -s bic
引数なしでBICを呼び出すと、ユーザーにはREPLプロンプトが表示されます。
bic>
ここでは、Cステートメントを入力して#includeさまざまなシステムヘッダーを使用して、システム上のさまざまなAPIへのアクセスを提供できます。ステートメントは、REPLに直接入力できます。それらが評価される機能を定義する必要はありません。次のCプログラムを実行したいとします。
#include <stdio.h>
int main ()
{
FILE * f = fopen ( "out.txt" , "w" );
fputs ( "Hello, world!n" , f );
return 0 ;
}次のコマンドを使用して、BICでREPLでこれを行うことができます。
bic> #include <stdio.h> bic> file *f; f bic> f = fopen( "test.txt"、 "w"); bic> fputs( "hello、world! n"、f); 1 bic>
これにより、BICはc-library fopen()およびfputs()関数に呼び出され、ファイルを作成し、Hello World文字列を書き込みます。 BIC Hello, Worldn終了する場合は、現在の作業ディレクトリにファイルtest.txtが表示されます。
式を評価した後、BICが評価の結果を印刷することに注意してください。これは、簡単な表現をテストするのに役立ちます。
bic> 2 * 8 + fileno(f); 19
BICを使用して、名前を付けて宣言された変数またはタイプに関する情報を取得できますか? 。この特別な構文は、REPLでのみ機能しますが、タイプと変数に関するさまざまな特性を取得できます。例えば:
bic> #include <stdio.h> bic>?stdout stdoutは、struct _io_fileへのポインターです。 stdoutの値は0x7ff1325bc5c0です。 sizeof(stdout)= 8バイト。 stdoutは:/usr/include/stdio.h:138で宣言されました。
REPLが起動すると、BICは~/.bicが存在するかどうかを確認します。それが行われた場合、それは自動的に評価され、結果の環境はREPLによって使用されます。これは、一般的に使用される機能または変数を定義するのに役立ちます。たとえば、 ~/.bicファイルが含まれているとします。
#include <stdio.h>
int increment ( int a )
{
return a + 1 ;
}
puts ( "Good morning, Dave." );REPLを起動すると、
$ bic おはようございます、デイブ。 bic> increment(2); 3
BICをソースファイルとともに-sとともに渡すと、コマンドラインの引数として、 main()関数を呼び出すことにより評価します。たとえば、以下を含むファイルtest.cがあるとします。
#include <stdio.h>
int factorial ( int n )
{
if (! n )
{
return 1 ;
}
return n * factorial ( n - 1 );
}
int main ()
{
printf ( "Factorial of 4 is: %dn" , factorial ( 4 ));
return 0 ;
}その後、 -s test.cでBICを呼び出して評価できます。
$ bic -s test.c 4の要因:24
引数をCファイルに渡す場合は、BICのコマンドラインに追加します。 BICが-s引数を処理すると、他のすべての引数は、プログラムに渡すパラメーターとして扱われます。これらのパラメーターは、 argcおよびargv変数として作成され、 main()に渡されます。 argv[0]の値は、BICが実行しているCファイルの名前です。次のCプログラムを検討してください。
#include <stdio.h>
int main ( int argc , char * argv [])
{
for ( int i = 0 ; i < argc ; i ++ )
printf ( "argv[%d] = %sn" , i , argv [ i ]);
return 0 ;
}引数に合格しない場合:
$ bic -s test.c argv [0] = test.c
一方、より多くの議論でBICを呼び出すと、それらはプログラムに渡されます。
$ bic -s test.c -a foo -s bar abc argv [0] = test.c argv [1] = -a argv [2] = foo argv [3] = -s argv [4] = bar argv [5] = a argv [6] = b argv [7] = c
特別な式を使用することもできます: <REPL>;ソースコードでは、ファイル評価の特定のポイントでBICをREPLに落とすようにします。

BICを使用して、LIBC以外の他のライブラリのAPIを探索できます。 Capstoneライブラリを探索したい場合は、 -lオプションを渡して、BICロードが開始されたときにそのライブラリを搭載します。例えば:

BICが複合データ型( structまたはunion )を印刷すると、すべてのメンバー名と対応する値が表示されることに注意してください。
BICの実装の中心には、 treeオブジェクトがあります。これらは、プログラム全体と現在の評価者状態を表すために使用できる一般的なオブジェクトです。 tree.hおよびtree.cに実装されています。各ツリータイプはc.langで定義されています。 c.langファイルは、次のようなLISPのような仕様です。
T_ADD 。Additionなどの人間の読み取り可能な名前。tADDなどのプロパティ名のプレフィックス。LHSやRHSなどのこのタイプのプロパティのリスト。上記の属性セットを持つオブジェクトを作成するコードは次のとおりです。
( deftype T_ADD " Addition " " tADD "
( " LHS " " RHS " ))定義されたら、次の方法でこのオブジェクトをCコードで使用できます。
tree make_increment ( tree number )
{
tree add = tree_make ( T_ADD );
tADD_LHS ( add ) = number ;
tADD_RHS ( add ) = tree_make_const_int ( 1 );
return add ;
}アクセサのマクロ、 tADD_LHS() 、およびtADD_RHS()のセットが、さまざまなプロパティスロットにアクセスするために生成されていることに注意してください。コンピレーション中に--enable-debugが設定された場合、これらのマクロのそれぞれがチェックに拡張され、オブジェクトのtADD_LHSプロパティを設定するときにオブジェクトが実際にT_ADDのインスタンスであることを確認します。
c.langファイルは、コードスニペットを生成する多数のソースからソース間コンパイラによって読み取られます。これらのユーティリティには次のものが含まれます。
gentype :ツリーオブジェクトタイプのリストを生成します。gentree :ツリーオブジェクトのすべてのプロパティデータを含む構造を生成します。genctypes :Cタイプのツリーオブジェクトのリストを生成します - これらはCの基本的なデータ型を表します。genaccess :ツリーオブジェクトのプロパティのアクセサーマクロを生成します。gengc :各ツリーオブジェクトのマーク関数を生成すると、ガベージコレクターがオブジェクトツリーを通過できます。gendump :ツリーオブジェクトを再帰的に捨てるコードを生成します。gendot :特定のtree階層のドットファイルを生成し、視覚化します。Lexer&Parserの出力は、 treeオブジェクト階層であり、その後、評価者( evaluator.c )に渡されます。評価者は、各ツリー要素を再帰的に評価し、内部評価者状態を更新し、それによりプログラムを実行します。
評価者の外部の関数への呼び出しは、プラットフォーム依存的に処理されます。現在、X86_64とAARCH64はサポートされている唯一のプラットフォームであり、これを処理するコードはそれぞれx86_64およびaarch64フォルダーにあります。これは、評価されたすべての引数を評価し、それらを単純なリンクリストにマーシャル化して、評価者から関数コールtreeオブジェクト( T_FN_CALLで表される)を取得することで機能します。これは、アセンブリで移動して、X86_64またはAARCH64呼び出しventionsに従って値を正しいレジスタに移動し、関数アドレスに分岐します。
パーサーとレクサーは、それぞれparser.m4とlex.m4に実装されています。 M4を通過した後、出力は2つのバイソンパーサーと2つのフレックスレキサーです。
2つのパーサーの理由は、C REPLの文法がCファイルの文法とは大きく異なるためです。たとえば、ユーザーが、関数にラッピングする必要なく、REPLでステートメントを入力できるようにしたいと考えています。残念ながら、関数本文の外側にあるステートメントを書くCが有効ではありません。そのため、ユーザーがCファイルに素朴なステートメントを記述できるようにしたくありません。これを達成するために、2つの異なる文法ルールがあり、2つのパーサーを生成します。文法ルールのほとんどは重複しているため、違いを処理するために単一のM4ファイルを使用します。