elf_file.c 28 KB

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