1.文件头ElfHeader
文件定义的数据结构,字段占用字节数
| 名称 | 大小 | 对齐 | 目的 |
|---|---|---|---|
| Elf32_Addr | 4 | 4 | 无符号程序地址 |
| Elf32_Half | 2 | 2 | 无符号中的整数 |
| Elf32_Off | 4 | 4 | 无符号文件偏移 |
| Elf32_Sword | 4 | 4 | 有符号大整数 |
| Elf32_Word | 4 | 4 | 无符号大整数 |
| unsigned char | 1 | 1 | 无符号小整数 |
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解读,上面贴的链接讲的挺不错的。
本文详细介绍了Elf文件的三个关键部分: ElfHeader、ProgramHeader和Section Header,并探讨了在解析过程中如何将字节转换为int、long和short等数据类型。通过阅读,你可以了解到Elf文件格式的基础知识以及Linux底层文件解析的挑战。
1212

被折叠的 条评论
为什么被折叠?



