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

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

commit 5d8cdeaea847bcaf0b9145dd922e0a83045067ca
Author: yinshengkai <yinsheng...@xiaomi.com>
AuthorDate: Wed Nov 29 12:35:29 2023 +0800

    note: print without relying on format strings
    
    Signed-off-by: yinshengkai <yinsheng...@xiaomi.com>
---
 drivers/note/Kconfig          |   5 +
 drivers/note/note_driver.c    | 322 +++++++++++++++++++++++++-----------------
 drivers/note/noteram_driver.c | 217 +++++++++++++++++-----------
 include/nuttx/compiler.h      |   8 +-
 include/nuttx/macro.h         | 140 ++++++++++++++++++
 include/nuttx/sched_note.h    |  86 +++++++++--
 sched/Kconfig                 |   4 +-
 7 files changed, 561 insertions(+), 221 deletions(-)

diff --git a/drivers/note/Kconfig b/drivers/note/Kconfig
index 49248bd121..e5469b6ab9 100644
--- a/drivers/note/Kconfig
+++ b/drivers/note/Kconfig
@@ -87,6 +87,11 @@ config DRIVERS_NOTERAM_CRASH_DUMP
 
 endif # DRIVERS_NOTERAM
 
+config DRIVERS_NOTE_STRIP_FORMAT
+       bool "Strip sched_note_printf format string"
+       ---help---
+               Strip sched_note_printf format string.
+
 config DRIVERS_NOTELOG
        bool "Note syslog driver"
        ---help---
diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c
index ea58c8be17..0b4d725c67 100644
--- a/drivers/note/note_driver.c
+++ b/drivers/note/note_driver.c
@@ -1483,39 +1483,14 @@ void sched_note_event_ip(uint32_t tag, uintptr_t ip, 
uint8_t event,
     }
 }
 
