feat(esp_trace): add compiler-instrumented function tracing support

This commit is contained in:
Erhan Kurubas
2026-07-16 10:18:25 +02:00
parent b8d937bbb3
commit 39d6aaaecb
33 changed files with 1498 additions and 274 deletions
@@ -0,0 +1,15 @@
idf_component_register(SRCS "ft_demo.c" "ft_demo_hot.c" "ft_demo_quiet.c"
INCLUDE_DIRS "include")
# Opt the whole component into compiler-instrumented function tracing by adding
# -finstrument-functions to its build. The guard keeps the flag out when the
# feature is off, otherwise the __cyg_profile_* hooks would be undefined at link.
# The exclude-list flags skip specific files / functions:
# - ft_demo_hot.c and ft_demo_quiet.c are excluded by file (comma-separated)
# - ft_demo_secret is excluded by function name
if(CONFIG_ESP_TRACE_FUNCTION_TRACE)
target_compile_options(${COMPONENT_LIB} PRIVATE
-finstrument-functions
-finstrument-functions-exclude-file-list=ft_demo_hot,ft_demo_quiet
-finstrument-functions-exclude-function-list=ft_demo_secret)
endif()
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Function Tracing Example - demo library
*/
#include "ft_demo.h"
/* noinline keeps each function as a distinct call so the compiler inserts
* enter/exit hooks instead of inlining them away. */
static uint32_t __attribute__((noinline)) ft_demo_level2(uint32_t v)
{
return v * 3u + 1u;
}
static uint32_t __attribute__((noinline)) ft_demo_level1(uint32_t v)
{
return ft_demo_level2(v) + ft_demo_level2(v + 1u);
}
void ft_demo_run(uint32_t iteration)
{
volatile uint32_t r = ft_demo_level1(iteration);
(void)r;
}
void __attribute__((noinline)) ft_demo_secret(void)
{
/* Excluded from instrumentation by name, so no enter/exit is recorded even
* though this file is compiled with -finstrument-functions. */
__asm__ volatile("");
}
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Function Tracing Example - demo library (excluded file)
*/
#include "ft_demo.h"
/* This whole file is listed in the component's -finstrument-functions-exclude-file-list
* flag, so none of its functions are instrumented even though the component opts
* in. Use this for hot paths you do not want to trace. */
uint32_t ft_demo_hot_loop(uint32_t n)
{
uint32_t acc = 0;
for (uint32_t i = 0; i < n; i++) {
acc += i * i;
}
return acc;
}
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Function Tracing Example - demo library (second excluded file)
*/
#include "ft_demo.h"
/* A second file added to the component's -finstrument-functions-exclude-file-list
* as a separate, comma-separated entry. It shows the exclude list accepts more
* than one substring. Like ft_demo_hot.c, none of its functions are instrumented. */
uint32_t ft_demo_quiet_path(uint32_t n)
{
uint32_t acc = 1;
for (uint32_t i = 1; i <= n; i++) {
acc = (acc * i) % 1000u;
}
return acc;
}
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*
* Function Tracing Example - demo library
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Runs a small nested call graph (ft_demo_run -> level1 -> level2). These
* functions are instrumented and appear as function_enter/function_exit. */
void ft_demo_run(uint32_t iteration);
/* Instrumented file, but excluded by name through the component's
* -finstrument-functions-exclude-function-list flag: it produces no events. */
void ft_demo_secret(void);
/* Lives in ft_demo_hot.c, which is excluded as a whole through the component's
* -finstrument-functions-exclude-file-list flag: it produces no events. */
uint32_t ft_demo_hot_loop(uint32_t n);
/* Lives in ft_demo_quiet.c, a second comma-separated entry in the component's
* -finstrument-functions-exclude-file-list flag: it also produces no events. */
uint32_t ft_demo_quiet_path(uint32_t n);
#ifdef __cplusplus
}
#endif