bic : AC 통역사 및 API 탐색기이 프로젝트는 개발자가 Repl이라고도하는 Read Eval Print 루프를 사용하여 C-API를 탐색하고 테스트 할 수있는 프로젝트입니다.

BIC의 런타임 종속성은 다음과 같습니다.
BIC를 구축하려면 다음이 필요합니다.
BIC를 구축하기 전에 설치해야합니다. 다음 명령은 Debian/Ubuntu 시스템에 설치해야합니다.
APT-GET 설치 빌드 필수 LIBREADLINE-DEV AUTOCONF-ARCHIVE LIBGMP-DEV FEART FLEX BISON AUTOMAKE M4 LIBTOOL PKG-CONFIG
다음 명령을 사용하여 MacOS 시스템에서 Homebrew를 통해 필요한 종속성을 설치할 수도 있습니다.
BREW 설치 Bison Flex GMP Readline Autoconf-Ararkive
다음 명령으로 BIC를 컴파일하고 설치할 수 있습니다.
autoreconf -i ./configure-enable-debug 만들다 설치하십시오
MACOS 시스템을 구축하려면 구성 라인을 다음과 같이 변경해야합니다.
yacc = "$ (Brew -Prefix Bison)/bin/bison -y"./configure-enable-debug
Docker를 사용하여 다음 명령으로 BIC를 구축하고 실행할 수 있습니다.
Docker 빌드 -t bic https://github.com/hexagonal-sun/bic.git#master
이미지가 빌드되면 다음과 함께 BIC를 실행할 수 있습니다.
Docker Run -I Bic
Arch Linux를 사용하는 경우 AUR에서 BIC를 설치할 수 있습니다.
예 -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와의 대체에서이를 수행 할 수 있습니다.
bic> #include <stdio.h> bic> 파일 *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를 사용하여 이름을 A와 접두사하여 선언 한 변수 또는 유형에 대한 정보를 얻을 수 있습니까 ? . 이 특수 구문은 REPL에서만 작동하지만 유형 및 변수에 대한 다양한 특성을 얻을 수 있습니다. 예를 들어:
bic> #include <stdio.h> bic>? stdout stdout은 구조물 _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> 증분 (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 IS : 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] = 바 Argv [5] = a Argv [6] = b Argv [7] = c
특별한 표현을 사용할 수도 있습니다 : <REPL>; 소스 코드에서 BIC가 파일 평가의 특정 지점에서 당신을 대체에 떨어 뜨리게합니다.

BIC를 사용하여 LIBC 이외의 다른 라이브러리의 API를 탐색 할 수 있습니다. Capstone 라이브러리를 탐색하고 싶다고 가정 해 봅시다. 우리는 라이브러리가 시작될 때 BIC로드를 만들기 위해 -l 옵션을 통과한다고 가정 해 봅시다. 예를 들어:

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 호출 컨벤션에 따라 값을 올바른 레지스터로 이동시킨 다음 함수 주소로 분기하기 위해 어셈블리에 통과합니다.
Parser와 Lexer는 각각 parser.m4 및 lex.m4 에서 구현됩니다. M4를 통과 한 후 출력은 2 개의 들소 파서와 2 개의 플렉스 렉서입니다.
두 파서의 이유는 C REPL의 문법이 C 파일의 문법과 매우 다르기 때문입니다. 예를 들어, 우리는 사용자가 함수에 래핑 할 필요없이 Repl에 평가할 진술을 입력 할 수 있기를 원합니다. 불행히도 기능 본문 외부에있는 진술을 작성하는 것은 유효하지 않습니다. 따라서 우리는 사용자가 C 파일에 베어 진술을 쓸 수 있기를 원하지 않습니다. 이를 달성하기 위해 우리는 두 개의 다른 문법 규칙 세트가 있습니다. 대부분의 문법 규칙은 겹치므로 단일 M4 파일을 사용하여 차이를 처리합니다.