-void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
-                           FAR const char *fmt, va_list va)
+void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
+                           uint32_t type, va_list va)
 {
   FAR struct note_printf_s *note;
   FAR struct note_driver_s **driver;
   bool formatted = false;
   uint8_t data[255];
-  begin_packed_struct union
-    {
-      int i;
-      long l;
-#ifdef CONFIG_HAVE_LONG_LONG
-      long long ll;
-#endif
-      intmax_t im;
-      size_t sz;
-      ptrdiff_t ptr;
-      FAR void *p;
-#ifdef CONFIG_HAVE_DOUBLE
-      double d;
-#  ifdef CONFIG_HAVE_LONG_DOUBLE
-      long double ld;
-#  endif
-#endif
-    }
-
-  end_packed_struct *var;
-
-  char c;
-  size_t length;
-  size_t next = 0;
-  bool infmt = false;
-  FAR const char *p = fmt;
+  size_t length = 0;
   FAR struct tcb_s *tcb = this_task();
 
   if (!note_isenabled_dump(tag))
@@ -1539,146 +1514,236 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
 
       if (!formatted)
         {
+          begin_packed_struct union
+            {
+              int i;
+              long l;
+#ifdef CONFIG_HAVE_LONG_LONG
+              long long ll;
+#endif
+              intmax_t im;
+              size_t sz;
+              ptrdiff_t ptr;
+              FAR void *p;
+              FAR const char *s;
+#ifdef CONFIG_HAVE_DOUBLE
+              double d;
+#  ifdef CONFIG_HAVE_LONG_DOUBLE
+              long double ld;
+#  endif
+#endif
+            }
+
+          end_packed_struct *var;
+          size_t next = 0;
           formatted = true;
           note = (FAR struct note_printf_s *)data;
           length = sizeof(data) - SIZEOF_NOTE_PRINTF(0);
 
-          while ((c = *p++) != '\0')
+          if (type)
             {
-              if (c != '%' && !infmt)
-                {
-                  continue;
-                }
-
-              infmt = true;
-              var = (FAR void *)&note->npt_data[next];
+              size_t count = NOTE_PRINTF_GET_COUNT(type);
+              size_t i;
 
-              if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
-                  c == 'o' || c == 'x' || c == 'X')
+              for (i = 0; i < count; i++)
                 {
-                  if (*(p - 2) == 'j')
+                  var = (FAR void *)&note->npt_data[next];
+                  switch (NOTE_PRINTF_GET_TYPE(type, i))
                     {
-                      if (next + sizeof(var->im) > length)
+                      case NOTE_PRINTF_UINT32:
                         {
-                          break;
+                          var->i = va_arg(va, int);
+                          if (next + sizeof(var->i) > length)
+                            {
+                              break;
+                            }
+
+                          next += sizeof(var->i);
                         }
+                      break;
+                      case NOTE_PRINTF_UINT64:
+                        {
+                          if (next + sizeof(var->ll) > length)
+                            {
+                              break;
+                            }
 
-                      var->im = va_arg(va, intmax_t);
-                      next += sizeof(var->im);
-                    }
-#ifdef CONFIG_HAVE_LONG_LONG
-                  else if (*(p - 2) == 'l' && *(p - 3) == 'l')
-                    {
-                      if (next + sizeof(var->ll) > length)
+                          var->ll = va_arg(va, long long);
+                          next += sizeof(var->ll);
+                        }
+                      break;
+                      case NOTE_PRINTF_STRING:
                         {
-                          break;
+                          size_t len;
+                          var->s = va_arg(va, FAR const char *);
+                          len = strlen(var->s) + 1;
+                          if (next + len > length)
+                            {
+                              len = length - next;
+                            }
+
+                          strlcpy(note->npt_data + next, var->s, len);
+                          next += len;
                         }
+                      break;
+                      case NOTE_PRINTF_DOUBLE:
+                        {
+                          var->d = va_arg(va, double);
+                          if (next + sizeof(var->d) > length)
+                            {
+                              break;
+                            }
 
-                      var->ll = va_arg(va, long long);
-                      next += sizeof(var->ll);
+                          next += sizeof(var->d);
+                        }
+                      break;
                     }
-#endif
-                  else if (*(p - 2) == 'l')
+                }
+            }
+          else
+            {
+              FAR const char *p = fmt;
+              bool infmt = false;
+              char c;
+
+              while ((c = *p++) != '\0')
+                {
+                  if (c != '%' && !infmt)
+                    {
+                      continue;
+                    }
+
+                  infmt = true;
+                  var = (FAR void *)&note->npt_data[next];
+
+                  if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
+                      c == 'o' || c == 'x' || c == 'X')
                     {
-                      if (next + sizeof(var->l) > length)
+                      if (*(p - 2) == 'j')
                         {
-                          break;
+                          if (next + sizeof(var->im) > length)
+                            {
+                              break;
+                            }
+
+                          var->im = va_arg(va, intmax_t);
+                          next += sizeof(var->im);
+                        }
+#ifdef CONFIG_HAVE_LONG_LONG
+                      else if (*(p - 2) == 'l' && *(p - 3) == 'l')
+                        {
+                          if (next + sizeof(var->ll) > length)
+                            {
+                              break;
+                            }
+
+                          var->ll = va_arg(va, long long);
+                          next += sizeof(var->ll);
                         }
+#endif
+                      else if (*(p - 2) == 'l')
+                        {
+                          if (next + sizeof(var->l) > length)
+                            {
+                              break;
+                            }
 
-                      var->l = va_arg(va, long);
-                      next += sizeof(var->l);
-                    }
-                  else if (*(p - 2) == 'z')
-                    {
-                      if (next + sizeof(var->sz) > length)
+                          var->l = va_arg(va, long);
+                          next += sizeof(var->l);
+                        }
+                      else if (*(p - 2) == 'z')
                         {
-                          break;
+                          if (next + sizeof(var->sz) > length)
+                            {
+                              break;
+                            }
+
+                          var->sz = va_arg(va, size_t);
+                          next += sizeof(var->sz);
                         }
+                      else if (*(p - 2) == 't')
+                        {
+                          if (next + sizeof(var->ptr) > length)
+                            {
+                              break;
+                            }
 
-                      var->sz = va_arg(va, size_t);
-                      next += sizeof(var->sz);
-                    }
-                  else if (*(p - 2) == 't')
-                    {
-                      if (next + sizeof(var->ptr) > length)
+                          var->ptr = va_arg(va, ptrdiff_t);
+                          next += sizeof(var->ptr);
+                        }
+                      else
                         {
-                          break;
+                          if (next + sizeof(var->i) > length)
+                            {
+                              break;
+                            }
+
+                          var->i = va_arg(va, int);
+                          next += sizeof(var->i);
                         }
 
-                      var->ptr = va_arg(va, ptrdiff_t);
-                      next += sizeof(var->ptr);
+                      infmt = false;
                     }
-                  else
+                  else if (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
+                           c == 'A' || c == 'E' || c == 'F' || c == 'G')
                     {
-                      if (next + sizeof(var->i) > length)
+#ifdef CONFIG_HAVE_DOUBLE
+#  ifdef CONFIG_HAVE_LONG_DOUBLE
+                      if (*(p - 2) == 'L')
                         {
-                          break;
+                          if (next + sizeof(var->ld) > length)
+                            {
+                              break;
+                            }
+
+                          var->ld = va_arg(va, long double);
+                          next += sizeof(var->ld);
+                        }
+                      else
+#  endif
+                        {
+                          if (next + sizeof(var->d) > length)
+                            {
+                              break;
+                            }
+
+                          var->d = va_arg(va, double);
+                          next += sizeof(var->d);
                         }
+#endif
 
+                      infmt = false;
+                    }
+                  else if (c == '*')
+                    {
                       var->i = va_arg(va, int);
                       next += sizeof(var->i);
                     }
-
-                  infmt = false;
-                }
-              else if (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
-                       c == 'A' || c == 'E' || c == 'F' || c == 'G')
-                {
-#ifdef CONFIG_HAVE_DOUBLE
-#  ifdef CONFIG_HAVE_LONG_DOUBLE
-                  if (*(p - 2) == 'L')
+                  else if (c == 's')
                     {
-                      if (next + sizeof(var->ld) > length)
+                      size_t len;
+                      var->s = va_arg(va, FAR char *);
+                      len = strlen(var->s) + 1;
+                      if (next + len > length)
                         {
-                          break;
+                          len = length - next;
                         }
 
-                      var->ld = va_arg(va, long double);
-                      next += sizeof(var->ld);
+                      strlcpy(note->npt_data + next, var->s, len);
+                      next += len;
+                      infmt = false;
                     }
-                  else
-#  endif
+                  else if (c == 'p')
                     {
-                      if (next + sizeof(var->d) > length)
+                      if (next + sizeof(var->p) > length)
                         {
                           break;
                         }
 
-                      var->d = va_arg(va, double);
-                      next += sizeof(var->d);
-                    }
-#endif
-
-                  infmt = false;
-                }
-              else if (c == '*')
-                {
-                  var->i = va_arg(va, int);
-                  next += sizeof(var->i);
-                }
-              else if (c == 's')
-                {
-                  FAR char *str = (FAR char *)va_arg(va, FAR char *);
-                  size_t len = strlen(str) + 1;
-                  if (next + len > length)
-                    {
-                      len = length - next;
-                    }
-
-                  strlcpy(&note->npt_data[next], str, len);
-                  next += len;
-                  infmt = false;
-                }
-              else if (c == 'p')
-                {
-                  if (next + sizeof(var->p) > length)
-                    {
-                      break;
+                      var->p = va_arg(va, FAR void *);
+                      next += sizeof(var->p);
+                      infmt = false;
                     }
-
-                  var->p = va_arg(va, FAR void *);
-                  next += sizeof(var->p);
-                  infmt = false;
                 }
             }
 
