elf_file.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. #include <elf.h>
  2. #include "elf_file.h"
  3. #include "elf_file_i.h"
  4. #include "elf_api_interface.h"
  5. #define TAG "elf"
  6. #define ELF_NAME_BUFFER_LEN 32
  7. #define SECTION_OFFSET(e, n) (e->section_table + n * sizeof(Elf32_Shdr))
  8. #define IS_FLAGS_SET(v, m) ((v & m) == m)
  9. #define RESOLVER_THREAD_YIELD_STEP 30
  10. // #define ELF_DEBUG_LOG 1
  11. #ifndef ELF_DEBUG_LOG
  12. #undef FURI_LOG_D
  13. #define FURI_LOG_D(...)
  14. #endif
  15. #define TRAMPOLINE_CODE_SIZE 6
  16. /**
  17. ldr r12, [pc, #2]
  18. bx r12
  19. */
  20. const uint8_t trampoline_code_little_endian[TRAMPOLINE_CODE_SIZE] =
  21. {0xdf, 0xf8, 0x02, 0xc0, 0x60, 0x47};
  22. typedef struct {
  23. uint8_t code[TRAMPOLINE_CODE_SIZE];
  24. uint32_t addr;
  25. } __attribute__((packed)) JMPTrampoline;
  26. /**************************************************************************************************/
  27. /********************************************* Caches *********************************************/
  28. /**************************************************************************************************/
  29. static bool address_cache_get(AddressCache_t cache, int symEntry, Elf32_Addr* symAddr) {
  30. Elf32_Addr* addr = AddressCache_get(cache, symEntry);
  31. if(addr) {
  32. *symAddr = *addr;
  33. return true;
  34. } else {
  35. return false;
  36. }
  37. }
  38. static void address_cache_put(AddressCache_t cache, int symEntry, Elf32_Addr symAddr) {
  39. AddressCache_set_at(cache, symEntry, symAddr);
  40. }
  41. /**************************************************************************************************/
  42. /********************************************** ELF ***********************************************/
  43. /**************************************************************************************************/
  44. static ELFSection* elf_file_get_section(ELFFile* elf, const char* name) {
  45. return ELFSectionDict_get(elf->sections, name);
  46. }
  47. static void elf_file_put_section(ELFFile* elf, const char* name, ELFSection* section) {
  48. ELFSectionDict_set_at(elf->sections, strdup(name), *section);
  49. }
  50. static bool elf_read_string_from_offset(ELFFile* elf, off_t offset, string_t name) {
  51. bool result = false;
  52. off_t old = storage_file_tell(elf->fd);
  53. do {
  54. if(!storage_file_seek(elf->fd, offset, true)) break;
  55. char buffer[ELF_NAME_BUFFER_LEN + 1];
  56. buffer[ELF_NAME_BUFFER_LEN] = 0;
  57. while(true) {
  58. uint16_t read = storage_file_read(elf->fd, buffer, ELF_NAME_BUFFER_LEN);
  59. string_cat_str(name, buffer);
  60. if(strlen(buffer) < ELF_NAME_BUFFER_LEN) {
  61. result = true;
  62. break;
  63. }
  64. if(storage_file_get_error(elf->fd) != FSE_OK || read == 0) break;
  65. }
  66. } while(false);
  67. storage_file_seek(elf->fd, old, true);
  68. return result;
  69. }
  70. static bool elf_read_section_name(ELFFile* elf, off_t offset, string_t name) {
  71. return elf_read_string_from_offset(elf, elf->section_table_strings + offset, name);
  72. }
  73. static bool elf_read_symbol_name(ELFFile* elf, off_t offset, string_t name) {
  74. return elf_read_string_from_offset(elf, elf->symbol_table_strings + offset, name);
  75. }
  76. static bool elf_read_section_header(ELFFile* elf, size_t section_idx, Elf32_Shdr* section_header) {
  77. off_t offset = SECTION_OFFSET(elf, section_idx);
  78. return storage_file_seek(elf->fd, offset, true) &&
  79. storage_file_read(elf->fd, section_header, sizeof(Elf32_Shdr)) == sizeof(Elf32_Shdr);
  80. }
  81. static bool
  82. elf_read_section(ELFFile* elf, size_t section_idx, Elf32_Shdr* section_header, string_t name) {
  83. if(!elf_read_section_header(elf, section_idx, section_header)) {
  84. return false;
  85. }
  86. if(section_header->sh_name && !elf_read_section_name(elf, section_header->sh_name, name)) {
  87. return false;
  88. }
  89. return true;
  90. }
  91. static bool elf_read_symbol(ELFFile* elf, int n, Elf32_Sym* sym, string_t name) {
  92. bool success = false;
  93. off_t old = storage_file_tell(elf->fd);
  94. off_t pos = elf->symbol_table + n * sizeof(Elf32_Sym);
  95. if(storage_file_seek(elf->fd, pos, true) &&
  96. storage_file_read(elf->fd, sym, sizeof(Elf32_Sym)) == sizeof(Elf32_Sym)) {
  97. if(sym->st_name)
  98. success = elf_read_symbol_name(elf, sym->st_name, name);
  99. else {
  100. Elf32_Shdr shdr;
  101. success = elf_read_section(elf, sym->st_shndx, &shdr, name);
  102. }
  103. }
  104. storage_file_seek(elf->fd, old, true);
  105. return success;
  106. }
  107. static ELFSection* elf_section_of(ELFFile* elf, int index) {
  108. ELFSectionDict_it_t it;
  109. for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); ELFSectionDict_next(it)) {
  110. ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it);
  111. if(itref->value.sec_idx == index) {
  112. return &itref->value;
  113. }
  114. }
  115. return NULL;
  116. }
  117. static Elf32_Addr elf_address_of(ELFFile* elf, Elf32_Sym* sym, const char* sName) {
  118. if(sym->st_shndx == SHN_UNDEF) {
  119. Elf32_Addr addr = 0;
  120. if(elf->api_interface->resolver_callback(sName, &addr)) {
  121. return addr;
  122. }
  123. } else {
  124. ELFSection* symSec = elf_section_of(elf, sym->st_shndx);
  125. if(symSec) {
  126. return ((Elf32_Addr)symSec->data) + sym->st_value;
  127. }
  128. }
  129. FURI_LOG_D(TAG, " Can not find address for symbol %s", sName);
  130. return ELF_INVALID_ADDRESS;
  131. }
  132. __attribute__((unused)) static const char* elf_reloc_type_to_str(int symt) {
  133. #define STRCASE(name) \
  134. case name: \
  135. return #name;
  136. switch(symt) {
  137. STRCASE(R_ARM_NONE)
  138. STRCASE(R_ARM_TARGET1)
  139. STRCASE(R_ARM_ABS32)
  140. STRCASE(R_ARM_THM_PC22)
  141. STRCASE(R_ARM_THM_JUMP24)
  142. default:
  143. return "R_<unknow>";
  144. }
  145. #undef STRCASE
  146. }
  147. static JMPTrampoline* elf_create_trampoline(Elf32_Addr addr) {
  148. JMPTrampoline* trampoline = malloc(sizeof(JMPTrampoline));
  149. memcpy(trampoline->code, trampoline_code_little_endian, TRAMPOLINE_CODE_SIZE);
  150. trampoline->addr = addr;
  151. return trampoline;
  152. }
  153. static void elf_relocate_jmp_call(ELFFile* elf, Elf32_Addr relAddr, int type, Elf32_Addr symAddr) {
  154. int offset, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
  155. int to_thumb, is_call, blx_bit = 1 << 12;
  156. /* Get initial offset */
  157. hi = ((uint16_t*)relAddr)[0];
  158. lo = ((uint16_t*)relAddr)[1];
  159. s = (hi >> 10) & 1;
  160. j1 = (lo >> 13) & 1;
  161. j2 = (lo >> 11) & 1;
  162. i1 = (j1 ^ s) ^ 1;
  163. i2 = (j2 ^ s) ^ 1;
  164. imm10 = hi & 0x3ff;
  165. imm11 = lo & 0x7ff;
  166. offset = (s << 24) | (i1 << 23) | (i2 << 22) | (imm10 << 12) | (imm11 << 1);
  167. if(offset & 0x01000000) offset -= 0x02000000;
  168. to_thumb = symAddr & 1;
  169. is_call = (type == R_ARM_THM_PC22);
  170. /* Store offset */
  171. int offset_copy = offset;
  172. /* Compute final offset */
  173. offset += symAddr - relAddr;
  174. if(!to_thumb && is_call) {
  175. blx_bit = 0; /* bl -> blx */
  176. offset = (offset + 3) & -4; /* Compute offset from aligned PC */
  177. }
  178. /* Check that relocation is possible
  179. * offset must not be out of range
  180. * if target is to be entered in arm mode:
  181. - bit 1 must not set
  182. - instruction must be a call (bl) or a jump to PLT */
  183. if(!to_thumb || offset >= 0x1000000 || offset < -0x1000000) {
  184. if(to_thumb || (symAddr & 2) || (!is_call)) {
  185. FURI_LOG_D(
  186. TAG,
  187. "can't relocate value at %x, %s, doing trampoline",
  188. relAddr,
  189. elf_reloc_type_to_str(type));
  190. Elf32_Addr addr;
  191. if(!address_cache_get(elf->trampoline_cache, symAddr, &addr)) {
  192. addr = (Elf32_Addr)elf_create_trampoline(symAddr);
  193. address_cache_put(elf->trampoline_cache, symAddr, addr);
  194. }
  195. offset = offset_copy;
  196. offset += (int)addr - relAddr;
  197. if(!to_thumb && is_call) {
  198. blx_bit = 0; /* bl -> blx */
  199. offset = (offset + 3) & -4; /* Compute offset from aligned PC */
  200. }
  201. }
  202. }
  203. /* Compute and store final offset */
  204. s = (offset >> 24) & 1;
  205. i1 = (offset >> 23) & 1;
  206. i2 = (offset >> 22) & 1;
  207. j1 = s ^ (i1 ^ 1);
  208. j2 = s ^ (i2 ^ 1);
  209. imm10 = (offset >> 12) & 0x3ff;
  210. imm11 = (offset >> 1) & 0x7ff;
  211. (*(uint16_t*)relAddr) = (uint16_t)((hi & 0xf800) | (s << 10) | imm10);
  212. (*(uint16_t*)(relAddr + 2)) =
  213. (uint16_t)((lo & 0xc000) | (j1 << 13) | blx_bit | (j2 << 11) | imm11);
  214. }
  215. static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf32_Addr symAddr) {
  216. switch(type) {
  217. case R_ARM_TARGET1:
  218. case R_ARM_ABS32:
  219. *((uint32_t*)relAddr) += symAddr;
  220. FURI_LOG_D(TAG, " R_ARM_ABS32 relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr));
  221. break;
  222. case R_ARM_THM_PC22:
  223. case R_ARM_THM_JUMP24:
  224. elf_relocate_jmp_call(elf, relAddr, type, symAddr);
  225. FURI_LOG_D(
  226. TAG, " R_ARM_THM_CALL/JMP relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr));
  227. break;
  228. default:
  229. FURI_LOG_E(TAG, " Undefined relocation %d", type);
  230. return false;
  231. }
  232. return true;
  233. }
  234. static bool elf_relocate(ELFFile* elf, Elf32_Shdr* h, ELFSection* s) {
  235. if(s->data) {
  236. Elf32_Rel rel;
  237. size_t relEntries = h->sh_size / sizeof(rel);
  238. size_t relCount;
  239. (void)storage_file_seek(elf->fd, h->sh_offset, true);
  240. FURI_LOG_D(TAG, " Offset Info Type Name");
  241. int relocate_result = true;
  242. string_t symbol_name;
  243. string_init(symbol_name);
  244. for(relCount = 0; relCount < relEntries; relCount++) {
  245. if(relCount % RESOLVER_THREAD_YIELD_STEP == 0) {
  246. FURI_LOG_D(TAG, " reloc YIELD");
  247. furi_delay_tick(1);
  248. }
  249. if(storage_file_read(elf->fd, &rel, sizeof(Elf32_Rel)) != sizeof(Elf32_Rel)) {
  250. FURI_LOG_E(TAG, " reloc read fail");
  251. string_clear(symbol_name);
  252. return false;
  253. }
  254. Elf32_Addr symAddr;
  255. int symEntry = ELF32_R_SYM(rel.r_info);
  256. int relType = ELF32_R_TYPE(rel.r_info);
  257. Elf32_Addr relAddr = ((Elf32_Addr)s->data) + rel.r_offset;
  258. if(!address_cache_get(elf->relocation_cache, symEntry, &symAddr)) {
  259. Elf32_Sym sym;
  260. string_reset(symbol_name);
  261. if(!elf_read_symbol(elf, symEntry, &sym, symbol_name)) {
  262. FURI_LOG_E(TAG, " symbol read fail");
  263. string_clear(symbol_name);
  264. return false;
  265. }
  266. FURI_LOG_D(
  267. TAG,
  268. " %08X %08X %-16s %s",
  269. (unsigned int)rel.r_offset,
  270. (unsigned int)rel.r_info,
  271. elf_reloc_type_to_str(relType),
  272. string_get_cstr(symbol_name));
  273. symAddr = elf_address_of(elf, &sym, string_get_cstr(symbol_name));
  274. address_cache_put(elf->relocation_cache, symEntry, symAddr);
  275. }
  276. if(symAddr != ELF_INVALID_ADDRESS) {
  277. FURI_LOG_D(
  278. TAG,
  279. " symAddr=%08X relAddr=%08X",
  280. (unsigned int)symAddr,
  281. (unsigned int)relAddr);
  282. if(!elf_relocate_symbol(elf, relAddr, relType, symAddr)) {
  283. relocate_result = false;
  284. }
  285. } else {
  286. FURI_LOG_E(TAG, " No symbol address of %s", string_get_cstr(symbol_name));
  287. relocate_result = false;
  288. }
  289. }
  290. string_clear(symbol_name);
  291. return relocate_result;
  292. } else {
  293. FURI_LOG_D(TAG, "Section not loaded");
  294. }
  295. return false;
  296. }
  297. /**************************************************************************************************/
  298. /********************************************* MISC ***********************************************/
  299. /**************************************************************************************************/
  300. static bool cstr_prefix(const char* prefix, const char* string) {
  301. return strncmp(prefix, string, strlen(prefix)) == 0;
  302. }
  303. /**************************************************************************************************/
  304. /************************************ Internal FAP interfaces *************************************/
  305. /**************************************************************************************************/
  306. typedef enum {
  307. SectionTypeERROR = 0,
  308. SectionTypeUnused = 1 << 0,
  309. SectionTypeData = 1 << 1,
  310. SectionTypeRelData = 1 << 2,
  311. SectionTypeSymTab = 1 << 3,
  312. SectionTypeStrTab = 1 << 4,
  313. SectionTypeManifest = 1 << 5,
  314. SectionTypeDebugLink = 1 << 6,
  315. SectionTypeValid = SectionTypeSymTab | SectionTypeStrTab | SectionTypeManifest,
  316. } SectionType;
  317. static bool elf_load_metadata(
  318. ELFFile* elf,
  319. Elf32_Shdr* section_header,
  320. FlipperApplicationManifest* manifest) {
  321. if(section_header->sh_size < sizeof(FlipperApplicationManifest)) {
  322. return false;
  323. }
  324. if(manifest == NULL) {
  325. return true;
  326. }
  327. return storage_file_seek(elf->fd, section_header->sh_offset, true) &&
  328. storage_file_read(elf->fd, manifest, section_header->sh_size) ==
  329. section_header->sh_size;
  330. }
  331. static bool elf_load_debug_link(ELFFile* elf, Elf32_Shdr* section_header) {
  332. elf->debug_link_info.debug_link_size = section_header->sh_size;
  333. elf->debug_link_info.debug_link = malloc(section_header->sh_size);
  334. return storage_file_seek(elf->fd, section_header->sh_offset, true) &&
  335. storage_file_read(elf->fd, elf->debug_link_info.debug_link, section_header->sh_size) ==
  336. section_header->sh_size;
  337. }
  338. static SectionType elf_preload_section(
  339. ELFFile* elf,
  340. size_t section_idx,
  341. Elf32_Shdr* section_header,
  342. string_t name_string,
  343. FlipperApplicationManifest* manifest) {
  344. const char* name = string_get_cstr(name_string);
  345. const struct {
  346. const char* prefix;
  347. SectionType type;
  348. } lookup_sections[] = {
  349. {".text", SectionTypeData},
  350. {".rodata", SectionTypeData},
  351. {".data", SectionTypeData},
  352. {".bss", SectionTypeData},
  353. {".preinit_array", SectionTypeData},
  354. {".init_array", SectionTypeData},
  355. {".fini_array", SectionTypeData},
  356. {".rel.text", SectionTypeRelData},
  357. {".rel.rodata", SectionTypeRelData},
  358. {".rel.data", SectionTypeRelData},
  359. {".rel.preinit_array", SectionTypeRelData},
  360. {".rel.init_array", SectionTypeRelData},
  361. {".rel.fini_array", SectionTypeRelData},
  362. };
  363. for(size_t i = 0; i < COUNT_OF(lookup_sections); i++) {
  364. if(cstr_prefix(lookup_sections[i].prefix, name)) {
  365. FURI_LOG_D(TAG, "Found section %s", lookup_sections[i].prefix);
  366. if(lookup_sections[i].type == SectionTypeRelData) {
  367. name = name + strlen(".rel");
  368. }
  369. ELFSection* section_p = elf_file_get_section(elf, name);
  370. if(!section_p) {
  371. ELFSection section = {
  372. .data = NULL,
  373. .sec_idx = 0,
  374. .rel_sec_idx = 0,
  375. .size = 0,
  376. };
  377. elf_file_put_section(elf, name, &section);
  378. section_p = elf_file_get_section(elf, name);
  379. }
  380. if(lookup_sections[i].type == SectionTypeRelData) {
  381. section_p->rel_sec_idx = section_idx;
  382. } else {
  383. section_p->sec_idx = section_idx;
  384. }
  385. return lookup_sections[i].type;
  386. }
  387. }
  388. if(strcmp(name, ".symtab") == 0) {
  389. FURI_LOG_D(TAG, "Found .symtab section");
  390. elf->symbol_table = section_header->sh_offset;
  391. elf->symbol_count = section_header->sh_size / sizeof(Elf32_Sym);
  392. return SectionTypeSymTab;
  393. } else if(strcmp(name, ".strtab") == 0) {
  394. FURI_LOG_D(TAG, "Found .strtab section");
  395. elf->symbol_table_strings = section_header->sh_offset;
  396. return SectionTypeStrTab;
  397. } else if(strcmp(name, ".fapmeta") == 0) {
  398. FURI_LOG_D(TAG, "Found .fapmeta section");
  399. if(elf_load_metadata(elf, section_header, manifest)) {
  400. return SectionTypeManifest;
  401. } else {
  402. return SectionTypeERROR;
  403. }
  404. } else if(strcmp(name, ".gnu_debuglink") == 0) {
  405. FURI_LOG_D(TAG, "Found .gnu_debuglink section");
  406. if(elf_load_debug_link(elf, section_header)) {
  407. return SectionTypeDebugLink;
  408. } else {
  409. return SectionTypeERROR;
  410. }
  411. }
  412. return SectionTypeUnused;
  413. }
  414. static bool elf_load_section_data(ELFFile* elf, ELFSection* section) {
  415. Elf32_Shdr section_header;
  416. if(section->sec_idx == 0) {
  417. FURI_LOG_D(TAG, "Section is not present");
  418. return true;
  419. }
  420. if(!elf_read_section_header(elf, section->sec_idx, &section_header)) {
  421. return false;
  422. }
  423. if(section_header.sh_size == 0) {
  424. FURI_LOG_D(TAG, "No data for section");
  425. return true;
  426. }
  427. section->data = aligned_malloc(section_header.sh_size, section_header.sh_addralign);
  428. section->size = section_header.sh_size;
  429. if(section_header.sh_type == SHT_NOBITS) {
  430. /* section is empty (.bss?) */
  431. /* no need to memset - allocator already did that */
  432. return true;
  433. }
  434. if((!storage_file_seek(elf->fd, section_header.sh_offset, true)) ||
  435. (storage_file_read(elf->fd, section->data, section_header.sh_size) !=
  436. section_header.sh_size)) {
  437. FURI_LOG_E(TAG, " seek/read fail");
  438. return false;
  439. }
  440. FURI_LOG_D(TAG, "0x%X", section->data);
  441. return true;
  442. }
  443. static bool elf_relocate_section(ELFFile* elf, ELFSection* section) {
  444. Elf32_Shdr section_header;
  445. if(section->rel_sec_idx) {
  446. FURI_LOG_D(TAG, "Relocating section");
  447. if(elf_read_section_header(elf, section->rel_sec_idx, &section_header))
  448. return elf_relocate(elf, &section_header, section);
  449. else {
  450. FURI_LOG_E(TAG, "Error reading section header");
  451. return false;
  452. }
  453. } else {
  454. FURI_LOG_D(TAG, "No relocation index"); /* Not an error */
  455. }
  456. return true;
  457. }
  458. static void elf_file_call_section_list(ELFFile* elf, const char* name, bool reverse_order) {
  459. ELFSection* section = elf_file_get_section(elf, name);
  460. if(section && section->size) {
  461. const uint32_t* start = section->data;
  462. const uint32_t* end = section->data + section->size;
  463. if(reverse_order) {
  464. while(end > start) {
  465. end--;
  466. ((void (*)(void))(*end))();
  467. }
  468. } else {
  469. while(start < end) {
  470. ((void (*)(void))(*start))();
  471. start++;
  472. }
  473. }
  474. }
  475. }
  476. /**************************************************************************************************/
  477. /********************************************* Public *********************************************/
  478. /**************************************************************************************************/
  479. ELFFile* elf_file_alloc(Storage* storage, const ElfApiInterface* api_interface) {
  480. ELFFile* elf = malloc(sizeof(ELFFile));
  481. elf->fd = storage_file_alloc(storage);
  482. elf->api_interface = api_interface;
  483. ELFSectionDict_init(elf->sections);
  484. AddressCache_init(elf->trampoline_cache);
  485. return elf;
  486. }
  487. void elf_file_free(ELFFile* elf) {
  488. // free sections data
  489. {
  490. ELFSectionDict_it_t it;
  491. for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it);
  492. ELFSectionDict_next(it)) {
  493. const ELFSectionDict_itref_t* itref = ELFSectionDict_cref(it);
  494. if(itref->value.data) {
  495. aligned_free(itref->value.data);
  496. }
  497. free((void*)itref->key);
  498. }
  499. ELFSectionDict_clear(elf->sections);
  500. }
  501. // free trampoline data
  502. {
  503. AddressCache_it_t it;
  504. for(AddressCache_it(it, elf->trampoline_cache); !AddressCache_end_p(it);
  505. AddressCache_next(it)) {
  506. const AddressCache_itref_t* itref = AddressCache_cref(it);
  507. free((void*)itref->value);
  508. }
  509. AddressCache_clear(elf->trampoline_cache);
  510. }
  511. if(elf->debug_link_info.debug_link) {
  512. free(elf->debug_link_info.debug_link);
  513. }
  514. storage_file_free(elf->fd);
  515. free(elf);
  516. }
  517. bool elf_file_open(ELFFile* elf, const char* path) {
  518. Elf32_Ehdr h;
  519. Elf32_Shdr sH;
  520. if(!storage_file_open(elf->fd, path, FSAM_READ, FSOM_OPEN_EXISTING) ||
  521. !storage_file_seek(elf->fd, 0, true) ||
  522. storage_file_read(elf->fd, &h, sizeof(h)) != sizeof(h) ||
  523. !storage_file_seek(elf->fd, h.e_shoff + h.e_shstrndx * sizeof(sH), true) ||
  524. storage_file_read(elf->fd, &sH, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)) {
  525. return false;
  526. }
  527. elf->entry = h.e_entry;
  528. elf->sections_count = h.e_shnum;
  529. elf->section_table = h.e_shoff;
  530. elf->section_table_strings = sH.sh_offset;
  531. return true;
  532. }
  533. bool elf_file_load_manifest(ELFFile* elf, FlipperApplicationManifest* manifest) {
  534. bool result = false;
  535. string_t name;
  536. string_init(name);
  537. FURI_LOG_D(TAG, "Looking for manifest section");
  538. for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) {
  539. Elf32_Shdr section_header;
  540. string_reset(name);
  541. if(!elf_read_section(elf, section_idx, &section_header, name)) {
  542. break;
  543. }
  544. if(string_cmp(name, ".fapmeta") == 0) {
  545. if(elf_load_metadata(elf, &section_header, manifest)) {
  546. FURI_LOG_D(TAG, "Load manifest done");
  547. result = true;
  548. break;
  549. } else {
  550. break;
  551. }
  552. }
  553. }
  554. string_clear(name);
  555. return result;
  556. }
  557. bool elf_file_load_section_table(ELFFile* elf, FlipperApplicationManifest* manifest) {
  558. SectionType loaded_sections = SectionTypeERROR;
  559. string_t name;
  560. string_init(name);
  561. FURI_LOG_D(TAG, "Scan ELF indexs...");
  562. for(size_t section_idx = 1; section_idx < elf->sections_count; section_idx++) {
  563. Elf32_Shdr section_header;
  564. string_reset(name);
  565. if(!elf_read_section(elf, section_idx, &section_header, name)) {
  566. loaded_sections = SectionTypeERROR;
  567. break;
  568. }
  569. FURI_LOG_D(TAG, "Preloading data for section #%d %s", section_idx, string_get_cstr(name));
  570. SectionType section_type =
  571. elf_preload_section(elf, section_idx, &section_header, name, manifest);
  572. loaded_sections |= section_type;
  573. if(section_type == SectionTypeERROR) {
  574. loaded_sections = SectionTypeERROR;
  575. break;
  576. }
  577. }
  578. string_clear(name);
  579. FURI_LOG_D(TAG, "Load symbols done");
  580. return IS_FLAGS_SET(loaded_sections, SectionTypeValid);
  581. }
  582. ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) {
  583. ELFFileLoadStatus status = ELFFileLoadStatusSuccess;
  584. ELFSectionDict_it_t it;
  585. AddressCache_init(elf->relocation_cache);
  586. size_t start = furi_get_tick();
  587. for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); ELFSectionDict_next(it)) {
  588. ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it);
  589. FURI_LOG_D(TAG, "Loading section '%s'", itref->key);
  590. if(!elf_load_section_data(elf, &itref->value)) {
  591. FURI_LOG_E(TAG, "Error loading section '%s'", itref->key);
  592. status = ELFFileLoadStatusUnspecifiedError;
  593. }
  594. }
  595. if(status == ELFFileLoadStatusSuccess) {
  596. for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it);
  597. ELFSectionDict_next(it)) {
  598. ELFSectionDict_itref_t* itref = ELFSectionDict_ref(it);
  599. FURI_LOG_D(TAG, "Relocating section '%s'", itref->key);
  600. if(!elf_relocate_section(elf, &itref->value)) {
  601. FURI_LOG_E(TAG, "Error relocating section '%s'", itref->key);
  602. status = ELFFileLoadStatusMissingImports;
  603. }
  604. }
  605. }
  606. /* Fixing up entry point */
  607. if(status == ELFFileLoadStatusSuccess) {
  608. ELFSection* text_section = elf_file_get_section(elf, ".text");
  609. if(text_section == NULL) {
  610. FURI_LOG_E(TAG, "No .text section found");
  611. status = ELFFileLoadStatusUnspecifiedError;
  612. } else {
  613. elf->entry += (uint32_t)text_section->data;
  614. }
  615. }
  616. FURI_LOG_D(TAG, "Relocation cache size: %u", AddressCache_size(elf->relocation_cache));
  617. FURI_LOG_D(TAG, "Trampoline cache size: %u", AddressCache_size(elf->trampoline_cache));
  618. AddressCache_clear(elf->relocation_cache);
  619. FURI_LOG_I(TAG, "Loaded in %ums", (size_t)(furi_get_tick() - start));
  620. return status;
  621. }
  622. void elf_file_pre_run(ELFFile* elf) {
  623. elf_file_call_section_list(elf, ".preinit_array", false);
  624. elf_file_call_section_list(elf, ".init_array", false);
  625. }
  626. int32_t elf_file_run(ELFFile* elf, void* args) {
  627. int32_t result;
  628. result = ((int32_t(*)(void*))elf->entry)(args);
  629. return result;
  630. }
  631. void elf_file_post_run(ELFFile* elf) {
  632. elf_file_call_section_list(elf, ".fini_array", true);
  633. }
  634. const ElfApiInterface* elf_file_get_api_interface(ELFFile* elf_file) {
  635. return elf_file->api_interface;
  636. }
  637. void elf_file_init_debug_info(ELFFile* elf, ELFDebugInfo* debug_info) {
  638. // set entry
  639. debug_info->entry = elf->entry;
  640. // copy debug info
  641. memcpy(&debug_info->debug_link_info, &elf->debug_link_info, sizeof(ELFDebugLinkInfo));
  642. // init mmap
  643. debug_info->mmap_entry_count = ELFSectionDict_size(elf->sections);
  644. debug_info->mmap_entries = malloc(sizeof(ELFMemoryMapEntry) * debug_info->mmap_entry_count);
  645. uint32_t mmap_entry_idx = 0;
  646. ELFSectionDict_it_t it;
  647. for(ELFSectionDict_it(it, elf->sections); !ELFSectionDict_end_p(it); ELFSectionDict_next(it)) {
  648. const ELFSectionDict_itref_t* itref = ELFSectionDict_cref(it);
  649. const void* data_ptr = itref->value.data;
  650. if(data_ptr) {
  651. debug_info->mmap_entries[mmap_entry_idx].address = (uint32_t)data_ptr;
  652. debug_info->mmap_entries[mmap_entry_idx].name = itref->key;
  653. mmap_entry_idx++;
  654. }
  655. }
  656. }
  657. void elf_file_clear_debug_info(ELFDebugInfo* debug_info) {
  658. // clear debug info
  659. memset(&debug_info->debug_link_info, 0, sizeof(ELFDebugLinkInfo));
  660. // clear mmap
  661. if(debug_info->mmap_entries) {
  662. free(debug_info->mmap_entries);
  663. debug_info->mmap_entries = NULL;
  664. }
  665. debug_info->mmap_entry_count = 0;
  666. }