libbpf-bootstrap安卓aarch64適配交叉編譯
1.為什么移植
疑惑
起初我也認為,像libbpf-bootstrap
這樣在ebpf程序開發(fā)中很常用的框架,理應(yīng)支持不同架構(gòu)的交叉編譯。尤其是向內(nèi)核態(tài)的ebpf程序本身就是直接通過clang的-target btf
直接生成字節(jié)碼,各個內(nèi)核上的ebpf虛擬機大同小異,對于字節(jié)碼大概率是兼容的。那么問題就落在用戶態(tài)程序生成上面。
加載器
由于libbpf-bootstrap
框架使用bpftools將xxx.bpf.c
生成為xxx.skel.h
再注入到用戶態(tài)xx.c
程序當中,因此,用戶態(tài)程序本身就是字節(jié)碼的加載器?;诎沧康膃bpf開發(fā)也有不少前輩探索過,如下圖

圖源:eBPF on Android之stackplz從0到1 - SeeFlowerX?ps:強推他的安卓package用戶態(tài)程序堆棧追蹤工具,我的不少靈感也來自于他的開發(fā)過程,在此謝過SeeFlowerX前輩了。
最終他選擇的解決方案是golang的ebpf生態(tài),交叉編譯相當方便。但我面臨的是性能的需要,我還是打算折騰一下純C的開發(fā)生態(tài),但是AOSP又實在太過龐大,且面臨API變動會使我們很頭疼。
2.使用方法

準備
Android NDK
gcc-aarch64-linux-gnu
Android phone with root and unlock BL
安裝依賴
設(shè)置環(huán)境變量
編譯和推送
安卓shell操作
運行效果如下:

3.針對安卓的特性
libelf,libz on aarch64 embedded.
x86 -> android13(aarch64) cross-compile you can directly write ebpf both kernel-program and user-program on x86 machine.
FlameGraph embedded to monitor performance.
For None BTF/vmlinux android-kernel(CONFIG_DEBUG_INFO_BTF not set) support.
adb debug (after compiling&linking, directly push into android-phone) embedded.
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ? ?


4.移植過程
尋找方案
于是我繼續(xù)折騰libbpf-bootstrap的交叉編譯,好巧不巧,在How to cross-compile programs from amd64 to arm64 · Issue #144 · libbpf/libbpf-bootstrap · GitHub這個issure中也發(fā)現(xiàn)了這個問題,顯然,直到現(xiàn)在還是open狀態(tài),給出的maintainer給出的方案是
Yes, libbpf depends on libelf and libz, so you need declare where the libraries and header files can be found.??such as,?
make EXTRA_CFLAGS="-IXXX" EXTRA_LDFLAGS="-LXXX" ARCH=arm64
.??You can get a copy of these libraries from?here?for quickly verification if you don't want to cross-compile them yourself.
我尋思著也可行,但是幾經(jīng)折騰后我發(fā)現(xiàn)了很多問題:
Android NDK在r17已經(jīng)宣稱不支持gcc,在r18已經(jīng)刪掉,最新版的r25只有clang,在使用NDK交叉編譯時會遇到一堆莫名其妙的問題。
我的開發(fā)機并沒有打開
CONFIG_DEBUG_BTF_INFO
,但是為了方便我想引入外部BTF file,但是有些目錄在android kernel并不可寫。
解決
最終我在本地幾經(jīng)嘗試交叉編譯出了libbpf
依賴的libelf以及l(fā)ibz
,很有趣的是在編譯的過程中我使用aarch64-linux-gnu
竟然編出來的依賴竟然可以用。在libbpf-bootstrap中,想到用戶態(tài)程序可能也沒有太多編譯上的新特性,于是我繼續(xù)使用aarch64-linux-gnu
交叉編譯,果然還是可行。最終,aarch64的可執(zhí)行文件還是編譯了出來。
為了優(yōu)化大家的開發(fā)速度,和不再折騰這個過程,我將所有的細節(jié),依賴都合并了起來,并且修改了libbpf
源碼加入了外部BTF文件路徑,且在repo中放入了一個a13-5.10
的btf 文件,我寫定了路徑為/data/local/tmp
,push到這里就可以使用。關(guān)于這個btf版本問題,我的內(nèi)核是5.4但是目前使用起來尚未發(fā)現(xiàn)問題。GitHub - JiaHuann/libbpf-bootstrap-android: Do something to fit android aarch64 to develop ebpf programs using libbpf-bootstrap framework
至此,可以ebpf程序源碼可以無需任何改動就運行在安卓kernel(當然有一些kernel版本決定的特性和api還是會限制的,這個與是否交叉編譯運行無關(guān))
PS:當初為了驗證是否可行,全是草率的靜態(tài)鏈接的,生成的可執(zhí)行文件可能會有點大,后續(xù)即將馬上修改為動態(tài)鏈接。
當然,如果有條件還是使用arm虛擬機或者qemu開發(fā)吧,交叉編譯確實不好折騰: (當我還在折騰的時候我同學的mac已經(jīng)能run了
原文作者:Linux內(nèi)核之旅
