This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7dfbd14eba9253282a8fe5cbdb366602733d8672
Author: anjiahao <[email protected]>
AuthorDate: Sun Oct 8 18:20:43 2023 +0800

    libc: add instrument api support
    
    Add registration function instrumentation API,
    which can achieve instrumentation of entering and
    exiting functions through the compiler's functionality.
    
    We can use CONFIG_ARCH_INSTRUMENT_ALL to add instrumentation for all
    source, or add '-finstrument-functions' to CFLAGS for Part of the
    source.
    
    Notice:
    1. use CONFIG_ARCH_INSTRUMENT_ALL must mark _start or entry 
noinstrument_function,
       becuase bss not set.
    2. Make sure your callbacks are not instrumented recursively.
    
    use instrument_register to register entry function and exit function.
    They will be called by the instrumented function
    
    Signed-off-by: anjiahao <[email protected]>
---
 arch/Kconfig                               |   7 ++
 arch/arm/src/armv7-m/arm_stackcheck.c      |  26 ++++---
 arch/arm/src/armv8-m/arm_stackcheck.c      |  26 +++++--
 arch/arm/src/cmake/armv7-a.cmake           |   4 +
 arch/arm/src/cmake/armv7-m.cmake           |   4 +
 arch/arm/src/cmake/armv8-m.cmake           |   4 +
 arch/arm/src/common/Toolchain.defs         |   6 ++
 arch/arm/src/common/arm_internal.h         |   4 +
 arch/arm/src/eoss3/eoss3_start.c           |   4 +
 arch/arm/src/gd32f4/gd32f4xx_start.c       |   4 +
 arch/arm/src/imxrt/imxrt_start.c           |   4 +
 arch/arm/src/kinetis/kinetis_start.c       |   4 +
 arch/arm/src/lpc17xx_40xx/lpc17_40_start.c |   4 +
 arch/arm/src/nrf52/nrf52_start.c           |   4 +
 arch/arm/src/nrf53/nrf53_start.c           |   4 +
 arch/arm/src/rtl8720c/ameba_start.c        |   5 ++
 arch/arm/src/sam34/sam_start.c             |   4 +
 arch/arm/src/samd5e5/sam_start.c           |   4 +
 arch/arm/src/samv7/sam_start.c             |   4 +
 arch/arm/src/stm32/stm32_start.c           |   4 +
 arch/arm/src/stm32f7/stm32_start.c         |   4 +
 arch/arm/src/stm32h7/stm32_start.c         |   4 +
 arch/arm/src/stm32l4/stm32l4_start.c       |   4 +
 arch/arm/src/stm32l5/stm32l5_start.c       |   4 +
 arch/arm/src/stm32u5/stm32_start.c         |   4 +
 arch/arm/src/stm32wb/stm32wb_start.c       |   4 +
 arch/arm/src/xmc4/xmc4_start.c             |   4 +
 arch/arm64/src/Toolchain.defs              |   6 ++
 arch/risc-v/src/common/Toolchain.defs      |   6 ++
 arch/xtensa/src/lx6/Toolchain.defs         |   6 ++
 arch/xtensa/src/lx7/Toolchain.defs         |   6 ++
 boards/sim/sim/sim/scripts/Make.defs       |   4 +
 drivers/note/note_driver.c                 |  66 ++++++++++------
 include/nuttx/instrument.h                 |  68 ++++++++++++++++
 libs/libc/misc/CMakeLists.txt              |   3 +-
 libs/libc/misc/Make.defs                   |   2 +-
 libs/libc/misc/lib_instrument.c            | 121 +++++++++++++++++++++++++++++
 37 files changed, 403 insertions(+), 43 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index fd0103cd13..deccaf4007 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -335,6 +335,13 @@ config ARCH_COVERAGE_ALL
                will get image size increased and performance decreased
                significantly.
 
+config ARCH_INSTRUMENT_ALL
+       bool "Instrument All"
+       default n
+       ---help---
+               Add instrument to all source files. we can use 
instrument_register
+               to register the instrument function.
+
 comment "Architecture Options"
 
 config ARCH_NOINTC
