elf_file.c 28 KB

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