登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

她三哥

Tsange

 
 
 

日志

 
 

ELF文件-节和节头  

2015-05-05 12:24:40|  分类: Reverse |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
目标文件中可以包含很多个(Section),每一个节都使用一个名为节头(Section Header)的结构体来描述,所有这些节的节头都被登记在一张称为节头部表(Section Header Table)的数组里面,于是,所有节的信息就被间接滴登记在节头部表中了;这样,通过节头部表中的每一个表项,就可以定位到对应的节了;
在ELF文件头部结构体Elf32_Ehdr/Elf64_Ehdr中的成员e_shoff给出节头部表的起始位置在ELF文件中相对于文件开始处的偏移地址,成员e_shnum给出节头部表中包含有多少个表项,成员e_shentsize给出每一个表项的大小,于是,就可以很方便地定位一个节了;
节头在节头部表中的位置索引的定义:
SHN_UNDEF     = 0     : 未定义的、不存在的节的索引;
SHN_LORESERVE = 0xff00: Start of reserved indices
SHN_LOPROC    = 0xff00: Start of processor-specific
SHN_BEFORE    = 0xff00: Order section before all others(Solaris)
SHN_AFTER     = 0xff01: Order section after all others(Solaris)
SHN_HIPROC    = 0xff1f: End of processor-specific
SHN_LOOS      = 0xff20: Start of OS-specific
SHN_HIOS      = 0xff3f: End of OS-specific
SHN_ABS       = 0xfff1: Associated symbol is absolute
SHN_COMMON    = 0xfff2: Associated symbol is common
SHN_XINDEX    = 0xffff: Index is in extra table
SHN_HIRESERVE = 0xffff: End of reserved indices

通常,目标文件中包含有众多的节,节区是目标文件中最大的部分,它们需要满足以下条件:
条件1:目标文件中的每一个节都一定对应有一个节头(Section Header),节头中包含有对应节的描述信息;但是,有的节头可以没有对应的节,而只是一个空的节头;
条件2:每一个节所占用的空间是连续的;
条件3:各个节之间不能相互重叠;
条件4:在目标文件中,节与节之间可能会存在一些多余的字节,这些字节不属于任何节;

节头(Section Header)使用结构体Elf32_Shdr/Elf64_Shdr来描述,其定义如下:
struct Elf32_Shdr
{
  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 */
};
struct Elf64_Shdr
{
  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 */
};
------字段详解------
1、sh_name:
该字段指出节的名字索引;节名字字符串以'\0'结尾,统一存储在字符串表中,然后使用该字段存储节名字字符串在字符串表中的索引位置;

2、sh_type:
该字段指出节的类型(Section Type);有效的节类型取值如下:
SHT_NULL     = 0: 该值表示该节是一个无效(非活动)的节头,它没有对应的节;该节头中的其它成员也都是无意义的;
SHT_PROGBITS = 1: 该值表示该节所包含的信息是由程序定义的,该节内容的格式和含义都是由程序来决定的;
SHT_SYMTAB   = 2: Symbol table;SHT_SYMTAB和SHT_DYNSYM这两类节中都含有符号表;目前,目标文件中最多只能各包含一个这两种节,但以后会取消这种限制;一般来说,SHT_SYMTAB提供的符号用于在创建目标文件的时候编辑链接,在运行期间也有可能会用于动态链接;SHT_SYMTAB包含完整的符号表,它往往会包含很多在运行期间(动态链接)用不到的符号;所以,一个目标文件可以再有一个SHT_DYNSYM节,它含有一个较小的符号表,专门用于动态链接;
SHT_STRTAB   = 3: String table;该值表示该节是一个字符串表;目标文件中可以包含多个字符串表节;
SHT_RELA     = 4: Relocation entries with addends;该值表示该节是一个重定位节,包含有带明确加数(Addend)的重定位项,对于32位类型的目标文件来说,这个加数就是Elf32_Rela;一个目标文件可能含有多个重定位节;
SHT_HASH     = 5: Symbol hash table;该值表示该节包含一张哈希表;所有参与动态链接的目标文件都必须包含一个符号哈希表;目前,一个目标文件中最多只能有一个哈希表,但这一限制以后可能取消;
SHT_DYNAMIC  = 6: Dynamic linking information;该值表示该节包含的是动态链接信息;目前,一个目标文件中最多只能有一个SHT_DYNAMIC节,但这一限制以后可能取消;
SHT_NOTE     = 7: Notes;该值表示该节中包含的信息用于以某种方式来标记文本文件;
SHT_NOBITS   = 8: Program space with no data (bss);该值表示该节的内容是空的,节并不占用实际空间;这时字段sh_offset只代表一个逻辑上的位置概念,并不代表实际的内容;
SHT_REL      = 9: Relocation entries,no addends;该值表示该节是一个重定位节,包含有带明确加数的重定位项,对于32位类型的目标文件来说,这个加数就是Elf32_Rel;一个目标文件中可能包含有多个重定位节;
SHT_SHLIB    = 10: Reserved;
SHT_DYNSYM   = 11: Dynamic linker symbol table;
SHT_INIT_ARRAY = 14: Array of constructors;
SHT_FINI_ARRAY = 15: Array of destructors;
SHT_PREINIT_ARRAY = 16: Array of pre-constructors;
SHT_GROUP         = 17: Section group;
SHT_SYMTAB_SHNDX  = 18: Extended section indeces;
SHT_NUM           = 19: Number of defined types;
SHT_LOOS          = 0x60000000: Start OS-specific;
SHT_GNU_ATTRIBUTES= 0x6ffffff5: Object attributes;
SHT_GNU_HASH      = 0x6ffffff6: GNU-style hash table;
SHT_GNU_LIBLIST   = 0x6ffffff7: Prelink library list;
SHT_CHECKSUM      = 0x6ffffff8: Checksum for DSO content;
SHT_LOSUNW        = 0x6ffffffa: Sun-specific low bound;
SHT_SUNW_move     = 0x6ffffffa
SHT_SUNW_COMDAT   = 0x6ffffffb
SHT_SUNW_syminfo  = 0x6ffffffc
SHT_GNU_verdef    = 0x6ffffffd: Version definition section;
SHT_GNU_verneed   = 0x6ffffffe: Version needs section;
SHT_GNU_versym    = 0x6fffffff: Version symbol table;
SHT_HISUNW        = 0x6fffffff: Sun-specific high bound;
SHT_HIOS          = 0x6fffffff: End OS-specific type;
SHT_LOPROC        = 0x70000000: Start of processor-specific;
SHT_HIPROC        = 0x7fffffff: End of processor-specific;
SHT_LOUSER        = 0x80000000: Start of application-specific;
SHT_HIUSER        = 0x8fffffff: End of application-specific;