diff --git a/arch/arm/src/armv7-m/arm_stackcheck.c 
b/arch/arm/src/armv7-m/arm_stackcheck.c
index d7167a9c55..0dee2604ab 100644
--- a/arch/arm/src/armv7-m/arm_stackcheck.c
+++ b/arch/arm/src/armv7-m/arm_stackcheck.c
@@ -48,6 +48,7 @@
 
 #include <stdint.h>
 
+#include <nuttx/instrument.h>
 #include "arm_internal.h"
 #include "nvic.h"
 
@@ -55,10 +56,19 @@
  * Private Functions
  ****************************************************************************/
 
-void __cyg_profile_func_enter(void *func, void *caller) naked_function;
-void __cyg_profile_func_exit(void *func, void *caller) naked_function;
+static void stack_check_enter(void *func, void *caller, void *arg)
+                              naked_function;
 void __stack_overflow_trap(void) naked_function;
 
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct instrument_s g_stack_check =
+{
+  .enter = stack_check_enter,
+};
+
 /****************************************************************************
  * Name: __stack_overflow_trap
  ****************************************************************************/
@@ -87,10 +97,10 @@ void __stack_overflow_trap(void)
 }
 
 /****************************************************************************
- * Name: __cyg_profile_func_enter
+ * Name: stack_check_enter
  ****************************************************************************/
 
-void __cyg_profile_func_enter(void *func, void *caller)
+static void stack_check_enter(void *func, void *caller, void *arg)
 {
     asm volatile (
             "   mrs r2, ipsr        \n" /* Check whether we are in interrupt 
mode */
@@ -112,12 +122,8 @@ void __cyg_profile_func_enter(void *func, void *caller)
     );
 }
 
-/****************************************************************************
- * Name: __cyg_profile_func_exit
- ****************************************************************************/
-
-void __cyg_profile_func_exit(void *func, void *caller)
+void noinstrument_function arm_stack_check_init(void)
 {
-    asm volatile("bx lr");
+  instrument_register(&g_stack_check);
 }
 #endif
diff --git a/arch/arm/src/armv8-m/arm_stackcheck.c 
b/arch/arm/src/armv8-m/arm_stackcheck.c
index cbe107ca00..1d05fdd5db 100644
--- a/arch/arm/src/armv8-m/arm_stackcheck.c
+++ b/arch/arm/src/armv8-m/arm_stackcheck.c
@@ -48,6 +48,7 @@
 
 #include <stdint.h>
 
+#include <nuttx/instrument.h>
 #include "arm_internal.h"
 #include "nvic.h"
 
@@ -55,9 +56,18 @@
  * Private Functions
  ****************************************************************************/
 
-void  __cyg_profile_func_enter(void *func, void *caller) naked_function;
-void  __cyg_profile_func_exit(void *func, void *caller) naked_function;
-void  __stack_overflow_trap(void) naked_function;
+static void stack_check_enter(void *func, void *caller, void *arg)
+                              naked_function;
+void __stack_overflow_trap(void) naked_function;
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct instrument_s g_stack_check =
+{
+  .enter = stack_check_enter,
+};
 
 /****************************************************************************
  * Name: __stack_overflow_trap
@@ -87,10 +97,10 @@ void __stack_overflow_trap(void)
 }
 
 /****************************************************************************
- * Name: __cyg_profile_func_enter
+ * Name: stack_check_enter
  ****************************************************************************/
 
