1——man elf的翻译——ELF header (Ehdr)

8 篇文章 0 订阅

学习ptrace,学习linux本质,elf是无法绕开的一个基础知识。所有的网上知识都没有man elf来的准确和优秀,唯一艰难的一点就是英文。这么多年,我也没在网上找到一个翻译版本,所以我觉得好好阅读一下,并用自己的话翻译出来于大家分享是一件不错的事情。抽空我会进行翻译和更新。在翻译结束之前就暂时不排版了,等都结束了,我会再汇总,认真设计一下结构。

名字
    elf——可执行和链接格式文件。就是这个意思,linux上允许的一切程序和生成程序的中间文件都是elf格式,
    无一例外。
描述
    <elf.h>头文件定义了elf二进制文件的格式,包括,可执行文件,.o临时文件,core文件,.a和.so共享文件。
    可执行文件的elf文件格式是这样的:首先是elf header,紧跟着是program header table或者section header table,
    或者他们两个都有。elf header一般是在文件的0偏移位置开始,也就是文件开头的意思,从第一个字节开始。
    program header table和section header table在文件中的偏移量是在elf header中定义的。它们两个呀,
    描述的是elf文件除了elf header之外,剩下的所有部分的细节,全在里面。
    基本格式
    下面要描述的这些个变量名的类型是这么个意思。大写的N,代表了32或者是64,因为现在主流的操作系统都是
    32位或者64位:
        ElfN_Addr       Unsigned program address, uintN_t
        ElfN_Off        Unsigned file offset, uintN_t
        ElfN_Section    Unsigned section index, uint16_t
        ElfN_Versym     Unsigned version symbol information, uint16_t
        Elf_Byte        unsigned char
        ElfN_Half       uint16_t
        ElfN_Sword      int32_t
        ElfN_Word       uint32_t
        ElfN_Sxword     int64_t
        ElfN_Xword      uint64_t
        
    所有的数据结构的格式都是natural的,就按正常的逻辑去思考即可,在需要字节对齐的时候也可以去对齐。

