note: print without relying on format strings

Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
yinshengkai 2023-11-29 12:35:29 +08:00 committed by Xiang Xiao
parent 57a385a994
commit 5d8cdeaea8
7 changed files with 580 additions and 240 deletions

View File

@ -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---

View File

@ -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)
size_t count = NOTE_PRINTF_GET_COUNT(type);
size_t i;
for (i = 0; i < count; i++)
{
continue;
var = (FAR void *)&note->npt_data[next];
switch (NOTE_PRINTF_GET_TYPE(type, i))
{
case NOTE_PRINTF_UINT32:
{
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->ll = va_arg(va, long long);
next += sizeof(var->ll);
}
break;
case NOTE_PRINTF_STRING:
{
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;
}
next += sizeof(var->d);
}
break;
}
}
}
else
{
FAR const char *p = fmt;
bool infmt = false;
char c;
infmt = true;
var = (FAR void *)&note->npt_data[next];
if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
c == 'o' || c == 'x' || c == 'X')
while ((c = *p++) != '\0')
{
if (*(p - 2) == 'j')
if (c != '%' && !infmt)
{
if (next + sizeof(var->im) > length)
{
break;
}
var->im = va_arg(va, intmax_t);
next += sizeof(var->im);
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 (*(p - 2) == 'j')
{
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)
else if (*(p - 2) == 'l' && *(p - 3) == 'l')
{
break;
}
if (next + sizeof(var->ll) > length)
{
break;
}
var->ll = va_arg(va, long long);
next += sizeof(var->ll);
}
var->ll = va_arg(va, long long);
next += sizeof(var->ll);
}
#endif
else if (*(p - 2) == 'l')
{
if (next + sizeof(var->l) > length)
else if (*(p - 2) == 'l')
{
break;
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)
{
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->ptr = va_arg(va, ptrdiff_t);
next += sizeof(var->ptr);
}
else
{
if (next + sizeof(var->i) > length)
{
break;
}
var->i = va_arg(va, int);
next += sizeof(var->i);
}
var->l = va_arg(va, long);
next += sizeof(var->l);
infmt = false;
}
else if (*(p - 2) == 'z')
else if (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
c == 'A' || c == 'E' || c == 'F' || c == 'G')
{
if (next + sizeof(var->sz) > length)
#ifdef CONFIG_HAVE_DOUBLE
# ifdef CONFIG_HAVE_LONG_DOUBLE
if (*(p - 2) == 'L')
{
break;
}
if (next + sizeof(var->ld) > length)
{
break;
}
var->sz = va_arg(va, size_t);
next += sizeof(var->sz);
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 (*(p - 2) == 't')
else if (c == '*')
{
if (next + sizeof(var->ptr) > length)
{
break;
}
var->ptr = va_arg(va, ptrdiff_t);
next += sizeof(var->ptr);
}
else
{
if (next + sizeof(var->i) > length)
{
break;
}
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)
{
len = length - next;
}
strlcpy(note->npt_data + next, var->s, len);
next += len;
infmt = false;
}
else if (c == 'p')
{
if (next + sizeof(var->p) > length)
{
break;
}
var->ld = va_arg(va, long double);
next += sizeof(var->ld);
var->p = va_arg(va, FAR void *);
next += sizeof(var->p);
infmt = false;
}
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);
}
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;
}
}
@ -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);
}

View File

@ -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;
}
FAR const char *p = note->npt_fmt;
bool infmt = false;
char fmtstr[64];
char c;
if (!infmt)
while ((c = *p++) != '\0')
{
len = 0;
infmt = true;
memset(fmtstr, 0, sizeof(fmtstr));
}
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')
{
if (*(p - 2) == 'j')
if (c != '%' && !infmt)
{
offset += sizeof(var->im);
ret += lib_sprintf(s, fmtstr, var->im);
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;
if (c == 'c' || c == 'd' || c == 'i' || c == 'u' ||
c == 'o' || c == 'x' || c == 'X')
{
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);
}
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);
}
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 (c == 'e' || c == 'f' || c == 'g' || c == 'a' ||
c == 'A' || c == 'E' || c == 'F' || c == 'G')
{
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')
{
offset += sizeof(var->ld);
ret += lib_sprintf(s, fmtstr, var->ld);
}
else
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);
}
{
offset += sizeof(var->d);
ret += lib_sprintf(s, fmtstr, var->d);
}
infmt = false;
}
infmt = false;
}
#endif
else if (c == '*')
{
itoa(var->i, fmtstr + len - 1, 10);
len = strlen(fmtstr);
offset += sizeof(var->i);
else if (c == '*')
{
itoa(var->i, fmtstr + len - 1, 10);
len = strlen(fmtstr);
offset += sizeof(var->i);
}
else if (c == 's')
{
const char *str = note->npt_data + offset;
offset += strlen(str) + 1;
ret += lib_sprintf(s, fmtstr, str);
infmt = false;
}
else if (c == 'p')
{
offset += sizeof(var->p);
ret += lib_sprintf(s, fmtstr, var->p);
infmt = false;
}
}
else if (c == 's')
if (*(p - 2) != '\n')
{
FAR const char *value = data + offset;
offset += strlen(value) + 1;
ret += lib_sprintf(s, fmtstr, value);
infmt = false;
}
else if (c == 'p')
{
offset += sizeof(var->p);
ret += lib_sprintf(s, fmtstr, var->p);
infmt = false;
lib_stream_putc(s, '\n');
ret++;
}
}
if (*(p - 2) != '\n')
else
{
lib_stream_putc(s, '\n');
ret++;
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')
{
len--;
}
ret += lib_sprintf(s, "%p", note->npt_fmt);
for (i = 0; i < count; i++)
{
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);
}
}
}
lib_stream_putc(s, '\n');
ret++;
}
return ret;

View File

@ -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

140
include/nuttx/macro.h Normal file
View File

@ -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 */

View File

@ -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)

View File

@ -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"