【问题标题】:Could I load elf and get virtual address from /proc/pid/maps before actually running it?我可以在实际运行之前加载 elf 并从 /proc/pid/maps 获取虚拟地址吗?
【发布时间】:2022-01-02 20:35:11
【问题描述】:

看看 perf 是如何工作的,用户可以使用“perf record -e cpu-clock ./binary”之类的命令来运行二进制文件并获取信息。 perf 是否加载二进制文件,进行一些配置然后运行它?如果是真的,我可以通过查看/proc/pid/maps 获得一些代码的虚拟地址吗?我是二进制执行的菜鸟,希望得到您的建议!

【问题讨论】:

    标签: c linux binary memory-address perf


    【解决方案1】:

    我可以在实际运行之前加载 elf 并从 /proc/pid/maps 获取虚拟地址吗?

    没有。地址空间是在程序运行时构建的。 “内存映射”是一个进程(正在运行并请求内存映射的软件),而不是二进制文件的属性。现在基本上所有主流操作系统都使用地址空间布局随机化(ASLR),这一点变得更加清楚!

    通常,很多事情是在之前您的 C main() 甚至运行 - 由加载程序(Linux 上的ld.so)完成,但这仍然是 从您的二进制文件中执行代码。

    您的 ELF 文件 包含 包含的部分是 可以在固定地址加载的部分,但如前所述,ASLR 使得这种情况很少见。这些天编译的大部分代码都是可重定位的,所以它只需要知道相对地址。

    您关于perf record 的问题无关紧要,但 perf 所做的是设置一些内核空间可观察对象(主要使用 eBPF),然后定期执行二进制文件,同时探测所述可观察对象。

    【讨论】:

    • 其实可以从elf header中获取virtual地址
    • @alinsoar hm,在 PIE 对象文件中,没有固定的虚拟地址;它都与全局偏移表中的值相关。例如,请参阅stackoverflow.com/questions/38189169/…
    • @alinsoar:是的,对于非 PIE 可执行文件,但你当然不能从/proc/<PID>/maps 获得它,就像问题所问的那样,除非有一个进程实际执行这个 ELF 可执行文件。 (您可以使用ptrace 让该进程在第一条用户空间指令like GDB uses to implement starti 之前停止。)
    • @Marcus: 由加载器(Linux 上的 ld.so) - 我很确定内核的 ELF 程序加载器仍然映射一个动态可执行文件以及 ELF 解释器的(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 事件(如cyclesinstructions)的实际作用是使用perf_event_open 让内核使用硬件性能计数器。内核在上下文切换时保存/恢复它们。这些计数器在达到编程点时溢出,导致中断或导致 CPU 将样本记录到一个小缓冲区中(用于现代 x86 上的“精确事件”)。这不是对它们进行异步采样的问题,除非您正在查看软件事件。哦,但问题指定-e cpu-clock 是软件,而不是cyclesuops_issued.any 或其他硬件事件。
    猜你喜欢
    • 1970-01-01
    • 2014-03-17
    • 2015-12-30
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2017-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多