@@ -1686,6 +1751,7 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
           note_common(tcb, &note->npt_cmn, length, NOTE_DUMP_PRINTF);
           note->npt_ip = ip;
           note->npt_fmt = fmt;
+          note->npt_type = type;
         }
 
       /* Add the note to circular buffer */
@@ -1694,12 +1760,12 @@ void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip,
     }
 }
 
-void sched_note_printf_ip(uint32_t tag, uintptr_t ip,
-                          FAR const char *fmt, ...)
+void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
+                          uint32_t type, ...)
 {
   va_list va;
-  va_start(va, fmt);
-  sched_note_vprintf_ip(tag, ip, fmt, va);
+  va_start(va, type);
+  sched_note_vprintf_ip(tag, ip, fmt, type, va);
   va_end(va);
 }
 
diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c
index 75400f1edd..c29447a28a 100644
--- a/drivers/note/noteram_driver.c
+++ b/drivers/note/noteram_driver.c
@@ -728,7 +728,8 @@ static int noteram_dump_printf(FAR struct lib_outstream_s 
*s,
       intmax_t im;
       size_t sz;
       ptrdiff_t pd;
-      uintptr_t p;
+      FAR void *p;
+      FAR const char *s;
 #ifdef CONFIG_HAVE_DOUBLE
       double d;
 #  ifdef CONFIG_HAVE_LONG_DOUBLE
@@ -738,117 +739,169 @@ static int noteram_dump_printf(FAR struct 
lib_outstream_s *s,
     }
 
   end_packed_struct *var;
-  FAR const char *p = note->npt_fmt;
-  FAR char *data = note->npt_data;
-  char fmtstr[64];
-  bool infmt = false;
   size_t offset = 0;
   size_t ret = 0;
   size_t len = 0;
-  char c;
 
-  while ((c = *p++) != '\0')
+  if (note->npt_type == 0)
     {
-      if (c != '%' && !infmt)
-        {
-          lib_stream_putc(s, c);
-          ret++;
-          continue;
-        }
-
-      if (!infmt)
-        {
-          len = 0;
-          infmt = true;
-          memset(fmtstr, 0, sizeof(fmtstr));
-        }
-
-      var = (FAR void *)(note->npt_data + offset);
-      fmtstr[len++] = c;
+      FAR const char *p = note->npt_fmt;
+      bool infmt = false;
+      char fmtstr[64];
+      char c;
 
-      if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
-          c == 'o' || c == 'x' || c == 'X')
+      while ((c = *p++) != '\0')
         {
-          if (*(p - 2) == 'j')
-            {
-              offset += sizeof(var->im);
-              ret += lib_sprintf(s, fmtstr, var->im);
-            }
-#ifdef CONFIG_HAVE_LONG_LONG
-          else if (*(p - 2) == 'l' && *(p - 3) == 'l')
+          if (c != '%' && !infmt)
             {
-              offset += sizeof(var->ll);
-              ret += lib_sprintf(s, fmtstr, var->ll);
+              lib_stream_putc(s, c);
+              ret++;
+              continue;
             }
-#endif
-          else if (*(p - 2) == 'l')
+
+          if (!infmt)
             {
-              offset += sizeof(var->l);
-              ret += lib_sprintf(s, fmtstr, var->l);
+              len = 0;
+              infmt = true;
+              memset(fmtstr, 0, sizeof(fmtstr));
             }
-          else if (*(p - 2) == 'z')
+
+          var = (FAR void *)(note->npt_data + offset);
+          fmtstr[len++] = c;
+
+          if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
+              c == 'o' || c == 'x' || c == 'X')
             {
-              offset += sizeof(var->sz);
-              ret += lib_sprintf(s, fmtstr, var->sz);
+              if (*(p - 2) == 'j')
+                {
+                  offset += sizeof(var->im);
+                  ret += lib_sprintf(s, fmtstr, var->im);
+                }
+#ifdef CONFIG_HAVE_LONG_LONG
+              else if (*(p - 2) == 'l' && *(p - 3) == 'l')
+                {
+                  offset += sizeof(var->ll);
+                  ret += lib_sprintf(s, fmtstr, var->ll);
+                }
+#endif
+              else if (*(p - 2) == 'l')
+                {
+                  offset += sizeof(var->l);
+                  ret += lib_sprintf(s, fmtstr, var->l);
+                }
+              else if (*(p - 2) == 'z')
+                {
+                  offset += sizeof(var->sz);
+                  ret += lib_sprintf(s, fmtstr, var->sz);
+                }
+              else if (*(p - 2) == 't')
+                {
+                  offset += sizeof(var->pd);
+                  ret += lib_sprintf(s, fmtstr, var->pd);
+                }
+              else
+                {
+                  offset += sizeof(var->i);
+                  ret += lib_sprintf(s, fmtstr, var->i);
+                }
+
+              infmt = false;
             }
-          else if (*(p - 2) == 't')
+          else if (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
+                  c == 'A' || c == 'E' || c == 'F' || c == 'G')
             {
-              offset += sizeof(var->pd);
-              ret += lib_sprintf(s, fmtstr, var->pd);
+#ifdef CONFIG_HAVE_DOUBLE
+#  ifdef CONFIG_HAVE_LONG_DOUBLE
+              if (*(p - 2) == 'L')
+                {
+                  offset += sizeof(var->ld);
+                  ret += lib_sprintf(s, fmtstr, var->ld);
+                }
+              else
+#  endif
+                {
+                  offset += sizeof(var->d);
+                  ret += lib_sprintf(s, fmtstr, var->d);
+                }
+
+              infmt = false;
             }
-          else
+#endif
+          else if (c == '*')
             {
+              itoa(var->i, fmtstr + len - 1, 10);
+              len = strlen(fmtstr);
               offset += sizeof(var->i);
-              ret += lib_sprintf(s, fmtstr, var->i);
             }
-
-          infmt = false;
-        }
-      else if (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
-              c == 'A' || c == 'E' || c == 'F' || c == 'G')
-        {
-#ifdef CONFIG_HAVE_DOUBLE
-#  ifdef CONFIG_HAVE_LONG_DOUBLE
-          if (*(p - 2) == 'L')
+          else if (c == 's')
             {
-              offset += sizeof(var->ld);
-              ret += lib_sprintf(s, fmtstr, var->ld);
+              const char *str = note->npt_data + offset;
+              offset += strlen(str) + 1;
+              ret += lib_sprintf(s, fmtstr, str);
+              infmt = false;
             }
-          else
-#  endif
+          else if (c == 'p')
             {
-              offset += sizeof(var->d);
-              ret += lib_sprintf(s, fmtstr, var->d);
+              offset += sizeof(var->p);
+              ret += lib_sprintf(s, fmtstr, var->p);
+              infmt = false;
             }
-
-          infmt = false;
         }
