问题是,如果您查看 ELF 共享库和普通可执行文件的 ELF 标头,它们根本没有区别。在我的 Linux 机器(Debian 11.4)上,甚至当考虑的文件是 ELF 可执行文件时,ELF 标头的 e_type 字段也设置为 共享目标文件,如 ht 实用程序报告。它看起来像是区分 ELF 可执行文件和 ELF 共享库的唯一简单可靠的方法,并且出于某种原因,GCC 仅使用此值填写 e_type 字段。尽管如此,file(1) 实用程序可以准确地告诉我我提供给她的输入文件是可执行文件还是共享库。
这个问题的第一个答案表明文件(1)的代码应该查找 PT_INTERP 程序头: 区分共享对象和位置无关的可执行文件
这听起来很合理,因为所有共享库都是在可执行文件首先加载后加载的,因此它们不需要再次加载解释器,因为普通的可执行文件已经完成了。
当我查看 magic.mgc 文件如何编译时,我在文件(1)源代码中发现了这一点:
0 name elf-le
>16 leshort 0 no file type,
!:mime application/octet-stream
>16 leshort 1 relocatable,
!:mime application/x-object
>16 leshort 2 executable,
!:mime application/x-executable
>16 leshort 3 ${x?pie executable:shared object},
我无法理解最后一行的含义,但如果我理解这一点,我似乎可以找到我的问题的答案。
>16 leshort 3 ${x?pie executable:shared object},
这意味着“查看文件偏移量 16 处的 2 字节小端字节序字。如果它的值为“3”,则检查该文件是否可执行(权限位)。如果是,则类型为“饼可执行文件',否则它是'共享对象'”
您可以查看 magic(5) 手册页以获取有关此语法的信息。
自从提交 03084b161cf8 以来,file(1) 使用 ELF 文件动态部分的
DF_1_PIE
条目中的 FLAGS_1
标志来调整可执行位,因此行为取决于 file(1) 实用程序的发行版版本。另外,在提交 d653309de04e 和 483e7d8f1a5c 之间,我相信所有动态 ELF 文件都被错误地识别为共享对象。