我在我的Linux机器上使用了几个二进制文件中的readelf,并在程序头文件中看到了令我吃惊的东西。 这个例子来自'ld'实用程序,但它也发生在我用gcc编译的任何东西上。
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 RE 0x4
这个段跨越了整个程序头文件。 为什么被标记为可执行文件? 它不包含机器代码。 而且,为什么即使这在目前的头文件? 我真的不希望在我的程序图像。
指向PHDR的PHDR告诉加载程序PHDR本身应该映射到进程地址空间,以使程序本身可以访问它们。
这主要用于动态链接。
主文件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程序头文件。 这些描述了包含可执行程序代码的程序部分,以便在加载时映射到程序地址空间。
/* 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;
这是从这里拿走的