-#endif
-      else if (c == '*')
+
+      if (*(p - 2) != '\n')
         {
-          itoa(var->i, fmtstr + len - 1, 10);
-          len = strlen(fmtstr);
-          offset += sizeof(var->i);
+          lib_stream_putc(s, '\n');
+          ret++;
         }
-      else if (c == 's')
+    }
+  else
+    {
+      size_t count = NOTE_PRINTF_GET_COUNT(note->npt_type);
+      size_t i;
+
+      len = strlen(note->npt_fmt);
+      if (note->npt_fmt[len - 1] == '\n')
         {
-          FAR const char *value = data + offset;
-          offset += strlen(value) + 1;
-          ret += lib_sprintf(s, fmtstr, value);
-          infmt = false;
+          len--;
         }
-      else if (c == 'p')
+
+      ret += lib_sprintf(s, "%p", note->npt_fmt);
+      for (i = 0; i < count; i++)
         {
-          offset += sizeof(var->p);
-          ret += lib_sprintf(s, fmtstr, var->p);
-          infmt = false;
+          int type = NOTE_PRINTF_GET_TYPE(note->npt_type, i);
+          var = (FAR void *)(note->npt_data + offset);
+
+          switch (type)
+            {
+              case NOTE_PRINTF_UINT32:
+                {
+                  offset += sizeof(var->i);
+                  ret += lib_sprintf(s, " %u", var->i);
+                }
+                break;
+              case NOTE_PRINTF_UINT64:
+                {
+                  offset += sizeof(var->ll);
+                  ret += lib_sprintf(s, " %llu", var->ll);
+                }
+                break;
+              case NOTE_PRINTF_STRING:
+                {
+                  const char *str = note->npt_data + offset;
+                  offset += strlen(str) + 1;
+                  ret += lib_sprintf(s, " %s", str);
+                }
+                break;
+              case NOTE_PRINTF_DOUBLE:
+                {
+                  offset += sizeof(var->d);
+                  ret += lib_sprintf(s, " %f", var->d);
+                }
+            }
         }
-    }
 
-  if (*(p - 2) != '\n')
-    {
-      lib_stream_putc(s, '\n');
-      ret++;
+        lib_stream_putc(s, '\n');
+        ret++;
     }
 
   return ret;