ELF header(EHdr)
    它是用Elf32_Ehdr和Elf64_Ehdr结构体来描述的:
    
    #define EI_NIDENT 16

           typedef struct {
               unsigned char e_ident[EI_NIDENT];
               uint16_t      e_type;
               uint16_t      e_machine;
               uint32_t      e_version;
               ElfN_Addr     e_entry;
               ElfN_Off      e_phoff;
               ElfN_Off      e_shoff;
               uint32_t      e_flags;
               uint16_t      e_ehsize;
               uint16_t      e_phentsize;
               uint16_t      e_phnum;
               uint16_t      e_shentsize;
               uint16_t      e_shnum;
               uint16_t      e_shstrndx;
           } ElfN_Ehdr;
        
    e_ident    是一个字符串数组,描述说明了这个文件。独立于处理器和文件剩下的部分,不相关完全独立。可以
                    说为空也没事。别看总共就16个字节,全部都是用宏来定义的,宏的前缀是EI_。开始的前4个字节是
                    固定的:0x7f,'E',‘L’,‘F’。内容如果也用宏表示的话,前缀是ELF这3个大写字母。
            
                    EI_MAG0    magic number的第1个字节,必须填写为ELFMAG0(0:0x7f)
                    EI_MAG1    magic number的第2个字节,必须填写为ELFMAG1(1:‘E’)
                    EI_MAG2    magic number的第3个字节,必须填写为ELFMAG2(2:‘L’)
                    EI_MAG3    magic number的第4个字节,必须填写为ELFMAG3(3:‘F’)
                    EI_CLASS 第5个字节,确定二进制文件的结构:
                            ELFCLASSNONE    this class无效。
                            ELFCLASS32        32位结构,支持4字节对齐。
                            ELFCLASS64        64位结构。
                    EI_DATA        第6个字节,确定数据的大小端:
                            ELFDATANONE        不确定。
                            ELFDATA2LSB        Two's complement,可能是二进制补码的意思,小端。
                            ELFDATA2MSB        Two's complement,可能是二进制补码的意思,大端。
                    EI_VERSION       第7个字节,文件specification的版本:
                                                            EV_NONE    无效版本。
                                                            EV_CURRENT    当前版本。
                    EI_OSABI     第8个字节,(ABI是运行程序接口的意思)确定操作系统和ABI。ELF其它的一些数据结构
                                         可能有标志和数值指明特定平台。它们都是根据这个字节定义哒。例如:
                                                ELFOSABI_NONE        Same as ELFOSABI_SYSV
                                                ELFOSABI_SYSV        UNIX System V ABI
                                                ELFOSABI_HPUX        HP-UX ABI
                                                ELFOSABI_NETBSD      NetBSD ABI
                                                ELFOSABI_LINUX       Linux ABI
                                                ELFOSABI_SOLARIS     Solaris ABI
                                                ELFOSABI_IRIX        IRIX ABI
                                                ELFOSABI_FREEBSD     FreeBSD ABI
                                                ELFOSABI_TRU64       TRU64 UNIX ABI
                                                ELFOSABI_ARM         ARM architecture ABI
                                                ELFOSABI_STANDALONE  Stand-alone (embedded) ABI
                     EI_ABIVERSION    第9字节,ABI的版本。有些ABI在两个不同的版本中是不相容的,这个字段就是做
                                                    这个区分使用。值的话和上一个字节(第8字节)有关。
                                                    Applications conforming to this specification use the value 0
                     EI_PAD    padding的开始。这是保留字段,默认填0.程序读取它们的话应该忽略它们。留着以后用。
                     EI_NIDENT    e_ident的size。

    e_type    identifies the object file type:也就是本文件的类型,因为咱们linux的这种elf文件也包含很多种
                            ET_NONE    不知道类型
                            ET_REL        可重定向文件
                            ET_EXEC     可执行文件
                            ET_DYN       共享object
                            ET_CORE    core文件

    e_machine    机器结构:
                 EM_NONE         An unknown machine
                 EM_M32          AT&T WE 32100
                 EM_SPARC        Sun Microsystems SPARC
                 EM_386          Intel 80386
                 EM_68K          Motorola 68000
                 EM_88K          Motorola 88000
                 EM_860          Intel 80860
                 EM_MIPS         MIPS RS3000 (big-endian only)
                 EM_PARISC       HP/PA
                 EM_SPARC32PLUS  SPARC with enhanced instruction set
                 EM_PPC          PowerPC
                 EM_PPC64        PowerPC 64-bit
                 EM_S390         IBM S/390
                 EM_ARM          Advanced RISC Machines
                 EM_SH           Renesas SuperH
                 EM_SPARCV9      SPARC v9 64-bit
                 EM_IA_64        Intel Itanium
                 EM_X86_64       AMD x86-64
                 EM_VAX          DEC Vax

    e_version    
            文件版本:
            EV_NONE    未知版本
            EV_CURRENT    当前版本。
    
    e_entry    系统第一次跳转的虚拟地址,也就是程序开始的位置。如果文件没有进入地址,它就是zero。
    
    e_phoff    保存的是program header table's file 以bytes为单位的偏移量。如果没有,就是zero。
    
    e_shoff    保存的是section header table‘s file 以bytes为单位的偏移量。如果没有,就是zero。

    e_flags    保存的是与文件相关的processor-specific标志。标志的名字以EF_’machine_flag'为格式。
            到现在为止,还没有标志的定义,也就是现在还空缺,没有意义。
            
    e_ehsize
            保存的是 ELF header 的大小。
    
    e_phentsize
            保存的是文件的 program header 的一个 entry 的大小,所有的 entry 的大小是相同的。
    
    e_phnum    保存的是在 program header table 里面 entry 的数量。也就是说 e_phentsize 和 e_phnum
            决定了 table 的大小。如果一个文件没有 program header , e_phnum就是0.
            
            如果 entry 的数量 >= PN_XNUM(0xffff)的话,e_phnum 为 PN_XNUM,真正的 entry 个数值
            被保存在 initial entry 的 sh_info中,否则,initial entry 的 sh_info 赋值0.

            PN_XNUM 被定义为0xffff,是 e_phnum 的最大值,指明了实际被分配的 program header 的
            数量。
            
    e_shentsize
            保存了 section's header 的大小。 a section header 就是 the section header table 的
            入口;所有的 entry 的大小是相同的。
            
    e_shnum    保存的是 section header table 的 entry 的数量。也就是说 e_shentsize 和 e_shnum 
            决定了 section header table 的大小。如果一个文件没有 section header table, e_shnum
            就是0.
            
            如果 entry 的数量 >= SHN_LORESERVE(0xff00)的话,e_shnum wei 0,真正的 entry 个数值
            被保存在 initial entry 的 sh_size中,否则,initial entry 的 sh_size 赋值0.
            
    e_shstrndx
            保存了与 section name table 相关联的 section header table 的索引号。如果文件没有
            section name table,e_shstrndx 赋值 SHN_UNDEF。
            
            如果section name table 中的 section 的索引号 >= SHN_LORESERVE(0xff00),e_shstrndx赋值
            SHN_XINDEX(0xffff),然后真正的索引号放在 initial entry 的 sh_link 中。否则,sh_link
            赋值0.
            
            (这里多次提到了 initial entry,值的是 initial entry in section header table)
 

           这篇文章今天又做了一些补充,把 ELF header 的说明补全了。以后就按照这种大块去贴出来,

    下一篇是 Program header。
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值