-void __cyg_profile_func_enter(void *func, void *caller)
+static void stack_check_enter(void *func, void *caller, void *arg)
 {
     asm volatile (
             "   mrs r2, ipsr        \n" /* Check whether we are in interrupt 
mode */
@@ -113,11 +123,11 @@ void __cyg_profile_func_enter(void *func, void *caller)
 }
 
 /****************************************************************************
- * Name: __cyg_profile_func_exit
+ * Name: arm_stack_check_init
  ****************************************************************************/
 
-void __cyg_profile_func_exit(void *func, void *caller)
+void noinstrument_function arm_stack_check_init(void)
 {
-    asm volatile("bx lr");
+  instrument_register(&g_stack_check);
 }
 #endif
diff --git a/arch/arm/src/cmake/armv7-a.cmake b/arch/arm/src/cmake/armv7-a.cmake
index 8566b54539..58a08fbeef 100644
--- a/arch/arm/src/cmake/armv7-a.cmake
+++ b/arch/arm/src/cmake/armv7-a.cmake
@@ -65,4 +65,8 @@ else()
   list(APPEND PLATFORM_FLAGS -mfloat-abi=soft)
 endif()
 
+if(CONFIG_ARCH_INSTRUMENT_ALL AND NOT CONFIG_ARMV8M_STACKCHECK)
+  list(APPEND PLATFORM_FLAGS -finstrument-functions)
+endif()
+
 add_compile_options(${PLATFORM_FLAGS})
diff --git a/arch/arm/src/cmake/armv7-m.cmake b/arch/arm/src/cmake/armv7-m.cmake
index 74dcd06fd2..f04f8379c2 100644
--- a/arch/arm/src/cmake/armv7-m.cmake
+++ b/arch/arm/src/cmake/armv7-m.cmake
@@ -90,4 +90,8 @@ if(CONFIG_ARMV7M_STACKCHECK)
   list(APPEND PLATFORM_FLAGS -finstrument-functions -ffixed-r10)
 endif()
 
+if(CONFIG_ARCH_INSTRUMENT_ALL AND NOT CONFIG_ARMV7M_STACKCHECK)
+  list(APPEND PLATFORM_FLAGS -finstrument-functions)
+endif()
+
 add_compile_options(${PLATFORM_FLAGS})
diff --git a/arch/arm/src/cmake/armv8-m.cmake b/arch/arm/src/cmake/armv8-m.cmake
index 5b1adf0c2c..514006f5af 100644
--- a/arch/arm/src/cmake/armv8-m.cmake
+++ b/arch/arm/src/cmake/armv8-m.cmake
@@ -65,6 +65,10 @@ if(CONFIG_ARMV8M_STACKCHECK)
   list(APPEND PLATFORM_FLAGS -finstrument-functions -ffixed-r10)
 endif()
 
+if(CONFIG_ARCH_INSTRUMENT_ALL AND NOT CONFIG_ARMV8M_STACKCHECK)
+  list(APPEND PLATFORM_FLAGS -finstrument-functions)
+endif()
+
 if(CONFIG_ARMV8M_CMSE)
   list(APPEND PLATFORM_FLAGS -mcmse)
 endif()
diff --git a/arch/arm/src/common/Toolchain.defs 
b/arch/arm/src/common/Toolchain.defs
index 991ce31b81..1e0184abc5 100644
--- a/arch/arm/src/common/Toolchain.defs
+++ b/arch/arm/src/common/Toolchain.defs
@@ -86,6 +86,12 @@ ifeq ($(CONFIG_MM_KASAN_DISABLE_WRITES_CHECK),y)
   ARCHOPTIMIZATION += --param asan-instrument-writes=0
 endif
 
+# Instrumentation options
+
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 ifeq ($(CONFIG_UNWINDER_ARM),y)
   ARCHOPTIMIZATION += -funwind-tables -fasynchronous-unwind-tables
 endif
diff --git a/arch/arm/src/common/arm_internal.h 
b/arch/arm/src/common/arm_internal.h
index 40b4b409f8..271aa05e28 100644
--- a/arch/arm/src/common/arm_internal.h
+++ b/arch/arm/src/common/arm_internal.h
@@ -531,6 +531,10 @@ int arm_gen_nonsecurefault(int irq, uint32_t *regs);
 # define arm_gen_nonsecurefault(i, r)  (0)
 #endif
 
+#if defined(CONFIG_ARMV7M_STACKCHECK) || defined(CONFIG_ARMV8M_STACKCHECK)
+void arm_stack_check_init(void) noinstrument_function;
+#endif
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/arch/arm/src/eoss3/eoss3_start.c b/arch/arm/src/eoss3/eoss3_start.c
index b1bcd96b37..560a3fe116 100644
--- a/arch/arm/src/eoss3/eoss3_start.c
+++ b/arch/arm/src/eoss3/eoss3_start.c
@@ -152,6 +152,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARMV7M_ITMSYSLOG
   /* Perform ARMv7-M ITM SYSLOG initialization */
 
diff --git a/arch/arm/src/gd32f4/gd32f4xx_start.c 
b/arch/arm/src/gd32f4/gd32f4xx_start.c
index 0ea5e0a7c9..70a09d4924 100644
--- a/arch/arm/src/gd32f4/gd32f4xx_start.c
+++ b/arch/arm/src/gd32f4/gd32f4xx_start.c
@@ -237,6 +237,10 @@ void __start(void)
       *dest++ = *src++;
     }
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   gd32_clockconfig();
diff --git a/arch/arm/src/imxrt/imxrt_start.c b/arch/arm/src/imxrt/imxrt_start.c
index b5aa9c7fc0..cc51d70e4e 100644
--- a/arch/arm/src/imxrt/imxrt_start.c
+++ b/arch/arm/src/imxrt/imxrt_start.c
@@ -210,6 +210,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   imxrt_clockconfig();
diff --git a/arch/arm/src/kinetis/kinetis_start.c 
b/arch/arm/src/kinetis/kinetis_start.c
index 085adf9c1b..c46abe0bec 100644
--- a/arch/arm/src/kinetis/kinetis_start.c
+++ b/arch/arm/src/kinetis/kinetis_start.c
@@ -153,6 +153,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Perform clock and Kinetis module initialization (This depends on
    * RAM functions having been copied to RAM).
    */
