elf_loader refactored and added more symbols (#347)
Some checks failed
Build Firmware / cyd-2432s024c (push) Has been cancelled
Build Firmware / cyd-2432s028r (push) Has been cancelled
Build Firmware / cyd-e32r28t (push) Has been cancelled
Build Firmware / cyd-2432s032c (push) Has been cancelled
Build Firmware / cyd-jc2432w328c (push) Has been cancelled
Build Firmware / cyd-8048s043c (push) Has been cancelled
Build Firmware / cyd-jc8048w550c (push) Has been cancelled
Build Firmware / cyd-4848s040c (push) Has been cancelled
Build Firmware / elecrow-crowpanel-advance-28 (push) Has been cancelled
Build Firmware / elecrow-crowpanel-advance-35 (push) Has been cancelled
Build Firmware / elecrow-crowpanel-advance-50 (push) Has been cancelled
Build Firmware / elecrow-crowpanel-basic-28 (push) Has been cancelled
Build Firmware / elecrow-crowpanel-basic-35 (push) Has been cancelled
Build Firmware / elecrow-crowpanel-basic-50 (push) Has been cancelled
Build Firmware / lilygo-tdeck (push) Has been cancelled
Build Firmware / lilygo-tlora-pager (push) Has been cancelled
Build Firmware / m5stack-cardputer (push) Has been cancelled
Build Firmware / m5stack-core2 (push) Has been cancelled
Build Firmware / m5stack-cores3 (push) Has been cancelled
Build Firmware / unphone (push) Has been cancelled
Build Firmware / waveshare-s3-touch-43 (push) Has been cancelled
Build Firmware / waveshare-s3-touch-lcd-147 (push) Has been cancelled
Build Firmware / waveshare-s3-touch-lcd-128 (push) Has been cancelled
Build Firmware / waveshare-s3-lcd-13 (push) Has been cancelled
Build SDK / esp32 (push) Has been cancelled
Build SDK / esp32s3 (push) Has been cancelled
Build Simulator / Build-Simulator-Linux (push) Has been cancelled
Build Simulator / Build-Simulator-macOS (push) Has been cancelled
Tests / Run (push) Has been cancelled

This commit is contained in:
Ken Van Hoeylandt 2025-09-27 09:18:51 +02:00 committed by GitHub
parent 9cc58099b4
commit dcf28d0868
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 782 additions and 57 deletions

View File

@ -15,6 +15,16 @@
Write the user choice to a file on the card. Write the user choice to a file on the card.
File contains 3 statuses: ignore, data, .. initdata? File contains 3 statuses: ignore, data, .. initdata?
The latter is used for auto-selecting it as data partition. The latter is used for auto-selecting it as data partition.
- Support direct installation of an `.app` file with `tactility.py install helloworld.app <ip>`
- Support `tactility.py target <ip>` to remember the device IP address.
- External app error code 22 should warn that the user might've forgotten a `main()` entry point
- Bug: `Buildscript/release-sdk-current.sh` should delete the currently released SDK. It should probably also output it with versioning and target platform naming so it can be referred to as if it is a real release.
- Tactility docs: external app dev guide should explain [debugging](https://docs.zephyrproject.org/latest/services/llext/debug.html)
- elf_loader changes/suggestions:
- Make entry-point optional (so we can build libraries, or have the `manifest` as a global symbol)
- Implement support for alternative symbol lists. e.g. a function pointer that resolves a single symbol.
- Implement the entire list of [soft-float library functions](https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html) to `tt_init.cpp`
- `tactility.py` should stop running applications when it is: uninstalling, installing, or running an application that is already running.
## Medium Priority ## Medium Priority
@ -29,6 +39,7 @@
- Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash. - Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash.
- Bug: Crash handling app cannot be exited with an EncoderDevice. (current work-around is to manually reset the device) - Bug: Crash handling app cannot be exited with an EncoderDevice. (current work-around is to manually reset the device)
- I2C app should show error when I2C port is disabled when the scan button was manually pressed - I2C app should show error when I2C port is disabled when the scan button was manually pressed
- TactilitySDK: Support automatic scanning of header files so that we can generate the `tt_init.cpp` symbols list.
## Lower Priority ## Lower Priority

View File

@ -1,5 +1,16 @@
# ChangeLog # ChangeLog
## v1.1.1 - 2025-06-26
* Added support for ESP32-C61
## v1.1.0 - 2025-05-06
* Added fast build for ELF application
* Added a script to generate the symbol table for the ELF APP:
* Supports generating symbols table based on ELF file
* Supports generating symbols table based on static libraries
## v1.0.0 - 2024-12-09 ## v1.0.0 - 2024-12-09
* Added support for the following RISC-V chips: ESP32-P4 and ESP32-C6 * Added support for the following RISC-V chips: ESP32-P4 and ESP32-C6

View File

@ -4,6 +4,10 @@ if(CONFIG_ELF_LOADER)
"src/esp_elf.c" "src/esp_elf.c"
"src/esp_elf_adapter.c") "src/esp_elf_adapter.c")
if(CONFIG_ELF_LOADER_CUSTOMER_SYMBOLS)
list(APPEND srcs "src/esp_all_symbol.c")
endif()
if(CONFIG_IDF_TARGET_ARCH_XTENSA) if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs "src/arch/esp_elf_xtensa.c") list(APPEND srcs "src/arch/esp_elf_xtensa.c")

