在后处理期间,perf
如何确定每个已加载映像(例如,共享库)的加载地址。例如,perf report
使用此信息使每个符号地址相对于每个已加载图像的开头。如下图所示(unwind: _int_malloc...
):
它是否存储在elf
二进制文件或分析输出(例如,perf.data
)中的某个位置?
发布于 2020-01-15 07:02:40
共享库加载地址存储在perf record
命令期间记录的perf.data文件中。您可以使用perf script -D
命令以部分解码的格式转储来自perf.data的数据。当你的程序被ld-linux*.so.2
加载时(或者当需要使用dlopen时),加载器将使用mmap
syscall搜索库并加载其段。这些mmap事件由内核记录,并在perf.data文件中具有PERF_RECORD_MMAP或PERF_RECORD_MMAP2类型。perf report
(和perf script
)将重建内存偏移量来解码符号名称。
$ perf record echo 1
$ perf script -D|grep MMAP -c
7
$ perf script -D|less
PERF_RECORD_MMAP2 ... r-xp /bin/echo
...
PERF_RECORD_MMAP2 ... r-xp /lib/x86_64-linux-gnu/libc-2.27.so
在https://github.com/torvalds/linux/blob/master/tools/perf/design.txt文件中描述了perf
的基本思想。要开始分析,有一个带有perf_event_attr *attr
参数的perf_event_open
syscall。Man page描述了attr的mmap相关字段:
The perf_event_attr structure provides detailed configuration
information for the event being created.
mmap : 1, /* include mmap data */
mmap_data : 1, /* non-exec mmap data */
mmap2 : 1, /* include mmap with inode data */
Linux内核在其内核子系统( perf_events
/ events )中将记录所分析进程所需的事件,并使用fd和mmap将数据导出到探查器。perf record
通常在不进行繁重处理的情况下将这些数据从内核转储到perf.data文件中(检查perf record
输出的“唤醒1次以写入数据”打印)。内核中的Mmap事件由从perf_event_mmap_event
中调用的perf_event_mmap_output
记录,该事件从perf_event_mmap
中调用。mm/mmap.c
中的mmap syscall实现有一些对perf_event_mmap
的无条件调用。
perf的design.txt提到了munmap,但当前实现没有munmap字段或事件,事件代码2被重用为PERF_RECORD_LOST。有一些想法认为,通过链接到https://lkml.org/lkml/2016/12/10/1和https://lkml.org/lkml/2017/1/27/452,munmap可以对https://www.spinics.net/lists/netdev/msg524414.html很有帮助
perf工具是linux内核源代码的一部分,可以通过LXR/elixir网站在线查看: mmap/mmap2事件的https://elixir.bootlin.com/linux/v5.4/source/tools/perf/处理代码在perf/util/machine.c machine__process_mmap_event
和machine__process_mmap2_event
中;记录的mmap参数、返回地址、偏移量和文件名在进程(pid/tid)的map__new
和thread__insert_map
的帮助下记录,并在以后用于将样本事件地址转换为符号名称。
PS:你的perf.data有300+ MB的大小,这是巨大的,并且处理可能会很慢。对于长时间运行的程序,您可能希望使用perf record
:perf record -F40
的-F freq
选项或使用-c
选项来降低性能记录事件采样频率。
发布于 2020-01-14 04:12:24
您不能仅仅通过查看ELF可执行文件和库来找到它。每次运行都会有所不同;即使像GDB那样被perf禁用了ASLR,程序也可能在使用某些后来加载可选库的dlopen
之前使用dlopen,因此dlopen必须选择与通常不同的地址来映射库。(正常的动态链接发生在main
运行之前,而不是通过dlopen,但perf
可能希望能够为任何文件备份映射记录地址->文件映射。)
可能perf将每个ELF对象的运行时基址保存在perf.data
中
https://stackoverflow.com/questions/59716303
复制相似问题