3、sh_flags:
该字段指出该节的一些属性信息;节的属性由一系列的标志比特位组成,各个比特位定义了节的不同属性,当某种属性被设置时,相应的标志比特位被设置为1,反之则设置为0;未定义的标志比特位全部被设置为0;
下面是有效的标志比特位的取值定义:
SHF_WRITE    =(1 << 0): 如果该位被设置为1,表示该节所包含的内容在进程运行过程中是可写的;
SHF_ALLOC    =(1 << 1): 如果该位被设置为1,表示该节所包含的内容在进程运行过程中需要占用内存单元;并不是所有节都会占用实际的内存,有一些起控制作用的节,在目标文件映射到进程地址空间时,并不需要占用内存;
SHF_EXECINSTR=(1 << 2): 如果该位被设置为1,表示该节所包含的内容是指令代码;
SHF_MERGE    =(1 << 4): Might be merged
SHF_STRINGS  =(1 << 5): Contains nul-terminated strings
SHF_INFO_LINK=(1 << 6): sh_info contains SHT index
SHF_LINK_ORDER=(1 << 7): Preserve order after combining
SHF_OS_NONCONFORMING=(1 << 8): Non-standard OS specific handling required
SHF_GROUP    =(1 << 9) : Section is member of a group
SHF_TLS      =(1 << 10): Section hold thread-local data
SHF_MASKOS   =0x0ff00000: OS-specific
SHF_MASKPROC =0xf0000000: Processor-specific
HF_ORDERED   =(1 << 30): Special ordering requirement (Solaris)
SHF_EXCLUDE  =(1 << 31): Section is excluded unless referenced or allocated (Solaris)

4、sh_addr:
该字段指出该节在内存中的起始地址;如果该节的内容需要被映射到进程地址空间中去,该字段指定映射的起始地址;如果不需要映射,该字段的是为0;

5、sh_offset:
该字段指出该节所在的位置;该字段的值是该节的第一个字节在文件中的位置,即:相对于文件开始位置处的偏移量;单位是字节;如果该节的类型是SHT_NOBITS,则 表明这个节的内容是空的,并不占用实际的空间,这时,sh_offset只代表一个逻辑上的位置概念,并不代表实际的内容;

6、sh_size:
该字段指出该节的大小,以字节为单位;如果该节的类型是SHT_NOBITS,该字段的值仍然可能为非零,但没有实际意义;

7、sh_link:
该字段是一个索引值,指向节头部表中该节所对应的位置;根据节的类型不同,该字段的意义也有所不同;

8、sh_info:
该字段含有该节的附加信息,根据节的类型不同,该字段的意义也有所不同;

