您的位置:首页 > 其它

ELF(三)程序头表

2014-01-11 18:07 190 查看

程序头表

以32位为例;程序头表由几个项组成,其处理方式类似于数组项。

数据结构

/* Program segment header.  */

 

typedef struct

{

 Elf32_Word  p_type;                       /* Segment type */

         描述段的种类,其中段的种类如下:

         PT_NULL表示的段。

         PT_LOAD表示可装载段,在程序执行前从二进制文件映射到内存。

         PT_DYNAMIC表示段包含了用于动态链接器的信息

         PT_INTERP表示当前段指定了可用于动态链接的程序解释器。通常是ld-linux.so

         PT_NOTE指定一个段,其中可能包含专用的编译器信息。

         还有两个是处理器相关,内核不关注。

 Elf32_Off      p_offset;           /* Segment file offset *

         /所述段在文件中的偏移量(从起始位置计算,单位为字节)

 Elf32_Addr   p_vaddr;           /* Segment virtual address */

         给出了段的数据映射到虚拟地址空间中的位置(对于PT_LOAD类型的段)。只支持物理寻址,不支持虚拟寻址的系统,将使用p_paddr保持信息。

 Elf32_Addr   p_paddr;           /* Segment physical address */物理寻址支持

 Elf32_Word  p_filesz;            /* Segment size in file */段在二进制文件中的长度

 Elf32_Word  p_memsz;                  /* Segment size in memory */段在虚拟地址空间中的长度,与文件中的物理的长度差值可通过截断数据或填充0字节来补偿。

 Elf32_Word  p_flags;             /* Segment flags */

         保持了标志信息,定义了该段的访问权限:

         PF_R表示只读

         PF_X表示文件可执行

  Elf32_Word  p_align;             /*Segment alignment */指明了段在内存和二进制文件中的对齐方式,(p_vaddr和p_offet地址必须是模p_align的,既是p_align的倍数)例如p_align的值为0x1000=4096,这意味着段必须对齐到4k页。

} Elf32_Phdr;

截图例子



         由上图可以看出该程序头表列出了8个段,这些组成了最终在内存中执行的程序。

其还提供了各段在虚拟地址空间和物理地址空间的位置、大小、标志、访问授权和对齐方面的信息。还指定了一个类型来更精确的描述段。

         PHDR保存程序头表。

         INTERP指定在程序已经从可执行映射到内存之后,必须调用解释器。在这里解释器并不意味着二进制文件的内存必须由另一个程序解释。它指的是这样的一个程序:通过链接其他库,来满足未解决的引用。

         通常/lib/ld-linux-so.2、/lib/ld-linux-ia-64.so.2等库,用于在虚拟地址空间中插入程序运行所需的动态库。对几乎所有的程序来说,可能c标准库都是必须映射的,还需要添加各种哭包括,GTK、数学库、libjpeg等。

         LOAD表示一个从二进制文件映射到虚拟地址空间的段。其中保存了常量数据(如字符串),程序的目标代码等等。

         DYNAMIC段保存了其他动态链接器(即,INTERP中指定的解释器)使用的信息。

         NOTE保存了专有信息。

         虚拟地址空间的各个段,填充了来自ELF文件中特定段的数据。

         readelf输出的第二部分指定了哪些节载入到哪些段。

程序举例

#include <stdio.h>

#include<stdlib.h>

#include<string.h>

#include<fcntl.h>

#include <elf.h>

#include<unistd.h>

#define elf_file_path           "/home/code/test/main"

#define MA                     1

#define PHDR_SIZE               8