diff --git a/arch/arm/src/lpc17xx_40xx/lpc17_40_start.c 
b/arch/arm/src/lpc17xx_40xx/lpc17_40_start.c
index 0fb65df0d0..eee92a234e 100644
--- a/arch/arm/src/lpc17xx_40xx/lpc17_40_start.c
+++ b/arch/arm/src/lpc17xx_40xx/lpc17_40_start.c
@@ -153,6 +153,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Perform early serial initialization */
 
 #ifdef USE_EARLYSERIALINIT
diff --git a/arch/arm/src/nrf52/nrf52_start.c b/arch/arm/src/nrf52/nrf52_start.c
index 2e3bf74b61..bc34a93d38 100644
--- a/arch/arm/src/nrf52/nrf52_start.c
+++ b/arch/arm/src/nrf52/nrf52_start.c
@@ -188,6 +188,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #if defined(CONFIG_ARCH_CHIP_NRF52832)
   /* Initialize the errdata work-around */
 
diff --git a/arch/arm/src/nrf53/nrf53_start.c b/arch/arm/src/nrf53/nrf53_start.c
index 07458a7659..b58c9112d7 100644
--- a/arch/arm/src/nrf53/nrf53_start.c
+++ b/arch/arm/src/nrf53/nrf53_start.c
@@ -236,6 +236,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV8M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_HAVE_FPU
   /* Initialize the FPU (if available) */
 
diff --git a/arch/arm/src/rtl8720c/ameba_start.c 
b/arch/arm/src/rtl8720c/ameba_start.c
index 3cafd0240a..df0cd4a11b 100644
--- a/arch/arm/src/rtl8720c/ameba_start.c
+++ b/arch/arm/src/rtl8720c/ameba_start.c
@@ -77,6 +77,11 @@ int promisc_recv_lens_func(void *padapter, uint8_t *payload, 
uint8_t plen)
 void app_start(void)
 {
   __asm volatile("MSR msplim, %0" : : "r"(0));
+
+#ifdef CONFIG_ARMV8M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   arm_earlyserialinit();
 #ifdef CONFIG_MBEDTLS240_AMEBAZ_HARDWARE_CRYPTO
   extern int mbedtls_platform_set_calloc_free(
diff --git a/arch/arm/src/sam34/sam_start.c b/arch/arm/src/sam34/sam_start.c
index 553f665b80..dac801ef10 100644
--- a/arch/arm/src/sam34/sam_start.c
+++ b/arch/arm/src/sam34/sam_start.c
@@ -164,6 +164,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   sam_clockconfig();
diff --git a/arch/arm/src/samd5e5/sam_start.c b/arch/arm/src/samd5e5/sam_start.c
index 689108d911..443d0a7bea 100644
--- a/arch/arm/src/samd5e5/sam_start.c
+++ b/arch/arm/src/samd5e5/sam_start.c
@@ -167,6 +167,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Initialize clocking and the FPU.  Configure the console UART so that
    * we can get debug output as soon as possible.
    */
diff --git a/arch/arm/src/samv7/sam_start.c b/arch/arm/src/samv7/sam_start.c
index e2c4f1f4cb..a6c1c6170a 100644
--- a/arch/arm/src/samv7/sam_start.c
+++ b/arch/arm/src/samv7/sam_start.c
@@ -199,6 +199,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   sam_clockconfig();
diff --git a/arch/arm/src/stm32/stm32_start.c b/arch/arm/src/stm32/stm32_start.c
index c369d1c7db..973c752389 100644
--- a/arch/arm/src/stm32/stm32_start.c
+++ b/arch/arm/src/stm32/stm32_start.c
@@ -158,6 +158,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)STM32_SYSCLK_FREQUENCY);
 #endif
