为raspberrypi编译bpftrace调试工具

2024-03-04 10:44

本文主要是介绍为raspberrypi编译bpftrace调试工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于eBPF的嵌入式应用调试

笔者之前写过几篇有关于使用eBPF调试Linux内核和应用的博客,其中提到,在嵌入式设备上使用BCC或bpftrace是不可行的;主要原因在于嵌入式设备的资源有限,而这两个调试工具依赖python/clang/llvm等库,需要将脚本编译为eBPF字节码加载入Linux内核来执行。然而,随着嵌入式设备的性能越来越强,板载资源越来越多,在嵌入式设备上运行bpftrace工具已成为可能。本文整理了笔者为raspberrypi 4设备编译bpftrace工具的过程,按照这些操作,笔者为工作中的嵌入式设备也制作了可用的bpftrace调试工具。

另外,22.04版本的Ubuntu系统自带的bpftrace已经不能用了,主要的原因是它不带符号表(strip -s);本文的内容也可用于PC端的bpftrace工具编译构建:

root@ubuntu:/usr/sbin# uname -a
Linux ubuntu 5.15.0-97-generic #107-Ubuntu SMP Wed Feb 7 13:26:48 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
root@ubuntu:/usr/sbin# ./execsnoop.bt
Attaching 3 probes...
ERROR: Could not resolve symbol: /proc/self/exe:BEGIN_trigger

编译使用的设备

首先,笔者使用的raspberrypi 4可插入两张TF卡,两张卡分别安装了debian系统和笔者编译的openwrt系统,二者的Linux内核版本大致相同,均为6.1版本。其次,树莓派设备的内存大小为2GB,这一点非常重要;因为bcc/bpftrace是由C++编写的,编译过程非常耗内存(笔者使用clang编译器构建)。最后,笔者是为了在openwrt系统中使用bpftrace,因此要求在构建openwrt系统时,选择glibc库。

零,安装clang编译器

编译在是树莓派的debian系统上完成的。需要按照apt.llvm.org的说明操作来安装,笔者选择了安装clang-10编译器:

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 10

之后,我们需要在debian安装其他依赖库(而不编译所有的依赖库,否则耗时太久了)。以下需要安装的库,是在raspberrypi/openwrt系统上缺少的,后面会直接复制到安装有openwrt系统的TF卡上:

sudo apt install flex bison zlib1g-dev liblzma-dev libbz2-dev cmake \libzstd-dev dwarves build-essential python3-setuptools libpython3-dev

一,编译elfutils

笔者下载了最新版本的elfutils,它提供了libelf依赖库,该软件包的配置、编译操作如下:

../configure --prefix=/opt/bpftrace CC=clang-10 CXX=clang++-10 \CFLAGS='-Wall -fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -Wno-unused-parameter' \CXXFLAGS='-Wall -fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -Wno-unused-parameter' \--disable-nls --enable-libdebuginfod=dummy --disable-debuginfod --with-zlib --with-lzma \--with-bzlib --with-zstd LDFLAGS='-Wl,-rpath=/opt/bpftrace/lib'
make && sudo make install

以上配置完成后,再执行make && sudo make install即可安装。

二,编译libbpf库

这里需要强调的是,依笔者的经验,libbpf库以及bcc、bpftrace版本的选择,不能任意;一定要根据Linux内核版本来选择。例如,树苺派的Linux内核版本为6.1,那么确认该版本内核的(初始)发布日期(是2023年初发布的),然后选择时间上相近的libbpf库。这里笔者选择的版本为libbpf-1.2.2。然而工作中,笔者因使用的嵌入式设备比较老,使用的版本为0.1.1

该库的编译操作如下:

cd $HOME ; tar -zxf libbpf-1.2.2.tar.gz
cd libbpf-1.2.2/src
make V=1 PREFIX=/opt/bpftrace CC=clang-10 CFLAGS='-fPIC -O2 -ggdb -Wall -fno-omit-frame-pointer -I/opt/bpftrace/include' LDFLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib'
sudo make V=1 PREFIX=/opt/bpftrace CC=clang-10 CFLAGS='-fPIC -O2 -ggdb -Wall -fno-omit-frame-pointer -I/opt/bpftrace/include' LDFLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' install

