ELF 文件格式介绍
来源:互联网 发布:wine for ubuntu下载 编辑:程序博客网 时间:2024/06/18 15:03
ELF文件是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。由4部分组成,分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)。
1、文件结构视图
2、elf重定义的数据类型
在linux-4.10/include/uapi/linux/elf.h
7 /* 32-bit ELF base types. */8 typedef __u32Elf32_Addr;9 typedef __u16Elf32_Half;10 typedef __u32Elf32_Off;11 typedef __s32Elf32_Sword;12 typedef __u32Elf32_Word;13 14 /* 64-bit ELF base types. */15 typedef __u64Elf64_Addr;16 typedef __u16Elf64_Half;17 typedef __s16Elf64_SHalf;18 typedef __u64Elf64_Off;19 typedef __s32Elf64_Sword;20 typedef __u32Elf64_Word;21 typedef __u64Elf64_Xword;22 typedef __s64Elf64_Sxword;知道了重定义的数据类型,我们才知道对应的结构体占用的字节数,方便读取和解析文件
3、elf文件的文件头
该结构体定义在 linux-4.10/include/uapi/linux/elf.h
201 #define EI_NIDENT16202 203 typedef struct elf32_hdr{204 unsigned chare_ident[EI_NIDENT];205 Elf32_Halfe_type;206 Elf32_Halfe_machine;207 Elf32_Worde_version;208 Elf32_Addre_entry; /* Entry point */209 Elf32_Offe_phoff;210 Elf32_Offe_shoff;211 Elf32_Worde_flags;212 Elf32_Halfe_ehsize;213 Elf32_Halfe_phentsize;214 Elf32_Halfe_phnum;215 Elf32_Halfe_shentsize;216 Elf32_Halfe_shnum;217 Elf32_Halfe_shstrndx;218 } Elf32_Ehdr;219 220 typedef struct elf64_hdr {221 unsigned chare_ident[EI_NIDENT];/* ELF "magic number" */222 Elf64_Half e_type;223 Elf64_Half e_machine;224 Elf64_Word e_version;225 Elf64_Addr e_entry;/* Entry point virtual address */226 Elf64_Off e_phoff;/* Program header table file offset */227 Elf64_Off e_shoff;/* Section header table file offset */228 Elf64_Word e_flags;229 Elf64_Half e_ehsize;230 Elf64_Half e_phentsize;231 Elf64_Half e_phnum;232 Elf64_Half e_shentsize;233 Elf64_Half e_shnum;234 Elf64_Half e_shstrndx;235 } Elf64_Ehdr;
Elf32_Ehdr和Elf64_Ehdr 结构体的成员是相同的,只是类型可能不同而已。
1)e_ident[EI_NIDENT] 长度为16 char数组,可以理解为文件的标识
2)e_type 该elf文件的类型
/* These constants define the different elf file types */64 #define ET_NONE 065 #define ET_REL 1 //可重定位文件,一般是编译后的.o文件66 #define ET_EXEC 2 //67 #define ET_DYN 3 //68 #define ET_CORE 4 //coredump文件69 #define ET_LOPROC 0xff0070 #define ET_HIPROC 0xffff
3)e_machine 运行时所需的cpu体系结构
4)e_version 文件的版本
5)e_entry; 可执行程序的入口地址
6)e_phoff 程序头表(programheader table)相对于文件开始位置的偏移量
7)e_shoff 节头表(sectionheader table)相对于文件开始位置的偏移量
8)e_flags相关文件的特定处理器标志
9)e_ehsize elf header的大小
10)e_phentsize 程序头表(program headertable)中每一项的大小
11)e_phnum 程序头表的数目,也就是有多少项
12)e_shentsize节头表(sectionheader table)中每一项的大小
13)e_shnum 节头表的数目,也就是有多少项
14)e_shstrndx 节名字字符表在节头表(sectionheader table)中的索引,也就是在那一项
该结构体定义在 linux-4.10/include/uapi/linux/elf.h
typedef struct elf32_phdr{244 Elf32_Wordp_type;245 Elf32_Offp_offset;246 Elf32_Addrp_vaddr;247 Elf32_Addrp_paddr;248 Elf32_Wordp_filesz;249 Elf32_Wordp_memsz;250 Elf32_Wordp_flags;251 Elf32_Wordp_align;252 } Elf32_Phdr;253 254 typedef struct elf64_phdr {255 Elf64_Word p_type;256 Elf64_Word p_flags;257 Elf64_Off p_offset;/* Segment file offset */258 Elf64_Addr p_vaddr;/* Segment virtual address */259 Elf64_Addr p_paddr;/* Segment physical address */260 Elf64_Xword p_filesz;/* Segment size in file */261 Elf64_Xword p_memsz;/* Segment size in memory */262 Elf64_Xword p_align;/* Segment alignment, file & memory */263 } Elf64_Phdr;
1)p_type描述的段的类型
25 #define PT_NULL 0 //未使用26 #define PT_LOAD 1 //可加载段27 #define PT_DYNAMIC 2 //给出动态链接的信息28 #define PT_INTERP 3 //解释器段29 #define PT_NOTE 4 //附加信息的位置和大小30 #define PT_SHLIB 5 //保留31 #define PT_PHDR 6 //程序头表自身位置和大小32 #define PT_TLS 7 /* Thread local storage segment */33 #define PT_LOOS 0x60000000 /* OS-specific */34 #define PT_HIOS 0x6fffffff /* OS-specific */35 #define PT_LOPROC 0x7000000036 #define PT_HIPROC 0x7fffffff37 #define PT_GNU_EH_FRAME0x6474e55038 39 #define PT_GNU_STACK(PT_LOOS + 0x474e551)
2)p_flags 此成员给出与段相关的标志
3)p_offset 此成员给出从文件头到该段第一个字节的偏移
4)p_vaddr 此成员给出段的第一个字节将被放到内存中的虚拟地址
5)p_paddr此成员仅用于与物理地址相关的系统中
6)p_filesz 此成员给出段在文件映像中所占的字节数
7)p_memsz 此成员给出段在内存映像中占用的字节数
8)p_align给出段在文件中和内存中如何对齐,数值 0 和 1 表示不需要对齐
程序表头中的每一项,就是上面文件结构视图中的一个segment,一个segment 可能包含多个section。
5、elf文件中的节头表
elf文件中的程序表头typedef struct elf32_shdr {303 Elf32_Wordsh_name;304 Elf32_Wordsh_type;305 Elf32_Wordsh_flags;306 Elf32_Addrsh_addr;307 Elf32_Offsh_offset;308 Elf32_Wordsh_size;309 Elf32_Wordsh_link;310 Elf32_Wordsh_info;311 Elf32_Wordsh_addralign;312 Elf32_Wordsh_entsize;313 } Elf32_Shdr;314 315 typedef struct elf64_shdr {316 Elf64_Word sh_name;/* Section name, index in string tbl */317 Elf64_Word sh_type;/* Type of section */318 Elf64_Xword sh_flags;/* Miscellaneous section attributes */319 Elf64_Addr sh_addr;/* Section virtual addr at execution */320 Elf64_Off sh_offset;/* Section file offset */321 Elf64_Xword sh_size;/* Size of section in bytes */322 Elf64_Word sh_link;/* Index of another section */323 Elf64_Word sh_info;/* Additional section information */324 Elf64_Xword sh_addralign;/* Section alignment */325 Elf64_Xword sh_entsize;/* Entry size if section holds table */326 } Elf64_Shdr;
1)sh_name 节的名称,在节区头部字符串中的索引
2)sh_type 节区内容的分类
3)sh_flags节的属性
4)sh_addr如果此节的内容将出现在进程空间里,这个字段给出了该节在内存中起始地址。
5)sh_offset如果此节在文件中占用一定的字节,这个字段给出了该节在整个文件中的起始偏移量。
6)sh_size如果此节在文件中占用一定的字节,这个字段给出了该节在文件中的字节大小
7)sh_link如果另一个节与这个节相关联,这个字段给出了相关的节在节头中的索引
8)sh_info 附加信息
9)sh_addralign地址对齐。
10)sh_entsize 代表字节大小的数,对某些节才有意义
package hxiong;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class ELFReader {public static final String ELF_FILE_PATH="E:\\private\\AOSP\\ndk\\tool\\readelf\\logcat";public static final String ELF_=""; public static final String ELF_IDENT="e_ident"; public static final String ELF_TYPE="e_type"; public static final String ELF_MACHINE="e_machine"; public static final String ELF_VERSION="e_version"; public static final String ELF_ENTRY="e_entry"; public static final String ELF_PHOFF="e_phoff;"; public static final String ELF_SHOFF="e_shoff"; public static final String ELF_FLAGS="e_flags"; public static final String ELF_EHSIZE="e_ehsize"; public static final String ELF_PHENTSIZE="e_phentsize"; public static final String ELF_PHNUM="e_phnum"; public static final String ELF_SHENTSIZE="e_shentsize"; public static final String ELF_SHNUM="e_shnum"; public static final String ELF_SHSTRNDX="e_shstrndx"; //public static final int ELF_32=1;public static final int ELF_64=2;public static final int ERROR=-1; /* These constants are for the segment types stored in the image headers */public static final int PT_LOAD = 1;public static final int PT_DYNAMIC = 2;public static final int PT_INTERP = 3;public static void main(String[] args) {ELFReader elfReader=new ELFReader();elfReader.readELF(ELF_FILE_PATH);}public void readELF(String elfPath){File file=new File(elfPath);if(file.exists()&&file.isFile()){readELF(file);}else{System.out.println("error:"+elfPath+"is not exit or not a file.");}}private void readELF(File elfFile){if(elfFile==null){System.out.println("error:elfFile is null.");}else{FileInputReader fReader=new FileInputReader(elfFile);readELF(fReader);fReader.close();}}private void readELF(FileInputReader fReader){byte[] ident=fReader.readBytes(16);System.out.println("-------------- elf header --------------");printfBytes(ELF_IDENT,ident);if(ident[4]==ELF_32){readELF32(fReader);}else if(ident[4]==ELF_64){readELF64(fReader);}else{System.out.println("error:unknown type.");}}//elf32文件的解析就不写出来了,参照elf64的解析过程即可private void readELF32(FileInputReader fReader){} private void readELF64(FileInputReader fReader){ printfShort(ELF_TYPE,fReader.readShort()); printfShort(ELF_MACHINE,fReader.readShort()); printfInt(ELF_VERSION,fReader.readInt()); long elfEntry=fReader.readLong(); long elfPhOff=fReader.readLong(); long elfShOff=fReader.readLong(); printfLong(ELF_ENTRY,elfEntry); printfLong(ELF_PHOFF,elfPhOff); printfLong(ELF_SHOFF,elfShOff); printfInt(ELF_FLAGS,fReader.readInt()); printfShort(ELF_EHSIZE,fReader.readShort()); short elfPhSize=fReader.readShort(); short elfPhNum=fReader.readShort(); short elfShSize=fReader.readShort(); short elfShNum=fReader.readShort(); short elfShStrIndx=fReader.readShort(); printfShort(ELF_PHENTSIZE,elfPhSize); printfShort(ELF_PHNUM,elfPhNum); printfShort(ELF_SHENTSIZE,elfShSize); printfShort(ELF_SHNUM,elfShNum); printfShort(ELF_SHSTRNDX,elfShStrIndx); if(elfPhNum>0){ readELFProgramHeader(fReader,elfPhOff,(int)elfPhSize,(int)elfPhNum); } if(elfShNum>0){ readELFSectionHeader(fReader,elfShOff,(int)elfShSize,(int)elfShNum); } if(elfShStrIndx>0){ readELFShStr(fReader,elfShOff,(int)elfShSize,(int)elfShStrIndx); }} private void readELFProgramHeader(FileInputReader fReader,long offset,int size,int num){ System.out.println(); System.out.println("-------------- program header --------------"); int segmentType=0; int segmentFlags=0; long segmentOffset=0; long segmentSize=0; if(fReader.markAndReset(offset)){ System.out.println("index\tp_type p_flags p_offset p_vaddr p_paddr p_filesz p_memsz p_align"); for(int i=0;i<num;i++){ segmentType=fReader.readInt(); if(segmentType==PT_INTERP){ segmentFlags=fReader.readInt(); segmentOffset=fReader.readLong(); System.out.print("["+i+"]\t"+ segmentType+"\t"+ segmentFlags+"\t"+ segmentOffset+"\t"); System.out.print(""+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"); segmentSize=fReader.readLong(); System.out.println(""+ segmentSize+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()); }else{ System.out.println("["+i+"]\t"+ segmentType+"\t"+ fReader.readInt()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()); } } if(segmentSize>0){ //PT_INTERPSystem.out.println(); System.out.println("-------------- interp segment --------------"); if(fReader.markAndReset(segmentOffset)){ byte[] segmentContent=fReader.readBytes((int)segmentSize); System.out.println("interp is:"+new String(segmentContent)); }} } } private void readELFSectionHeader(FileInputReader fReader,long offset,int size,int num){ System.out.println(); System.out.println("-------------- section header --------------"); if(fReader.markAndReset(offset)){ System.out.println("index\tsh_name sh_type sh_flags sh_add sh_offset sh_size sh_link sh_info sh_addralign sh_entsize"); for(int i=0;i<num;i++){ System.out.println("["+i+"]\t"+ fReader.readInt()+"\t"+ fReader.readInt()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()+"\t"+ fReader.readInt()+"\t"+ fReader.readInt()+"\t"+ fReader.readLong()+"\t"+ fReader.readLong()); } } } private void readELFShStr(FileInputReader fReader,long offset,int size,int index){ System.out.println(); System.out.println("-------------- section string table --------------"); long shStrOffset=offset+ size* index; if(fReader.markAndReset(shStrOffset)){ fReader.readInt(); fReader.readInt();fReader.readLong(); fReader.readLong();long strOffset=fReader.readLong(); int strSize=(int)fReader.readLong(); if(fReader.markAndReset(strOffset)){ byte[] strBytes=fReader.readBytes(strSize); String str=new String(strBytes); String[] ss=str.split("\0"); System.out.println("index\t value"); for(int i=0;i<ss.length;i++){ System.out.println("["+i+"]\t"+ss[i]); } } } }private void printfBytes(String tag,byte[] bs){System.out.print(tag+":\t");for(byte b:bs){System.out.print(" "+b);}System.out.println();}private void printfShort(String tag,short s){System.out.println(tag+":\t"+s);}private void printfInt(String tag,int i){System.out.println(tag+":\t"+i);}private void printfLong(String tag,long l){System.out.println(tag+":\t"+l);}class FileInputReader{private FileInputStream mFin;private File mFile;FileInputReader(File file){this.mFile=file;try {this.mFin=new FileInputStream(mFile);} catch (FileNotFoundException e) {e.printStackTrace();}}boolean markAndReset(long pos){try {close();mFin=new FileInputStream(mFile);mFin.skip(pos);return true;} catch (Exception e) {e.printStackTrace();}return false;}int readByte(){try {return mFin.read();} catch (Exception e) {e.printStackTrace();}return ERROR;}short readShort(){try {int byte0=mFin.read();int byte1=mFin.read();return (short)((byte1<<8)|byte0);} catch (Exception e) {e.printStackTrace();}return ERROR;}int readInt(){try {int byte0=mFin.read();int byte1=mFin.read();int byte2=mFin.read();int byte3=mFin.read();return ((byte3<<24)|(byte2<<16)|(byte1<<8)|byte0);} catch (Exception e) {e.printStackTrace();}return ERROR;}long readLong(){try {int byte0=mFin.read();int byte1=mFin.read();int byte2=mFin.read();int byte3=mFin.read();int byte4=mFin.read(); //no need ??int byte5=mFin.read(); //no need ??int byte6=mFin.read(); //no need ??int byte7=mFin.read(); //no need ??return ((byte3<<24)|(byte2<<16)|(byte1<<8)|byte0);} catch (Exception e) {e.printStackTrace();}return ERROR;}byte[] readBytes(int size){try {byte[] bytes=new byte[size];mFin.read(bytes);return bytes;} catch (Exception e) {e.printStackTrace();}return new byte[0];}void close(){try {if(mFin!=null) mFin.close();} catch (IOException e) {e.printStackTrace();}}}}
运行结果
-------------- elf header --------------e_ident: 127 69 76 70 2 1 1 0 0 0 0 0 0 0 0 0e_type:3e_machine:183e_version:1e_entry:9924e_phoff;:64e_shoff:33240e_flags:0e_ehsize:64e_phentsize:56e_phnum:9e_shentsize:64e_shnum:29e_shstrndx:28-------------- program header --------------indexp_type p_flags p_offset p_vaddr p_paddr p_filesz p_memsz p_align[0]646464645045048[1]3456856856821211[2]1500028932289324096[3]16306083470434704218422724096[4]263132835424354246246248[5]4459259259256564[6]1685382480428864288642886468684[7]16853824816000000[8]16853824826306083470434704216021608-------------- interp segment --------------interp is:/system/bin/linker64-------------- section header --------------indexsh_name sh_type sh_flags sh_add sh_offset sh_size sh_link sh_info sh_addralign sh_entsize[0]0000000000[1]1112568568210010[2]1972592592240040[3]3972616616320040[4]58112648648242451824[5]66323072307221710010[6]741879048182252485248644080[7]8418790481912531253122024022[8]971879048190255165516805240[9]112425600560076840824[10]122466636863682064411824[11]1271684328432140800816[12]1321698409840125640040[13]13812224042240461070040[14]1461228512285123520080[15]156122886428864680040[16]1701633470430608160080[17]1851433472030624160080[18]1971533473630640160080[19]2091334752306566720080[20]22263354243132862450816[21]2311336048319521040080[22]2361336152320567120080[23]245133686432768240080[24]251833688832792880080[25]256148032792990011[26]26570032892280040[27]28810032920120010[28]1300329323030010-------------- section string table --------------index value[0][1].shstrtab[2].interp[3].note.android.ident[4].note.gnu.build-id[5].dynsym[6].dynstr[7].gnu.hash[8].gnu.version[9].gnu.version_r[10].rela.dyn[11].rela.plt[12].text[13].rodata[14].eh_frame[15].eh_frame_hdr[16].preinit_array[17].init_array[18].fini_array[19].data.rel.ro[20].dynamic[21].got[22].got.plt[23].data[24].bss[25].comment[26].note.gnu.gold-version[27].gnu_debuglink
- elf文件格式介绍
- ELF文件格式概要介绍
- ELF文件格式介绍
- ELF文件格式概要介绍
- ELF 文件格式介绍
- elf文件格式
- elf文件格式
- elf文件格式
- ELF文件格式
- ELF 文件格式
- ELF文件格式
- elf文件格式
- ELF文件格式
- elf文件格式
- ELF文件格式
- ELF文件格式
- ELF文件格式
- elf文件格式
- 我亲手调教的AI,竟然开始歧视我了!
- 小白笔记---------------------------------leetcode(70. Climbing Stairs )
- mysql5.7.19 安装配置方法图文教程
- windows10+cuda8.0+cudnn+python3.5+tensorflow-gpu-1.3.0-rc0( bottleneck() argument after ** must be )
- Spring的JdbcTemplate
- ELF 文件格式介绍
- Best Time to Buy and Sell Stock III
- 小小的公共库,大大的耦合,你痛过吗?
- 38.开源项目--git常用命令总结
- 用Dom4j解析自定义数据库XML配置文件
- Java IO 转换流 字节转字符流
- 浅析各类排序算法(四) 插入类排序之直接插入排序及折半插入,2-路插入算法
- Android应用性能优化系列视图篇——ListView自适应导致的严重性能问题
- 线程练习,感觉自己眼瞎了