diff --git a/arch/arm/src/stm32f7/stm32_start.c 
b/arch/arm/src/stm32f7/stm32_start.c
index e333385fed..a37e63e7e2 100644
--- a/arch/arm/src/stm32f7/stm32_start.c
+++ b/arch/arm/src/stm32f7/stm32_start.c
@@ -223,6 +223,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   stm32_clockconfig();
diff --git a/arch/arm/src/stm32h7/stm32_start.c 
b/arch/arm/src/stm32h7/stm32_start.c
index 9959d49f9d..7bd4013e48 100644
--- a/arch/arm/src/stm32h7/stm32_start.c
+++ b/arch/arm/src/stm32h7/stm32_start.c
@@ -239,6 +239,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Configure the UART so that we can get debug output as soon as possible */
 
   stm32_clockconfig();
diff --git a/arch/arm/src/stm32l4/stm32l4_start.c 
b/arch/arm/src/stm32l4/stm32l4_start.c
index c95e6e1225..7b5b9a7977 100644
--- a/arch/arm/src/stm32l4/stm32l4_start.c
+++ b/arch/arm/src/stm32l4/stm32l4_start.c
@@ -179,6 +179,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)STM32_SYSCLK_FREQUENCY);
 #endif
diff --git a/arch/arm/src/stm32l5/stm32l5_start.c 
b/arch/arm/src/stm32l5/stm32l5_start.c
index 1f09ed1046..47efcf57e7 100644
--- a/arch/arm/src/stm32l5/stm32l5_start.c
+++ b/arch/arm/src/stm32l5/stm32l5_start.c
@@ -181,6 +181,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV8M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)STM32_SYSCLK_FREQUENCY);
 #endif
diff --git a/arch/arm/src/stm32u5/stm32_start.c 
b/arch/arm/src/stm32u5/stm32_start.c
index cbb0c640f8..2f4572325e 100644
--- a/arch/arm/src/stm32u5/stm32_start.c
+++ b/arch/arm/src/stm32u5/stm32_start.c
@@ -181,6 +181,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV8M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)STM32_SYSCLK_FREQUENCY);
 #endif
diff --git a/arch/arm/src/stm32wb/stm32wb_start.c 
b/arch/arm/src/stm32wb/stm32wb_start.c
index 6ab5605da8..2f829f8d03 100644
--- a/arch/arm/src/stm32wb/stm32wb_start.c
+++ b/arch/arm/src/stm32wb/stm32wb_start.c
@@ -199,6 +199,10 @@ void __start(void)
 
   showprogress('C');
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
 #ifdef CONFIG_ARCH_PERF_EVENTS
   up_perf_init((void *)STM32_SYSCLK_FREQUENCY);
 #endif
diff --git a/arch/arm/src/xmc4/xmc4_start.c b/arch/arm/src/xmc4/xmc4_start.c
index 4e55e7ec21..b40f5502dd 100644
--- a/arch/arm/src/xmc4/xmc4_start.c
+++ b/arch/arm/src/xmc4/xmc4_start.c
@@ -220,6 +220,10 @@ void __start(void)
     }
 #endif
 
