Linux 为什么程序头是可执行的?

Linux 为什么程序头是可执行的?,linux,elf,Linux,Elf,我在linux机器上的几个二进制文件上使用了readelf,并在程序头中看到了令我吃惊的东西。这个eample来自'ld'实用程序,但它也出现在我用gcc编译的任何东西中 PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4 此段跨越整个程序标题。为什么被标记为可执行文件?它不包含机器代码。但是,为什么在标题中也会出现这种情况呢?我真的不希望它出现在我的程序映像中。主文件ELF头可以轻松找到存储其他部分的文件中的偏移量。然后,每个

我在linux机器上的几个二进制文件上使用了readelf,并在程序头中看到了令我吃惊的东西。这个eample来自'ld'实用程序,但它也出现在我用gcc编译的任何东西中

PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4


此段跨越整个程序标题。为什么被标记为可执行文件?它不包含机器代码。但是,为什么在标题中也会出现这种情况呢?我真的不希望它出现在我的程序映像中。

主文件ELF头可以轻松找到存储其他部分的文件中的偏移量。然后,每个副标题在其部分中描述数据

主ELF标头如下所示:

/* ELF File Header */
typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;
程序头之所以存在,是因为它们描述了ELF可执行文件的可执行部分

程序的下一部分是 ELF程序头。这些 描述程序的各个部分 包含可执行程序代码的 要映射到程序地址 空间,因为它加载


这取自指向PHDR的PHDR告诉加载程序PHDR本身应该映射到进程地址空间,以便程序本身可以访问它们

这主要用于动态链接


内存被标记为可执行的原因是PHDR小于一页,并且正好位于可执行代码的开头。如果phdr的权限与程序文本的权限不同,则链接器必须在它们之间插入填充。

我知道它们存在的原因。我问为什么会有一个程序头,告诉我们头在哪里。如果您可以读取头文件,那么您已经知道在哪里可以查看。@eye:有上面提到的程序头文件,也有主文件ELF头文件,其中包含对所有子头文件的引用。这就是你所说的吗?不,有一个程序头,它定义了一个覆盖整个程序头集的段。请尝试readelf-l/bin/ls@eye:我在任何地方都找不到ELF格式的描述?这是在加载时还是在运行时?我猜,如果是在运行时,gcc可能不够聪明,无法发现没有执行任何运行时库加载。它也没有解释为什么这个内存应该是可执行的。程序链接的任何动态库都可能被动态加载插件的版本所取代,因此,动态链接的程序在执行期间始终能够加载共享对象,因此PHDR需要存在。内存是可执行的,因为PHDR小于一页,并且正好位于可执行代码的开头。如果PHDR的权限与程序文本的权限不同,则链接器必须在它们之间插入填充。Aha。这终于开始有意义了。
/* Program segment header.  */

typedef struct
{
  Elf32_Word    p_type;                 /* Segment type */
  Elf32_Off     p_offset;               /* Segment file offset */
  Elf32_Addr    p_vaddr;                /* Segment virtual address */
  Elf32_Addr    p_paddr;                /* Segment physical address */
  Elf32_Word    p_filesz;               /* Segment size in file */
  Elf32_Word    p_memsz;                /* Segment size in memory */
  Elf32_Word    p_flags;                /* Segment flags */
  Elf32_Word    p_align;                /* Segment alignment */
} Elf32_Phdr;