Linux perf无法解析以0xffffffff开头的高地址符号问题咨询
我使用以下命令编译并分析程序:
g++ -std=c++17 -fno-omit-frame-pointer -O0 -g3 -o main main.cpp perf stat ./main 5 perf report
执行后perf报告显示:
20.98% main [unknown] [k] 0xffffffffb1077f22 ◆ 19.11% main main [.] func ▒ 17.96% main libc-2.31.so [.] __memset_avx2_erms ▒ 13.07% main [unknown] [k] 0xffffffffb067a936 ▒ 5.75% main [unknown] [k] 0xffffffffb10e68e5 ▒ 3.30% main main [.] std::min<int> ▒ 1.72% main [unknown] [k] 0xffffffffb1077f25 ▒ 1.58% main [unknown] [k] 0xffffffffb086f485 ▒ 1.01% main main [.] std::max<int>
其中,main.cpp中的func、调用的std::max、memset等符号已成功解析,但像0xffffffffb1077f22这类以0xffffffff开头的高地址无法解析,且通过nm main确认其不属于目标程序符号,也非可解析的库函数。我在macOS的Ubuntu虚拟机中运行perf,想咨询这些未知地址是什么?
解答
这些以0xffffffff开头的高地址是Linux内核空间的代码地址。x86_64架构下,Linux内核默认占据虚拟地址空间的高1GB区域,地址起始于0xffffffff80000000附近,这类地址对应的是Ubuntu虚拟机(Guest OS)内核中的执行代码。
无法解析的原因及解决方法如下:
缺少内核调试符号包:Ubuntu默认不会安装带调试符号的内核包,perf需要这些符号才能将内核地址映射为具体函数名。可以通过以下命令安装对应内核版本的调试符号:
sudo apt install linux-image-$(uname -r)-dbgsym注意:需要先启用Ubuntu的调试源,可编辑
/etc/apt/sources.list添加deb http://ddebs.ubuntu.com/ <release> main restricted universe multiverse(替换<release>为当前Ubuntu版本代号,比如focal),再执行sudo apt update。权限不足:普通用户运行perf时,没有足够权限读取内核符号表。改用root权限运行perf即可:
sudo perf stat ./main 5 sudo perf report虚拟机环境限制:macOS上的虚拟机(如VirtualBox、UTM)中,Guest OS的内核符号可能未被perf正确识别,可尝试指定内核镜像路径:
perf report --vmlinux /usr/lib/debug/boot/vmlinux-$(uname -r)
内容的提问来源于stack exchange,提问作者Tokubara

