Elf文件简单分析

本文详细介绍了Elf文件的三个关键部分: ElfHeader、ProgramHeader和Section Header,并探讨了在解析过程中如何将字节转换为int、long和short等数据类型。通过阅读,你可以了解到Elf文件格式的基础知识以及Linux底层文件解析的挑战。

1.文件头ElfHeader

文件定义的数据结构,字段占用字节数

名称大小对齐目的
Elf32_Addr44无符号程序地址
Elf32_Half22无符号中的整数
Elf32_Off44无符号文件偏移
Elf32_Sword44有符号大整数
Elf32_Word44无符号大整数
unsigned char11无符号小整数

ElfHeader结构体:

#define EI_NIDENT 16
typedef struct {
       unsigned char e_ident[EI_NIDENT];//魔数
       ELF32_Half e_type;//类型
       ELF32_Half e_machine;//系统架构
       ELF32_Word e_version;//版本
       ELF32__Addr e_entry;//入口地址
       ELF32_Off e_phoff;//程序头偏移值
       ELF32_Off e_shoff;//段头偏移值
       ELF32_Word e_flags;//标志
       ELF32_Half e_ehsize;//elf文件头大小
       ELF32_Half e_phentsize;//程序头大小
       ELF32_Half e_phnum;//程序个数
       ELF32_Half e_shentsize;//段头大小
       ELF32_Half e_shnum;//段头个数
       ELF32_Half e_shstrndx;//字符串表段索引
}Elf32_Ehdr;

解析Elf文件 头部信息,根据字段对应的字节个数,读取字节就可以了

    type_32.hdr.e_ident = Utils.copyBytes(header, 0, 16);
    type_32.hdr.e_type = Utils.copyBytes(header, 16, 2);
    type_32.hdr.e_machine = Utils.copyBytes(header, 18, 2);
    type_32.hdr.e_version = Utils.copyBytes(header, 20, 4);
    type_32.hdr.e_entry = Utils.copyBytes(header, 24, 4);
    type_32.hdr.e_phoff = Utils.copyBytes(header, 28, 4);
    type_32.hdr.e_shoff = Utils.copyBytes(header, 32, 4);
    type_32.hdr.e_flags = Utils.copyBytes(header, 36, 4);
    type_32.hdr.e_ehsize = Utils.copyBytes(header, 40, 2);
    type_32.hdr.e_phentsize = Utils.copyBytes(header, 42, 2);
    type_32.hdr.e_phnum = Utils.copyBytes(header, 44,2);
    type_32.hdr.e_shentsize = Utils.copyBytes(header, 46,2);
    type_32.hdr.e_shnum = Utils.copyBytes(header, 48, 2);
    type_32.hdr.e_shstrndx = Utils.copyBytes(header, 50, 2);

2.程序头ProgramHeader

typedef struct {  
    Elf32_Word p_type;       //此数组元素描述的段的类型,或者如何解释此数组元素的信息。 
    Elf32_Off  p_offset;     //此成员给出从文件头到该段第一个字节的偏移
    Elf32_Addr p_vaddr;      //此成员给出段的第一个字节将被放到内存中的虚拟地址
    Elf32_Addr p_paddr;      //此成员仅用于与物理地址相关的系统中。System V忽略所有应用程序的物理地址信息。
    Elf32_Word p_filesz;     //此成员给出段在文件映像中所占的字节数。可以为0。
    Elf32_Word p_memsz;      //此成员给出段在内存映像中占用的字节数。可以为0。
    Elf32_Word p_flags;      //此成员给出与段相关的标志。
    Elf32_Word p_align;      //此成员给出段在文件中和内存中如何对齐。
} Elf32_phdr;

程序头字段的信息读取

    phdr.p_type = Utils.copyBytes(header, 0, 4);
    phdr.p_offset = Utils.copyBytes(header, 4, 4);
    phdr.p_vaddr = Utils.copyBytes(header, 8, 4);
    phdr.p_paddr = Utils.copyBytes(header, 12, 4);
    phdr.p_filesz = Utils.copyBytes(header, 16, 4);
    phdr.p_memsz = Utils.copyBytes(header, 20, 4);
    phdr.p_flags = Utils.copyBytes(header, 24, 4);
    phdr.p_align = Utils.copyBytes(header, 28, 4);

