画布1
ELF(Executable and Linking Format)
  ELF Header
    unsigned char e_ident[EI_NIDENT];
      EI_NIDENT=16,e_ident是16个字节的标识码,包括以下信息:
      0x7F454C46:ELF头标识
      N-bit architectures
        0x0 非法目标文件
        0x1 32位目标文件
        0x2 64位目标文件
      EI_DATA:数据编码格式
        0x0 非法编码格式
        0x1 LSB小端对齐
        0x2 MSB大端对齐
      EI_VERSION:ELF文件头版本
        0x0 EV_NONE:无效ELF文件头版本
        0x1 EV_CURRENT:当前ELF文件头版本
        0x EI_OSABI
      EI_OSABI:指明该文件的目标操作系统和应用二进制接口
        0x3 ELFOSABI_LINUX
        0x61 ELFOSABI_ARM
        ...
      EI_PAD~EI_NIDENT-1:这个区间暂不使用,留作以后拓展
      EI_NIDENT:e_ident数组的大小
    u16 e_type:
      0x0 ET_REL:未知文件类型
      0x1 ET_REL:可重定位文件
      0x2 ET_EXEC:可执行文件
      0x3 ET_DYN:动态链接库文件
      0x4 ET_CORE:Core文件
      0xFF00 ET_LOPROC~0xFFFF ET_HIPROC:特定处理器文件类型扩展上下边界
    u16 e_machine:
      0x3 EM_386:Intel Architecture
      0x7 EM_860:Intel 80860
      0x28 EM_ARM:ARM
      0x3E EM_X86_64:X86_84
      0xB7 EM_AARCH64:AARCH64
      ...
    u32 e_version:目标文件版本
      0x1 EV_CURRENT:当前版本号
      0x0 EV_NONE:非法版本号
    ElfN_Addr e_entry:程序入口的虚拟地址
    ElfN_Off e_phoff:程序头表的文件偏移
    ElfN_Off e_shoff:节头表的文件偏移
    u32 e_flags:处理器相关的标志位
    u16 e_ehsize:ELF Header的大小,字节为单位
    u16 e_phentsize:程序头表中每个表项的大小,字节为单位
    u16 e_phnum:程序头表中表项个数
    u16 e_shentsize:节头表中每个表项的大小,字节为单位
    u16 e_shnum:节头表中表项个数
    u16 e_shstrndx:节头表中存储节名字的.shstrtab节的索引
  Program Header Table
    uN p_type:段类型
      0x0 PT_NULL:本程序头未使用,应忽略
      0x1 PT_LOAD:本程序头指向一个可装载的段
      0x2 PT_DYNAMIC:所指向的段阐明了动态连接的信息
      0x3 PT_INTERP:本段指向一个字符串,这个字符串是ELF解析器的路径(仅对可执行文件有意义)
      0x4 PT_NOTE:本段包含一些辅助信息
      0x5 PT_SHLIB:该段类型是保留的
      0x6 PT_PHDR:程序头表所覆盖的段只是整个程序的一部分时,才会出现一次此表项,且出现在可装载段的表项前
      ...
    ElfN_Off p_offset:本段的文件偏移
    ElfN_Addr p_vaddr:本段在进程空间中的虚拟地址
    ElfN_Addr p_paddr:本段在进程空间中的物理地址(多数情况下无用)
    uN p_filesz:本段在文件中的大小,字节为单位
    uN p_memsz:本段在内存中的大小字节为单位
    uN p_flags:本段的权限标志
      0x0 PF_None
      0x1 PF_Exec
      0x2 PF_Write
      0x3 PF_Write_Exec
      0x4 PF_Read
      0x5 PF_Read_Exec
      0x6 PF_Read_Write
      0x7 PF_Read_Write_Exec
    uN p_align:本段对齐
      0x0/0x1 没有对齐要求
      2的幂次数 表示对齐要求
  Section Header Table
    u32 sh_name:本节的名字,指向节名字表.shstrtab的索引
      0x00000000(SHN_UNDEF)节头表第一项总是未定义
      ,bss:包含目标文件中未初始化的全局变量,在运行期间的bss段是由系统初始化而成的，在目标文件中.bss节并不包含任何内容，其长度为0，它的节类型为SHT_NOBITS
      .comment:本节包含版本控制信息(SHT_PROGBITS)
      .ctors:本节包含指向C++构造函数的初始化指针(SHT_PROGBITS)
      .data:本节包含有助于程序内存镜像的初始化数据(SHT_PROGBITS)
      .data1:同上
      .debug:本节包含用于符号调试的信息(SHT_PROGBITS)
      .dtors:本节包含指向C++析构函数的初始化指针(SHT_PROGBITS)
      .dynamic:本节包含动态连接信息(SHT_DYNAMIC)
        ElfN_Dyn
          sN d_tag:d_tag控制着对d_un的解析
            0x0 DT_NULL:用于标记.DYNAMIC数组的结束
            0x1 DT_NEEDED:此元素指明了一个所需的库的名字,是一个指向由"DT_STRTAB"所标记的字符串表中的索引
            0x2 DT_PLTRELSZ:此元素含有与过程链接表(.plt)相关的所有重定位项的总大小,以字节为单位
            0x3 DT_PLTGOT:此元素包含过程链接表或全局偏移表的地址
            0x4 DT_HASH:此元素含有符号哈希表的地址
            0x5 DT_STRTAB:此元素包含字符串表的地址,此表中包含符号名、库名等
            0x6 DT_SYMTAB:此元素包含符号表的地址
            0x7 DT_RELA:此元素包含一个重定位表的地址
            0x8 DT_RELASZ:此元素持有DT_RELA相应的重定位表的大小,以字节为单位
            0x9 DT_RELAENT:此元素持有DT_RELA相应的重定位表项的大小,以字节为单位
            0xA DT_STRSZ:此元素持有字符串表的大小,以字节为单位
            0xB DT_SYMENT:此元素持有符号表项的大小,以字节为单位
            0xC DT_INIT:此元素持有初始化函数的地址
            0xD DT_FINI:此元素持有终止函数的地址
            0xE DT_SONAME:此元素持有一个字符串表中的偏移量，该位置存储了一个以“null”结尾的字符串,是一个共享目标的名字.相应的字符串表由DT_STRTAB指定
            0xF DT_RPATH:此元素持有一个字符串表中的偏移量，该位置存储了一个以“null”结尾的字符串,是一个用于搜索库文件的路径名.相应的字符串表由DT_STRTAB指定
            0x10 DT_SYMBOLIC:在共享目标文件中,此元素的出现与否决定了动态链接器解析符号时所用的算法
            0x11 DT_REL:此元素与DT_RELA相似,只是它所指向的重定位表中,“加数”是隐含的而不是显式的
            0x12 DT_RELSZ
            0x13 DT_RELENT
            0x14 DT_PLTREL:本成员指明了过程链接表所引用的重定位项的类型
            0x15 DT_DEBUG:本成员用于调试,格式未明确定义
            0x16 DT_TEXTREL:如果此元素出现,重定位过程中链接编辑器也可以修改只读段,否则不能
            0x17 DT_JMPREL:此类型元素如果存在的话,其d_ptr成员是与过程链接表单独关联的重定位项地址.本项指向第一个重定位项的位置.此操作与后期绑定有关
            0x18 DT_BIND_NOW:如果此元素存在的话，动态链接器必须在程序开始执行以前,完成所有包含此项的目标的重定位工作
            0x70000000 DT_LOPROC~0x7fffffff DT_HIPROC:为处理器保留
          union d_un
            uN d_val
            uN d_ptr
      .dynstr:此节含有用于动态连接的字符串,一般是那些与符号表相关的名字.字符串以“null”结尾(SHT_STRTAB)
      .dynsym:本节包含动态链接符号表.动态链接符号表包含所有外部引入的符号,表项结构同.symtab节的ElfN_Sym(SHT_DYNSYM)
      .fini:此节包含进程终止时要执行的程序指令(SHT_PROGBITS)
      .gnu.version:包含版本符号表,是一个ElfN_Half类型元素的数组(SHT_DNU_versym)
      .gnu.version_d:包含版本符号定义,是一个ElfN_Verdef结构体表(SHT_DNU_verdef)
      .gnu.version_r:包含版本符号所需的元素,是一个ElfN_Verneed结构体表(SHT_DNU_versym)
      .got:包含全局偏移表(SHT_PROGBITS)
        结构:格式和解析方法是依处理器而不同
          extern Elf32_Addr _GLOBAL_OFFSET_TABLE_[];
          extern Elf64_Addr _GLOBAL_OFFSET_TABLE_[];
        作用:把位置独立的地址重定向到绝对地址
      .got.plt:在解析函数绝对地址时,给.plt节起辅助作用.是PLT表的GOT表,结构同GOT表.此节可以懒加载,而,got节则不可(SHT_PROGBITS)
      .hash:包含一张符号哈希表(SHT_HASH)
      .init:此节包含进程初始化时要执行的程序指令(SHT_PROGBITS)
      .interp:此节含有ELF程序解析器的路径名(SHT_PROGBITS)
      .line:包含用于符号调试的行号信息,描述了程序源代码和机器代码之间的对应关系(SHT_PROGBITS)
      .note:包含注释项数组(SHT_NOTE)
        具体格式依处理器而定,给出参考格式
          u16 namesz:指定name长度
          u16 descsz:指定desc长度
          u16 type:给出desc的解释,每个系统提供商都会定义自己的type.当程序读取注释信息的时候，它必须同时辨认出name和type才能理解desc的内容
          name:null结尾的字符串,包含"null"长度由namesz指定
          desc:描述信息,长度由descsz指定
      .note.FNU-stack:此节在Linux目标文件中用于声明堆栈属性,向GNU链接器声明需要可执行堆栈(SHT_PROGBITS)
      .plt:包含函数连接表(SHT_PROGBITS)
        结构:该表中的每一项都占用3个字(12 字节),并且表的最后一项后跟nop指令
        作用:把位置独立的函数调用重定向到绝对地址
      .plt.got:意义不明
      .relNAME:含有重定位信息(SHT_REL)
      .relaNAME:同上(SHT_RELA)
      .rodata:本节包含程序中的只读数据(SHT_PROGBITS)
      .rodata:同上(SHT_PROGBITS)
      .shstrtab:保存节名字表.字符串以"null"结尾(SHT_STRTAB)
      .strtab:保存字符串表,主要是那些符号表项的名字.字符串以"null"结尾(SHT_STRTAB)
      .symtab:本节用于存放符号表(SHT_SYMTAB)
        Symbol Table(符号表)所包含的信息用于定位和重定位程序中的符号定义和引用,目标文件的其它部分通过一个符号在这个表中的索引值来使用该符号.第一项通常为0表示未定义的符号.ElfN_Sym
          u32 st_name:符号的名字,指向字符串表.strtab的索引值
          uN st_value:可能代表一个数值,也可以是一个地址,需要依照上下文进行解释
            在重定位文件中,如果一个符号关联的节的索引值是SHN_COMMON,st_value值指明节内容的对齐字节
            在重定位文件中,如果一个符号是已定义的,st_value值是该符号的起始地址在其所在节中的偏移量,而其所在的节的索引由st_shndx给出
            在可执行文件和共享库文件中,st_value不再是一个节内的偏移量,而是一个虚拟地址,直接指向符号所在的内存位置,此时则不需要st_shndx
            如果一个可执行文件中含有一个函数的引用,而这个函数是定义在一个共享目标文件中,那么在可执行文件中,针对那个共享目标文件的符号表应该含有这个函数的符号.符号表的st_shndx成员值为0x0 SHN_UNDEF,这就告诉了动态连接器,这个函数的符号定义并不在可执行文件中.
