当前位置: 首页 > 软件库 > 开发工具 > 编译器 >

bic

A C interpreter and API explorer.
授权协议 GPL-2.0 License
开发语言 C/C++
所属分类 开发工具、 编译器
软件类型 开源软件
地区 不详
投 递 者 沙岳
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

bic: A C interpreter and API explorer

This a project that allows developers to explore and test C-APIs using a read eval print loop, also known as a REPL.

Dependencies

BIC’s run-time dependencies are as follows:

To build BIC, you’ll need:

Please ensure you have these installed before building bic. The following command should install these on a Debian/Ubuntu system:

apt-get install build-essential libreadline-dev autoconf-archive libgmp-dev expect flex bison automake m4 libtool pkg-config

You can also use the following command to install the required dependencies via Homebrew on a MacOS system.

brew install bison flex gmp readline autoconf-archive

Installation

You can compile and install bic with the following commands:

autoreconf -i
./configure --enable-debug
make
make install

For building on a MacOS system, you need to change the configure line to:

YACC="$(brew --prefix bison)/bin/bison -y" ./configure --enable-debug

Docker

You can use docker to build and run bic with the following command:

docker build -t bic https://github.com/hexagonal-sun/bic.git#master

Once the image is build you can then run bic with:

docker run -i bic

Arch Linux

If you are using Arch Linux, you can install bic from AUR:

yay -S bic

Usage

REPL

When invoking bic with no arguments the user is presented with a REPL prompt:

BIC>

Here you can type C statements and #include various system headers to provide access to different APIs on the system. Statements can be entered directly into the REPL; there is no need to define a function for them to be evaluated. Say we wish to execute the following C program:

#include <stdio.h>

int main()
{
    FILE *f = fopen("out.txt", "w");
    fputs("Hello, world!\n", f);
    return 0;
}

We can do this on the REPL with BIC using the following commands:

BIC> #include <stdio.h>
BIC> FILE *f;
f
BIC> f = fopen("test.txt", "w");
BIC> fputs("Hello, World!\n", f);
1
BIC>

This will cause bic to call out to the C-library fopen() and fputs() functions to create a file and write the hello world string into it. If you now exit bic, you should see a file test.txt in the current working directory with the string Hello, World\n contained within it.

Notice that after evaluating an expression bic will print the result of evaluation. This can be useful for testing out simple expressions:

BIC> 2 * 8 + fileno(f);
19

The Inspector

You can use bic to obtain information about any variable or type that has been declared by prefixing it’s name with a ?. This special syntax only works in the REPL but will allow you to obtain various characteristics about types and variables. For example:

BIC> #include <stdio.h>
BIC> ?stdout
stdout is a pointer to a struct _IO_FILE.
value of stdout is 0x7ff1325bc5c0.
sizeof(stdout) = 8 bytes.
stdout was declared at: /usr/include/stdio.h:138.

Startup Files

When the REPL starts, bic will see if ~/.bic exists. If it does it is automatically evaluated and the resulting enviroment is used by the REPL. This can be useful for defining functions or varibles that are commonly used. For instance, say our ~/.bic file contains:

#include <stdio.h>

int increment(int a)
{
    return a + 1;
}

puts("Good morning, Dave.");

When we launch the REPL we get:

$ bic
Good morning, Dave.
BIC> increment(2);
3

Evaluating Files

If you pass bic a source file, along with -s, as a command line argument it will evaluate it, by calling a main() function. For example, suppose we have the file test.c that contains the following:

#include <stdio.h>

int factorial(int n)
{
  if (!n)
  {
    return 1;
  }

  return n * factorial(n - 1);
}

int main()
{
  printf("Factorial of 4 is: %d\n", factorial(4));

  return 0;
}

We can then invoke bic with -s test.c to evaluate it:

$ bic -s test.c
Factorial of 4 is: 24

Passing Arguments

If you wish to pass arguments to a C file, append them to bic’s command line. Once bic has processed the -s argument all other arguments are treated as parameters to be passed to the program. These parameters are created as argc and argv variables and passed to main(). The value of argv[0] is the name of the C file that bic is executing. Consider the following C program:

#include <stdio.h>

int main(int argc, char *argv[])
{
    for (int i = 0; i < argc; i++)
        printf("argv[%d] = %s\n", i, argv[i]);

    return 0;
}

If we don’t pass any arguments:

$ bic -s test.c
argv[0] = test.c

Whereas if we invoke bic with more arguments, they are passed to the program:

$ bic -s test.c -a foo -s bar a b c
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

Dropping Into a REPL

You can also use a special expression: <REPL>; in your source code to make bic drop you into the repl at a particular point in the file evaluation:

Exploring external libraries with the REPL

You can use bic to explore the APIs of other libraries other than libc. Let’s suppose we wish to explore the Capstone library, we pass in a -l option to make bic load that library when it starts. For example:

Notice that when bic prints a compound data type (a struct or a union), it shows all member names and their corresponding values.

Implementation Overview

Tree Objects

At the heart of bic’s implementation is the tree object. These are generic objects that can be used to represent an entire program as well as the current evaluator state. It is implemented in tree.h and tree.c. Each tree type is defined in c.lang. The c.lang file is a lisp-like specification of:

  • Object name, for example T_ADD.
  • A human readable name, such as Addition.
  • A property name prefix, such as tADD.
  • A list of properties for this type, such as LHS and RHS.

The code to create an object with the above set of attributes would be:

(deftype T_ADD "Addition" "tADD"
         ("LHS" "RHS"))

Once defined, we can use this object in our C code in the following way:

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