diff --git a/include/nuttx/compiler.h b/include/nuttx/compiler.h
index dc994002e4..4658e26aff 100644
--- a/include/nuttx/compiler.h
+++ b/include/nuttx/compiler.h
@@ -172,7 +172,7 @@
  * unnecessary "weak" functions can be excluded from the link.
  */
 
-#undef CONFIG_HAVE_WEAKFUNCTIONS
+#  undef CONFIG_HAVE_WEAKFUNCTIONS
 
 #  if !defined(__CYGWIN__) && !defined(CONFIG_ARCH_GNU_NO_WEAKFUNCTIONS)
 #    define CONFIG_HAVE_WEAKFUNCTIONS 1
@@ -344,6 +344,7 @@
 #  define syslog_like(a, b) __attribute__((__format__(__syslog__, a, b)))
 #  define scanf_like(a, b) __attribute__((__format__(__scanf__, a, b)))
 #  define strftime_like(a) __attribute__((__format__(__strftime__, a, 0)))
+#  define object_size(o, t) __builtin_object_size(o, t)
 
 /* GCC does not use storage classes to qualify addressing */
 
@@ -612,6 +613,7 @@
 #  define syslog_like(a, b)
 #  define scanf_like(a, b)
 #  define strftime_like(a)
+#  define object_size(o, t) ((size_t)-1)
 
 /* The reentrant attribute informs SDCC that the function
  * must be reentrant.  In this case, SDCC will store input
@@ -756,6 +758,7 @@
 #  define syslog_like(a, b)
 #  define scanf_like(a, b)
 #  define strftime_like(a)
+#  define object_size(o, t) ((size_t)-1)
 
 /* REVISIT: */
 
@@ -871,6 +874,7 @@
 #  define syslog_like(a, b)
 #  define scanf_like(a, b)
 #  define strftime_like(a)
+#  define object_size(o, t) ((size_t)-1)
 
 #  define FAR
 #  define NEAR
@@ -1049,6 +1053,7 @@
 #  define syslog_like(a, b)
 #  define scanf_like(a, b)
 #  define strftime_like(a)
+#  define object_size(o, t) ((size_t)-1)
 
 #  define FAR
 #  define NEAR
@@ -1118,6 +1123,7 @@
 #  define syslog_like(a, b)
 #  define scanf_like(a, b)
 #  define strftime_like(a)
+#  define object_size(o, t) ((size_t)-1)
 
 #  define FAR
 #  define NEAR