3.段头Section Header

typedef struct elf32_shdr {
  Elf32_Word    sh_name;//段名
  Elf32_Word    sh_type;//段类型
  Elf32_Word    sh_flags;//段标志
  Elf32_Addr    sh_addr;
  Elf32_Off     sh_offset;
  Elf32_Word    sh_size;
  Elf32_Word    sh_link;
  Elf32_Word    sh_info;
  Elf32_Word    sh_addralign;
  Elf32_Word    sh_entsize;
} Elf32_Shdr;

段头信息 按字节读取

    shdr.sh_name = Utils.copyBytes(header, 0, 4);
    shdr.sh_type = Utils.copyBytes(header, 4, 4);
    shdr.sh_flags = Utils.copyBytes(header, 8, 4);
    shdr.sh_addr = Utils.copyBytes(header, 12, 4);
    shdr.sh_offset = Utils.copyBytes(header, 16, 4);
    shdr.sh_size = Utils.copyBytes(header, 20, 4);
    shdr.sh_link = Utils.copyBytes(header, 24, 4);
    shdr.sh_info = Utils.copyBytes(header, 28, 4);
    shdr.sh_addralign = Utils.copyBytes(header, 32, 4);
    shdr.sh_entsize = Utils.copyBytes(header, 36, 4);

了解Elf文件格式后,接触到了字节转int,short等方法;

byte to int

public static int byte2Int(byte[] res) {   
    int targets = (res[0] & 0xff) 
            | ((res[1] << 8) & 0xff00)
            | ((res[2] << 24) >>> 8) 
            | (res[3] << 24);   
    return targets;   
}

byte to long

public static long byte2Long(byte[] b) {
    long s = 0;
    long s0 = b[0] & 0xff;// 最低位
    long s1 = b[1] & 0xff;
    long s2 = b[2] & 0xff;
    long s3 = b[3] & 0xff;
    long s4 = b[4] & 0xff;// 最低位
    long s5 = b[5] & 0xff;
    long s6 = b[6] & 0xff;
    long s7 = b[7] & 0xff;
    // s0不变
    s1 <<= 8;
    s2 <<= 16;
    s3 <<= 24;
    s4 <<= 8 * 4;
    s5 <<= 8 * 5;
    s6 <<= 8 * 6;
    s7 <<= 8 * 7;
    s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
    return s;
}

byte to short

public static short byte2Short(byte[] b) { 
    short s = 0; 
    short s0 = (short) (b[0] & 0xff);// 最低位 
    short s1 = (short) (b[1] & 0xff); 
    s1 <<= 8; 
    s = (short) (s0 | s1); 
    return s; 
}

long to byte

public static byte[] long2ByteAry(long number) { 
    long temp = number; 
    byte[] b = new byte[8]; 
    for (int i = 0; i < b.length; i++) { 
        b[i] = new Long(temp & 0xff).byteValue();// 将最低位保存在最低位 
        temp = temp >> 8; // 向右移8位 
    } 
    return b; 
} 

int to byte

public static byte[] int2Byte(int number) { 
    int temp = number; 
    byte[] b = new byte[4]; 
    for (int i = 0; i < b.length; i++) { 
        b[i] = new Integer(temp & 0xff).byteValue();// 将最低位保存在最低位 
        temp = temp >> 8; // 向右移8位 
    } 
    return b;
}

short to byte

public static byte[] short2Byte(short number) { 
    int temp = number; 
    byte[] b = new byte[2]; 
    for (int i = 0; i < b.length; i++) { 
        b[i] = new Integer(temp & 0xff).byteValue();//将最低位保存在最低位 
        temp = temp >> 8; // 向右移8位 
    } 
    return b;
}

文章参考:http://blog.youkuaiyun.com/feglass/article/details/51469511

Elf文件是Linux底层文件,解读时比较难,比较详细的Elf解读,上面贴的链接讲的挺不错的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值