View File

@ -1,15 +1,15 @@
menu "Espressif ELF Loader Configuration" menu "Espressif ELF Loader Configuration"
visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) visible if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61)
config ELF_LOADER_BUS_ADDRESS_MIRROR config ELF_LOADER_BUS_ADDRESS_MIRROR
bool bool
default y if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) default y if (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
default n if (IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) default n if (IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61)
config ELF_LOADER config ELF_LOADER
bool "Enable Espressif ELF Loader" bool "Enable Espressif ELF Loader"
default y default y
depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4) depends on (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61)
help help
Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices. Select this option to enable ELF Loader and show the submenu with ELF Loader configuration choices.
@ -29,7 +29,7 @@ menu "Espressif ELF Loader Configuration"
config ELF_LOADER_LOAD_PSRAM config ELF_LOADER_LOAD_PSRAM
bool "Load ELF to PSRAM" bool "Load ELF to PSRAM"
default y default y
depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4 || IDF_TARGET_ESP32C61) && SPIRAM
select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) select ELF_LOADER_CACHE_OFFSET if (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3)
select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2 select ELF_LOADER_SET_MMU if IDF_TARGET_ESP32S2
help help

View File

@ -13,6 +13,7 @@ This ELF loader supports following SoCs:
- ESP32-S3, support running ELF in PSRAM - ESP32-S3, support running ELF in PSRAM
- ESP32-P4, support running ELF in PSRAM - ESP32-P4, support running ELF in PSRAM
- ESP32-C6 - ESP32-C6
- ESP32-C61, support running ELF in PSRAM
### Usage ### Usage
@ -62,6 +63,29 @@ project_elf(XXXX)
Build the project as an ordinary ESP-IDF project, and then the ELF file named `XXXX.app.elf` is in the build directory. Build the project as an ordinary ESP-IDF project, and then the ELF file named `XXXX.app.elf` is in the build directory.
### ELF APP Fast Build
Users can enable ELF fast build functionality by configuring CMAKE's generator as Unit Makefile. The reference command is as follows:
```bash
idf.py -G 'Unix Makefiles' set-target <chip-name>
```
Then input the ELF APP build command as follows:
```
idf.py elf
```
The build system will only build ELF target components and show the following logs:
```
Building C object esp-idf/main/CMakeFiles/__idf_main.dir/main.c.obj
Linking C static library libmain.a
Build ELF: hello_world.app.elf
Built target elf
```
### Adding the Component to Your Project ### Adding the Component to Your Project
Please use the component manager command add-dependency to add the elf_loader component as a dependency in your project. During the CMake step, the component will be downloaded automatically. Please use the component manager command add-dependency to add the elf_loader component as a dependency in your project. During the CMake step, the component will be downloaded automatically.

View File

@ -52,7 +52,16 @@ macro(project_elf project_name)
if(ELF_COMPONENTS) if(ELF_COMPONENTS)
foreach(c ${ELF_COMPONENTS}) foreach(c ${ELF_COMPONENTS})
list(APPEND elf_libs "esp-idf/${c}/lib${c}.a") list(APPEND elf_libs "esp-idf/${c}/lib${c}.a")
if(${CMAKE_GENERATOR} STREQUAL "Unix Makefiles")
add_custom_command(OUTPUT elf_${c}_app
COMMAND +${CMAKE_MAKE_PROGRAM} "__idf_${c}/fast"
COMMENT "Build Component: ${c}"
)
list(APPEND elf_dependeces "elf_${c}_app")
else()
list(APPEND elf_dependeces "idf::${c}") list(APPEND elf_dependeces "idf::${c}")
endif()
endforeach() endforeach()
endif() endif()
if (ELF_LIBS) if (ELF_LIBS)

View File

@ -1,4 +1,11 @@
version: "1.0.0" version: "1.1.1"
targets:
- esp32
- esp32s2
- esp32s3
- esp32c6
- esp32c61
- esp32p4
description: Espressif ELF(Executable and Linkable Format) Loader description: Espressif ELF(Executable and Linkable Format) Loader
url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader url: https://github.com/espressif/esp-iot-solution/tree/master/components/elf_loader
dependencies: dependencies:

View File

