标题: Ubuntu 22上自编译bpftrace 创建: 2022-10-22 17:58 更新: 2022-10-24 20:00 链接: https://scz.617.cn/unix/202210221758.txt 参看 https://github.com/iovisor/bpftrace/blob/master/INSTALL.md aptitude install libbpfcc-dev libbpf-dev aptitude install bison cmake flex g++ git libelf-dev zlib1g-dev libfl-dev systemtap-sdt-dev binutils-dev libcereal-dev llvm-12-dev llvm-12-runtime libclang-12-dev clang-12 libpcap-dev libgtest-dev libgmock-dev asciidoctor cd /home/scz/src git clone https://github.com/iovisor/bpftrace git config --global --unset http.postBuffer cp -R bpftrace bpftrace_scz mkdir bpftrace_scz/build cd bpftrace_scz/build cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_UNSAFE_PROBE:BOOL=ON .. make -j8 make install (可以不做) 最近git clone不挂代理时下载速率还可以,此时无需配置http.postBuffer,好像只 在挂代理时才碰上那个问题。 $ /home/scz/src/bpftrace_scz/build/src/bpftrace --version bpftrace v0.16.0-32-gcf34 $ /home/scz/src/bpftrace_scz/build/src/bpftrace --info |& grep bfd: bfd: yes "bfd: yes"支持"(k|u)probe:some+off"的语法,对应HAVE_BFD_DISASM宏,参看 bpftrace/src/build_info.cpp "-DALLOW_UNSAFE_PROBE:BOOL=ON"会对CMakeLists.txt产生影响 -------------------------------------------------------------------------- if (ALLOW_UNSAFE_PROBE) set(BPFTRACE_FLAGS "${BPFTRACE_FLAGS}" HAVE_UNSAFE_PROBE) endif(ALLOW_UNSAFE_PROBE) -------------------------------------------------------------------------- 最终会在编译命令中出现"-DHAVE_UNSAFE_PROBE"。该宏真正起作用的地方只有一处 -------------------------------------------------------------------------- /* * bpftrace/src/attached_probe.cpp */ static void check_alignment(std::string &path, std::string &symbol, uint64_t sym_offset, uint64_t func_offset, bool safe_mode, ProbeType type) { ... // If we did not allow unaligned uprobes in the // compile time, force the safe mode now. #ifndef HAVE_UNSAFE_PROBE safe_mode = true; #endif -------------------------------------------------------------------------- cmake -DCMAKE_BUILD_TYPE=Release .. 相当于 cmake -DCMAKE_BUILD_TYPE=Release -DALLOW_UNSAFE_PROBE:BOOL=OFF .. 即默认未定义HAVE_UNSAFE_PROBE宏,safe_mode被强制赋值true,此时不允许在单条 指令中间位置安装Hook,这真是没事找事的需求。 Ubuntu 22目前安装的0.14.0版bpftrace没有启用HAVE_UNSAFE_PROBE宏,也没有启用 HAVE_BFD_DISASM宏,后者的缺失对功能限制太大。 -------------------------------------------------------------------------- Q: 如何安全判断bpftrace是否启用HAVE_BFD_DISASM宏? A: "bpftrace --info |& grep bfd:"报yes时表示启用HAVE_BFD_DISASM宏,报no表示未 启用。 $ objdump --prefix-addresses --show-raw-insn --disassemble=__open /lib/x86_64-linux-gnu/libc.so.6 | less ... 0000000000114690 <__open> f3 0f 1e fa endbr64 0000000000114694 <__open+0x4> 41 54 push %r12 0000000000114696 <__open+0x6> 41 89 f2 mov %esi,%r10d 0000000000114699 <__open+0x9> 41 89 f4 mov %esi,%r12d 000000000011469c <__open+0xc> 55 push %rbp 000000000011469d <__open+0xd> 48 89 fd mov %rdi,%rbp 00000000001146a0 <__open+0x10> 48 83 ec 68 sub $0x68,%rsp 00000000001146a4 <__open+0x14> 48 89 54 24 40 mov %rdx,0x40(%rsp) 00000000001146a9 <__open+0x19> 64 48 8b 04 25 28 00 00 00 mov %fs:0x28,%rax 00000000001146b2 <__open+0x22> 48 89 44 24 28 mov %rax,0x28(%rsp) ... 用如下命令测试,不报错表示启用HAVE_BFD_DISASM宏,报错表示未启用。 /home/scz/src/bpftrace_scz/build/src/bpftrace -e 'uprobe:libc:open+4 /comm == str($1)/ {printf("%s (%d)\n",comm,pid)}' cat -------------------------------------------------------------------------- Q: 如何安全判断bpftrace是否启用HAVE_UNSAFE_PROBE宏? A: 用如下命令测试 /home/scz/src/bpftrace_scz/build/src/bpftrace --unsafe -e 'uprobe:libc:open+5 /comm == str($1)/ {printf("%s (%d)\n",comm,pid)}' cat 报"WARNING: Unsafe uprobe in the middle of the instruction",但仍继续运行, 表示启用HAVE_UNSAFE_PROBE宏。 报"ERROR: Could not add uprobe into middle of instruction",结束运行,表示 未启用HAVE_UNSAFE_PROBE宏。 -------------------------------------------------------------------------- 若"uprobe:addr"位于函数入口,无需启用HAVE_BFD_DISASM宏,但此时也没必要用 "uprobe:addr",用"uprobe:func"即可。若"uprobe:addr"位于函数中部,必须启用 HAVE_BFD_DISASM宏,但与HAVE_UNSAFE_PROBE宏关系不大,除非addr不在正常指令边 界上。 启用HAVE_BFD_DISASM宏有意义,启用HAVE_UNSAFE_PROBE宏没啥意义啊,谁吃饱了撑 得去单条指令中间安装Hook? 注意到奇特现象,即使已启用HAVE_UNSAFE_PROBE宏,仍然有 $ /home/scz/src/bpftrace_scz/build/src/bpftrace --info |& grep "unsafe uprobe:" unsafe uprobe: no $ cd /home/scz/src/bpftrace_scz/build $ grep -RI "unsafe uprobe:" src/build_info.cpp: << " unsafe uprobe: " 在build_info.cpp中查看附近代码 -------------------------------------------------------------------------- << " unsafe uprobe: " #ifdef HAVE_UNSAFE_UPROBE << "yes" << std::endl; #else << "no" << std::endl; #endif -------------------------------------------------------------------------- 此处判断是否启用HAVE_UNSAFE_UPROBE宏,整个项目中该宏只在此处出现,显然这是 一处笔误 HAVE_UNSAFE_PROBE // 正确写法 HAVE_UNSAFE_UPROBE // 笔误 若无此笔误,"-DALLOW_UNSAFE_PROBE:BOOL=ON"之后应该有"unsafe uprobe: yes"。 这解释了为什么满世界放狗,都看不到"unsafe uprobe: yes",我被这个笔误坑得死 去活来。