如果动态链接器已经在可执行文件中给这个符号申请了一个过程链接表项,而且符号表项的st_value成员不是0,那么st_value值就将是对应的过程链接表项中第一条指令的地址.
          uN st_size:符号的大小,如果一个符号的大小为0或者大小未知,则此值为0
          uchar st_info:符号的类型和属性.标识了“符号绑定(symbol binding)”、“符号类型(symbol type)”和“符号信息(symbol infomation)”三种属性
            符号绑定(Symbol Binding)
              0x0 STB_LOCAL:表明本符号是一个本地符号
              0x1 STB_GLOBAL:表明本符号是一个全局符号
              0x2 STB_WEAK:类似于全局符号,但是相对于STB_GLOBAL,该类符号的优先级更低
              0xD STB_LOPROC~0xF STB_HIPROC:为特殊处理器保留的属性区间
            符号类型(Symbol Types)
              0x0 STT_NOTYPE:本符号类型未指定
              0x1 STT_OBJECT:本符号是一个数据对象.如变量、数组等
              0x2 STT_FUNC:本符号是一个函数
              0x3 STT_SECTION:本符号与一个节相关联,用于重定位
              0x4 STT_FILE:本符号是一个文件符号
              0xD STT_LOPROC~0xF STT_HIPROC:为特殊处理器保留
            符号信息(symbol infomation):上面两者的结合体
          uchar st_other:定义了符号的可见性
          u16 st_shndx:本成员即指明了该符号表项相关联的节,是一个索引值,它指向相关联的节在节头表中的索引
            在重定位过程中,节的位置会改变,本数据成员的值也随之改变,继续指向节的新位置.当本数据成员指向下面三种特殊的节索引值时,本符号具有如下特别的意义:
              SHN_ABS:符号的值是绝对的，具有常量性，在重定位过程中，此值不需要改变
              SHN_COMMON:本符号所关联的是一个还没有分配的公共节.链接器将为本符号分配内存,st_value指明对齐方式,st_shndx指明分配字节数
              SHN_UNDEF:当一个符号指向第1节(SHN_UNDEF)时,表明本符号在当前目标文件中未定义
      .text:本节包含程序指令代码(SHT_PROGBITS)
      “NAME”由重定位所应用的部分提供,如.plt使用.rel.plt
        重定位表项ElfN_Rela/ElfN_Rel
          uN r_offset:此成员给出重定位所作用的位置.
