## ELF Loader Example This example shows how to use ELF loader to run ELF file. ## How to Use Example Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`. * Note: Only ESP32, ESP32-S2, ESP32-S3 and ESP32-P4 are supported ### Hardware Required * A development board based on espressif ESP32/ESP32-S2/ESP32-S3/ESP32-C6/ESP32-P4 SoC * A USB cable for power supply and programming ### Configure the Project Open the project configuration menu (`idf.py menuconfig`). In the `Example Configuration` menu: * Enable ELF input arguments in the `Support arguments for ELF main` option if necessary. * Set the arguments in the `Arguments of ELF main` option. ### Generate the ELF File The `test_xtensa.elf` or `test_riscv.elf` used for testing is corresponding ELF file generated by [build_elf_file_example](https://github.com/espressif/esp-iot-solution/tree/master/examples/elf_loader/build_elf_file_example), corresponding to the `xtensa` and `risc-v` processor architectures respectively. In `build_elf_file_example` example, `hello_world.app.elf` will be generated, and you can copy this ELF file to the `elf_loader_example/main`, e.g. ``` cp build/hello_world.app.elf ../elf_loader_example/main/test_xtensa.elf ``` You can refer to [build_elf_file_example](https://github.com/espressif/esp-iot-solution/tree/master/examples/elf_loader/build_elf_file_example) to generate the ELF file you need. ### Generate functions or variables that can be used by ELF applications The functions or variables in symbols table can be used by the ELF application, according to your needs, you can use `symbol.py` to generate the following types of symbols table: 1. Generate symbols table based on ELF files. 2. Generate symbols table based on static libraries. #### Generate symbols table based on ELF files The `components/elf_loader/src/esp_all_symbol.c` contains functions and variables used by the ELF application, this file is generated by `components/elf_loader/tool/symbols.py`. This script will generate functions or variables for the current project that can be used by ELF applications. You can use the ELF file of the current project to generate `components/elf_loader/src/esp_all_symbol.c`. e.g. 1. Enter the `elf_loader_example` directory: ```linux cd ./esp-iot-solution/examples/elf_loader/elf_loader_example ``` 2. Use the `idf.py` tool to set the compiler chip, and then compile it, the instructions are: ```linux # Set compiler chip idf.py set-target esp32p4 # Compile idf.py build ``` 3. Use the `symbols.py` to generate `esp_all_symbol.c`: ```linux # Generate esp_all_symbol.c based on ELF application python ../../../components/elf_loader/tool/symbols.py -u -i main/test_riscv.elf -t e ``` Note: the symbols table are unlinked functions or variables in the ELF application. ```linux # Generate esp_all_symbol.c based on the ELF of the current project python ../../../components/elf_loader/tool/symbols.py -i build/elf-loader.elf -t e ``` Note: the symbols table are functions or variables that have been linked to the project ELF. #### Generate symbols table based on static libraries The `components/elf_loader/src/xxx_symbol.c(xxx is the component name, such as esp_wifi ...)` contains functions and variables used by the ELF application, this file is generated by `components/elf_loader/tool/symbols.py`. This script will generate functions or variables for the current project that can be used by ELF applications. You can use the ELF file of the current project to generate `components/elf_loader/src/xxx_symbol.c`. e.g. 1. Enter the `elf_loader_example` directory: ```linux cd ./esp-iot-solution/examples/elf_loader/elf_loader_example ``` 2. Use the `idf.py` tool to set the compiler chip, and then compile it, the instructions are: ```linux # Set compiler chip idf.py set-target esp32p4 # Compile idf.py build ``` 3. Use the `symbols.py` to generate `xxx_symbol.c(e.g. esp_wifi_symbol.c)`: ```linux # generate esp_all_symbol.c python ../../../components/elf_loader/tool/symbols.py -i build/esp-idf/esp_wifi/libesp_wifi.a -t l ``` 4. Add `g_xxx_elfsyms` in `xxx_symbol.c` to `components/elf_loader/src/esp_elf_symbol.c`. e.g: `esp_wifi_symbol.c` ```c ... uintptr_t elf_find_sym(const char *sym_name) { ... extern const struct esp_elfsym g_esp_wifi_elfsyms[]; syms = g_esp_wifi_elfsyms; while (syms->name) { if (!strcmp(syms->name, sym_name)) { return (uintptr_t)syms->sym; } syms++; } ... } ``` 5. Add `xxx_symbol.c` to `components/elf_loader/CMakeLists.txt`. e.g: `esp_wifi_symbol.c` ```cmake if(CONFIG_ELF_LOADER) ... list(APPEND srcs "src/esp_wifi_symbol.c") ... endif() ``` ### Build and Flash Run `idf.py -p PORT flash monitor` to build, flash and monitor the project. (To exit the serial monitor, type ``Ctrl-]``.) ## Example Output As you run the example, you will see the following log: ``` I (0) cpu_start: Starting scheduler on APP CPU. I (382) elf_loader: Start to relocate ELF I (392) elf_loader: Start to run ELF hello world 0 hello world 1 hello world 2 hello world 3 hello world 4 hello world 5 hello world 6 hello world 7 hello world 8 hello world 9 I (10392) elf_loader: Success to exit from APP of ELF ```
To create a project from this example, run:
idf.py create-project-from-example "espressif/elf_loader=1.1.0:elf_loader_example"