int main(int argc,char** argv) {

#ifdef __x86_64__

#if MA  

   Elf64_Phdr *phdrs = malloc(sizeof (Elf64_Phdr)*PHDR_SIZE);

    if(phdrs == NULL) {

       perror("malloc error");

    }

#else

   Elf64_Phdr phdrs[PHDR_SIZE];

#endif

#else

#if MA  

    Elf32_Phdr*phdrs = malloc(sizeof(Elf32_Phdr)*PHDR_SIZE);

    if(phdrs == NULL) {

       perror("malloc error");

    }

#else

   Elf32_Phdr phdrs[PHDR_SIZE];

#endif

#endif

#ifdef __x86_64__

   memset(phdrs, 0, sizeof (Elf64_Phdr)*PHDR_SIZE);

#else

    memset(phdrs,0, sizeof (Elf32_Phdr)*PHDR_SIZE);

#endif

    int fd = open(elf_file_path, O_RDONLY);

    if(fd < 0) {

       perror("open elf file failed");

    }

#ifdef __x86_64__

   lseek(fd, 64, SEEK_SET);

    intret;

    if((ret = read(fd, phdrs, sizeof (Elf64_Phdr)*PHDR_SIZE)) < 1) {

       perror("read elf file failed");

    }

#else

   lseek(fd, 52, SEEK_SET);

    int ret;

    if((ret = read(fd, phdrs, sizeof (Elf32_Phdr)*PHDR_SIZE)) < 1) {

       perror("read elf file failed");

    }

#endif

    int i= 0;

   printf("Type           Offset      VirtAddr        PhysAddr       FileSiz         MemSiz         Flg             Align\n");

#if 1

    for(; i < PHDR_SIZE; i++) {

#ifdef __x86_64__

#if MA

       Elf64_Phdr *phdr = phdrs++;

#else

       Elf64_Phdr
bc63
*phdr = &phdrs[i];

#endif 

#else

#if MA

       Elf32_Phdr *phdr = phdrs++;

#else

       Elf32_Phdr *phdr = &phdrs[i];

#endif    

#endif

       switch (phdr->p_type) {

           case PT_NULL:

               printf("%s     ", "NULL");

               break;

           case PT_LOAD:

               printf("%s     ", "LOAD");

               break;

           case PT_DYNAMIC:

               printf("%s     ", "DYNA");

               break;

           case PT_INTERP:

               printf("%s     ", "INTERP");

               break;

           case PT_NOTE:

               printf("%s     ", "NOTE");

               break;

           case PT_SHLIB:

               printf("%s     ", "SHLIB");

               break;

           case PT_PHDR:

               printf("%s     ", "PHDR");

               break;

           case PT_TLS:

               printf("%s     ", "TLS");

               break;

           case PT_NUM:

               printf("%s     ", "NUM");

               break;

           case PT_LOOS:

               printf("%s     ", "LOOS");

               break;

           case PT_GNU_EH_FRAME:

               printf("%s     ", "GNU_EH_FRAME");

               break;

           case PT_GNU_STACK:

               printf("%s      ","GNU_STACK");

               break;

           default:

               printf("%s     ", "OTHER");

               break;

       }

       printf("     0x%-6X     0x%-8X     0x%-8X      0x%-6X       0x%-6X",

               (phdr)->p_offset,

               (phdr)->p_vaddr,

               (phdr)->p_paddr,

               (phdr)->p_filesz,

               (phdr)->p_memsz);

       switch ((phdr)->p_flags) {

           case PF_W:

               printf("       %s", " W ");

               break;

           case PF_R:

               printf("       %s", "R  ");

               break;

           case (PF_W + PF_R):

               printf("       %s", "RW ");

               break;

           case PF_X:

               printf("       %s", "  E");

               break;

           case (PF_X + PF_R):

               printf("       %s", "R E");

               break;

           case (PF_X + PF_W):

               printf("       %s", " WE");

               break;

           case (PF_X + PF_W + PF_R):

               printf("       %s", "RWE");

               break;

           case (PF_MASKOS):

               printf("       %s", "MASKOS");

               break;

           case (PF_MASKPROC):

               printf("       %s", "MASKPROC");

               break;

           default:

               printf("       %s", " ");

               break;

       }

       printf("              0x%-4X\n", (phdr)->p_align);

    }

#if MA

    

    if(phdrs != NULL){

       phdrs = phdrs - PHDR_SIZE;

       free(phdrs);

    }

       

#endif

#endif

   close(fd);

   return (EXIT_SUCCESS);

}

运行程序截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息