如何恢复因异常终止导致size字段为0的perf.data文件
恢复意外终止生成的损坏perf.data文件
针对你遇到的perf.data因VM意外关机损坏、data size字段为0的问题,以下是可行的解决思路:
一、手动修复文件头的data_size字段
perf.data的文件头包含关键元数据,其中data_size字段记录了样本数据的总大小,你的情况是这个字段被置为0,导致perf无法识别有效数据。可以通过以下步骤修复:
- 查看文件头结构:用十六进制工具查看文件头,执行:
输出里开头的xxd -l 64 perf.dataPERFILE2是魔数,后面跟着多个8字节的字段,其中data_size字段的偏移通常是第41-48字节(十六进制0x28位置),当前显示为全0。 - 计算实际data_size值:
- 获取文件总大小:
ls -l perf.data | awk '{print $5}',得到字节数(比如550MB对应576716800)。 - 从文件头找到
data_offset字段(偏移0x20,即第33-40字节),这个值是样本数据在文件中的起始偏移量。 - 实际
data_size= 文件总大小 -data_offset的值。
- 获取文件总大小:
- 修改二进制文件:用十六进制编辑器(如
hexedit)打开perf.data,定位到0x28位置,将全0的8字节替换为计算出的data_size的主机字节序值(x86架构为小端序)。修改后保存,再尝试用perf report打开。
二、尝试perf内置的应急命令
- 强制解析:执行
perf report --force,让perf忽略部分元数据错误,尝试解析有效样本。 - 转换文件格式:用
perf data convert命令尝试将损坏的文件转换为CTF格式,转换过程可能跳过损坏的元数据,提取有效数据:
转换完成后,用perf data convert --to-ctf perf.data converted.ctfperf report -i converted.ctf查看结果。
三、手动提取原始样本数据
如果上述方法失败,可以直接跳过损坏的文件头提取样本数据:
- 根据之前找到的
data_offset值,用dd命令提取从该偏移开始的所有数据:dd if=perf.data of=raw_samples bs=1 skip=<data_offset的值> - 借助perf的libperf库或编写简单C程序,基于perf的样本格式定义解析
raw_samples文件,提取调用栈、事件计数等信息。
四、后续预防措施
为避免再出现类似问题,后续使用perf record时可以:
- 启用定期切换输出文件:
sudo perf record -a -g -F 99 -e cycles:u --switch-output=1h -- sleep 50000 &,每1小时生成一个新的perf文件,意外关机后至少能保留之前完整时段的数据。 - 提前预估被测程序的运行时长,设置更合理的sleep时间,避免perf进程长时间闲置。
内容的提问来源于stack exchange,提问作者Bartłomiej Dudek
相关产品推荐
相关产品推荐