Notice that a set of accessor macros, tADD_LHS() and tADD_RHS(), have been generated for us to access the different property slots. When --enable-debug is set during compilation each one of these macros expands to a check to ensure that when setting the tADD_LHS property of an object that the object is indeed an instance of a T_ADD.

The c.lang file is read by numerous source-to-source compilers that generate code snippets. These utilities include:

  • gentype: Generates a list of tree object types.
  • gentree: Generates a structure that contains all the property data for tree objects.
  • genctypes: Generates a list of C-Type tree objects - these represent the fundamental data types in C.
  • genaccess: Generate accessor macros for tree object properties.
  • gengc: Generate a mark function for each tree object, this allows the garbage collector to traverse object trees.
  • gendump: Generate code to dump out tree objects recursively.
  • gendot: Generate a dot file for a given tree hierarchy, allowing it to be visualised.

Evaluator

The output of the lexer & parser is a tree object hierarchy which is then passed into the evaluator (evaluator.c). The evaluator will then recursively evaluate each tree element, updating internal evaluator state, thereby executing a program.

Calls to functions external to the evaluator are handled in a platform-dependent way. Currently x86_64 and aarch64 are the only supported platforms and the code to handle this is in the x86_64 and aarch64 folders respectively. This works by taking a function call tree object (represented by a T_FN_CALL) from the evaluator with all arguments evaluated and marshalling them into a simple linked-list. This is then traversed in assembly to move the value into the correct register according to the x86_64 or aarch64 calling-conventions and then branching to the function address.

Parser & Lexer

The parser and lexer are implemented in parser.m4 and lex.m4 respectively. After passing through M4 the output is two bison parsers and two flex lexers.

The reason for two parsers is that the grammar for a C REPL is very different than that of a C file. For example, we want the user to be able to type in statements to be evaluated on the REPL without the need for wrapping them in a function. Unfortunately writing a statement that is outside a function body isn’t valid C. As such, we don’t want the user to be able to write bare statements in a C file. To achieve this we have two different set of grammar rules which produces two parsers. Most of the grammar rules do overlap and therefore we use a single M4 file to take care of the differences.

  • 以下内容源于网络资源的整理,如有其侵权请告知删除。 1、bic 位清除指令(Bit Clear) 指令格式 bic{条件}{S}  Rd,Rn,operand 指令说明 将 Rn 的值与操作数 operand 的反码按位逻辑”与”,结果存放到目的寄存器Rd 中(?) (对于上面这个描述我是存在疑问的。根据实际代码的效果,操作数operand的哪位为1,则Rn对应的位将清除。我不清楚这里的清除是不是

  • 1.简介 信息准则(information criterion):经常地,对一堆数据进行建模的时候,特别是分类和回归模型,我们有很多的变量可供使用,选择不同的变量组合可以得到不同的模型,例如我们有5个变量,2的5次方,我们将有32个变量组合,可以训练出32个模型。但是哪个模型更加的好呢?就用信息准则来衡量。 下面介绍四种信息准则方法:AIC、BIC、FPE、LILC。 信息准则有两部分组成,一部分

  • BIC算法 当发生丢包的时候,当前窗口为W-max, 减小窗口后的大小为W, BIC算法就是根据这个原理在(W, W-max]区间内做二分搜索 当接近于W-max时曲线应该更平滑,当离W-max较远的时候,曲线可以更加陡峭 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32st

  • 在回归分析中, 解释变量的个数应当是越少越好, 因为模型越简洁应用范围越广, 也越容易被理解。但是, 为了模型拟合好, 我们又期望模型越复杂越好, 解释变量越多, 模型的拟合优度$R^2$ 数据介绍 使用上一篇教程用过的数据: icecream.dta, 具体内容可以参看上篇文章: stata教程05-自相关的检验和处理/ 1use data/icecream.dta, clear 进行回归分析1

  • 一文帮你理解【模型选择方法】:AIC、BIC 和交叉验证! 本文先讲透模型选择的基本思想,再逐一叙述几种比较典型和常用的模型选择方法,希望可以帮助你理解。 一、模型选择的基本思想 模型选择的核心思想就是从某个模型中选择最佳模型。模型选择主要用于解决过拟合现象。 它与一般的“调参”不一样,调参很多时候可能是针对优化算法中的某些参数进行调整,比如步长(学习速率)、迭代次数等,也会涉及到模型中调整参数(

  • BIC工具就是为解决这一反馈问题的工具。B代表Behavior(行为),I代Impact(影响),C代表Consequence(后果)。 B:谈及对方行为的时候,要说事实而不是说观点。比如员工经常迟到,找对方谈话,不能说“你又迟到了吧”,而应该说“九点上班,你是九点十分才到吧”,这样就可以避免预设对方是不负责任的员工,构建谈话的基础,让对方更容易听进去。 I:这部分需要谈及影响,这种影响是短期的、

  • 一、模型选择之AIC和BIC 人们提出许多信息准则,通过加入模型复杂度的惩罚项来避免过拟合问题,此处我们介绍一下常用的两个模型选择方法 赤池信息准则(Akaike Information Criterion,AIC)和贝叶斯信息准则(Bayesian Information Criterion,BIC) AIC是衡量统计模型拟合优良性的一种标准,由日本统计学家赤池弘次在1974年提出 它建立在熵的

  • ARIMA模型,用BIC矩阵确定p、q参数的时候BIC矩阵输出全是None 最近学习时间序列,学习到ARIMA模型时,采用了前人的教程(在此感谢),但在新的版本上运行出现错误。 Python == 3.9 statsmodels == 0.13.2 具体代码如下: # 定阶 df['销量'] = df['销量'].astype(float) # 转换为float类型 pmax = int(len

相关阅读

相关文章

相关问答

相关文档