diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index bc5e42547b..0968a31a82 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -1,8 +1,16 @@ set(srcs "app_trace.c" "app_trace_util.c" - "host_file_io.c" - "gcov/gcov_rtio.c") + "host_file_io.c") + +if(CONFIG_APPTRACE_GCOV_ENABLE) + if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + list(APPEND srcs + "gcov/gcov_rtio.c") + else() + fail_at_build_time(app_trace "Only GNU compiler can link with Gcov library") + endif() +endif() set(include_dirs "include") @@ -54,13 +62,49 @@ idf_component_register(SRCS "${srcs}" REQUIRES esp_timer LDFRAGMENTS linker.lf) -# disable --coverage for this component, as it is used as transport -# for gcov -target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage") - # Force app_trace to also appear later than gcov in link line idf_component_get_property(app_trace app_trace COMPONENT_LIB) -target_link_libraries(${COMPONENT_LIB} INTERFACE $ gcov $ c) + +if(CONFIG_APPTRACE_GCOV_ENABLE) + # The original Gcov library from toolchain will be objcopy with symbols redefinitions (see file gcov/io_sym.map). + # This needs because ESP has no file-system onboard, and redefined functions solves this problem and transmits + # output file to host PC. + + # Set a name for Gcov library + set(GCOV_LIB libgcov_rtio) + + # Set include direcrory of Gcov internal headers + execute_process(COMMAND ${CMAKE_C_COMPILER} -print-file-name=plugin + OUTPUT_VARIABLE gcc_plugin_dir + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + set_source_files_properties(gcov/gcov_rtio.c + PROPERTIES COMPILE_FLAGS "-I${gcc_plugin_dir}/include") + + # Copy libgcov.a with symbols redefinition + find_library(GCOV_LIBRARY_PATH gcov ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES}) + add_custom_command(OUTPUT ${GCOV_LIB}.a + COMMAND ${_CMAKE_TOOLCHAIN_PREFIX}objcopy + --redefine-syms ${CMAKE_CURRENT_LIST_DIR}/gcov/io_sym.map + ${GCOV_LIBRARY_PATH} ${GCOV_LIB}.a + MAIN_DEPENDENCY ${GCOV_LIBRARY_PATH} + VERBATIM) + add_custom_target(${GCOV_LIB}_target DEPENDS ${GCOV_LIB}.a) + add_library(${GCOV_LIB} STATIC IMPORTED) + set_target_properties(${GCOV_LIB} + PROPERTIES + IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${GCOV_LIB}.a) + add_dependencies(${GCOV_LIB} ${GCOV_LIB}_target) + add_dependencies(${COMPONENT_LIB} ${GCOV_LIB}) + + # disable --coverage for this component, as it is used as transport for gcov + target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage") + target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=__gcov_init") + + target_link_libraries(${COMPONENT_LIB} INTERFACE ${GCOV_LIB} $ c) +else() + target_link_libraries(${COMPONENT_LIB} INTERFACE $ c) +endif() # This function adds a dependency on the given component if the component is included into the build. function(maybe_add_component component_name) diff --git a/components/app_trace/gcov/gcov_rtio.c b/components/app_trace/gcov/gcov_rtio.c index 614c3c8ebc..80b67563fc 100644 --- a/components/app_trace/gcov/gcov_rtio.c +++ b/components/app_trace/gcov/gcov_rtio.c @@ -103,7 +103,7 @@ static int esp_dbg_stub_gcov_entry(void) return ESP_OK; } -int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused))) +void gcov_rtio_init(void) { uint32_t capabilities = 0; ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); @@ -112,7 +112,6 @@ int gcov_rtio_atexit(void (*function)(void) __attribute__ ((unused))) esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_CAPABILITIES, capabilities | ESP_DBG_STUB_CAP_GCOV_TASK); } esp_register_freertos_tick_hook(gcov_create_task_tick_hook); - return ESP_OK; } void esp_gcov_dump(void) @@ -172,4 +171,19 @@ long gcov_rtio_ftell(void *stream) ESP_EARLY_LOGV(TAG, "%s(%p) = %ld", __FUNCTION__, stream, ret); return ret; } + +void gcov_rtio_setbuf(void *arg1 __attribute__ ((unused)), void *arg2 __attribute__ ((unused))) +{ + return; +} + +/* Wrappers for Gcov functions */ + +extern void __real___gcov_init(void *info); +void __wrap___gcov_init(void *info) +{ + __real___gcov_init(info); + gcov_rtio_init(); +} + #endif diff --git a/components/app_trace/gcov/io_sym.map b/components/app_trace/gcov/io_sym.map new file mode 100644 index 0000000000..727766648b --- /dev/null +++ b/components/app_trace/gcov/io_sym.map @@ -0,0 +1,7 @@ +fopen gcov_rtio_fopen +fclose gcov_rtio_fclose +fwrite gcov_rtio_fwrite +fread gcov_rtio_fread +fseek gcov_rtio_fseek +ftell gcov_rtio_ftell +setbuf gcov_rtio_setbuf