欢迎来到盹猫的博客本篇文章主要介绍了
[rbpf虚拟机-打包和代码执行]
❤博主广交技术好友,喜欢我的文章的可以关注一下❤
一、概述
该篇文章是记录rbpf虚拟机执行文件打包和执行的过程。
(学习该虚拟机的目的是为了搞懂solana合约的执行方式,solana使用的rbpf是在该虚拟机上进行扩展。)
二、依赖安装
2.1 clang安装
因为要对c代码进行编译,所以需要安装clang,它可以比较好的支持将c代码打包为.o文件,当然你也可以使用用其它语言的并配合不同的打包程序进行打包,这边使用c语言.对于不同的linux有不同的安装方法:
Centos安装
yum install clang
Deebin安装
apt install clang
安装完成后可以使用以下命令检查是否安装成功:
clang -v
2.2 安装linux-headers头文件
eBPF 程序通常需要与内核进行交互,因此需要使用内核提供的 BPF 接口和相关数据结构。这些接口和数据结构定义在内核头文件中。所以这里需要安装头文件,使用以下命令进行安装:
Centos安装
yum install kernel-headers
yum install kernel-devel
Deebin安装
apt install linux-headers
三、bpf打包
在打包时确保已经安装了上述的依赖文件,并使用以下命令进行打包:
clang -target bpf -c load_elf__block_a_port.c -o load_elf__block_a_port.o
-target
:打包的目标文件为bpf文件。
-c
: 要打包的c代码目标
-o
:打包后的文件名称。
运行后会在当前目录中生成load_elf__block_a_port.o
文件。若要查看其机器码可以使用以下命令查看其反汇编码:
llvm-objdump -d load_elf__block_a_port.o
这里需要用到llvm,使用以下命令安装:
yum install llvm
四、执行代码
4.1 文件加载
let filename = "examples/load_elf__block_a_port.o";
//获取文件路径
let path = PathBuf::from(filename);
println!("----------------------------------------------");
println!("path:{:?}", path);
//以elf文件的格式读取
let file = match elf::File::open_path(path) {
Ok(f) => f,
Err(e) => panic!("Error: {:?}", e),
};
println!("file:{:?}", file);
println!("----------------------------------------------");
//具体的方法块
let text_scn = match file.get_section(".classifier") {
Some(s) => s,
None => panic!("Failed to look up .classifier section"),
};
println!("text_scn:{:?}", text_scn);
let prog = &text_scn.data;
println!("----------------------------------------------");
rbpf虚拟机执行的是字节码,所以这里需要对文件进行读取,使用elf库可以将.o类型的bpf文件读取为json,上述代码中的file即为json格式。在未编译的c文件中,使用SEC进行标识section方法。
相关文档:elf文档
SEC(".classifier")
int handle_ingress(struct __sk_buff *skb)
所以上面通过file.get_section(".classifiler")
可以获取这个具体执行的方法。通过.data
获取方法的字节码。
4.2 运行
有了字节码数据,就可以通过vm.execute_program
方法对字节码程序进行执行。
具体执行可参考:rbpf虚拟机-JIT和解释执行
五、总结
因为solana合约执行的虚拟机是建立在rbpf虚拟机之上的,通过对rbpf虚拟机打包和代码执行,可以想到,solana的使用rust打包完成和部署的so文件,其本质和原理类似对.o文件的打包。其代码的执行原理,也类似于对字节码数据的执行。
代码来源:rbpf虚拟机
鸣谢: qmonnet 提供的开源代码.
当然,我也会将带有中文注释和自己理解的一些代码上传的我的github页面,感兴趣的朋友可以进行clone查看.
我的GitHub:forked