+#ifdef CONFIG_ARMV7M_STACKCHECK
+  arm_stack_check_init();
+#endif
+
   /* Set FLASH wait states prior to the configuration of clocking */
 
   xmc4_flash_waitstates();
diff --git a/arch/arm64/src/Toolchain.defs b/arch/arm64/src/Toolchain.defs
index efebeb5651..214b481d5e 100644
--- a/arch/arm64/src/Toolchain.defs
+++ b/arch/arm64/src/Toolchain.defs
@@ -84,6 +84,12 @@ ifeq ($(CONFIG_MM_KASAN_ALL),y)
   ARCHOPTIMIZATION += -fsanitize=kernel-address
 endif
 
+# Instrumentation options
+
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 ifeq ($(CONFIG_ARCH_FPU),y)
   ARCHCXXFLAGS += -D_LDBL_EQ_DBL
   ARCHCFLAGS   += -D_LDBL_EQ_DBL
diff --git a/arch/risc-v/src/common/Toolchain.defs 
b/arch/risc-v/src/common/Toolchain.defs
index 61d7f270c3..3d0e5296a9 100644
--- a/arch/risc-v/src/common/Toolchain.defs
+++ b/arch/risc-v/src/common/Toolchain.defs
@@ -251,6 +251,12 @@ ifeq ($(CONFIG_MM_UBSAN_TRAP_ON_ERROR),y)
   ARCHOPTIMIZATION += -fsanitize-undefined-trap-on-error
 endif
 
+# Instrumentation options
+
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 # Default toolchain
 
 CC      = $(CROSSDEV)gcc
diff --git a/arch/xtensa/src/lx6/Toolchain.defs 
b/arch/xtensa/src/lx6/Toolchain.defs
index 1be4627c92..686dc70087 100644
--- a/arch/xtensa/src/lx6/Toolchain.defs
+++ b/arch/xtensa/src/lx6/Toolchain.defs
@@ -95,6 +95,12 @@ ifeq ($(CONFIG_ARCH_COVERAGE_ALL),y)
   ARCHOPTIMIZATION += -fprofile-generate -ftest-coverage
 endif
 
+# Instrumentation options
+
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 ARCHCFLAGS += -fno-common
 ARCHCXXFLAGS += -fno-common -nostdinc++
 
diff --git a/arch/xtensa/src/lx7/Toolchain.defs 
b/arch/xtensa/src/lx7/Toolchain.defs
index 710b19677d..6d5da909cf 100644
--- a/arch/xtensa/src/lx7/Toolchain.defs
+++ b/arch/xtensa/src/lx7/Toolchain.defs
@@ -99,6 +99,12 @@ ifeq ($(CONFIG_ARCH_COVERAGE_ALL),y)
   ARCHOPTIMIZATION += -fprofile-generate -ftest-coverage
 endif
 
+# Instrumentation options
+
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 ARCHCFLAGS += -fno-common
 ARCHCXXFLAGS += -fno-common -nostdinc++
 
diff --git a/boards/sim/sim/sim/scripts/Make.defs 
b/boards/sim/sim/sim/scripts/Make.defs
index 6c9a77b0ce..efc9dd9383 100644
--- a/boards/sim/sim/sim/scripts/Make.defs
+++ b/boards/sim/sim/sim/scripts/Make.defs
@@ -95,6 +95,10 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_ARCH_INSTRUMENT_ALL),y)
+  ARCHOPTIMIZATION += -finstrument-functions
+endif
+
 # Add -fno-common because macOS "ld -r" doesn't seem to pick objects
 # for common symbols.
 ARCHCFLAGS += -fno-common
diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c
index ae1c979637..758f1c5a77 100644
--- a/drivers/note/note_driver.c
+++ b/drivers/note/note_driver.c
@@ -40,9 +40,14 @@
 #include <nuttx/note/notelog_driver.h>
 #include <nuttx/spinlock.h>
 #include <nuttx/sched_note.h>
