我在linux盒子上的几个二进制文件中使用了readelf,并在程序头文件中看到了让我感到意外的东西。这个例子来自'ld'实用程序,但它也出现在我用gcc编译的任何东西中。为什么程序头可执行?
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120řË为0x4
这段跨越程序头的整体。为什么被标记为可执行文件?它不包含机器代码。但是,为什么即使是在头文件中?我真的不希望它在我的程序图像中。
我在linux盒子上的几个二进制文件中使用了readelf,并在程序头文件中看到了让我感到意外的东西。这个例子来自'ld'实用程序,但它也出现在我用gcc编译的任何东西中。为什么程序头可执行?
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120řË为0x4
这段跨越程序头的整体。为什么被标记为可执行文件?它不包含机器代码。但是,为什么即使是在头文件中?我真的不希望它在我的程序图像中。
采取的PHDR指向PHDRS告诉了PHDRS本身应被映射到进程的地址空间的装载机,以便使它们对程序本身访问。
这主要用于动态链接。
主文件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;
这是从here
我知道他们为什么在那里。我问为什么有一个程序头,告诉我们头在哪里。如果你可以阅读标题,那么你已经知道在哪里看。 – eyesathousand 2011-05-31 11:03:16
@eye:有上面提到的程序头文件,还有主文件ELF头文件,它包含对所有子头文件的引用。那是你正在谈论的那个吗? – 2011-05-31 11:06:32
没有一个程序头文件定义了一个覆盖整个程序头文件的段。 尝试 readelf -l/bin/ls – eyesathousand 2011-05-31 11:10:03
这是在加载时还是在运行时?我猜如果是在运行时,gcc可能不够聪明,没有发现运行时库加载正在执行。 – eyesathousand 2011-05-31 11:30:16
它也不能解释为什么这个内存应该是可执行的。 – eyesathousand 2011-05-31 11:33:52
程序所链接的任何动态库都可以被动态加载插件的版本替代,因此动态链接的程序将始终能够在执行期间加载共享对象,因此需要存在PHDR。 – 2011-05-31 11:43:35