diff --git a/include/nuttx/macro.h b/include/nuttx/macro.h
new file mode 100644
index 0000000000..c9c2481430
--- /dev/null
+++ b/include/nuttx/macro.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+ * include/nuttx/macro.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_MACRO_H
+#define __INCLUDE_NUTTX_MACRO_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define GET_ARG_VALUE(_00, _01, _02, _03, _04, _05, _06, _07, \
+                      _08, _09, _10, _11, _12, _13, _14, _15, \
+                      _16, _17, _18, _19, _20, _21, _22, _23, \
+                      _24, _25, _26, _27, _28, _29, _30, _31, \
+                      _32, name, ...) name
+
+/* Get the number of arguments (up to 32) */
+
+#define GET_ARG_COUNT(...) \
+        GET_ARG_VALUE(_0, ##__VA_ARGS__, 32, 31, 30, \
+        29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
+        19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
+        9,  8,  7,  6,  5,  4,  3,  2,  1,  0)
+
+/* Reverse the arguments */
+
+#define EXPAND(x) x
+
+#define REVERSE_00()
+#define REVERSE_01(a)     a
+#define REVERSE_02(a,b)   b,a
+#define REVERSE_03(a,...) EXPAND(REVERSE_02(__VA_ARGS__)),a
+#define REVERSE_04(a,...) EXPAND(REVERSE_03(__VA_ARGS__)),a
+#define REVERSE_05(a,...) EXPAND(REVERSE_04(__VA_ARGS__)),a
+#define REVERSE_06(a,...) EXPAND(REVERSE_05(__VA_ARGS__)),a
+#define REVERSE_07(a,...) EXPAND(REVERSE_06(__VA_ARGS__)),a
+#define REVERSE_08(a,...) EXPAND(REVERSE_07(__VA_ARGS__)),a
+#define REVERSE_09(a,...) EXPAND(REVERSE_08(__VA_ARGS__)),a
+#define REVERSE_10(a,...) EXPAND(REVERSE_09(__VA_ARGS__)),a
+#define REVERSE_11(a,...) EXPAND(REVERSE_10(__VA_ARGS__)),a
+#define REVERSE_12(a,...) EXPAND(REVERSE_11(__VA_ARGS__)),a
+#define REVERSE_13(a,...) EXPAND(REVERSE_12(__VA_ARGS__)),a
+#define REVERSE_14(a,...) EXPAND(REVERSE_13(__VA_ARGS__)),a
+#define REVERSE_15(a,...) EXPAND(REVERSE_14(__VA_ARGS__)),a
+#define REVERSE_16(a,...) EXPAND(REVERSE_15(__VA_ARGS__)),a
+#define REVERSE_17(a,...) EXPAND(REVERSE_16(__VA_ARGS__)),a
+#define REVERSE_18(a,...) EXPAND(REVERSE_17(__VA_ARGS__)),a
+#define REVERSE_19(a,...) EXPAND(REVERSE_18(__VA_ARGS__)),a
+#define REVERSE_20(a,...) EXPAND(REVERSE_19(__VA_ARGS__)),a
+#define REVERSE_21(a,...) EXPAND(REVERSE_20(__VA_ARGS__)),a
+#define REVERSE_22(a,...) EXPAND(REVERSE_21(__VA_ARGS__)),a
+#define REVERSE_23(a,...) EXPAND(REVERSE_22(__VA_ARGS__)),a
+#define REVERSE_24(a,...) EXPAND(REVERSE_23(__VA_ARGS__)),a
+#define REVERSE_25(a,...) EXPAND(REVERSE_24(__VA_ARGS__)),a
+#define REVERSE_26(a,...) EXPAND(REVERSE_25(__VA_ARGS__)),a
+#define REVERSE_27(a,...) EXPAND(REVERSE_26(__VA_ARGS__)),a
+#define REVERSE_28(a,...) EXPAND(REVERSE_27(__VA_ARGS__)),a
+#define REVERSE_29(a,...) EXPAND(REVERSE_28(__VA_ARGS__)),a
+#define REVERSE_30(a,...) EXPAND(REVERSE_29(__VA_ARGS__)),a
+#define REVERSE_31(a,...) EXPAND(REVERSE_30(__VA_ARGS__)),a
+#define REVERSE_32(a,...) EXPAND(REVERSE_31(__VA_ARGS__)),a
+
+#define REVERSE_ARG_(...) \
+        GET_ARG_VALUE(0, ##__VA_ARGS__, \
+        REVERSE_32, REVERSE_31, REVERSE_30, REVERSE_29, REVERSE_28, 
REVERSE_27, \
+        REVERSE_26, REVERSE_25, REVERSE_24, REVERSE_23, REVERSE_22, 
REVERSE_21, \
+        REVERSE_20, REVERSE_19, REVERSE_18, REVERSE_17, REVERSE_16, 
REVERSE_15, \
+        REVERSE_14, REVERSE_13, REVERSE_12, REVERSE_11, REVERSE_10, 
REVERSE_09, \
+        REVERSE_08, REVERSE_07, REVERSE_06, REVERSE_05, REVERSE_04, 
REVERSE_03, \
+        REVERSE_02, REVERSE_01, REVERSE_00)(__VA_ARGS__)
+
+#define REVERSE_ARG(...) REVERSE_ARG_(##__VA_ARGS__)
+
+/* Apply the macro to each argument */
+
+#define FOREACH_00(action, count, ...)      0
+#define FOREACH_01(action, count, arg, ...) action(arg, count - 1 )
+#define FOREACH_02(action, count, arg, ...) action(arg, count - 2 ) 
FOREACH_01(action, count, __VA_ARGS__)
+#define FOREACH_03(action, count, arg, ...) action(arg, count - 3 ) 
FOREACH_02(action, count, __VA_ARGS__)
+#define FOREACH_04(action, count, arg, ...) action(arg, count - 4 ) 
FOREACH_03(action, count, __VA_ARGS__)
+#define FOREACH_05(action, count, arg, ...) action(arg, count - 5 ) 
FOREACH_04(action, count, __VA_ARGS__)
+#define FOREACH_06(action, count, arg, ...) action(arg, count - 6 ) 
FOREACH_05(action, count, __VA_ARGS__)
+#define FOREACH_07(action, count, arg, ...) action(arg, count - 7 ) 
FOREACH_06(action, count, __VA_ARGS__)
+#define FOREACH_08(action, count, arg, ...) action(arg, count - 8 ) 
FOREACH_07(action, count, __VA_ARGS__)
+#define FOREACH_09(action, count, arg, ...) action(arg, count - 9 ) 
FOREACH_08(action, count, __VA_ARGS__)
+#define FOREACH_10(action, count, arg, ...) action(arg, count - 10) 
FOREACH_09(action, count, __VA_ARGS__)
+#define FOREACH_11(action, count, arg, ...) action(arg, count - 11) 
FOREACH_10(action, count, __VA_ARGS__)
+#define FOREACH_12(action, count, arg, ...) action(arg, count - 12) 
FOREACH_11(action, count, __VA_ARGS__)
+#define FOREACH_13(action, count, arg, ...) action(arg, count - 13) 
FOREACH_12(action, count, __VA_ARGS__)
+#define FOREACH_14(action, count, arg, ...) action(arg, count - 14) 
FOREACH_13(action, count, __VA_ARGS__)
+#define FOREACH_15(action, count, arg, ...) action(arg, count - 15) 
FOREACH_14(action, count, __VA_ARGS__)
+#define FOREACH_16(action, count, arg, ...) action(arg, count - 16) 
FOREACH_15(action, count, __VA_ARGS__)
+#define FOREACH_17(action, count, arg, ...) action(arg, count - 17) 
FOREACH_16(action, count, __VA_ARGS__)
+#define FOREACH_18(action, count, arg, ...) action(arg, count - 18) 
FOREACH_17(action, count, __VA_ARGS__)
+#define FOREACH_19(action, count, arg, ...) action(arg, count - 19) 
FOREACH_18(action, count, __VA_ARGS__)
+#define FOREACH_20(action, count, arg, ...) action(arg, count - 20) 
FOREACH_19(action, count, __VA_ARGS__)
+#define FOREACH_21(action, count, arg, ...) action(arg, count - 21) 
FOREACH_20(action, count, __VA_ARGS__)
+#define FOREACH_22(action, count, arg, ...) action(arg, count - 22) 
FOREACH_21(action, count, __VA_ARGS__)
+#define FOREACH_23(action, count, arg, ...) action(arg, count - 23) 
FOREACH_22(action, count, __VA_ARGS__)
+#define FOREACH_24(action, count, arg, ...) action(arg, count - 24) 
FOREACH_23(action, count, __VA_ARGS__)
+#define FOREACH_25(action, count, arg, ...) action(arg, count - 25) 
FOREACH_24(action, count, __VA_ARGS__)
+#define FOREACH_26(action, count, arg, ...) action(arg, count - 26) 
FOREACH_25(action, count, __VA_ARGS__)
+#define FOREACH_27(action, count, arg, ...) action(arg, count - 27) 
FOREACH_26(action, count, __VA_ARGS__)
+#define FOREACH_28(action, count, arg, ...) action(arg, count - 28) 
FOREACH_27(action, count, __VA_ARGS__)
+#define FOREACH_29(action, count, arg, ...) action(arg, count - 29) 
FOREACH_28(action, count, __VA_ARGS__)
+#define FOREACH_30(action, count, arg, ...) action(arg, count - 30) 
FOREACH_29(action, count, __VA_ARGS__)
+#define FOREACH_31(action, count, arg, ...) action(arg, count - 31) 
FOREACH_30(action, count, __VA_ARGS__)
+#define FOREACH_32(action, count, arg, ...) action(arg, count - 32) 
FOREACH_31(action, count, __VA_ARGS__)
+
+#define FOREACH_ARG_(action, count, ...) \
+        GET_ARG_VALUE(0, ##__VA_ARGS__, \
+        FOREACH_32, FOREACH_31, FOREACH_30, FOREACH_29, FOREACH_28, 
FOREACH_27, \
+        FOREACH_26, FOREACH_25, FOREACH_24, FOREACH_23, FOREACH_22, 
FOREACH_21, \
+        FOREACH_20, FOREACH_19, FOREACH_18, FOREACH_17, FOREACH_16, 
FOREACH_15, \
+        FOREACH_14, FOREACH_13, FOREACH_12, FOREACH_11, FOREACH_10, 
FOREACH_09, \
+        FOREACH_08, FOREACH_07, FOREACH_06, FOREACH_05, FOREACH_04, 
FOREACH_03, \
+        FOREACH_02, FOREACH_01, FOREACH_00)(action, count, ##__VA_ARGS__)
+
+#define FOREACH_ARG(action, ...) \
+        FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), ##__VA_ARGS__)
+
+#endif /* __INCLUDE_NUTTX_MACRO_H */
+
diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h
index 50d587ddb5..305bad308e 100644
--- a/include/nuttx/sched_note.h
+++ b/include/nuttx/sched_note.h
@@ -32,6 +32,7 @@
 #include <stdbool.h>
 #include <stdarg.h>
 
