其他分享
首页 > 其他分享> > ELF文件-结构体数据

ELF文件-结构体数据

作者:互联网

ELF文件包含文件头(ELF Header)、程序头表(Program Head Table)、节(Sections)或段(Segments)、节头表(Section Header Table)四个部分。ELF文件提供了两种视图,分别是链接视图和执行视图。其中,节是链接视图的基本单位,在文件进行链接操作时使用;段是执行视图的基本单位,在文件运行时使用。一个段可包含一个或多个节,段和节在文件中没有固定的顺序。以下是elf.h中相关结构体的定义。

 

1. 文件头结构体(ELF Header)

文件头描述整个文件的组织结构。使用Elf32_Ehdr和Elf64_Ehdr描述。

#define EI_NIDENT (16)

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;
typedef struct
{
    unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
    Elf64_Half    e_type;                 /* Object file type */
    Elf64_Half    e_machine;              /* Architecture */
    Elf64_Word    e_version;              /* Object file version */
    Elf64_Addr    e_entry;                /* Entry point virtual address */
    Elf64_Off     e_phoff;                /* Program header table file offset */
    Elf64_Off     e_shoff;                /* Section header table file offset */
    Elf64_Word    e_flags;                /* Processor-specific flags */
    Elf64_Half    e_ehsize;               /* ELF header size in bytes */
    Elf64_Half    e_phentsize;            /* Program header table entry size */
    Elf64_Half    e_phnum;                /* Program header table entry count */
    Elf64_Half    e_shentsize;            /* Section header table entry size */
    Elf64_Half    e_shnum;                /* Section header table entry count */
    Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

以上,

e_ident 字段前四位为文件标识,一般为“\x7fELF”,通过这四位,可以查看该文件是否为ELF文件。

e_type  字段表示ELF文件的类型,如ET_REL表示可重定位文件,ET_EXEC表示可执行文件,ET_DYN表示共享目标文件。

e_phoff 字段表示程序头表在文件中的偏移,可根据该字段找到程序头表的起始地址。

e_shoff 字段表示节头表在文件中的偏移,可根据该字段找到节头表的起始地址。

e_shstrndx 字段表示字符串表在节头表中的索引,一般为节头表中的最后一个,即e_shstrndx=e_shnum-1。

 

2. 程序头结构体(Program Header)

程序头表描述文件中各种段的信息。每个程序头的结构体定义如下,使用Elf32_Phdr和Elf64_Phdr描述。

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;
typedef struct
{
    Elf64_Word  p_type;          /* Segment type */
    Elf64_Word  p_flags;         /* Segment flags */
    Elf64_Off   p_offset;        /* Segment file offset */
    Elf64_Addr  p_vaddr;         /* Segment virtual address */
    Elf64_Addr  p_paddr;         /* Segment physical address */
    Elf64_Xword p_filesz;        /* Segment size in file */
    Elf64_Xword p_memsz;         /* Segment size in memory */
    Elf64_Xword p_align;         /* Segment alignment */
}Elf64_Phdr;

以上,

p_type 字段表示该段的类型,如果值为PT_LOAD,则表示该段是一个可加载到内存中的段,且必须满足 p_memsz ≥ p_filesz ,多出的字节清零,否则该段的内容不能完全加载。在程序头表中,所有PT_LOAD类型的程序头都按照p_vaddr的值升序排列。

 

3. 节头结构体(Section Header)

节头表描述文件中各种节的信息。每个节头的结构体定义如下,使用Elf32_Shdr和Elf64_Shdr描述。

typedef struct
{
    Elf32_Word  sh_name;       /* Section name (string tbl index) */
    Elf32_Word  sh_type;       /* Section type */
    Elf32_Word  sh_flags;      /* Section flags */
    Elf32_Addr  sh_addr;       /* Section virtual addr at execution */
    Elf32_Off   sh_offset;     /* Section file offset */
    Elf32_Word  sh_size;       /* Section size in bytes */
    Elf32_Word  sh_link;       /* Link to another section */
    Elf32_Word  sh_info;       /* Additional section information */
    Elf32_Word  sh_addralign;  /* Section alignment */
    Elf32_Word  sh_entsize;    /* Entry size if section holds table */
}Elf32_Shdr;
typedef struct
{
    Elf64_Word   sh_name;      /* Section name (string tbl index) */
    Elf64_Word   sh_type;      /* Section type */
    Elf64_Xword  sh_flags;     /* Section flags */
    Elf64_Addr   sh_addr;      /* Section virtual addr at execution */
    Elf64_Off    sh_offset;    /* Section file offset */
    Elf64_Xword  sh_size;      /* Section size in bytes */
    Elf64_Word   sh_link;      /* Link to another section */
    Elf64_Word   sh_info;      /* Additional section information */
    Elf64_Xword  sh_addralign; /* Section alignment */
    Elf64_Xword  sh_entsize;   /* Entry size if section holds table */
}Elf64_Shdr;

以上,

sh_name 字段指出节的名字索引,节名字符串以'\0'结尾,统一存储在字符串表中,然后该字段的值就表示对应节名字符串在字符串表中的索引。

 

4. 字符串表

字符串表存储ELF文件中的节名、符号名等字符串,下面是一个示例,来说明字符串表的存储方式。

假设字符串表如下所示:

则可以理解为:

下面是从字符串表中获取节名字符串的伪代码示例:

//The target is to get a section's name
//1. get sh_name
index = section_head_table[i]->sh_name;
//2. find string_table
string_table = section_head_table[e_shstrndx]->sh_offset;
//3. get name
name = string_table + index;

 

参考资料

1. ELF文件格式解析

2. ELF文件格式分析(ELF文件头)

3. ELF文件-段和程序头

4. ELF文件-节和节头

5. 字符串表

标签:Elf64,文件,Word,Section,ELF,Elf32,sh,table,结构
来源: https://www.cnblogs.com/from-zero/p/12621039.html