elf.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * elf.c
  3. */
  4. typedef unsigned char u8_t;
  5. typedef unsigned short u16_t;
  6. typedef unsigned int u32_t;
  7. typedef signed char s8_t;
  8. typedef signed short s16_t;
  9. typedef signed int s32_t;
  10. typedef u32_t Elf_Addr; // 无符号地址
  11. typedef u16_t Elf_Half; // 无符号半整型
  12. typedef u32_t Elf_Off; // 无符号文件偏移量
  13. typedef s32_t Elf_Sword; // 有符号整型
  14. typedef u32_t Elf_Word; // 无符号整型
  15. typedef u8_t Elf_Uchar; // 无符号短整型
  16. #define ELFMAG "\x7f""ELF" // ELF 魔数
  17. #define EI_NIDENT 16
  18. #define ET_REL 1 // 可重定位文件
  19. #define ET_EXEC 2 // 可执行文件
  20. #define EM_MIPS 8 // MIPS 体系结构
  21. #define EF_MIPS_PIC 2 // MIPS 位置无关代码
  22. #define EF_MIPS_CPIC 4 // MIPS 位置无关代码
  23. #define PT_LOAD 1 // 可装载段
  24. #define PF_X 1 // 可执行
  25. #define SHT_NULL 0 // 无效节头
  26. #define SHT_PROGBITS 1 // 程序
  27. #define SHT_SYMTAB 2 // 符号表
  28. #define SHT_STRTAB 3 // 字符串表
  29. #define SHT_RELA 4 // 重定位节
  30. #define SHT_NOBITS 8 // 空内容
  31. #define SHT_REL 9 // 重定位节
  32. #define SHF_ALLOC 2 // 分配内存
  33. #define SHF_EXECINSTR 4 // 指令代码
  34. #define STB_LOCAL 0 // 局部符号
  35. #define STB_GLOBAL 1 // 全局符号
  36. #define STB_WEAK 2 // 弱符号
  37. #define STT_OBJECT 1 // 数据对象
  38. #define STT_FUNC 2 // 函数
  39. #define STT_SECTION 3 // 节
  40. #define STT_FILE 4 // 文件
  41. #define STV_DEFAULT 0 // 默认可见性
  42. #define STV_INTERNAL 1 // 内部
  43. #define STV_HIDDEN 2 // 隐藏
  44. #define STV_PROTECTED 3 // 保护
  45. #define STO_MIPS16 0xf0 // MIPS16
  46. #define SHN_UNDEF 0 // 未定义
  47. #define SHN_ABS 0xfff1 // 绝对值
  48. #define ELF_ST_BIND(_i) ((_i) >> 4) // 符号绑定
  49. #define ELF_ST_TYPE(_i) ((_i) & 0xf) // 符号类型
  50. #define ELF_ST_INFO(_b, _t) \
  51. \
  52. (((_b) << 4) | ((_t) & 0xf))
  53. #define ELF_ST_VISIBILITY(_o) ((_o) & 0x3) // 可见性
  54. #define SET_ST_VISIBILITY(_o, _v) \
  55. \
  56. (_o) = (((_o) & ~0x3) | (_v))
  57. #define ELF_ST_IS_MIPS16(_o) \
  58. \
  59. (((_o) & 0xf0) == STO_MIPS16)
  60. #define ELF_R_SYM(_i) ((_i) >> 8)
  61. #define ELF_R_TYPE(_i) ((Elf_Uchar)(_i))
  62. typedef struct
  63. {
  64. Elf_Uchar e_ident[EI_NIDENT]; // 识别标志
  65. Elf_Half e_type; // 文件类型
  66. Elf_Half e_machine; // 体系结构
  67. Elf_Word e_version; // 文件版本
  68. Elf_Addr e_entry; // 程序入口地址
  69. Elf_Off e_phoff; // 程序头表偏移
  70. Elf_Off e_shoff; // 节头表偏移
  71. Elf_Word e_flags; // 标志
  72. Elf_Half e_ehsize; // 文件头大小
  73. Elf_Half e_phentsize; // 程序头表项大小
  74. Elf_Half e_phnum; // 程序头表项数
  75. Elf_Half e_shentsize; // 节头表项大小
  76. Elf_Half e_shnum; // 节头表项数
  77. Elf_Half e_shstrndx; // 节名表索引
  78. } Elf_Ehdr; // 文件头
  79. typedef struct
  80. {
  81. Elf_Word p_type; // 段类型
  82. Elf_Off p_offset; // 段偏移
  83. Elf_Addr p_vaddr; // 虚拟地址
  84. Elf_Addr p_paddr; // 物理地址
  85. Elf_Word p_filesz; // 文件内容大小
  86. Elf_Word p_memsz; // 内存镜像大小
  87. Elf_Word p_flags; // 段标志
  88. Elf_Word p_align; // 对齐
  89. } Elf_Phdr; // 程序头
  90. typedef struct
  91. {
  92. Elf_Word sh_name; // 节名索引
  93. Elf_Word sh_type; // 节类型
  94. Elf_Word sh_flags; // 节标志
  95. Elf_Addr sh_addr; // 映射地址
  96. Elf_Off sh_offset; // 节偏移
  97. Elf_Word sh_size; // 节大小
  98. Elf_Word sh_link; // 连接索引
  99. Elf_Word sh_info; // 信息
  100. Elf_Word sh_addralign; // 地址对齐
  101. Elf_Word sh_entsize; // 表项大小
  102. } Elf_Shdr; // 节头
  103. typedef struct
  104. {
  105. Elf_Word st_name; // 符号名
  106. Elf_Addr st_value; // 值
  107. Elf_Word st_size; // 大小
  108. Elf_Uchar st_info; // 绑定和类型
  109. Elf_Uchar st_other; // 其它
  110. Elf_Half st_shndx; // 节头索引
  111. } Elf_Sym; // 符号表项
  112. typedef struct
  113. {
  114. Elf_Addr r_offset; // 重定位偏移
  115. Elf_Word r_info; // 重定位信息
  116. } Elf_Rel; // 重定位项
  117. static Elf_Shdr* get_shdrtab(FILE* file, Elf_Ehdr* ehdr)
  118. {
  119. Elf_Shdr* shdrtab;
  120. if ((shdrtab = malloc(ehdr->e_shnum * sizeof(Elf_Shdr))) == NULL)
  121. goto err;
  122. /* 节头表 */
  123. fseek(file, ehdr->e_shoff, SEEK_SET);
  124. fread(shdrtab, sizeof(Elf_Shdr), ehdr->e_shnum, file);
  125. return shdrtab;
  126. err:
  127. return NULL;
  128. }
  129. static char* get_shstrtab(FILE* file, Elf_Ehdr* ehdr, Elf_Shdr* shdrtab)
  130. {
  131. Elf_Shdr* shdr = &shdrtab[ehdr->e_shstrndx];
  132. char* shstrtab;
  133. /* 节名字符串表 */
  134. if ((shstrtab = malloc(shdr->sh_size)) == NULL)
  135. goto err;
  136. fseek(file, shdr->sh_offset, SEEK_SET);
  137. fread(shstrtab, shdr->sh_size, 1, file);
  138. return shstrtab;
  139. err:
  140. return NULL;
  141. }
  142. static char* get_strtab(FILE* file, Elf_Ehdr* ehdr, char* shstrtab, Elf_Shdr* shdrtab)
  143. {
  144. Elf_Shdr* shdr = NULL;
  145. char* strtab;
  146. int i;
  147. /* 节头表 */
  148. for (i = 0; i < ehdr->e_shnum; i++)
  149. {
  150. char* sh_name;
  151. shdr = &shdrtab[i];
  152. sh_name = &shstrtab[shdr->sh_name];
  153. /* 字符串表? */
  154. if (strcmp(sh_name, ".strtab") == 0)
  155. break;
  156. }
  157. if (i >= ehdr->e_shnum)
  158. goto err;
  159. if ((strtab = malloc(shdr->sh_size)) == NULL)
  160. goto err;
  161. fseek(file, shdr->sh_offset, SEEK_SET);
  162. fread(strtab, shdr->sh_size, 1, file);
  163. return strtab;
  164. err:
  165. return NULL;
  166. }
  167. static Elf_Sym* get_symtab(FILE* file, Elf_Ehdr* ehdr, char* shstrtab, int* num_syms, Elf_Shdr* shdrtab)
  168. {
  169. Elf_Shdr* shdr = NULL;
  170. Elf_Sym* symtab;
  171. int i;
  172. /* 节头表 */
  173. for (i = 0; i < ehdr->e_shnum; i++)
  174. {
  175. char* sh_name;
  176. shdr = &shdrtab[i];
  177. sh_name = &shstrtab[shdr->sh_name];
  178. /* 符号表? */
  179. if (strcmp(sh_name, ".symtab") == 0)
  180. break;
  181. }
  182. if (i >= ehdr->e_shnum)
  183. goto err;
  184. if ((symtab = malloc(shdr->sh_size)) == NULL)
  185. goto err;
  186. fseek(file, shdr->sh_offset, SEEK_SET);
  187. fread(symtab, shdr->sh_size, 1, file);
  188. *num_syms = shdr->sh_size / sizeof(Elf_Sym);
  189. return symtab;
  190. err:
  191. return NULL;
  192. }
  193. typedef struct
  194. {
  195. FILE* file;
  196. Elf_Ehdr ehdr;
  197. char* shstrtab;
  198. char* strtab;
  199. Elf_Sym* symtab;
  200. int num_syms;
  201. Elf_Shdr* shdrtab;
  202. int shnum;
  203. } elf_obj_t;
  204. static FILE* elf_obj_fopen(const char* file_name, Elf_Ehdr* ehdr)
  205. {
  206. FILE* file;
  207. if ((file = fopen(file_name, "rb")) == NULL)
  208. goto err;
  209. /* 文件头 */
  210. fread(ehdr, sizeof(Elf_Ehdr), 1, file);
  211. /* 目标文件? */
  212. if (ehdr->e_type != ET_REL)
  213. goto err;
  214. return file;
  215. err:
  216. if (file != NULL)
  217. fclose(file);
  218. return NULL;
  219. }
  220. static void elf_obj_free(elf_obj_t* obj)
  221. {
  222. if (obj == NULL)
  223. return;
  224. if (obj->file != NULL)
  225. fclose(obj->file);
  226. if (obj->symtab != NULL)
  227. free(obj->symtab);
  228. if (obj->strtab != NULL)
  229. free(obj->strtab);
  230. if (obj->shstrtab != NULL)
  231. free(obj->shstrtab);
  232. if (obj->shdrtab != NULL)
  233. free(obj->shdrtab);
  234. free(obj);
  235. }
  236. static elf_obj_t* elf_obj_load(char* file_name)
  237. {
  238. elf_obj_t* obj = malloc(sizeof(elf_obj_t));
  239. memset(obj, 0, sizeof(elf_obj_t));
  240. if ((obj->file = elf_obj_fopen(file_name, &obj->ehdr)) == NULL)
  241. goto err;
  242. if ((obj->shdrtab = get_shdrtab(obj->file, &obj->ehdr)) == NULL)
  243. goto err;
  244. obj->shnum = obj->ehdr.e_shnum;
  245. if ((obj->shstrtab = get_shstrtab(obj->file, &obj->ehdr, obj->shdrtab)) == NULL)
  246. goto err;
  247. if ((obj->strtab = get_strtab(obj->file, &obj->ehdr, obj->shstrtab, obj->shdrtab)) == NULL)
  248. goto err;
  249. if ((obj->symtab = get_symtab(obj->file, &obj->ehdr, obj->shstrtab, &obj->num_syms, obj->shdrtab)) == NULL)
  250. goto err;
  251. return obj;
  252. err:
  253. elf_obj_free(obj);
  254. return NULL;
  255. }