记一次ebpf的for循环问题
记一次ebpf的for循环问题
起因
一段BCC开发的uprobe代码中包含一个for循环,在redhat 4.18上可以运行,在redhat 3.10上无法正常运行。
在kernel verifier部分检测出存在for循环。
Code:
1 |
|
1 |
|
原因分析
为什么在4.18上可以运行,但在3.10上无法运行?
高版本kernel中允许ebpf代码中存在有限for循环,而3.10中不允许任何循环的存在
该如何解决3.10无法运行问题?
让for循环在编译阶段展开
尝试使用 #pragma unroll
以及 ebpf::BPF init
添加 编译参数-funroll-loops
均未解决问题
尝试从BCC中获取更多的信息,debug模式重编BCC并安装 (非源码安装可以直接安装debug-info)
再次运行包含for循环的代码,发现报错如下:
1 |
|
无论是通过添加伪编译指令 #pragma unroll
以及 增加编译参数 -funroll-loops
实际上并没有展开循环.
实际上,上述两种方式均是建议clang编译器进行编译优化展开循环,但由于展开后的字节码大小过大,编译器拒绝了我的展开建议.
解决方案
使用#pragma unroll(16)
指定clang展开for循环的次数
建议
- for循环在编译阶段就要确定是有限for循环
- 循环体内代码尽量精简(避免声明局部变量等),减少单次循环的指令数量
记一次ebpf的for循环问题
https://zongjiangu.github.io/2023/03/13/记一次ebpf的for循环问题/