对于重定位文件来说,此值是受重定位作用的存储单元在节中的字节偏移量;
对于可执行文件或共享目标文件来说,此值是受重定位作用的存储单元的虚拟地址
          uN r_info:此成员指定需要重定位的符号表索引以及要应用的重定位类型
            #define ELF32_R_SYM(x) ((x) >> 8)
            #define ELF32_R_TYPE(x) ((x) & 0xff)
          i32 r_addend(Rela):此成员指定常量加数,用于计算需要重定位的域的值
    u32 sh_type:本节的类型
      0x0 SHT_NULL:无效的节头,没有对应的节
      0x1 SHT_PROGBITS:本节所含有的信息由程序定义,格式和含义由程序决定
      0x2 SHT_SYMTAB:本节包含符号表,用于在创建目标文件时候编辑链接,运行期间可能用于动态链接
      0x3 SHT_STRTAB:本节是字符串表,一个目标文件可能包含多个本类型的节
      0x4 SHT_RELA:本节是重定位节,且含有带明确加数的重定位项,一个目标文件可包含多个本节
      0x5 SHT_HASH:本节包含一个符号哈希表,所有参与动态连接的目标文件都必须要包含一个符号哈希表
      0x6 SHT_DYNAMIC:此值表明本节包含的是动态连接信息
      0x7 SHT_NOTE:本节包含的信息用于以某种方式来标记本文件
      0x8 SHT_NOBITS:此值表明这一节的内容是空的,节并不占用实际的空间
      0x9 SHT_REL:本节是重定位节,且不含有带明确加数的重定位项
      0xA SHT_SHLIB:保留值,暂未指定语义
      0xB SHT_DYNSYM:本节包含一个较小的符号表,专门用于动态链接
      ...
    uN sh_flags:标明权限属性
      0x1 SHF_WRITE:如果此标志被设置，表示本节所包含的内容在进程运行过程中是可写的
      0x2 SHF_ALLOC:如果此标志被设置，表示本节内容在进程运行过程中要占用内存单元
      0x4 SHF_EXECINSTR:如果此标志被设置，表示此节内容是指令代码
      0xf0000000 SHF_MASHPROC:所有被此掩码覆盖的位都是保留做特殊处理器扩展用的
    uN sh_addr:如本节需要映射到进程空间中去,此成员指定映射的起始地址,否则置零
    uN sh_offset:本节的文件偏移
    uN sh_size:本节大小,字节为单位
    u32 sh_link:此成员是索引值,指向节头表中某个位置
    u32 sh_info:含有此节的附加信息
    uN sh_addralign:指明本节内容如何对齐字节
      0x0/0x1 没有对齐要求
      2的幂次数 表示对齐要求
    uN sh_entsize:对于内容是表的节来说,本成员指明表项大小,字节为单位
    图1-11 不同类型的节中sh_link和sh_info的不同意义
  视图
    链接视图:可以理解为目标文件的内容视图.静态链接器会以链接视图生成ELF文件,链接视图可以没有段表
    执行视图:可以理解为目标文件的内存视图.动态链接器会以执行视图解析ELF并动态链接,执行视图可以没有节表
  本思维导图tips
    uN:32-bit is u32(unsigned int by 32bit), 64-bit is u64(unsigned int by 64bit);
"i" is int, i32 is int32;
"s" is signed int, s32 is signed int32;
    "..." means that there are more items but I do not record them, maybe they are not very important for understanding ELF file.
    /* defination from jni.h */
/* 32-bit ELF base types. */
typedef __u32 Elf32_Addr;
typedef __u16 Elf32_Half;
typedef __u32 Elf32_Off;
typedef __s32 Elf32_Sword;
typedef __u32 Elf32_Word;
/* 64-bit ELF base types. */
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;