@ -12,9 +12,7 @@
extern "C" { extern "C" {
#endif #endif
// Tactility custom --> #define ESP_ELFSYM_EXPORT(_sym) { #_sym, (void*)&_sym }
#define ESP_ELFSYM_EXPORT(_sym) { #_sym, (const void*)&_sym }
// <-- Tactility custom
#define ESP_ELFSYM_END { NULL, NULL } #define ESP_ELFSYM_END { NULL, NULL }
/** @brief Function symbol description */ /** @brief Function symbol description */
@ -33,9 +31,23 @@ struct esp_elfsym {
*/ */
uintptr_t elf_find_sym(const char *sym_name); uintptr_t elf_find_sym(const char *sym_name);
// Tactility custom -->
void elf_set_custom_symbols(const struct esp_elfsym* symbols); /**
// <-- Tactility custom * @brief Resolves a symbol name (e.g. function name) to its address.
*
* @param sym_name - Symbol name
* @return Symbol address if success or 0 if failed.
*/
typedef uintptr_t (*symbol_resolver)(const char *sym_name);
/**
* @brief Override the internal symbol resolver.
* The default resolver is based on static lists that are determined by KConfig.
* This override allows for an arbitrary implementation.
*
* @param resolver the resolver function
*/
void elf_set_symbol_resolver(symbol_resolver resolver);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include "private/elf_symbol.h"
/* Extern declarations from ELF symbol table */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
#pragma GCC diagnostic pop
/* Available ELF symbols table: g_customer_elfsyms */
const struct esp_elfsym g_customer_elfsyms[] = {
ESP_ELFSYM_END
};

View File

@ -19,12 +19,27 @@
#include "private/elf_symbol.h" #include "private/elf_symbol.h"
#include "private/elf_platform.h" #include "private/elf_platform.h"
#include "esp_elf.h"
#define stype(_s, _t) ((_s)->type == (_t)) #define stype(_s, _t) ((_s)->type == (_t))
#define sflags(_s, _f) (((_s)->flags & (_f)) == (_f)) #define sflags(_s, _f) (((_s)->flags & (_f)) == (_f))
#define ADDR_OFFSET (0x400) #define ADDR_OFFSET (0x400)
uintptr_t elf_find_sym_default(const char *sym_name);
static const char *TAG = "ELF"; static const char *TAG = "ELF";
static symbol_resolver current_resolver = elf_find_sym_default;
/**
* @brief Find symbol address by name.
*
* @param sym_name - Symbol name
*
* @return Symbol address if success or 0 if failed.
*/
uintptr_t elf_find_sym(const char *sym_name) {
return current_resolver(sym_name);
}
#if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR #if CONFIG_ELF_LOADER_BUS_ADDRESS_MIRROR
@ -306,6 +321,18 @@ static int esp_elf_load_segment(esp_elf_t *elf, const uint8_t *pbuf)
} }
#endif #endif
/**
* @brief Override the internal symbol resolver.
* The default resolver is based on static lists that are determined by KConfig.
* This override allows for an arbitrary implementation.
*
* @param resolver the resolver function
*/
void elf_set_symbol_resolver(symbol_resolver resolver) {
current_resolver = resolver;
}
/** /**
* @brief Map symbol's address of ELF to physic space. * @brief Map symbol's address of ELF to physic space.
* *

View File

@ -27,13 +27,6 @@ extern int __gtdf2(double a, double b);
extern double __floatunsidf(unsigned int i); extern double __floatunsidf(unsigned int i);
extern double __divdf3(double a, double b); extern double __divdf3(double a, double b);
// Tactility custom -->
static const struct esp_elfsym* custom_symbols = NULL;
void elf_set_custom_symbols(const struct esp_elfsym* symbols) {
custom_symbols = symbols;
}
// <-- Tactility custom
/** @brief Libc public functions symbols look-up table */ /** @brief Libc public functions symbols look-up table */
static const struct esp_elfsym g_esp_libc_elfsyms[] = { static const struct esp_elfsym g_esp_libc_elfsyms[] = {
@ -163,7 +156,7 @@ static const struct esp_elfsym g_esp_espidf_elfsyms[] = {
* *
* @return Symbol address if success or 0 if failed. * @return Symbol address if success or 0 if failed.
*/ */
uintptr_t elf_find_sym(const char *sym_name) uintptr_t elf_find_sym_default(const char *sym_name)
{ {
const struct esp_elfsym *syms; const struct esp_elfsym *syms;
@ -208,16 +201,5 @@ uintptr_t elf_find_sym(const char *sym_name)
} }
#endif #endif
// Tactility custom -->
syms = custom_symbols;
while (syms->name) {
if (!strcmp(syms->name, sym_name)) {
return (uintptr_t)syms->sym;
}
syms++;
}
// <-- Tactility custom
return 0; return 0;
} }

View File

@ -0,0 +1,268 @@
#!/usr/bin/env python
#
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
#
# SPDX-License-Identifier: Apache-2.0
import logging
import os
import argparse
import sys
import re
import subprocess
def get_global_symbols(lines, type, undefined=False, symbol_types=None):
"""
Extract global symbols from the given lines of a symbol table.
:param lines: List of lines from the symbol table, each representing a symbol.
:param type: Type of the input file ('e' for ELF files, 'l' for static libraries).
:param undefined: If True, only extract undefined (UND) symbols; otherwise, extract all GLOBAL symbols.
:param symbol_types: A list of symbol types to filter by (e.g., ['FUNC', 'OBJECT']). If None, no filtering by type.
:return: List of symbol names if any match the criteria; otherwise, returns an empty list.
"""
symbols = []
if type == 'e':
# Pattern for ELF files
if not undefined:
pattern = re.compile(
r'^\s*\d+:\s+(\S+)\s+(\d+)\s+(FUNC|OBJECT)\s+GLOBAL\s+DEFAULT\s+(?:\d+|ABS|UND|COM|DEBUG)\s+(\S+)',
re.MULTILINE
)
else:
pattern = re.compile(
r'^\s*\d*:\s*\w*\s*\d*\s*NOTYPE\s*GLOBAL\s*DEFAULT\s*UND\s+(\S*)',
re.MULTILINE
)
for line in lines:
match = pattern.match(line)
if match:
if not undefined:
address, size, symbol_type, symbol_name = match.groups()
# Filter by symbol type if specified
if symbol_types and symbol_type not in symbol_types:
continue
symbols.append(symbol_name)
else:
symbol_name = match.group(1)
symbols.append(symbol_name)
elif type == 'l':
# Patterns for static libraries
func_pattern = re.compile(r'^\s*[0-9a-fA-F]+\s+[TD]\s+(\S+)$')
var_pattern = re.compile(r'^\s*[0-9a-fA-F]+\s+[BD]\s+(\S+)$')
for line in lines:
if not undefined:
func_match = func_pattern.match(line)
var_match = var_pattern.match(line)
if func_match:
symbols.append(func_match.group(1))
elif var_match:
symbols.append(var_match.group(1))
return symbols
def save_c_file(symbols, output, symbol_table, exclude_symbols=None):
"""
Write extern declarations and ESP_ELFSYM structure to a C file, excluding specified symbols.
:param symbols: List of symbol names.
:param output: Path to the output C file.
:param exclude_symbols: List of symbol names to exclude; defaults to ['elf_find_sym'].
"""
if exclude_symbols is None:
exclude_symbols = ['elf_find_sym'] # Set default excluded symbols
# Filter out excluded symbols
filtered_symbols = [name for name in symbols if name not in exclude_symbols]
# Build the content of the C file
buf = '/*\n'
buf += ' * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD\n'
buf += ' *\n'
buf += ' * SPDX-License-Identifier: Apache-2.0\n'
buf += ' */\n\n'
# Add standard library headers
libc_headers = ['stddef'] # Add more headers as needed
buf += '\n'.join([f'#include <{h}.h>' for h in libc_headers]) + '\n\n'
# Add custom header
buf += '#include "private/elf_symbol.h"\n\n'
# Generate extern declarations if there are symbols
if filtered_symbols:
buf += '/* Extern declarations from ELF symbol table */\n\n'
buf += '#pragma GCC diagnostic push\n'
buf += '#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"\n'
for symbol_name in filtered_symbols:
buf += f'extern int {symbol_name};\n'
buf += '#pragma GCC diagnostic pop\n\n'
# Define the symbol table structure with dynamic variable name
symbol_table_var = f'g_{symbol_table}_elfsyms'
buf += f'/* Available ELF symbols table: {symbol_table_var} */\n'
buf += f'\nconst struct esp_elfsym {symbol_table_var}[] = {{\n'
# Generate ESP_ELFSYM_EXPORT entries
if filtered_symbols:
for symbol_name in filtered_symbols:
buf += f' ESP_ELFSYM_EXPORT({symbol_name}),\n'
# End the symbol table
buf += ' ESP_ELFSYM_END\n'
buf += '};\n'
# Write to the file
with open(output, 'w+') as f:
f.write(buf)
def main():
"""
Main function to parse command-line arguments and process the input file's symbol table.
"""
parser = argparse.ArgumentParser(description='Extract all public functions from an application project', prog='symbols')
parser.add_argument(
'--output-file', '-of',
help='Custom output file path with filename (overrides --output)',
default=None
)
parser.add_argument(
'--input', '-i',
help='Input file name with full path',
required=True
)
parser.add_argument(
'--undefined', '-u',
action='store_true',
help='If set, only extract undefined (UND) symbols; otherwise, extract all GLOBAL symbols.',
default=False
)
parser.add_argument(
'--exclude', '-e',
nargs='+',
help='Symbols to exclude from the generated C file (e.g., memcpy __ltdf2). Default: elf_find_sym',
default=[] # User can extend this list
)
parser.add_argument(
'--type', '-t',
choices=['e', 'l'],
required=True,
help='Type of the input file: "elf" for ELF file, "lib" for static library (.a)'
)
parser.add_argument(
'--debug', '-d',
help='Debug level(option is \'debug\')',
default='no',
type=str)
args = parser.parse_args()
# Configure logging
if args.debug == 'debug':
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
else:
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# Get the absolute path of the current file
cur_dir = os.path.dirname(os.path.abspath(__file__))
if args.type == 'e':
extracted_part = 'customer'
elif args.type == 'l':
# Convert relative path to absolute path
input_abs_path = os.path.abspath(args.input)
# Get the base name of the input file (without extension)
input_basename = os.path.basename(input_abs_path)
# Use a regular expression to extract the middle part
match = re.search(r'^lib(.+)\.a$', input_basename)
if match:
extracted_part = match.group(1)
else:
logging.error('Invalid input file name format. Expected format: lib<name>.a')
sys.exit(1)
# Determine the output file path
if args.output_file:
# Use the custom file path provided by the user
elfsym_file_dir = os.path.abspath(args.output_file)
output_dir = os.path.dirname(elfsym_file_dir)
output_abs_path = os.path.abspath(args.output_file)
output_basename = os.path.basename(output_abs_path)
extracted_part = os.path.splitext(output_basename)[0]
else:
# Use the default behavior: generate the file in the parent directory's 'src' folder
parent_dir = os.path.dirname(cur_dir)
output_dir = os.path.join(parent_dir, 'src') # Default directory is 'src' under the parent directory
output_file_name = f'esp_all_symbol.c'
elfsym_file_dir = os.path.join(output_dir, output_file_name)
# Ensure the output directory exists
os.makedirs(output_dir, exist_ok=True)
# Set default excluded symbols and allow user to extend the list
exclude_symbols = ['elf_find_sym', 'g_customer_elfsyms'] + args.exclude
if args.type == 'e':
cmd = ['readelf', '-s', '-W', args.input]
elif args.type == 'l':
cmd = ['nm', '--defined-only', '-g', args.input]
# Execute the readelf or nm command for static libraries
try:
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True)
lines = result.stdout.splitlines()
except subprocess.CalledProcessError as e:
logging.error(f'Error executing command: {e.stderr}')
sys.exit(1)
except FileNotFoundError:
logging.error('nm command not found. Please ensure it is installed and available in your PATH.')
sys.exit(1)
# Extract global symbols from ELF file or static library
symbols = get_global_symbols(lines, type=args.type, undefined=args.undefined, symbol_types=['FUNC', 'OBJECT'])
if not symbols:
logging.warning('No global symbols found in the input file.')
sys.exit(0)
logging.debug('symbols: %s'%(cmd))
logging.debug('symbols: %s'%(symbols))
logging.debug('elfsym_file_dir: %s'%(elfsym_file_dir))
logging.debug('extracted_part: %s'%(extracted_part))
logging.debug('exclude_symbols: %s'%(exclude_symbols))
# Save the C file
try:
save_c_file(symbols, elfsym_file_dir, extracted_part, exclude_symbols=exclude_symbols)
logging.info(f"C file with extern declarations and symbol table has been saved to '{elfsym_file_dir}'.")
except Exception as e:
logging.error(f'Error writing C file: {e}')
sys.exit(1)
def _main():
"""
Wrapper for the main function to catch and handle runtime errors.
"""
try:
main()
except RuntimeError as e:
logging.error(f'A fatal error occurred: {e}')
sys.exit(2)
if __name__ == '__main__':
_main()

View File

@ -9,6 +9,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
idf_component_register( idf_component_register(
SRCS ${SOURCE_FILES} SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Include/" INCLUDE_DIRS "Include/"
PRIV_INCLUDE_DIRS "Private/"
REQUIRES lvgl REQUIRES lvgl
PRIV_REQUIRES Tactility TactilityCore elf_loader PRIV_REQUIRES Tactility TactilityCore elf_loader
) )
@ -21,16 +22,12 @@ else()
add_library(TactilityC OBJECT) add_library(TactilityC OBJECT)
target_sources(TactilityC
PRIVATE ${SOURCES}
)
target_include_directories(TactilityC
PUBLIC Include/
)
add_definitions(-D_Nullable=) add_definitions(-D_Nullable=)
add_definitions(-D_Nonnull=) add_definitions(-D_Nonnull=)
target_sources(TactilityC PRIVATE ${SOURCES})
include_directories(TactilityC PRIVATE Private/)
target_include_directories(TactilityC PUBLIC Include/)
target_link_libraries(TactilityC target_link_libraries(TactilityC
PRIVATE Tactility PRIVATE Tactility
PRIVATE TactilityCore PRIVATE TactilityCore

View File

@ -0,0 +1,13 @@
#pragma once
#include <private/elf_symbol.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const esp_elfsym gcc_soft_float_symbols[];
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,280 @@
#include <cstdlib>
#include <symbols/gcc_soft_float.h>
extern "C" {
// Reference: https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html
extern float __addsf3(float a, float b);
extern double __adddf3(double a, double b);
// extern long double __addtf3(long double a, long double b);
// extern long double __addxf3(long double a, long double b);
extern float __subsf3(float a, float b);
extern double __subdf3(double a, double b);
// extern long double __subtf3(long double a, long double b);
// extern long double __subxf3(long double a, long double b);
extern float __mulsf3(float a, float b);
extern double __muldf3(double a, double b);
// extern long double __multf3(long double a, long double b);
// extern long double __mulxf3(long double a, long double b);
extern float __divsf3(float a, float b);
extern double __divdf3(double a, double b);
// extern long double __divtf3(long double a, long double b);
// extern long double __divxf3(long double a, long double b);
extern float __negsf2(float a);
extern double __negdf2(double a);
// extern long double __negtf2(long double a);
// extern long double __negxf2(long double a);
extern double __extendsfdf2(float a);
// extern long double __extendsftf2(float a);
// extern long double __extendsfxf2(float a);
// extern long double __extenddftf2(double a);
// extern long double __extenddfxf2(double a);
// extern double __truncxfdf2(long double a);
// extern double __trunctfdf2(long double a);
// extern float __truncxfsf2(long double a);
// extern float __trunctfsf2(long double a);
extern float __truncdfsf2(double a);
extern int __fixsfsi(float a);
extern int __fixdfsi(double a);
// extern int __fixtfsi(long double a);
// extern int __fixxfsi(long double a);
extern long __fixsfdi(float a);
extern long __fixdfdi(double a);
// extern long __fixtfdi(long double a);
// extern long __fixxfdi(long double a);
// extern long long __fixsfti(float a);
// extern long long __fixdfti(double a);
// extern long long __fixtfti(long double a);
// extern long long __fixxfti(long double a);
// extern unsigned int __fixunssfsi(float a);
// extern unsigned int __fixunsdfsi(double a);
// extern unsigned int __fixunstfsi(long double a);
// extern unsigned int __fixunsxfsi(long double a);
extern unsigned long __fixunssfdi(float a);
extern unsigned long __fixunsdfdi(double a);
// extern unsigned long __fixunstfdi(long double a);
// extern unsigned long __fixunsxfdi(long double a);
// extern unsigned long long __fixunssfti(float a);
// extern unsigned long long __fixunsdfti(double a);
// extern unsigned long long __fixunstfti(long double a);
// extern unsigned long long __fixunsxfti(long double a);
// extern float __floatsisf(int i);
// extern double __floatsidf(int i);
// extern long double __floatsitf(int i);
// extern long double __floatsixf(int i);
extern float __floatdisf(long i);
extern double __floatdidf(long i);
// extern long double __floatditf(long i);
// extern long double __floatdixf(long i);
// extern float __floattisf(long long i);
// extern double __floattidf(long long i);
// extern long double __floattitf(long long i);
// extern long double __floattixf(long long i);
extern float __floatunsisf(unsigned int i);
extern double __floatunsidf(unsigned int i);
// extern long double __floatunsitf(unsigned int i);
// extern long double __floatunsixf(unsigned int i);
extern float __floatundisf(unsigned long i);
extern double __floatundidf(unsigned long i);
// extern long double __floatunditf(unsigned long i);
// extern long double __floatundixf(unsigned long i);
// extern float __floatuntisf(unsigned long long i);
// extern double __floatuntidf(unsigned long long i);
// extern long double __floatuntitf(unsigned long long i);
// extern long double __floatuntixf(unsigned long long i);
float __powisf2(float a, int b);
double __powidf2(double a, int b);
// long double __powitf2(long double a, int b);
// long double __powixf2(long double a, int b);
// int __cmpsf2(float a, float b);
int __cmpdf2(double a, double b);
// int __cmptf2(long double a, long double b);
int __unordsf2(float a, float b);
int __unorddf2(double a, double b);
// int __unordtf2(long double a, long double b);
int __eqsf2(float a, float b);
int __eqdf2(double a, double b);
// int __eqtf2(long double a, long double b);
int __nesf2(float a, float b);
int __nedf2(double a, double b);
// int __netf2(long double a, long double b);
int __gesf2(float a, float b);
int __gedf2(double a, double b);
// int __getf2(long double a, long double b);
int __ltsf2(float a, float b);
int __ltdf2(double a, double b);
// int __lttf2(long double a, long double b);
int __lesf2(float a, float b);
int __ledf2(double a, double b);
// int __letf2(long double a, long double b);
int __gtsf2(float a, float b);
int __gtdf2(double a, double b);
// int __gttf2(long double a, long double b);
const esp_elfsym gcc_soft_float_symbols[] = {
ESP_ELFSYM_EXPORT(__addsf3),
ESP_ELFSYM_EXPORT(__adddf3),
// ESP_ELFSYM_EXPORT(__addtf3),
// ESP_ELFSYM_EXPORT(__addxf3),
ESP_ELFSYM_EXPORT(__subsf3),
ESP_ELFSYM_EXPORT(__subdf3),
// ESP_ELFSYM_EXPORT(__subtf3),
// ESP_ELFSYM_EXPORT(__subxf3),
ESP_ELFSYM_EXPORT(__mulsf3),
ESP_ELFSYM_EXPORT(__muldf3),
// ESP_ELFSYM_EXPORT(__multf3),
// ESP_ELFSYM_EXPORT(__mulxf3),
ESP_ELFSYM_EXPORT(__divsf3),
ESP_ELFSYM_EXPORT(__divdf3),
// ESP_ELFSYM_EXPORT(__divtf3),
// ESP_ELFSYM_EXPORT(__divxf3),
ESP_ELFSYM_EXPORT(__negsf2),
ESP_ELFSYM_EXPORT(__negdf2),
// ESP_ELFSYM_EXPORT(__negtf2),
// ESP_ELFSYM_EXPORT(__negxf2),
ESP_ELFSYM_EXPORT(__extendsfdf2),
// ESP_ELFSYM_EXPORT(__extendsftf2),
// ESP_ELFSYM_EXPORT(__extendsfxf2),
// ESP_ELFSYM_EXPORT(__extenddftf2),
// ESP_ELFSYM_EXPORT(__extenddfxf2),
// ESP_ELFSYM_EXPORT(__truncxfdf2),
// ESP_ELFSYM_EXPORT(__trunctfdf2),
// ESP_ELFSYM_EXPORT(__truncxfsf2),
// ESP_ELFSYM_EXPORT(__trunctfsf2),
ESP_ELFSYM_EXPORT(__truncdfsf2),
ESP_ELFSYM_EXPORT(__fixsfsi),
ESP_ELFSYM_EXPORT(__fixdfsi),
// ESP_ELFSYM_EXPORT(__fixtfsi),
// ESP_ELFSYM_EXPORT(__fixxfsi),
ESP_ELFSYM_EXPORT(__fixsfdi),
ESP_ELFSYM_EXPORT(__fixdfdi),
// ESP_ELFSYM_EXPORT(__fixtfdi),
// ESP_ELFSYM_EXPORT(__fixxfdi),
// ESP_ELFSYM_EXPORT(__fixsfti),
// ESP_ELFSYM_EXPORT(__fixdfti),
// ESP_ELFSYM_EXPORT(__fixtfti),
// ESP_ELFSYM_EXPORT(__fixxfti),
// ESP_ELFSYM_EXPORT(__fixunssfsi),
// ESP_ELFSYM_EXPORT(__fixunsdfsi),
// ESP_ELFSYM_EXPORT(__fixunstfsi),
// ESP_ELFSYM_EXPORT(__fixunsxfsi),
ESP_ELFSYM_EXPORT(__fixunssfdi),
ESP_ELFSYM_EXPORT(__fixunsdfdi),
// ESP_ELFSYM_EXPORT(__fixunstfdi),
// ESP_ELFSYM_EXPORT(__fixunsxfdi),
// ESP_ELFSYM_EXPORT(__fixunssfti),
// ESP_ELFSYM_EXPORT(__fixunsdfti),
// ESP_ELFSYM_EXPORT(__fixunstfti),
// ESP_ELFSYM_EXPORT(__fixunsxfti),
// ESP_ELFSYM_EXPORT(__floatsisf),
// ESP_ELFSYM_EXPORT(__floatsidf),
// ESP_ELFSYM_EXPORT(__floatsitf),
// ESP_ELFSYM_EXPORT(__floatsixf),
ESP_ELFSYM_EXPORT(__floatdisf),
ESP_ELFSYM_EXPORT(__floatdidf),
// ESP_ELFSYM_EXPORT(__floatditf),
// ESP_ELFSYM_EXPORT(__floatdixf),
// ESP_ELFSYM_EXPORT(__floattisf),
// ESP_ELFSYM_EXPORT(__floattidf),
// ESP_ELFSYM_EXPORT(__floattitf),
// ESP_ELFSYM_EXPORT(__floattixf),
ESP_ELFSYM_EXPORT(__floatunsisf),
ESP_ELFSYM_EXPORT(__floatunsidf),
// ESP_ELFSYM_EXPORT(__floatunsitf),
// ESP_ELFSYM_EXPORT(__floatunsixf),
ESP_ELFSYM_EXPORT(__floatundisf),
ESP_ELFSYM_EXPORT(__floatundidf),
// ESP_ELFSYM_EXPORT(__floatunditf),
// ESP_ELFSYM_EXPORT(__floatundixf),
// ESP_ELFSYM_EXPORT(__floatuntisf),
// ESP_ELFSYM_EXPORT(__floatuntidf),
// ESP_ELFSYM_EXPORT(__floatuntitf),
// ESP_ELFSYM_EXPORT(__floatuntixf),
ESP_ELFSYM_EXPORT(__powisf2),
ESP_ELFSYM_EXPORT(__powidf2),
// ESP_ELFSYM_EXPORT(__powitf2),
// ESP_ELFSYM_EXPORT(__powixf2),
// ESP_ELFSYM_EXPORT(__cmpsf2),
// ESP_ELFSYM_EXPORT(__cmpdf2),
// ESP_ELFSYM_EXPORT(__cmptf2),
ESP_ELFSYM_EXPORT(__unordsf2),
ESP_ELFSYM_EXPORT(__unorddf2),
// ESP_ELFSYM_EXPORT(__unordtf2),
ESP_ELFSYM_EXPORT(__eqsf2),
ESP_ELFSYM_EXPORT(__eqdf2),
// ESP_ELFSYM_EXPORT(__eqtf2),
ESP_ELFSYM_EXPORT(__nesf2),
ESP_ELFSYM_EXPORT(__nedf2),
// ESP_ELFSYM_EXPORT(__netf2),
ESP_ELFSYM_EXPORT(__gesf2),
ESP_ELFSYM_EXPORT(__gedf2),
// ESP_ELFSYM_EXPORT(__getf2),
ESP_ELFSYM_EXPORT(__ltsf2),
ESP_ELFSYM_EXPORT(__ltdf2),
// ESP_ELFSYM_EXPORT(__lttf2),
ESP_ELFSYM_EXPORT(__lesf2),
ESP_ELFSYM_EXPORT(__ledf2),
// ESP_ELFSYM_EXPORT(__letf2),
ESP_ELFSYM_EXPORT(__gtsf2),
ESP_ELFSYM_EXPORT(__gtdf2),
// ESP_ELFSYM_EXPORT(__gttf2),
ESP_ELFSYM_END
};
}

View File

@ -25,38 +25,72 @@
#include "tt_timer.h" #include "tt_timer.h"
#include "tt_wifi.h" #include "tt_wifi.h"
#include <private/elf_symbol.h>
#include "symbols/gcc_soft_float.h"
#include <cstring> #include <cstring>
#include <ctype.h> #include <ctype.h>
#include <private/elf_symbol.h>
#include <esp_log.h> #include <esp_log.h>
#include <esp_http_client.h> #include <esp_http_client.h>
#include <cassert> #include <cassert>
#include <getopt.h>
#include <lvgl.h> #include <lvgl.h>
#include <pthread.h>
#include <setjmp.h>
extern "C" { extern "C" {
// Hidden functions work-around // GCC internal new and delete
extern void* _Znwj(uint32_t size); extern void* _Znwj(uint32_t size);
extern void _ZdlPvj(void* p, uint64_t size); extern void _ZdlPvj(void* p, uint64_t size);
extern double __adddf3(double a, double b);
extern double __subdf3(double a, double b);
extern double __muldf3 (double a, double b);
extern double __divdf3 (double a, double b);
extern int __nedf2 (double a, double b);
const esp_elfsym elf_symbols[] { const esp_elfsym elf_symbols[] {
// Hidden functions work-around // GCC internal
ESP_ELFSYM_EXPORT(_ZdlPvj), // new? ESP_ELFSYM_EXPORT(_Znwj), // new
ESP_ELFSYM_EXPORT(_Znwj), // delete? ESP_ELFSYM_EXPORT(_ZdlPvj), // delete
ESP_ELFSYM_EXPORT(__adddf3), // Routines for floating point emulation: // stdlib.h
ESP_ELFSYM_EXPORT(__subdf3), // See https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html ESP_ELFSYM_EXPORT(malloc),
ESP_ELFSYM_EXPORT(__muldf3), ESP_ELFSYM_EXPORT(calloc),
ESP_ELFSYM_EXPORT(__nedf2), ESP_ELFSYM_EXPORT(realloc),
ESP_ELFSYM_EXPORT(__divdf3), ESP_ELFSYM_EXPORT(free),
// <cassert> // unistd.h
ESP_ELFSYM_EXPORT(usleep),
ESP_ELFSYM_EXPORT(sleep),
ESP_ELFSYM_EXPORT(exit),
ESP_ELFSYM_EXPORT(close),
// time.h
ESP_ELFSYM_EXPORT(clock_gettime),
ESP_ELFSYM_EXPORT(strftime),
// pthread
ESP_ELFSYM_EXPORT(pthread_create),
ESP_ELFSYM_EXPORT(pthread_attr_init),
ESP_ELFSYM_EXPORT(pthread_attr_setstacksize),
ESP_ELFSYM_EXPORT(pthread_detach),
ESP_ELFSYM_EXPORT(pthread_join),
ESP_ELFSYM_EXPORT(pthread_exit),
// sys/errno.h
ESP_ELFSYM_EXPORT(__errno),
// freertos_tasks_c_additions.h
ESP_ELFSYM_EXPORT(__getreent),
#ifdef __HAVE_LOCALE_INFO__
// ctype.h
ESP_ELFSYM_EXPORT(__locale_ctype_ptr),
#else
ESP_ELFSYM_EXPORT(_ctype_),
#endif
// getopt.h
ESP_ELFSYM_EXPORT(getopt_long),
ESP_ELFSYM_EXPORT(optind),
ESP_ELFSYM_EXPORT(opterr),
ESP_ELFSYM_EXPORT(optarg),
ESP_ELFSYM_EXPORT(optopt),
// setjmp.h
ESP_ELFSYM_EXPORT(longjmp),
ESP_ELFSYM_EXPORT(setjmp),
// cassert
ESP_ELFSYM_EXPORT(__assert_func), ESP_ELFSYM_EXPORT(__assert_func),
// <cstdio> // cstdio
ESP_ELFSYM_EXPORT(fclose), ESP_ELFSYM_EXPORT(fclose),
ESP_ELFSYM_EXPORT(feof), ESP_ELFSYM_EXPORT(feof),
ESP_ELFSYM_EXPORT(ferror), ESP_ELFSYM_EXPORT(ferror),
@ -90,6 +124,12 @@ const esp_elfsym elf_symbols[] {
ESP_ELFSYM_EXPORT(strcat), ESP_ELFSYM_EXPORT(strcat),
ESP_ELFSYM_EXPORT(strchr), ESP_ELFSYM_EXPORT(strchr),
ESP_ELFSYM_EXPORT(strstr), ESP_ELFSYM_EXPORT(strstr),
ESP_ELFSYM_EXPORT(strerror),
ESP_ELFSYM_EXPORT(strtod),
ESP_ELFSYM_EXPORT(strrchr),
ESP_ELFSYM_EXPORT(strtol),
ESP_ELFSYM_EXPORT(strcspn),
ESP_ELFSYM_EXPORT(strncat),
ESP_ELFSYM_EXPORT(memset), ESP_ELFSYM_EXPORT(memset),
ESP_ELFSYM_EXPORT(memcpy), ESP_ELFSYM_EXPORT(memcpy),
ESP_ELFSYM_EXPORT(memcmp), ESP_ELFSYM_EXPORT(memcmp),
@ -490,8 +530,27 @@ const esp_elfsym elf_symbols[] {
ESP_ELFSYM_END ESP_ELFSYM_END
}; };
uintptr_t resolve_symbol(const esp_elfsym* source, const char* symbolName) {
const esp_elfsym* symbol_iterator = source;
while (symbol_iterator->name) {
if (!strcmp(symbol_iterator->name, symbolName)) {
return reinterpret_cast<uintptr_t>(symbol_iterator->sym);
}
symbol_iterator++;
}
return 0;
}
uintptr_t tt_symbol_resolver(const char* symbolName) {
uintptr_t address = resolve_symbol(elf_symbols, symbolName);
if (address != 0) {
return address;
}
return resolve_symbol(gcc_soft_float_symbols, symbolName);
}
void tt_init_tactility_c() { void tt_init_tactility_c() {
elf_set_custom_symbols(elf_symbols); elf_set_symbol_resolver(tt_symbol_resolver);
} }
} }