+#include <nuttx/macro.h>
 #include <nuttx/sched.h>
 #include <nuttx/spinlock.h>
 
@@ -125,15 +126,83 @@
 #  define NOTE_FILTER_TAGMASK_ZERO(s)
 #endif
 
+/* Printf argument type */
+
+#define NOTE_PRINTF_UINT32 0
+#define NOTE_PRINTF_UINT64 1
+#define NOTE_PRINTF_DOUBLE 2
+#define NOTE_PRINTF_STRING 3
+
+/* Get/set printf tag. each parameter occupies 2 bits. The highest
+ * four bits are used to represent the number of parameters, So up to
+ * 14 variable arguments can be passed.
+ */
+
+#define NOTE_PRINTF_GET_TYPE(tag, index) (((tag) >> (index) * 2) & 0x03)
+#define NOTE_PRINTF_GET_COUNT(tag)       (((tag) >> 28) & 0x0f)
+
+/* Check if a variable is 32-bit or 64-bit */
+
+#define NOTE_PRINTF_INT_TYPE(arg) (sizeof((arg) + 0) <= sizeof(uint32_t) ? \
+                                   NOTE_PRINTF_UINT32 : NOTE_PRINTF_UINT64)
+
+/* Use object_size to mark strings of known size */
+
+#define NOTE_PRINTF_OBJECT_SIZE(arg) object_size((FAR void *)(uintptr_t)(arg), 
2)
+
+/* Use _Generic to determine the type of the parameter */
+
+#define NOTE_PRINTF_ARG_TYPE(__arg__) \
+        _Generic((__arg__) + 0, \
+                 float : NOTE_PRINTF_DOUBLE, \
+                 double: NOTE_PRINTF_DOUBLE, \
+                 char *: ({NOTE_PRINTF_OBJECT_SIZE(__arg__) > 0 ? \
+                         NOTE_PRINTF_STRING : \
+                         NOTE_PRINTF_INT_TYPE(__arg__);}), \
+                 const char *: ({NOTE_PRINTF_OBJECT_SIZE(__arg__) > 0 ? \
+                               NOTE_PRINTF_STRING : \
+                               NOTE_PRINTF_INT_TYPE(__arg__);}), \
+                 default: NOTE_PRINTF_INT_TYPE(__arg__))
+
+/* Set the type of each parameter */
+
+#define NOTE_PRINTF_TYPE(arg, index) + ((NOTE_PRINTF_ARG_TYPE(arg) << (index) 
* 2))
+#define NOTE_PRINTF_TYPES(...)       FOREACH_ARG(NOTE_PRINTF_TYPE, 
##__VA_ARGS__)
+
+/* Using macro expansion to calculate the expression of tag, tag will
+ * be a constant at compile time, which will reduce the number of
+ * size in the code.
+ */
+
+#define NOTE_PRINTF_TAG(...) \
+        ((GET_ARG_COUNT(__VA_ARGS__) << 28) + NOTE_PRINTF_TYPES(__VA_ARGS__))
+
 #define SCHED_NOTE_IP \
         ({ __label__ __here; __here: (unsigned long)&&__here; })
 
 #define sched_note_event(tag, event, buf, len) \
         sched_note_event_ip(tag, SCHED_NOTE_IP, event, buf, len)
 #define sched_note_vprintf(tag, fmt, va) \