注意,以上编译的库在debian/arm64系统下会被安装到/opt/bpftrace/lib64路径下,需要移到/opt/bpftrace/lib路径下,并修改/opt/bpftrace/lib/pkgconfig/libbpf.pc文件。

三,安装cereal头文件

早期的bpftrace工具不依赖该库,但现在是需要了,笔者选择了cereal-1.3.2.tar.gz版本:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer' \-DBUILD_DOC=OFF -DBUILD_SANDBOX=OFF -DSKIP_PERFORMANCE_COMPARISON=ON -DBUILD_TESTS=OFF ..
sudo make install

注意,该库以头文件的形式提供,以上不会有动态库编译生成。

四,编译bcc

bcc的版本为v0.27.0,笔者已验证最新版本的bcc编译得到的bpftrace存在异常。需要注意的是,笔者下载的源代码文件名为bcc-src-with-submodule.tar.gz。以下是配置、编译安装的操作:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include' \-DCMAKE_EXE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_MODULE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_SHARED_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DENABLE_LLVM_SHARED=ON -DENABLE_TESTS=OFF -DRUN_LUA_TESTS=OFF -DENABLE_LIBDEBUGINFOD=OFF ..
make && sudo make install

编译完成后,笔者删除了所有的静态库(因为笔者希望所有的库是动态链接的):sudo rm -rf /opt/bpftrace/lib/*.a。注意,这个编译过程比较耗时,大约持继在一小时以上。因rasbperrypi 4内存有2GB,上面可以make -j2来编译加速。

五,编译bpftrace

笔者选择的bpftrace版本为v0.17.1(正如上面提到的,笔者验证最新版本的bpftracearm64/linux-6.1系统下运行不正常。配置、编译安装的操作如下:

mkdir -p build_aarch64 && cd build_aarch64
cmake -DCMAKE_BUILD_TYPE=release -DCMAKE_INSTALL_PREFIX=/opt/bpftrace \-DCMAKE_C_COMPILER=clang-10 -DCMAKE_CXX_COMPILER=clang++-10 \-DCMAKE_C_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include -I${HOME}/libbpf-1.2.2/include -I${HOME}/libbpf-1.2.2/include/uapi' \-DCMAKE_CXX_FLAGS='-fPIC -O2 -D_GNU_SOURCE -ggdb -fno-omit-frame-pointer -I/opt/bpftrace/include -I${HOME}/libbpf-1.2.2/include -I${HOME}/libbpf-1.2.2/include/uapi' \-DCMAKE_EXE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_MODULE_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DCMAKE_SHARED_LINKER_FLAGS='-L/opt/bpftrace/lib -Wl,-rpath=/opt/bpftrace/lib' \-DUSE_SYSTEM_BPF_BCC=ON -DSTATIC_LINKING=OFF -DALLOW_UNSAFE_PROBE=ON -DBUILD_TESTING=OFF ..
make && sudo make install

需要注意的是,上面的编译选项,直接指定了libbpf-1.2.2头文件包含的路径。至此,笔者的编译就结束了,接下来将编译结果复制到安装有openwrt系统的TF卡中。

在raspberrypi/openwrt系统下使用bpftrace

首先,除了/opt/bpftrace外,笔者从树莓派的debian系统中复制了以下库到openwrt系统:

root@OpenWrt:/lib/aarch64-linux-gnu# ls -lh -t | head -n 8
-rw-r--r--    1 root     root       64.8M Sep  9 22:40 libLLVM-10.so.1
-rw-r--r--    1 root     root       65.0K Sep  9 22:42 libbz2.so.1.0
-rw-r--r--    1 root     root       27.7M Sep  9 22:41 libclang-10.so.1
-rw-r--r--    1 root     root      179.1K Sep  9 22:43 libedit.so.2
-rw-r--r--    1 root     root       30.2K Sep  9 22:42 libffi.so.6
-rw-r--r--    1 root     root      130.2K Sep  9 22:41 liblzma.so.5
-rw-r--r--    1 root     root      158.6K Sep  9 22:43 libtinfo.so.5
-rw-r--r--    1 root     root      405.8K Sep  9 22:41 libzstd.so.1

然后,笔者为树莓派的内核使能了相关的内核选项,详见此处的详细说明。还有,bpftrace的正常运行,可能还需要访问内核的头文件,这就需要使能CONFIG_IKHEADERS=m,在树莓派启动后,手动加载该内核模块:insmod kheaders.ko。最后,笔者在树莓派的openwrt系统下使用bpftrace的结果如下:

root@OpenWrt:~# insmod kheaders.ko
module is already loaded - kheaders
root@OpenWrt:~# uname -a
Linux OpenWrt 6.1.50 #0 SMP Fri Sep  1 21:45:47 2023 aarch64 GNU/Linux
root@OpenWrt:~# /opt/bpftrace/bin/bpftrace --info
SystemOS: Linux 6.1.50 #0 SMP Fri Sep  1 21:45:47 2023Arch: aarch64Buildversion: v0.17.1LLVM: 10.0.1unsafe uprobe: nobfd: nolibdw (DWARF support): yeslibbpf: failed to find valid kernel BTF
Kernel helpersprobe_read: yesprobe_read_str: yesprobe_read_user: yesprobe_read_user_str: yesprobe_read_kernel: yesprobe_read_kernel_str: yesget_current_cgroup_id: yessend_signal: yesoverride_return: noget_boot_ns: yesdpath: noskboutput: noKernel featuresInstruction limit: 1000000Loop support: yesbtf: nomap batch: yesuprobe refcount (depends on Build:bcc bpf_attach_uprobe refcount): yesMap typeshash: yespercpu hash: yesarray: yespercpu array: yesstack_trace: yesperf_event_array: yesProbe typeskprobe: yestracepoint: yesperf_event: yeskfunc: noiter:task: noiter:task_file: nokprobe_multi: noraw_tp_special: yesroot@OpenWrt:~# cd /opt/bpftrace/share/bpftrace/tools/
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools# ls
bashreadline.bt    gethostlatency.bt  runqlen.bt         tcpdrop.bt
biolatency.bt      killsnoop.bt       setuids.bt         tcplife.bt
biosnoop.bt        loads.bt           ssllatency.bt      tcpretrans.bt
biostacks.bt       mdflush.bt         sslsnoop.bt        tcpsynbl.bt
bitesize.bt        naptime.bt         statsnoop.bt       threadsnoop.bt
capable.bt         old                swapin.bt          undump.bt
cpuwalk.bt         oomkill.bt         syncsnoop.bt       vfscount.bt
dcsnoop.bt         opensnoop.bt       syscount.bt        vfsstat.bt
doc                pidpersec.bt       tcpaccept.bt       writeback.bt
execsnoop.bt       runqlat.bt         tcpconnect.bt      xfsdist.bt
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools# /opt/bpftrace/bin/bpftrace ./execsnoop.bt
libbpf: failed to find valid kernel BTF
libbpf: failed to find valid kernel BTF
Attaching 3 probes...
TIME(ms)   PID   ARGS
26138      2490  /etc/init.d/firewall reload
26168      2502  readlink /etc/init.d/firewall
26170      2503  basename /etc/init.d/firewall
26172      2504  flock -n 1000
26174      2505  flock 1000
26178      2506  readlink /etc/init.d/firewall
26181      2507  readlink /etc/init.d/firewall
26183      2508  basename /etc/init.d/firewall
26186      2509  flock -n 1000
26188      2510  fw4 reload
26191      2511  flock -x 1000
26193      2512  rm -f /var/run/fw4.state
26195      2513  utpl -S /usr/share/firewall4/main.uc
26195      2514  nft -f /dev/stdin
26303      2515  sh -c /usr/sbin/nft --terse --json list flowtables inet
26305      2515  /usr/sbin/nft --terse --json list flowtables inet
26393      2516  utpl -S /usr/share/firewall4/main.uc
29341      2517  /etc/init.d/firewall status
29371      2529  readlink /etc/init.d/firewall
29373      2530  basename /etc/init.d/firewall
29375      2531  flock -n 1000
29377      2532  flock 1000
29381      2533  readlink /etc/init.d/firewall
29384      2534  basename /etc/init.d/firewall
29387      2537  jsonfilter -e @["firewall"]
29388      2539  jshn -w
29391      2540  ubus call service list { "name": "firewall" }
29397      2543  jsonfilter -e $.instances
63078      2544  /etc/init.d/network status
63108      2556  readlink /etc/init.d/network
63110      2557  basename /etc/init.d/network
63112      2558  flock -n 1000
63114      2559  flock 1000
63118      2560  readlink /etc/init.d/network
63121      2561  basename /etc/init.d/network
63124      2564  jsonfilter -e @["network"]
63125      2566  jshn -w
63128      2567  ubus call service list { "name": "network" }
63134      2570  jsonfilter -e $.instances
63137      2571  jsonfilter -s { "instance1": { "running": true, "pid": 769, "command": [ "\/sbin\/netifd" ], "term_timeout": 5,
"limits": { "core": "unlimited" }, "respawn": { "threshold": 3600, "timeout": 5, "retry": 5 } } } -e $[*].running
^C
root@OpenWrt:/opt/bpftrace/share/bpftrace/tools#

至此,可以说明我们编译的bpftrace工具可以正常工作了。

这篇关于为raspberrypi编译bpftrace调试工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/772928

相关文章

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

ASIO网络调试助手之一:简介

多年前,写过几篇《Boost.Asio C++网络编程》的学习文章,一直没机会实践。最近项目中用到了Asio,于是抽空写了个网络调试助手。 开发环境: Win10 Qt5.12.6 + Asio(standalone) + spdlog 支持协议: UDP + TCP Client + TCP Server 独立的Asio(http://www.think-async.com)只包含了头文件,不依

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

vscode中文乱码问题,注释,终端,调试乱码一劳永逸版

忘记咋回事突然出现了乱码问题,很多方法都试了,注释乱码解决了,终端又乱码,调试窗口也乱码,最后经过本人不懈努力,终于全部解决了,现在分享给大家我的方法。 乱码的原因是各个地方用的编码格式不统一,所以把他们设成统一的utf8. 1.电脑的编码格式 开始-设置-时间和语言-语言和区域 管理语言设置-更改系统区域设置-勾选Bata版:使用utf8-确定-然后按指示重启 2.vscode

超强的截图工具:PixPin

你是否还在为寻找一款功能强大、操作简便的截图工具而烦恼?市面上那么多工具,常常让人无从选择。今天,想给大家安利一款神器——PixPin,一款真正解放双手的截图工具。 想象一下,你只需要按下快捷键就能轻松完成多种截图任务,还能快速编辑、标注甚至保存多种格式的图片。这款工具能满足这些需求吗? PixPin不仅支持全屏、窗口、区域截图等基础功能,它还可以进行延时截图,让你捕捉到每个关键画面。不仅如此

PR曲线——一个更敏感的性能评估工具

在不均衡数据集的情况下,精确率-召回率(Precision-Recall, PR)曲线是一种非常有用的工具,因为它提供了比传统的ROC曲线更准确的性能评估。以下是PR曲线在不均衡数据情况下的一些作用: 关注少数类:在不均衡数据集中,少数类的样本数量远少于多数类。PR曲线通过关注少数类(通常是正类)的性能来弥补这一点,因为它直接评估模型在识别正类方面的能力。 精确率与召回率的平衡:精确率(Pr