在ELF中查找函数的起始偏移

12
假设我有一个函数fn,它位于 ELF64 可执行文件的.text节中。有没有办法知道从 ELF 文件的开头算起,fn函数所在的偏移量(以字节为单位)?请注意,我不需要知道链接时它被重定位到哪个虚拟地址,只需要知道它在 ELF 文件中的位置。
3个回答

12

通常来说,可以通过直接解析ELF文件或者将objdump和readelf等工具的输出结合起来来实现。

更具体地说, 您可以使用 'readelf -S file' 命令获取您的 .text 部分的偏移量和虚拟地址-请记下这些信息。此外,您可以使用 'readelf -s file' 命令列出符号,只要可执行文件没有被剥离并且您的函数是可见的(不是静态函数或匿名命名空间中的函数),那么您应该能够找到您的函数及其虚拟地址。

因此,您可以通过以下方式计算出偏移量:

fn symbol offset = fn symbol VA - .text VA + .text offset

假设您想要使用常用工具进行“离线”操作。如果您无法访问未剥离的ELF文件,则更加困难,并且由于仅有部分ELF文件留存在内存中,因此可能需要使用“离线”技巧添加一些信息才能完成操作。


4

只需使用 objdump -F 选项

user@phoenix-amd64:~$ objdump -D -F /opt/phoenix/i486/heap-xxx -D | grep main
08048630 <__libc_start_main@plt> (File Offset: 0x630):
8048679:       e8 b2 ff ff ff          call   8048630 <__libc_start_main@plt> (File 
Offset: 0x630)
080487d5 <main> (File Offset: 0x7d5):

-C 标志还将解码名称。 - John Cramerus

3

Norbert Lange的回答适用于列在ELF文件符号表中的函数。但是static函数不会出现在其中,因此即使例如GDB可以通过使用DWARF调试信息找到它们,readelf -s也不会。

在这种情况下,您可以使用GDB。例如,让我们查找/usr/bin/xfsettingsdxfce_displays_helper_normalize_crtc的偏移量(这是我的实际用例,因此选择了这个晦涩的示例)。

$ gdb -q -ex 'p &xfce_displays_helper_normalize_crtc' -ex q xfsettingsd
Reading symbols from xfsettingsd...
Reading symbols from /usr/lib/debug/.build-id/b2/2ad9713642253d4d7a6f94acf0174ccfe3d487.debug...
$1 = (void (*)(XfceRRCrtc *, XfceDisplaysHelper *)) 0x11e80 <xfce_displays_helper_normalize_crtc>

请注意,这里我们只使用GDB加载文件,不要让它启动。然后使用p命令(完整形式为print)获取地址。所以在我的情况下,该函数的偏移量为0x11e80
在某些情况下,即使在我们startstarti程序之前,GDB也会将偏移解析为虚拟地址。这种情况特别发生在x86-32上。在这种情况下,我们可以简单地减去由readelf -l给出的文件映像的虚拟地址:
$ readelf -l /bin/sleep | grep ' VirtAddr \|\<LOAD *0x[0-9a-f]\+\>'
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x05230 0x05230 R E 0x1000

在上面的例子中,文件镜像的虚拟地址是0x8048000,如果GDB输出虚拟地址而不是偏移量,则需要从函数的虚拟地址中减去该值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接