[FL-3097] fbt, faploader: minimal app module implementation (#2420)

* fbt, faploader: minimal app module implementation
* faploader, libs: moved API hashtable core to flipper_application
* example: compound api
* lib: flipper_application: naming fixes, doxygen comments
* fbt: changed `requires` manifest field behavior for app extensions
* examples: refactored plugin apps; faploader: changed new API naming; fbt: changed PLUGIN app type meaning
* loader: dropped support for debug apps & plugin menus
* moved applications/plugins -> applications/external
* Restored x bit on chiplist_convert.py
* git: fixed free-dap submodule path
* pvs: updated submodule paths
* examples: example_advanced_plugins.c: removed potential memory leak on errors
* examples: example_plugins: refined requires
* fbt: not deploying app modules for debug/sample apps; extra validation for .PLUGIN-type apps
* apps: removed cdefines for external apps
* fbt: moved ext app path definition
* fbt: reworked fap_dist handling; f18: synced api_symbols.csv
* fbt: removed resources_paths for extapps
* scripts: reworked storage
* scripts: reworked runfap.py & selfupdate.py to use new api
* wip: fal runner
* fbt: moved file packaging into separate module
* scripts: storage: fixes
* scripts: storage: minor fixes for new api
* fbt: changed internal artifact storage details for external apps
* scripts: storage: additional fixes and better error reporting; examples: using APP_DATA_PATH()
* fbt, scripts: reworked launch_app to deploy plugins; moved old runfap.py to distfap.py
* fbt: extra check for plugins descriptors
* fbt: additional checks in emitter
* fbt: better info message on SDK rebuild
* scripts: removed requirements.txt
* loader: removed remnants of plugins & debug menus
* post-review fixes
This commit is contained in:
hedger
2023-03-14 18:29:28 +04:00
committed by GitHub
parent 4bd3dca16f
commit 53435579b3
376 changed files with 2041 additions and 1036 deletions

View File

@@ -3,10 +3,14 @@
#include <elf.h>
#include <stdbool.h>
#define ELF_INVALID_ADDRESS 0xFFFFFFFF
typedef struct {
/**
* @brief Interface for ELF loader to resolve symbols
*/
typedef struct ElfApiInterface {
uint16_t api_version_major;
uint16_t api_version_minor;
bool (*resolver_callback)(const char* name, Elf32_Addr* address);
bool (*resolver_callback)(
const struct ElfApiInterface* interface,
const char* name,
Elf32_Addr* address);
} ElfApiInterface;

View File

@@ -17,6 +17,8 @@
#define FURI_LOG_D(...)
#endif
#define ELF_INVALID_ADDRESS 0xFFFFFFFF
#define TRAMPOLINE_CODE_SIZE 6
/**
@@ -166,7 +168,7 @@ static ELFSection* elf_section_of(ELFFile* elf, int index) {
static Elf32_Addr elf_address_of(ELFFile* elf, Elf32_Sym* sym, const char* sName) {
if(sym->st_shndx == SHN_UNDEF) {
Elf32_Addr addr = 0;
if(elf->api_interface->resolver_callback(sName, &addr)) {
if(elf->api_interface->resolver_callback(elf->api_interface, sName, &addr)) {
return addr;
}
} else {
@@ -514,10 +516,13 @@ static SectionType elf_preload_section(
section_p->sec_idx = section_idx;
if(section_header->sh_type == SHT_PREINIT_ARRAY) {
furi_assert(elf->preinit_array == NULL);
elf->preinit_array = section_p;
} else if(section_header->sh_type == SHT_INIT_ARRAY) {
furi_assert(elf->init_array == NULL);
elf->init_array = section_p;
} else if(section_header->sh_type == SHT_FINI_ARRAY) {
furi_assert(elf->fini_array == NULL);
elf->fini_array = section_p;
}
@@ -605,10 +610,17 @@ ELFFile* elf_file_alloc(Storage* storage, const ElfApiInterface* api_interface)
elf->api_interface = api_interface;
ELFSectionDict_init(elf->sections);
AddressCache_init(elf->trampoline_cache);
elf->init_array_called = false;
return elf;
}
void elf_file_free(ELFFile* elf) {
// furi_check(!elf->init_array_called);
if(elf->init_array_called) {
FURI_LOG_W(TAG, "Init array was called, but fini array wasn't");
elf_file_call_section_list(elf->fini_array, true);
}
// free sections data
{
ELFSectionDict_it_t it;
@@ -774,19 +786,26 @@ ELFFileLoadStatus elf_file_load_sections(ELFFile* elf) {
return status;
}
void elf_file_pre_run(ELFFile* elf) {
void elf_file_call_init(ELFFile* elf) {
furi_check(!elf->init_array_called);
elf_file_call_section_list(elf->preinit_array, false);
elf_file_call_section_list(elf->init_array, false);
elf->init_array_called = true;
}
int32_t elf_file_run(ELFFile* elf, void* args) {
int32_t result;
result = ((int32_t(*)(void*))elf->entry)(args);
return result;
bool elf_file_is_init_complete(ELFFile* elf) {
return elf->init_array_called;
}
void elf_file_post_run(ELFFile* elf) {
void* elf_file_get_entry_point(ELFFile* elf) {
furi_check(elf->init_array_called);
return (void*)elf->entry;
}
void elf_file_call_fini(ELFFile* elf) {
furi_check(elf->init_array_called);
elf_file_call_section_list(elf->fini_array, true);
elf->init_array_called = false;
}
const ElfApiInterface* elf_file_get_api_interface(ELFFile* elf_file) {

View File

@@ -82,24 +82,34 @@ bool elf_file_load_section_table(ELFFile* elf_file);
ELFFileLoadStatus elf_file_load_sections(ELFFile* elf_file);
/**
* @brief Execute ELF file pre-run stage, call static constructors for example (load stage #3)
* @brief Execute ELF file pre-run stage,
* call static constructors for example (load stage #3)
* Must be done before invoking any code from the ELF file
* @param elf
*/
void elf_file_pre_run(ELFFile* elf);
void elf_file_call_init(ELFFile* elf);
/**
* @brief Run ELF file (load stage #4)
* @brief Check if ELF file pre-run stage was executed and its code is runnable
* @param elf
*/
bool elf_file_is_init_complete(ELFFile* elf);
/**
* @brief Get actual entry point for ELF file
* @param elf_file
* @param args
* @return int32_t
*/
int32_t elf_file_run(ELFFile* elf_file, void* args);
void* elf_file_get_entry_point(ELFFile* elf_file);
/**
* @brief Execute ELF file post-run stage, call static destructors for example (load stage #5)
* @brief Execute ELF file post-run stage,
* call static destructors for example (load stage #5)
* Must be done if any code from the ELF file was executed
* @param elf
*/
void elf_file_post_run(ELFFile* elf);
void elf_file_call_fini(ELFFile* elf);
/**
* @brief Get ELF file API interface

View File

@@ -45,6 +45,8 @@ struct ELFFile {
ELFSection* preinit_array;
ELFSection* init_array;
ELFSection* fini_array;
bool init_array_called;
};
#ifdef __cplusplus