mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-10-17 02:45:05 +00:00
Moved stdio wrapping to app-module
app-module is the owning module for this feature
This commit is contained in:
parent
4ce62e7a87
commit
9be33a3ebe
@ -14,11 +14,26 @@ tactility_add_module(app-module
|
|||||||
|
|
||||||
# Tells source/io.cpp its real-syscall fallback must go through __real_read/write/close() rather
|
# Tells source/io.cpp its real-syscall fallback must go through __real_read/write/close() rather
|
||||||
# than calling ::read/::write/::close() directly, on every platform where those are wrapped: via
|
# than calling ::read/::write/::close() directly, on every platform where those are wrapped: via
|
||||||
# -Wl,--wrap= on ESP-IDF and non-Apple POSIX (see Tactility/CMakeLists.txt and the top-level
|
# -Wl,--wrap= on ESP-IDF (see the top-level CMakeLists.txt) and non-Apple POSIX (below), or via
|
||||||
# CMakeLists.txt), or via AppStdioWrap.cpp's dyld interpose on Apple (whose linker lacks --wrap).
|
# source/stdio_wrap.cpp's dyld interpose on Apple (whose linker lacks --wrap).
|
||||||
tactility_get_module_name(app-module MODULE_NAME)
|
tactility_get_module_name(app-module MODULE_NAME)
|
||||||
target_compile_definitions(${MODULE_NAME} PRIVATE TT_APP_IO_WRAPS_STDIO)
|
target_compile_definitions(${MODULE_NAME} PRIVATE TT_APP_IO_WRAPS_STDIO)
|
||||||
|
|
||||||
|
# Routes every read()/write()/close() and printf-family call to source/stdio_wrap.cpp's __wrap_*
|
||||||
|
# functions; see that file for what they do and why. ESP-IDF wraps the same symbols itself (see
|
||||||
|
# the top-level CMakeLists.txt); Apple gets the same routing via dyld interpose instead, self-
|
||||||
|
# registered in that file. PUBLIC so every consumer of this module (Tactility, and any test target
|
||||||
|
# that links app-module directly) gets the flags too.
|
||||||
|
if (NOT ESP_PLATFORM AND NOT APPLE)
|
||||||
|
tactility_get_module_name(app-module MODULE_NAME)
|
||||||
|
target_link_options(${MODULE_NAME} PUBLIC
|
||||||
|
"-Wl,--wrap=read" "-Wl,--wrap=write" "-Wl,--wrap=close"
|
||||||
|
"-Wl,--wrap=printf" "-Wl,--wrap=fprintf" "-Wl,--wrap=vprintf" "-Wl,--wrap=vfprintf"
|
||||||
|
"-Wl,--wrap=puts" "-Wl,--wrap=fputs" "-Wl,--wrap=putchar" "-Wl,--wrap=fputc"
|
||||||
|
"-Wl,--wrap=getchar" "-Wl,--wrap=fgetc" "-Wl,--wrap=fgets"
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
# install.cpp resolves an installed binary's fixed bin/<platform>/<binary>.so path itself, so it
|
# install.cpp resolves an installed binary's fixed bin/<platform>/<binary>.so path itself, so it
|
||||||
# needs the same platform-arch string app-posix-module's own CMakeLists.txt defines for its
|
# needs the same platform-arch string app-posix-module's own CMakeLists.txt defines for its
|
||||||
# loader (the ESP32 equivalent, CONFIG_IDF_TARGET, comes for free from sdkconfig.h there).
|
# loader (the ESP32 equivalent, CONFIG_IDF_TARGET, comes for free from sdkconfig.h there).
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
// Paired with -Wl,--wrap=read/write/close on POSIX (Tactility/CMakeLists.txt) and ESP32
|
// Paired with -Wl,--wrap=read/write/close on POSIX (this module's own CMakeLists.txt) and ESP32
|
||||||
// (top-level CMakeLists.txt); self-registered via dyld interpose below on Apple, whose linker
|
// (top-level CMakeLists.txt); self-registered via dyld interpose below on Apple, whose linker
|
||||||
// doesn't support --wrap.
|
// doesn't support --wrap.
|
||||||
#include <app/io.h>
|
#include <app/io.h>
|
||||||
@ -69,14 +69,14 @@ TT_DYLD_INTERPOSE(__wrap_close, close)
|
|||||||
// region glibc stdio wraps
|
// region glibc stdio wraps
|
||||||
//
|
//
|
||||||
// libc's printf/fprintf/etc are compiled into the C library and call an internal, non-exported
|
// libc's printf/fprintf/etc are compiled into the C library and call an internal, non-exported
|
||||||
// write() alias - --wrap=write/the read/write/close interpose above can't reach that call, only
|
// write() alias, which --wrap=write/the read/write/close interpose above can't reach: only calls
|
||||||
// calls WE make to the public symbol. These wraps instead redirect calls WE make to printf/
|
// WE make to the public symbol. These wraps instead redirect calls WE make to printf/fprintf/etc,
|
||||||
// fprintf/etc, the same trick as read/write/close above. Newlib (ESP-IDF) doesn't have this gap -
|
// the same trick as read/write/close above. Newlib (ESP-IDF) doesn't have this gap: its stdio does
|
||||||
// its stdio does call the wrappable syscall stubs - so this block is POSIX-only.
|
// call the wrappable syscall stubs, so this block is POSIX-only.
|
||||||
//
|
//
|
||||||
// Scoped to the printf/getc families only: fread/fwrite take an arbitrary FILE* and are already
|
// Scoped to the printf/getc families only: fread/fwrite take an arbitrary FILE* and are already
|
||||||
// used sitewide for real file I/O (e.g. File.cpp's readBinaryInternal), so wrapping them would
|
// used sitewide for real file I/O (e.g. File.cpp's readBinaryInternal), so wrapping them would
|
||||||
// route every such call through this file's stdin/stdout check - a correctness risk for unrelated
|
// route every such call through this file's stdin/stdout check, a correctness risk for unrelated
|
||||||
// code that isn't worth taking here. putc/getc are excluded too since libc defines them as
|
// code that isn't worth taking here. putc/getc are excluded too since libc defines them as
|
||||||
// macros, not real calls, so wrapping those symbols wouldn't reliably intercept them.
|
// macros, not real calls, so wrapping those symbols wouldn't reliably intercept them.
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ char* __real_fgets(char* buffer, int size, FILE* stream);
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
|
|
||||||
// --wrap synthesizes these automatically elsewhere; on Apple they're defined here via
|
// --wrap synthesizes these automatically elsewhere; on Apple they're defined here via
|
||||||
// dlsym(RTLD_NEXT, ...) instead - see the read/write/close __real_* block above for why.
|
// dlsym(RTLD_NEXT, ...) instead. See the read/write/close __real_* block above for why.
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -6,28 +6,12 @@ enable_language(C CXX ASM)
|
|||||||
file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp)
|
file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/source/*.cpp)
|
||||||
add_executable(AppModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
add_executable(AppModuleTests EXCLUDE_FROM_ALL ${TEST_SOURCES})
|
||||||
|
|
||||||
# Provides __wrap_read/write/close: paired with the -Wl,--wrap= below on non-Apple platforms (see
|
|
||||||
# Tactility/CMakeLists.txt), or self-registered via dyld interpose on Apple (see the file itself).
|
|
||||||
target_sources(AppModuleTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../../../Tactility/Source/AppStdioWrap.cpp)
|
|
||||||
|
|
||||||
target_include_directories(AppModuleTests PRIVATE ${DOCTESTINC} ${CMAKE_CURRENT_LIST_DIR}/../private)
|
target_include_directories(AppModuleTests PRIVATE ${DOCTESTINC} ${CMAKE_CURRENT_LIST_DIR}/../private)
|
||||||
|
|
||||||
add_test(NAME AppModuleTests COMMAND AppModuleTests)
|
add_test(NAME AppModuleTests COMMAND AppModuleTests)
|
||||||
|
|
||||||
# Matches app-module's own TT_APP_IO_WRAPS_STDIO (see Modules/app-module/CMakeLists.txt): io.cpp
|
# No --wrap flags or stdio_wrap.cpp source needed here: linking app-module below already brings
|
||||||
# calls __real_read/write/close() on every POSIX platform, so any final link of it needs these
|
# both along (see its own CMakeLists.txt).
|
||||||
# wraps too, or those symbols go unresolved. The printf-family/getc-family flags are needed for
|
|
||||||
# the same reason: AppStdioWrap.cpp compiles those __wrap_* functions unconditionally on this
|
|
||||||
# platform, and they reference __real_vfprintf/fputs/fputc/fgetc/fgets. --wrap provides all of
|
|
||||||
# these __real_* symbols on non-Apple; AppStdioWrap.cpp provides its own on Apple (see that file).
|
|
||||||
if (NOT APPLE)
|
|
||||||
target_link_options(AppModuleTests PRIVATE
|
|
||||||
"-Wl,--wrap=read" "-Wl,--wrap=write" "-Wl,--wrap=close"
|
|
||||||
"-Wl,--wrap=printf" "-Wl,--wrap=fprintf" "-Wl,--wrap=vprintf" "-Wl,--wrap=vfprintf"
|
|
||||||
"-Wl,--wrap=puts" "-Wl,--wrap=fputs" "-Wl,--wrap=putchar" "-Wl,--wrap=fputc"
|
|
||||||
"-Wl,--wrap=getchar" "-Wl,--wrap=fgetc" "-Wl,--wrap=fgets"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(AppModuleTests PUBLIC
|
target_link_libraries(AppModuleTests PUBLIC
|
||||||
TactilityKernel
|
TactilityKernel
|
||||||
|
|||||||
@ -6,3 +6,12 @@ add_library(platform-posix OBJECT)
|
|||||||
target_sources(platform-posix PRIVATE ${SOURCES})
|
target_sources(platform-posix PRIVATE ${SOURCES})
|
||||||
#target_include_directories(platform-posix PUBLIC include/)
|
#target_include_directories(platform-posix PUBLIC include/)
|
||||||
target_link_libraries(platform-posix PUBLIC TactilityKernel)
|
target_link_libraries(platform-posix PUBLIC TactilityKernel)
|
||||||
|
|
||||||
|
# Routes every pthread_attr_setstack() call to __wrap_pthread_attr_setstack() in source/pthread_stack_wrap.c,
|
||||||
|
# which no-ops it. see that file for why.
|
||||||
|
# --wrap is a GNU ld option; Apple's linker doesn't support it, so that file instead self-registers a dyld interpose
|
||||||
|
# for this symbol on Apple, needing no link flag. PUBLIC so every consumer of this OBJECT library
|
||||||
|
# (Tactility, and every test target that links platform-posix directly) gets it applied too.
|
||||||
|
if (NOT APPLE)
|
||||||
|
target_link_options(platform-posix PUBLIC "-Wl,--wrap=pthread_attr_setstack")
|
||||||
|
endif ()
|
||||||
|
|||||||
@ -9,8 +9,8 @@
|
|||||||
* No-op'ing the call instead leaves every task's pthread_attr_t at its pthread_attr_init() default,
|
* No-op'ing the call instead leaves every task's pthread_attr_t at its pthread_attr_init() default,
|
||||||
* so pthread_create() gives it a real, properly sized stack.
|
* so pthread_create() gives it a real, properly sized stack.
|
||||||
*
|
*
|
||||||
* Linked via -Wl,--wrap=pthread_attr_setstack (Tactility/CMakeLists.txt) on non-Apple platforms;
|
* Linked via -Wl,--wrap=pthread_attr_setstack (this module's own CMakeLists.txt) on non-Apple
|
||||||
* reused as a dyld interpose target below on Apple platforms, whose linker lacks --wrap.
|
* platforms; reused as a dyld interpose target below on Apple platforms, whose linker lacks --wrap.
|
||||||
*/
|
*/
|
||||||
int __wrap_pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize) {
|
int __wrap_pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize) {
|
||||||
(void)attr;
|
(void)attr;
|
||||||
|
|||||||
@ -185,34 +185,9 @@ else ()
|
|||||||
# Exports Tactility's own symbols (-rdynamic) so a dlopen()ed app-posix-module app can resolve
|
# Exports Tactility's own symbols (-rdynamic) so a dlopen()ed app-posix-module app can resolve
|
||||||
# calls back into it - the OS-native equivalent of app-esp32-module's custom symbol resolver.
|
# calls back into it - the OS-native equivalent of app-esp32-module's custom symbol resolver.
|
||||||
set_target_properties(Tactility PROPERTIES ENABLE_EXPORTS ON)
|
set_target_properties(Tactility PROPERTIES ENABLE_EXPORTS ON)
|
||||||
# Routes every pthread_attr_setstack() call (FreeRTOS's POSIX port hands each task a stack
|
# pthread_attr_setstack and read/write/close/printf-family aren't wrapped here: linking
|
||||||
# carved out of its own heap through this) to __wrap_pthread_attr_setstack() in
|
# platform-posix and app-module already brings those wraps along (see their own
|
||||||
# Platforms/platform-posix/source/pthread_stack_wrap.c, which no-ops it - see that file for why.
|
# CMakeLists.txt files).
|
||||||
# --wrap is a GNU ld option; Apple's linker doesn't support it, so that file instead
|
|
||||||
# self-registers a dyld interpose for this symbol on Apple, needing no link flag here.
|
|
||||||
if (NOT APPLE)
|
|
||||||
target_link_options(Tactility PRIVATE "-Wl,--wrap=pthread_attr_setstack")
|
|
||||||
# Routes every read()/write()/close() call to Tactility/Source/AppStdioWrap.cpp's
|
|
||||||
# __wrap_read/write/close(), which forward into app_io_read/write/close() - the fd-table
|
|
||||||
# dispatch that lets an app's own stdio (e.g. a fileselection dialog's printf'd result
|
|
||||||
# path) reach an AppStream a parent bound via app_manager_start_with_streams(). Mirrors
|
|
||||||
# what ESP-IDF's build already does for the ESP32 target (see top-level CMakeLists.txt).
|
|
||||||
# On Apple, AppStdioWrap.cpp self-registers the same routing via dyld interpose instead.
|
|
||||||
target_link_options(Tactility PRIVATE "-Wl,--wrap=read" "-Wl,--wrap=write" "-Wl,--wrap=close")
|
|
||||||
# glibc's printf/fprintf/etc don't call the public write() symbol internally (they're
|
|
||||||
# already compiled into libc.so, out of --wrap's reach), so the read/write/close wrap
|
|
||||||
# above can't see them. Newlib (ESP-IDF) doesn't have this gap - its stdio does call the
|
|
||||||
# wrappable syscall stubs - so this block is POSIX-only. Wrapping these symbols instead
|
|
||||||
# redirects OUR OWN calls to them (the only ones --wrap can rewrite) through
|
|
||||||
# AppStdioWrap.cpp's __wrap_* functions, which check the target stream (stdout/stdin) and
|
|
||||||
# fall back to the real libc function for any other FILE*. Apple gets the same routing via
|
|
||||||
# dyld interpose, self-registered in that file - see its own #ifdef __APPLE__ block.
|
|
||||||
target_link_options(Tactility PRIVATE
|
|
||||||
"-Wl,--wrap=printf" "-Wl,--wrap=fprintf" "-Wl,--wrap=vprintf" "-Wl,--wrap=vfprintf"
|
|
||||||
"-Wl,--wrap=puts" "-Wl,--wrap=fputs" "-Wl,--wrap=putchar" "-Wl,--wrap=fputc"
|
|
||||||
"-Wl,--wrap=getchar" "-Wl,--wrap=fgetc" "-Wl,--wrap=fgets"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@ -85,7 +85,7 @@ int32_t appMain(int argc, char* argv[]) {
|
|||||||
|
|
||||||
if (ctx.resultCode == 0) {
|
if (ctx.resultCode == 0) {
|
||||||
// The parent captures this via an AppStream bound to our stdout (see startWithMode()) -
|
// The parent captures this via an AppStream bound to our stdout (see startWithMode()) -
|
||||||
// see AppStdioWrap.cpp for how printf() itself gets routed there on POSIX.
|
// see Modules/app-module/source/stdio_wrap.cpp for how printf() itself gets routed there on POSIX.
|
||||||
LOG_I(TAG, "Result: %s", ctx.resultPath.c_str());
|
LOG_I(TAG, "Result: %s", ctx.resultPath.c_str());
|
||||||
printf("%s", ctx.resultPath.c_str());
|
printf("%s", ctx.resultPath.c_str());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -138,7 +138,7 @@ int32_t appMain(int argc, char* argv[]) {
|
|||||||
|
|
||||||
if (ctx.resultCode == 0) {
|
if (ctx.resultCode == 0) {
|
||||||
// The caller captures this via an AppStream bound to our stdout (see start()); see
|
// The caller captures this via an AppStream bound to our stdout (see start()); see
|
||||||
// AppStdioWrap.cpp for how printf() itself gets routed there on POSIX.
|
// Modules/app-module/source/stdio_wrap.cpp for how printf() itself gets routed there on POSIX.
|
||||||
printf("%s", ctx.resultText.c_str());
|
printf("%s", ctx.resultText.c_str());
|
||||||
}
|
}
|
||||||
return ctx.resultCode;
|
return ctx.resultCode;
|
||||||
|
|||||||
@ -19,19 +19,9 @@ target_include_directories(TactilityTests PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../P
|
|||||||
|
|
||||||
add_test(NAME TactilityTests COMMAND TactilityTests)
|
add_test(NAME TactilityTests COMMAND TactilityTests)
|
||||||
|
|
||||||
# Matches Tactility/CMakeLists.txt's own set of --wrap flags: this binary also compiles
|
# No --wrap flags declared here: linking platform-posix and app-module below already brings all
|
||||||
# AppStdioWrap.cpp and links app-module (whose io.cpp calls __real_read/write/close() on every
|
# of pthread_attr_setstack/read/write/close/the printf family along (see their own CMakeLists.txt
|
||||||
# POSIX platform - see TT_APP_IO_WRAPS_STDIO in Modules/app-module/CMakeLists.txt), so it needs
|
# files).
|
||||||
# the same wraps applied on non-Apple, or those go unresolved; AppStdioWrap.cpp provides its own
|
|
||||||
# on Apple via dyld interpose (see that file).
|
|
||||||
if (NOT APPLE)
|
|
||||||
target_link_options(TactilityTests PRIVATE
|
|
||||||
"-Wl,--wrap=pthread_attr_setstack" "-Wl,--wrap=read" "-Wl,--wrap=write" "-Wl,--wrap=close"
|
|
||||||
"-Wl,--wrap=printf" "-Wl,--wrap=fprintf" "-Wl,--wrap=vprintf" "-Wl,--wrap=vfprintf"
|
|
||||||
"-Wl,--wrap=puts" "-Wl,--wrap=fputs" "-Wl,--wrap=putchar" "-Wl,--wrap=fputc"
|
|
||||||
"-Wl,--wrap=getchar" "-Wl,--wrap=fgetc" "-Wl,--wrap=fgets"
|
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(TactilityTests PRIVATE
|
target_link_libraries(TactilityTests PRIVATE
|
||||||
TactilityKernel
|
TactilityKernel
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user