(转载)http://blog.chinaunix.net/uid-21273878-id-1828736.html
ELF文件 |
可重定位文件(relocatable file) |
可重定位文件(relocatable file),用于与其它目标文件进行连接以构建可执行文件或动态链接库。可重定位文件就是常说的目标文件,由源文件编译而成,但还没有连接成可执行文件。在 UNIX系统下,一般有扩展名”.o”。之所以称其为“可重定位”,是因为在这些文件中,如果引用到其它目标文件或库文件中定义的符号(变量或者函数)的话,只是给出一个名字,这里还并不知道这个符号在哪里,其具体的地址是什么。需要在连接的过程中,把对这些外部符号的引用重新定位到其真正定义的位置上,所以称目标文件为“可重定位”或者“待重定位”的。 |
共享目标文件(shared object file) |
即动态连接库文件。它在以下两种情况下被使用:第一,在连接过程中与其它动态链接库或可重定位文件一起构建新的目标文件;第二,在可执行文件被加载的过程中,被动态链接到新的进程中,成为运行代码的一部分。 |
|
可执行文件(executable file ) |
经过连接的,可以执行的程序文件。 |
#define EI_NIDENT 16 |
我使用Ultraedit打开一个ELF文件,来分析它的前52个字节:
e_ident[0] |
7F |
目标文件最开头的前四个字节。 文件标志,表示是ELF文件 EI_MAG0 = 0, EI_MAG1 = 1, EI_MAG2 = 2, EI_MAG3 = 3 |
|||||||||||||||||||||
e_ident[1] |
45 == ‘E’ |
||||||||||||||||||||||
e_ident[2] |
4C == ’L’ |
||||||||||||||||||||||
e_ident[3] |
46 == ‘F’ |
||||||||||||||||||||||
e_ident[4] |
01 |
文件类别,取值如下:(EI_CLASS = 4)
|
|||||||||||||||||||||
e_ident[5] |
01 |
编码格式,取值如下:(EI_DATA = 5)
|
|||||||||||||||||||||
e_ident[6] |
01 |
文件版本,(EI_VERSION),为1表明是目前版本 |
|||||||||||||||||||||
e_ident[7] to e_ident[15] |
00 00 00 00 00 00 00 00 00 |
这就个字节暂且不使用,留在以后扩展。 |
|||||||||||||||||||||
e_type |
00 01 |
此字段表明文件属于那种类型:
|
|||||||||||||||||||||
e_machine |
00 03 |
体系结构类型 : Intel 80386 |
|||||||||||||||||||||
e_version |
00 00 00 01 |
目前版本 |
|||||||||||||||||||||
e_entry |
00 00 00 00 |
|
|||||||||||||||||||||
e_phoff |
00 00 00 00 |
没有程序头部表。 |
|||||||||||||||||||||
e_shoff |
00 00 00 FC |
e_ident[0]是文件的第一个字节,从它开始FC(252)字节后就是节的数据信息。 |
|||||||||||||||||||||
e_flags |
00 00 00 00 |
|
|||||||||||||||||||||
e_ehsize |
00 34 |
52字节的ELF头部结构体 |
|||||||||||||||||||||
e_phentsize |
00 00 |
因为没有程序头部表,所以大小为0 |
|||||||||||||||||||||
e_phnum |
00 00 |
同上 |
|||||||||||||||||||||
e_shentsize |
00 28 |
40字节的节区头部表 |
|||||||||||||||||||||
e_shnum |
00 0B |
节区头部表的表项有B(11)个 |
|||||||||||||||||||||
e_shstrndx |
00 08 |
节头表中与节名字表相对应的表项的索引。 |
下面的一段程序用来读ELF文件的头部:readelf_h.c:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <fcntl.h> 6 #include <unistd.h> 7 #include <errno.h> 8 9 #define FALSE 0 10 #define TURE 1 11 #define MAX_SIZE 52 12 13 typedef short int Elf32_Half; 14 typedef int Elf32_Word; 15 typedef Elf32_Word Elf32_Addr; 16 typedef Elf32_Word Elf32_Off; 17 /*Elf头部文件部分重要数据*/ 18 typedef struct{ 19 Elf32_Half e_type; 20 Elf32_Half e_machine; 21 Elf32_Word e_version; 22 Elf32_Addr e_entry; //程序入口的虚拟地址,如果目标文件没有程序入口,为0 23 24 Elf32_Off e_phoff; //程序头部表格的偏移量(按字节),如果文件中没有,为0 25 26 Elf32_Off e_shoff; //节区头部表格的偏移量(按字节),如果文件中没有,为0 27 28 Elf32_Word e_flags; // 29 30 Elf32_Half e_ehsize; //ELF头部的大小 31 32 Elf32_Half e_phentsize; //程序头部表格的表项大小。 33 34 Elf32_Half e_phnum; //程序头部表格的表项数目。 35 36 Elf32_Half e_shentsize; //节区头部表格的表项大小。 37 38 Elf32_Half e_shnum; //节区头部表格的表项数目。 39 40 Elf32_Half e_shstrndx; 41 }Elf_lan; 42 static Elf_lan lan_elf; 43 int OpenElf(char *filename) 44 { 45 int fd; 46 fd = open(filename, O_RDONLY); 47 if(fd == -1){ 48 printf("Open %s Error!\n", filename); 49 return FALSE; 50 } 51 return fd; 52 } 53 //读取Elf头部表函数 :int ReadElf(int fd); 54 55 int ReadElf(int fd) 56 { 57 char str[MAX_SIZE]; 58 int num; 59 memset(str, 0, MAX_SIZE); 60 if((num = read(fd, str, 52)) != 52){ 61 perror("File NO ELF!\n"); 62 return FALSE; 63 } 64 if((str[0] == 0x7f) && (str[1] == 'E') && (str[2] == 'L') && (str[3] == 'F')){ 65 printf("This is ELF file.\n"); 66 printf("文件类别: "); 67 switch(str[4]){ 68 case 0: 69 printf("非法目标文件\n"); 70 break; 71 case 1: 72 printf("32位目标文件\n"); 73 break; 74 case 2: 75 printf("64位目标文件\n"); 76 break; 77 default: 78 break; 79 } 80 printf("编码格式: "); 81 switch(str[5]){ 82 case 0: 83 printf("非法编码格式\n"); 84 break; 85 case 1: 86 printf("小端编码格式\n"); 87 break; 88 case 2: 89 printf("大端编码格式\n"); 90 break; 91 default: 92 break; 93 } 94 printf("文件版本: "); 95 if(str[6] == 1){ 96 printf("当前版本\n"); 97 }else{ 98 printf("NULL\n"); 99 } 100 printf("目标文件类型: "); 101 lan_elf.e_type = *((Elf32_Half *)&str[16]); 102 printf("e_type = %d\t", lan_elf.e_type); 103 switch(lan_elf.e_type){ 104 case 0: 105 printf("未知文件类型\n"); 106 break; 107 case 1: 108 printf("可重定位文件类型\n"); 109 break; 110 case 2: 111 printf("可执行文件\n"); 112 break; 113 case 3: 114 printf("动态链接库文件\n"); 115 break; 116 case 4: 117 printf("CORE文件\n"); 118 break; 119 default: 120 break; 121 } 122 printf("体系结构为:"); 123 lan_elf.e_machine = *((Elf32_Half *)&str[18]); 124 printf("e_machine = %d\n", lan_elf.e_machine); 125 switch(lan_elf.e_machine){ 126 case 0: 127 printf("未知体系结构"); 128 break; 129 case 3: 130 printf("Intel 8086"); 131 } 132 printf("版本信息: "); 133 lan_elf.e_version = *((Elf32_Word *)&str[20]); 134 if(lan_elf.e_version == 1){ 135 printf("当前版本\n"); 136 }else{ 137 printf("NULL\n"); 138 } 139 printf("程序入口的虚拟地址:"); 140 lan_elf.e_entry = *((Elf32_Word *)&str[24]); 141 printf("0x%x\n", lan_elf.e_entry); 142 143 printf("程序头部表格的偏移量(按字节): "); 144 lan_elf.e_phoff = *((Elf32_Off *)&str[28]); 145 printf("0x%x, %d\n", lan_elf.e_phoff, lan_elf.e_phoff); 146 147 printf("节区头部表格的偏移量(按字节): "); 148 lan_elf.e_shoff = *((Elf32_Off *)&str[32]); 149 printf("0x%x, %d\n", lan_elf.e_shoff, lan_elf.e_shoff); 150 151 printf("处理器标志位: "); 152 lan_elf.e_flags = *((Elf32_Off *)&str[36]); 153 printf("%d\n", lan_elf.e_flags); 154 155 printf("ELF头文件大小: "); 156 lan_elf.e_ehsize = *((Elf32_Half *)&str[40]); 157 printf("0x%x, %d\n", lan_elf.e_ehsize, lan_elf.e_ehsize); 158 159 printf("程序头部表大小: "); 160 lan_elf.e_phentsize = *((Elf32_Half *)&str[42]); 161 printf("0x%x, %d\n", lan_elf.e_phentsize, lan_elf.e_phentsize); 162 163 printf("程序头部表的数目:"); 164 lan_elf.e_phnum = *((Elf32_Half *)&str[44]); 165 printf("0x%x, %d\n", lan_elf.e_phnum, lan_elf.e_phnum); 166 167 printf("节区头部表大小: "); 168 lan_elf.e_shentsize = *((Elf32_Half *)&str[46]); 169 printf("0x%x, %d\n", lan_elf.e_shentsize, lan_elf.e_shentsize); 170 171 printf("节区头部表数目: "); 172 lan_elf.e_shnum = *((Elf32_Half *)&str[48]); 173 printf("0x%x, %d\n", lan_elf.e_shnum, lan_elf.e_shnum); 174 175 printf("节头表与节名字相对应的表项的索引: "); 176 lan_elf.e_shstrndx = *((Elf32_Half *)&str[50]); 177 printf("0x%x, %d\n", lan_elf.e_shstrndx, lan_elf.e_shstrndx); 178 return TURE; 179 }else{ 180 perror("File NO ELF!\n"); 181 return FALSE; 182 } 183 } 184 185 int main(int argc, char *argv[]) 186 { 187 int boolen; 188 if(argc == 2){ 189 boolen = OpenElf(argv[1]); 190 if(boolen == FALSE){ 191 return -1; 192 } 193 ReadElf(boolen); 194 } 195 196 return 0; 197 }
$./readelf_lan readelf_lan.o
This is ELF file.
文件类别: 32位目标文件
编码格式: 小端编码格式
文件版本: 当前版本
目标文件类型: e_type = 1 可重定位文件类型
体系结构为:e_machine = 3
Intel 8086版本信息: 当前版本
程序入口的虚拟地址:0x0
程序头部表格的偏移量(按字节): 0x0, 0
节区头部表格的偏移量(按字节): 0xc00, 3072
处理器标志位: 0
ELF头文件大小: 0x34, 52
程序头部表大小: 0x0, 0
程序头部表的数目:0x0, 0
节区头部表大小: 0x28, 40
节区头部表数目: 0xc, 12
节头表与节名字相对应的表项的索引: 0x9, 9