+#include <nuttx/instrument.h>
 
 #include "sched/sched.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
 #if defined(CONFIG_DRIVERS_NOTERAM) +  defined(CONFIG_DRIVERS_NOTELOG) + \
     defined(CONFIG_DRIVERS_NOTESNAP) + defined(CONFIG_DRIVERS_NOTERTT) + \
     defined(CONFIG_SEGGER_SYSVIEW) > CONFIG_DRIVERS_NOTE_MAX
@@ -150,6 +155,18 @@ struct note_taskname_s
  * Private Data
  ****************************************************************************/
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
+static void note_driver_instrument_enter(FAR void *this_fn,
+            FAR void *call_site, FAR void *arg) noinstrument_function;
+static void note_driver_instrument_leave(FAR void *this_fn,
+            FAR void *call_site, FAR void *arg) noinstrument_function;
+static struct instrument_s g_note_instrument =
+{
+  .entry = note_driver_instrument_enter,
+  .exit = note_driver_instrument_leave,
+};
+#endif
+
 #ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
 static struct note_filter_s g_note_filter =
 {
@@ -1924,6 +1941,22 @@ FAR const char *note_get_taskname(pid_t pid)
 
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
+static void note_driver_instrument_enter(FAR void *this_fn,
+                                         FAR void *call_site,
+                                         FAR void *arg)
+{
+  sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "B");
+}
+
+static void note_driver_instrument_leave(FAR void *this_fn,
+                                         FAR void *call_site,
+                                         FAR void *arg)
+{
+  sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "E");
+}
+#endif
+
 /****************************************************************************
  * Name: note_driver_register
  ****************************************************************************/
@@ -1931,8 +1964,17 @@ FAR const char *note_get_taskname(pid_t pid)
 int note_driver_register(FAR struct note_driver_s *driver)
 {
   int i;
-  DEBUGASSERT(driver);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
+  static bool initialized;
 
+  if (!initialized)
+    {
+      instrument_register(g_note_instrument)
+      initialized = true;
+    }
+#endif
+
+  DEBUGASSERT(driver);
   for (i = 0; i < CONFIG_DRIVERS_NOTE_MAX; i++)
     {
       if (g_note_drivers[i] == NULL)
@@ -1945,25 +1987,3 @@ int note_driver_register(FAR struct note_driver_s 
*driver)
   return -ENOMEM;
 }
 
-#ifdef CONFIG_SCHED_INSTRUMENTATION_FUNCTION
-
-/****************************************************************************
- * Name: __cyg_profile_func_enter
- ****************************************************************************/
-
-void noinstrument_function
-__cyg_profile_func_enter(void *this_fn, void *call_site)
-{
-  sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "B");
-}
-
-/****************************************************************************
- * Name: __cyg_profile_func_exit
- ****************************************************************************/
-
-void noinstrument_function
-__cyg_profile_func_exit(void *this_fn, void *call_site)
-{
-  sched_note_string_ip(NOTE_TAG_ALWAYS, (uintptr_t)this_fn, "E");
-}
-#endif
diff --git a/include/nuttx/instrument.h b/include/nuttx/instrument.h
new file mode 100644
index 0000000000..c39b9462ac
--- /dev/null
+++ b/include/nuttx/instrument.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+ * include/nuttx/instrument.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_INSTRUMENT_H
+#define __INCLUDE_NUTTX_INSTRUMENT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/compiler.h>
+#include <nuttx/queue.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef CODE void (instrument_fun_t)(FAR void *this_fn,
+                                     FAR void *call_site,
+                                     FAR void *arg);
+
+struct instrument_s
+{
+  sq_entry_t entry;
+  FAR instrument_fun_t *enter;
+  FAR instrument_fun_t *leave;
+  FAR void *arg;
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: instrument_register
+ *
+ * Description: register instrument, it will be called
+ *              when function enter or exit.
+ *
+ * Input Parameters:
+ *   entry - instrument entry structure.
+ * Notice:
+ *  use CONFIG_ARCH_INSTRUMENT_ALL must mark _start or entry
+ *  noinstrument_function, becuase bss not set.
+ *  Make sure your callbacks are not instrumented recursively.
+ *
+ ****************************************************************************/
+
+void instrument_register(FAR struct instrument_s *entry);
+
+#endif /* __INCLUDE_NUTTX_INSTRUMENT_H */
diff --git a/libs/libc/misc/CMakeLists.txt b/libs/libc/misc/CMakeLists.txt
index e24d3ef05c..dbbf69ca5d 100644
--- a/libs/libc/misc/CMakeLists.txt
+++ b/libs/libc/misc/CMakeLists.txt
@@ -79,7 +79,8 @@ list(
   lib_glob.c
   lib_execinfo.c
   lib_ftok.c
-  lib_err.c)
+  lib_err.c
+  lib_instrument.c)
 
 # Keyboard driver encoder/decoder
 
diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs
index 5e71c0649d..605779e0d6 100644
--- a/libs/libc/misc/Make.defs
+++ b/libs/libc/misc/Make.defs
@@ -40,7 +40,7 @@ endif
 CSRCS += lib_dumpbuffer.c lib_dumpvbuffer.c lib_fnmatch.c lib_debug.c
 CSRCS += lib_crc64.c lib_crc32.c lib_crc16.c lib_crc16ccitt.c lib_crc8.c
 CSRCS += lib_crc8ccitt.c lib_crc8table.c lib_glob.c lib_execinfo.c
-CSRCS += lib_ftok.c lib_err.c
+CSRCS += lib_ftok.c lib_err.c lib_instrument.c
 
 # Keyboard driver encoder/decoder
 
diff --git a/libs/libc/misc/lib_instrument.c b/libs/libc/misc/lib_instrument.c
new file mode 100644
index 0000000000..e16af3b3b8
--- /dev/null
+++ b/libs/libc/misc/lib_instrument.c
@@ -0,0 +1,121 @@
+/****************************************************************************
+ * libs/libc/misc/lib_instrument.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/instrument.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Avoid instrument bootstrap */
+
+#define MAIGC_NUMBMER 0x5a5a5a5a
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Use static to avoid instrument bootstrap */
+
+static volatile uint32_t g_magic;
+static sq_queue_t g_instrument_queue;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: __cyg_profile_func_enter
+ ****************************************************************************/
+
+void noinstrument_function
+__cyg_profile_func_enter(FAR void *this_fn, FAR void *call_site)
+{
+  FAR struct instrument_s *instrument;
+  FAR sq_entry_t *entry;
+
+  if (g_magic != MAIGC_NUMBMER)
+    {
+      return;
+    }
+
+  sq_for_every(&g_instrument_queue, entry)
+    {
+      instrument = (FAR struct instrument_s *)entry;
+      if (instrument->enter)
+        {
+          instrument->enter(this_fn, call_site, instrument->arg);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: __cyg_profile_func_exit
+ ****************************************************************************/
+
+void noinstrument_function
+__cyg_profile_func_exit(FAR void *this_fn, FAR void *call_site)
+{
+  FAR struct instrument_s *instrument;
+  FAR sq_entry_t *entry;
+
+  if (g_magic != MAIGC_NUMBMER)
+    {
+      return;
+    }
+
+  sq_for_every(&g_instrument_queue, entry)
+    {
+      instrument = (FAR struct instrument_s *)entry;
+      if (instrument->leave)
+        {
+          instrument->leave(this_fn, call_site, instrument->arg);
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: instrument_register
+ *
+ * Description: register instrument, it will be called
+ *              when function enter or exit.
+ *
+ * Input Parameters:
+ *   entry - instrument entry structure.
+ * Notice:
+ *  use CONFIG_ARCH_INSTRUMENT_ALL must mark _start or entry
+ *  noinstrument_function, becuase bss not set.
+ *  Make sure your callbacks are not instrumented recursively.
+ *
+ ****************************************************************************/
+
+void noinstrument_function
+instrument_register(FAR struct instrument_s *entry)
+{
+  if (entry != NULL)
+    {
+      sq_addlast((FAR sq_entry_t *)entry, &g_instrument_queue);
+      g_magic = MAIGC_NUMBMER;
+    }
+}

Reply via email to