#define EI_NIDENT 16
typedef __u32 Elf32_Addr;
typedef __u16 Elf32_Half;
typedef __u32 Elf32_Off;
typedef __s32 Elf32_Sword;
typedef __u32 Elf32_Word;
typedef __u64 Elf64_Addr;
typedef __u16 Elf64_Half;
typedef __s16 Elf64_SHalf;
typedef __u64 Elf64_Off;
typedef __s32 Elf64_Sword;
typedef __u32 Elf64_Word;
typedef __u64 Elf64_Xword;
typedef __s64 Elf64_Sxword;

typedef struct elf32_hdr { unsigned char e_ident[EI_NIDENT];// 初始字节将文件标记为目标文件,并提供与机器无关的数据,通过这些数据可以解码和解释文件的内容 Elf32_Half e_type;// 该成员标识目标文件类型 Elf32_Half e_machine;// 指定单个文件所需的体系结构。如EM_386、EM_ARM、EM_MIPS Elf32_Word e_version;// 目标文件的版本。 EV_CURRENT 1 Elf32_Addr e_entry;// 该成员提供系统首先将控制权转移到的虚拟地址,从而开始该过程。如果文件没有关联的入口点,则此成员为零。 Elf32_Off e_phoff;// 该成员保存程序头表的文件偏移量(以字节为单位)。如果文件没有程序头表,则该成员为零。program header offset Elf32_Off e_shoff;// 该成员保存节头表的文件偏移量(以字节为单位)。如果文件没有节头表,则此成员为零。section header offset Elf32_Word e_flags;// 保存与文件关联的特定于处理器的标志. 如EF_ARM_EABI_VER5 0x05000000 Elf32_Half e_ehsize;// 保存ELF header的大小 Elf32_Half e_phentsize;// 保存文件程序头表中一个条目的大小(以字节为单位)。每个program header大小相同 Elf32_Half e_phnum;// program header的个数因此,e_phentsize的乘积 e_phnum给出表的大小(以字节为单位)。如果文件没有程序头表,e_phnum 则将其值保持为零。 Elf32_Half e_shentsize;// 定义 section header 的大小 Elf32_Half e_shnum;// 定义section header的个数。因此,e_shentsize和 的乘积e_shnum给出了节头表的大小(以字节为单位)。如果文件没有节头表, e_shnum则将其值保持为零。 Elf32_Half e_shstrndx;// 该成员保存与节名称字符串表关联的条目的节标题表索引。如果该文件没有节名称字符串表,则该成员将保留value SHN_UNDEF } Elf32_Ehdr;
typedef struct elf64_hdr {
  unsigned char e_ident[EI_NIDENT];
  Elf64_Half e_type;
  Elf64_Half e_machine;
  Elf64_Word e_version;
  Elf64_Addr e_entry;
  Elf64_Off e_phoff;
  Elf64_Off e_shoff;
  Elf64_Word e_flags;
  Elf64_Half e_ehsize;
  Elf64_Half e_phentsize;
  Elf64_Half e_phnum;
  Elf64_Half e_shentsize;
  Elf64_Half e_shnum;
  Elf64_Half e_shstrndx;
} Elf64_Ehdr;

  

e_ident: 占16个字节, 每个字节( 从0开始)含义如下:
第0字节: 0x7f 含义:文件识别。 名称:EI_MAG0
第1字节: E 含义:文件识别      名称:EI_MAG1
第2字节: L 含义:文件识别      名称:EI_MAG2
第3字节: F 含义:文件识别          名称:EI_MAG3
第4字节: [012] 含义:文件类别。 0表示未知,1表示32位,2表示64位  名称:EI_CLASS
第5字节: [012] 含义:指定目标文件容器使用的数据结构和目标文件部分中包含的数据的编码。 0表示未知,1表示小端模式,2表示大端模式  名称:EI_DATA
小端模式:低地址放低数据。 如有一个数据0x0102 低数据是02 较高数据是01 那么在文件(内存)中,存放是0201。 02低数据放在前面。 因为前面的就是低地址,从小到大
大端模式:最高有效字节占据最低地址。如有一个数据0x01020304, 那么在文件(内存)中就是01020304 在这样的方式存放的。 
这个很好记,以人类思维方式存放的,就是大端模式。 否则就是小端。
第6字节: [01] 含义:文件版本。 0表示无效,1表示当前版本。    名称:EI_VERSION
第7字节: [0-255] 含义:指定系统或者指令架构。 0表示未指定 名称:EI_OSABI
第8字节: [0-255] 含义:ABI版本。 0表示未指定 名称:EI_ABIVERSION
第9-15字节: [0-255] 含义:未使用的字节。 用0填充 名称:EI_PAD
e_type: 标识目标文件类型
0: 没有可执类型
1: 可重定位文件
2: 可执行文件
3: 共享对象文件
4: core 文件
0xfe00: 特定于操作系统
0xfeff:
特定于操作系统
0xff00: 特定于处理器
0xffff: 特定于处理器

e_shstrndx:  是str section索引. 可以用js理解, sections = [".bss", ".data", ".rodata", ".shstrtab"]; e_shstrndx的值就是3
字符串section描述了,整个文件常量字符串信息。

elf 之  header_编程