-        sched_note_vprintf_ip(tag, SCHED_NOTE_IP, fmt, va)
-#define sched_note_printf(tag, fmt, ...) \
-        sched_note_printf_ip(tag, SCHED_NOTE_IP, fmt, ##__VA_ARGS__)
+        sched_note_vprintf_ip(tag, SCHED_NOTE_IP, fmt, 0, va)
+
+#ifdef CONFIG_DRIVERS_NOTE_STRIP_FORMAT
+#  define sched_note_printf(tag, fmt, ...) \
+          do \
+            { \
+              static const locate_data(".printf_format") \
+              char __fmt__[] = fmt; \
+              uint32_t __type__ = NOTE_PRINTF_TAG(__VA_ARGS__); \
+              static_assert(GET_ARG_COUNT(__VA_ARGS__) <= 14, \
+                            "The number of sched_note_nprintf " \
+                            "parameters needs to be less than 14"); \
+              sched_note_printf_ip(tag, SCHED_NOTE_IP, __fmt__, \
+                                   __type__, ##__VA_ARGS__); \
+            } \
+          while (0)
+#else
+#  define sched_note_printf(tag, fmt, ...) \
+          sched_note_printf_ip(tag, SCHED_NOTE_IP, fmt, 0, ##__VA_ARGS__)
+#endif
 
 #define sched_note_begin(tag) \
         sched_note_event(tag, NOTE_DUMP_BEGIN, NULL, 0)
@@ -410,6 +479,7 @@ struct note_printf_s
   struct note_common_s npt_cmn; /* Common note parameters */
   uintptr_t npt_ip;             /* Instruction pointer called from */
   FAR const char *npt_fmt;      /* Printf format string */
+  uint32_t npt_type;            /* Printf parameter type */
   char npt_data[1];             /* Print arguments */
 };
 
@@ -585,13 +655,13 @@ void sched_note_heap(uint8_t event, FAR void *heap, FAR 
void *mem,
 void sched_note_event_ip(uint32_t tag, uintptr_t ip, uint8_t event,
                          FAR const void *buf, size_t len);
 void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
-                           va_list va) printf_like(3, 0);
-void sched_note_printf_ip(uint32_t tag, uintptr_t ip,
-                          FAR const char *fmt, ...) printf_like(3, 4);
+                           uint32_t type, va_list va) printf_like(3, 0);
+void sched_note_printf_ip(uint32_t tag, uintptr_t ip, FAR const char *fmt,
+                          uint32_t type, ...) printf_like(3, 5);
 #else
 #  define sched_note_event_ip(t,ip,e,b,l)
-#  define sched_note_vprintf_ip(t,ip,f,v)
-#  define sched_note_printf_ip(t,ip,f,...)
+#  define sched_note_vprintf_ip(t,ip,f,p,v)
+#  define sched_note_printf_ip(t,ip,f,p,...)
 #endif /* CONFIG_SCHED_INSTRUMENTATION_DUMP */
 
 #if defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT)
diff --git a/sched/Kconfig b/sched/Kconfig
index be765d9928..2dbbb0a588 100644
--- a/sched/Kconfig
+++ b/sched/Kconfig
@@ -1307,8 +1307,8 @@ config SCHED_INSTRUMENTATION_DUMP
                Use note dump for instrumentation.
 
                        void sched_note_event_ip(uint32_t tag, uintptr_t ip, 
uint8_t event, FAR const void *buf, size_t len);
-                       void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, 
FAR const char *fmt, va_list va) printf_like(3, 0);
-                       void sched_note_printf_ip(uint32_t tag, uintptr_t ip, 
FAR const char *fmt, ...) printf_like(3, 4);
+                       void sched_note_vprintf_ip(uint32_t tag, uintptr_t ip, 
FAR const char *fmt, uint32_t type, va_list va) printf_like(3, 0);
+                       void sched_note_printf_ip(uint32_t tag, uintptr_t ip, 
FAR const char *fmt, uint32_t type, ...) printf_like(3, 5);
 
 config SCHED_INSTRUMENTATION_FUNCTION
        bool "Enable function auto-tracing"


Reply via email to