// SPDX-License-Identifier: Apache-2.0 // Symbols resolved for ELF apps ahead of every other module's (see app_esp32_symbol_resolver()). // Firmware code calling the same functions never gets here. // Pending signals are delivered here, at the entry and again when a call was interrupted by one, // since the app holds no lock of the system itself there. // Allocations are counted per app instance (see app/memory.h). #include #include #include #include #include #include #include #include #include #include #include #include namespace { ssize_t app_read(int fd, void* buffer, size_t size) { app_signal_deliver_pending(); const ssize_t result = read(fd, buffer, size); if (result < 0 && errno == EINTR) { app_signal_deliver_pending(); } return result; } ssize_t app_write(int fd, const void* buffer, size_t size) { app_signal_deliver_pending(); const ssize_t result = write(fd, buffer, size); if (result < 0 && errno == EINTR) { app_signal_deliver_pending(); } return result; } int app_poll(struct pollfd* fds, nfds_t nfds, int timeout) { app_signal_deliver_pending(); const int result = poll(fds, nfds, timeout); if (result < 0 && errno == EINTR) { app_signal_deliver_pending(); } return result; } int app_usleep(useconds_t usec) { app_signal_deliver_pending(); int result; if (!app_libc_try_usleep(usec, &result)) { return usleep(usec); } app_signal_deliver_pending(); return result; } unsigned int app_sleep(unsigned int seconds) { app_signal_deliver_pending(); unsigned int result; if (!app_libc_try_sleep(seconds, &result)) { return sleep(seconds); } app_signal_deliver_pending(); return result; } int app_kill(pid_t pid, int sig) { const int result = kill(pid, sig); // A signal sent to the app itself is delivered before kill() returns app_signal_deliver_pending(); return result; } pid_t app_getpid() { int result; return app_libc_try_getpid(&result) ? result : 0; } pid_t app_getppid() { int result; return app_libc_try_getppid(&result) ? result : 0; } void* record_alloc(void* ptr) { if (ptr != nullptr) { app_memory_record_alloc(heap_caps_get_allocated_size(ptr)); } return ptr; } void record_free(void* ptr) { if (ptr != nullptr) { app_memory_record_free(heap_caps_get_allocated_size(ptr)); } } void* app_malloc(size_t size) { return record_alloc(malloc(size)); } void* app_calloc(size_t count, size_t size) { return record_alloc(calloc(count, size)); } void* app_realloc(void* ptr, size_t size) { const size_t old_size = (ptr != nullptr) ? heap_caps_get_allocated_size(ptr) : 0; void* result = realloc(ptr, size); // A failed realloc() leaves the old block allocated if (result != nullptr || size == 0) { if (ptr != nullptr) { app_memory_record_free(old_size); } record_alloc(result); } return result; } void app_free(void* ptr) { record_free(ptr); free(ptr); } char* app_strdup(const char* s) { return static_cast(record_alloc(strdup(s))); } char* app_strndup(const char* s, size_t n) { return static_cast(record_alloc(strndup(s, n))); } void* app_operator_new(size_t size) { return record_alloc(::operator new(size)); } void* app_operator_new_array(size_t size) { return record_alloc(::operator new[](size)); } void app_operator_delete(void* ptr) { record_free(ptr); ::operator delete(ptr); } void app_operator_delete_array(void* ptr) { record_free(ptr); ::operator delete[](ptr); } void app_operator_delete_sized(void* ptr, size_t) { app_operator_delete(ptr); } void app_operator_delete_array_sized(void* ptr, size_t) { app_operator_delete_array(ptr); } } // namespace extern "C" { extern const ModuleSymbol app_esp32_symbols[] = { { "read", reinterpret_cast(app_read) }, { "write", reinterpret_cast(app_write) }, { "poll", reinterpret_cast(app_poll) }, { "usleep", reinterpret_cast(app_usleep) }, { "sleep", reinterpret_cast(app_sleep) }, { "kill", reinterpret_cast(app_kill) }, { "getpid", reinterpret_cast(app_getpid) }, { "getppid", reinterpret_cast(app_getppid) }, { "malloc", reinterpret_cast(app_malloc) }, { "calloc", reinterpret_cast(app_calloc) }, { "realloc", reinterpret_cast(app_realloc) }, { "free", reinterpret_cast(app_free) }, { "strdup", reinterpret_cast(app_strdup) }, { "strndup", reinterpret_cast(app_strndup) }, { "_Znwj", reinterpret_cast(app_operator_new) }, // operator new(unsigned int) { "_Znaj", reinterpret_cast(app_operator_new_array) }, // operator new[](unsigned int) { "_ZdlPv", reinterpret_cast(app_operator_delete) }, // operator delete(void*) { "_ZdaPv", reinterpret_cast(app_operator_delete_array) }, // operator delete[](void*) { "_ZdlPvj", reinterpret_cast(app_operator_delete_sized) }, // operator delete(void*, unsigned int) { "_ZdaPvj", reinterpret_cast(app_operator_delete_array_sized) }, // operator delete[](void*, unsigned int) MODULE_SYMBOL_TERMINATOR }; }