【发布时间】:2022-01-02 20:35:11
【问题描述】:
看看 perf 是如何工作的,用户可以使用“perf record -e cpu-clock ./binary”之类的命令来运行二进制文件并获取信息。 perf 是否加载二进制文件,进行一些配置然后运行它?如果是真的,我可以通过查看/proc/pid/maps 获得一些代码的虚拟地址吗?我是二进制执行的菜鸟,希望得到您的建议!
【问题讨论】:
标签: c linux binary memory-address perf
看看 perf 是如何工作的,用户可以使用“perf record -e cpu-clock ./binary”之类的命令来运行二进制文件并获取信息。 perf 是否加载二进制文件,进行一些配置然后运行它?如果是真的,我可以通过查看/proc/pid/maps 获得一些代码的虚拟地址吗?我是二进制执行的菜鸟,希望得到您的建议!
【问题讨论】:
标签: c linux binary memory-address perf
我可以在实际运行之前加载 elf 并从 /proc/pid/maps 获取虚拟地址吗?
没有。地址空间是在程序运行时构建的。 “内存映射”是一个进程(正在运行并请求内存映射的软件),而不是二进制文件的属性。现在基本上所有主流操作系统都使用地址空间布局随机化(ASLR),这一点变得更加清楚!
通常,很多事情是在之前您的 C main() 甚至运行 - 由加载程序(Linux 上的ld.so)完成,但这仍然是 从您的二进制文件中执行代码。
您的 ELF 文件 包含 包含的部分是 可以在固定地址加载的部分,但如前所述,ASLR 使得这种情况很少见。这些天编译的大部分代码都是可重定位的,所以它只需要知道相对地址。
您关于perf record 的问题无关紧要,但 perf 所做的是设置一些内核空间可观察对象(主要使用 eBPF),然后定期执行二进制文件,同时探测所述可观察对象。
【讨论】:
/proc/<PID>/maps 获得它,就像问题所问的那样,除非有一个进程实际执行这个 ELF 可执行文件。 (您可以使用ptrace 让该进程在第一条用户空间指令like GDB uses to implement starti 之前停止。)
ld.so's) 自己的文本/数据段。例如,如果您strace /bin/true,您会看到ld.so 进行的系统调用,它们不包括可执行文件的open / mmap。仅限libc.so.6。另外,如果你使用GDB来starti就可以了,你在ld.so的_start的第一条指令之前停止。即使在那个时候,您也会在/proc/<PID>/maps 中看到程序自己的段以及 ld.so 的映射。
perf record 对硬件 PMU 事件(如cycles 和instructions)的实际作用是使用perf_event_open 让内核使用硬件性能计数器。内核在上下文切换时保存/恢复它们。这些计数器在达到编程点时溢出,导致中断或导致 CPU 将样本记录到一个小缓冲区中(用于现代 x86 上的“精确事件”)。这不是对它们进行异步采样的问题,除非您正在查看软件事件。哦,但问题指定-e cpu-clock 是软件,而不是cycles 或uops_issued.any 或其他硬件事件。