9、sh_addralign:
该字段指出该节的内容如何对齐字节,即:该节中的内容的地址应该向多少个字节对齐;也就是说,该节内容在进程地址空间中的映射地址sh_addr必须是一个向sh_addralign对齐的值,即,能够被sh_addralign整除的值;目前,sh_addralign字段的取值只能是0、1、或2的整数倍;如果该字段的值是0或1,表明该节没有字节对齐的约束;

10、sh_entsize:
有些节的内容是一张表,其中每一个表项的大小是固定的,比如符号表;对于这种表来说,该字段指明这种表中的每一个表项的大小;如果该字段的值为0,则表示该节的内容不是这种表格;

特殊节:
在ELF文件中,有一些特定的节是预先定义好的,其内容是指令代码或控制信息;这些预先定义好的节专门为操作系统所使用,对于不同的操作系统,这些节的类型和属性会有所不同;
在构建可执行程序时,链接器(Linker)可能需要把一些独立的目标文件和库文件链接在一起,在这个过程中,链接器要解析各个文件中的相互引用,调整某些目标文件中的绝对引用,并重定位指令码;当运行一个已经构建好的可执行程序时,在链接和装载过程中,需要读取目标文件的内容并把它们装入到各个节中;
每种操作系统都有自己的一套链接模型,但总的来说,不外乎静态链接和动态链接;
静态链接:所有的目标文件和动态链接库被静态地绑定在一起,所有的符号都被解析出来,所创建的目标文件是完整的,运行时不依赖于任何外部的库;
动态链接:所有的目标文件、系统共享资源以及共享库,以动态的形式链接在一起,外部库文件的内容没有被完整地拷贝进来;如果创建的是可执行程序,则程序在运行时,构建可执行文件时所依赖的那些库文件必须在系统中能够找到,把它们一并装载之后,程序才能够运行起来;运行期间如何解析那些动态链接进来的符号引用,不同的系统有各自不同的方式;
这些预先定义好的节,有些节包含调试信息,比如:.debug和.line节,还有些节包含程序控制信息,比如:.bss、.data、.data1、.rodata和.rodata1,等等;
那些包含程序或控制信息的节,由系统使用,有指定的类型和属性;它们中的大多数都将用于链接过程;动态链接过程所需要的信息由.dynsym、.dynstr、.interp、.hash、.dynamic、.rel、.rela、.got、.plt等节提供;.init节和.fini节用于进程的初始化和终止过程;
下面是一些常见的特殊节:
.text: 该节中包含程序的指令代码;
.init: 该节包含进程初始化时要执行的程序指令;当程序开始运行时,系统会在进程进入主函数之前先执行这一个节中的指令代码;
.fini: 该节中包含进程终止时要执行的指令代码;当程序退出时,系统会执行这个节中的指令代码;
.bss : 该节中包含目标文件中未初始化的全局变量;一般情况下,可执行程序在开始执行时,系统会把这一段内容清零;但是在运行期间的.bss段是由系统动态初始化而成的,目标文件中的.bss节中并不包含任何内容,其长度为0,所以它的节类型为SHT_NOBITS;
.data/.data1:这两个节用于存放程序中已被初始化过的全局变量;在目标文件中,它们是要占用实际的存储空间的,这一点与.bss节不同;
.rodata/.rodata1:这两个节中包含程序中的只读数据,在程序装载时,它们一般会被装入到进程地址空间中的那些只读的段中;
.dynamic: 该节中包含动态链接信息,并且可能有SHF_ALLOC和SHF_WRITE等属性;
.dynstr : 该节中包含用于动态链接的字符串,一般是那些与符号表相关的名字;
.dynsym : 该节中包含动态链接符号表;
.got    : 该节中包含全局偏移表(global offset table);
.plt    : 该节中包含函数链接表(function link table);
.hash   : 该节中包含一张哈希表;
.interp : 该节中包含ELF文件解析器的路径名;如果该节被包含在某个可装载的段中,那么该节的属性中应设置SHF_ALLOC标志位,苟泽不设置此标志位;
.strtab : 该节用于存放字符串,主要是那些符号表项的名字;如果一个目标文件中有一个可装载的段,并且其中含有符号表,则该节的属性中应该有SHF_ALLOC属性;
.symtab : 该节用于存放符号表;如果一个目标文件中有一个可装载的段,并且其中含有符号表,则该节的属性中应该有SHF_ALLOC属性;
.shstrtab: 该节是节名字表,含有所有其它节的名字;
.comment: 该节中包含版本控制信息;
.line   : 该节中包含调试信息,包括哪些调试符号的行号,为程序指令码与源文件的行号建立联系;
.note   : 该节中包含注释;
.relX/.relaX:这两个节中包含重定位信息;如果该节被包含在某个可装载的段中,则该节的属性中应设置SHF_ALLOC标志位;X表示那些需要重定位的节的名字;比如:.text节的重定位节的名字将是.rel.text或.rela.text;
  评论这张
 
阅读(3998)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018