我想学习Linux ebpf虚拟机,如果我编写一个ebpf程序test.c,并使用llvm:
clang -O2 -target bpf -o test.o test.c。如何获得类似于经典bpf中tcpdump -d的ebpf汇编代码呢?谢谢。
我想学习Linux ebpf虚拟机,如果我编写一个ebpf程序test.c,并使用llvm:
clang -O2 -target bpf -o test.o test.c。如何获得类似于经典bpf中tcpdump -d的ebpf汇编代码呢?谢谢。
这取决于您对“学习Linux ebpf vm”确切的理解。
如果您是指学习eBPF指令,即类似汇编的语言本身,则可以查看内核文档(相当密集)或bcc项目中的此语法摘要。
linux/kernel/bpf
下(特别是文件core.c
)。另外,还提供了一个更简单的用户空间实现。
现在,如果您想查看从C编译到eBPF的代码,这里有几个解决方案。
对于我来说,我使用tc-bpf
手册中提供的命令进行编译:
__bcc() {
clang -O2 -emit-llvm -c $1 -o - | \
llc -march=bpf -filetype=obj -o "`basename $1 .c`.o"
}
alias bcc=__bcc
objdump
或readelf
等工具检查我的程序。例如,如果我的程序在classifier
部分中:$ bcc return_zero.c
$ readelf -x classifier return_zero.o
Hex dump of section 'classifier':
0x00000000 b7000000 02000000 95000000 00000000 ................
0x
开头的第一个字段是节内偏移量)。我们可以解析它们以整理指令并得到:b7 0 0 0000 00000002 // Load 0x02 in register r0
95 0 0 0000 00000000 // Exit and return value in r0
可以将内核中加载的程序指令转储出来(然后可能将其附加到可用的BPF挂钩之一),以eBPF汇编指令或者如果该程序已经 JIT 编译,则以机器指令的形式。 bpftool 是进行这种操作的首选工具,它依赖于 libbpf。例如,可以使用以下命令查看当前加载的程序,并注意它们的标识:
# bpftool prog show
然后,倾倒给定ID程序的指令就像这样简单:
# bpftool prog dump xlated id <id>
# bpftool prog dump jited id <id>
对于eBPF或JIT(如果可用)指令,可以分别输出。如果需要,输出也可以格式化为JSON。
根据您用于将BPF注入内核的工具,您通常可以转储内核验证器的输出,其中包含大多数以人类友好方式格式化的指令。
使用bcc工具集(与先前的命令没有直接关联,也与旧的16位编译器没有任何关系),您可以通过使用相关标志来获取BPF对象实例的此内容,而使用tc filter add dev eth0 bpf obj … verbose
则可以使用verbose
关键字完成此操作。
add32 r0,r1
等)指令作为输入并转换为目标文件,或者相反。llvm-objdump -S -no-show-raw-insn my_file.o
来获得漂亮格式的输出。clang -O2 -Wall -emit-llvm -c“$ @” -o -
| llc -march = bpf -filetype = obj -o“ $(basename“ $ 1” .c). o”
。请注意,$()
允许轻松嵌套双引号,与反引号相比。我在clang命令行中使用了“$ @”
,因此您可以传递foo.c -O3 -Wextra -mtune = native
或其他内容。嗯,我想一些优化/调整选项需要在llc
命令行上使用?所以也许是llc“ $ { @:2}”
来获取除$1之外的选项。 - Peter Cordesllvm-objdump -S
在编译时需要-g
标志)。无论如何,重点在于字节码转储而不是编译步骤。话虽如此,你的命令仍然有效,再次感谢。 - Qeolealias bcc=__bcc
。你可以重新定义已经定义的shell函数,所以改变函数内容不需要额外的间接层。(另外,我认为你没有理解关于其他bcc
的要点。它是一个旧项目,主要用于制作引导程序。16位x86机器代码比32位更过时,对于Linux内核来说是无用的,因为它运行在32或64位模式下!) - Peter Cordes
tcpdump
的输出是什么样子的小例子。我猜它可能类似于objdump -d
。 - Shift_Lefttcpdump -i any -d ip
(000) ldh [14] (001) jeq #0x800 jt 2 jf 3 (002) ret #65535 (003) ret #0 - Junli Outcpdump -d
命令会以旧的 BPF (也称为 _cBPF_)格式打印指令。提示:使用tcpdump -ddd
命令,每个显示的指令都有 4 个字段(eBPF 有 5 个字段)。 - Qeole