lib: os: cbprintf: Extend API to support new packaging modes
Added new flags to packaging API: - CBPRINTF_PACKAGE_ADD_RO_STR_IDXS - when set, read-only string locations are appended to the package - CBPRINTF_PACKAGE_ADD_RW_STR_IDXS - when set, read-write string locations are appended to the package (instead of appending actual strings) - CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(n) - indicate that n first strings are known to be read only. Ignored in runtime packaging. Add function for copying packages with optional appending strings. Changed CBPRINTF_MUST_RUNTIME_PACKAGE to use same flags as packaging. Aligned logging and test to those changes. Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
parent
c31cb0075a
commit
c917e6c2ce
10 changed files with 532 additions and 158 deletions
|
@ -693,7 +693,7 @@ void log_generic(struct log_msg_ids src_level, const char *fmt, va_list ap,
|
|||
static inline void log2_generic(uint8_t level, const char *fmt, va_list ap)
|
||||
{
|
||||
z_log_msg2_runtime_vcreate(CONFIG_LOG_DOMAIN_ID, NULL, level,
|
||||
NULL, 0, fmt, ap);
|
||||
NULL, 0, 0, fmt, ap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -800,7 +800,7 @@ __syscall void z_log_hexdump_from_user(uint32_t src_level_val,
|
|||
} \
|
||||
if (IS_ENABLED(CONFIG_LOG2)) { \
|
||||
z_log_msg2_runtime_vcreate(CONFIG_LOG_DOMAIN_ID, _source, \
|
||||
_level, NULL, 0, _str, _valist); \
|
||||
_level, NULL, 0, 0, _str, _valist); \
|
||||
break; \
|
||||
} \
|
||||
uint16_t _id = \
|
||||
|
|
|
@ -192,21 +192,23 @@ enum z_log_msg2_mode {
|
|||
Z_LOG_MSG2_ALIGNMENT), \
|
||||
sizeof(uint32_t))
|
||||
|
||||
#define Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, _dlen, ...)\
|
||||
#define Z_LOG_MSG2_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, _dlen, ...) \
|
||||
do { \
|
||||
int _plen; \
|
||||
if (GET_ARG_N(1, __VA_ARGS__) == NULL) { \
|
||||
_plen = 0; \
|
||||
} else { \
|
||||
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
||||
0, __VA_ARGS__); \
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
struct log_msg2 *_msg; \
|
||||
Z_LOG_MSG2_ON_STACK_ALLOC(_msg, Z_LOG_MSG2_LEN(_plen, 0)); \
|
||||
if (_plen) { \
|
||||
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, \
|
||||
_plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
||||
0, __VA_ARGS__);\
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
__VA_ARGS__);\
|
||||
} \
|
||||
struct log_msg2_desc _desc = \
|
||||
Z_LOG_MSG_DESC_INITIALIZER(_domain_id, _level, \
|
||||
|
@ -217,10 +219,11 @@ do { \
|
|||
} while (0)
|
||||
|
||||
#ifdef CONFIG_LOG_SPEED
|
||||
#define Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, _level, ...) do { \
|
||||
#define Z_LOG_MSG2_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, _level, ...) do { \
|
||||
int _plen; \
|
||||
CBPRINTF_STATIC_PACKAGE(NULL, 0, _plen, Z_LOG_MSG2_ALIGN_OFFSET, \
|
||||
0, __VA_ARGS__); \
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
__VA_ARGS__); \
|
||||
size_t _msg_wlen = Z_LOG_MSG2_ALIGNED_WLEN(_plen, 0); \
|
||||
struct log_msg2 *_msg = z_log_msg2_alloc(_msg_wlen); \
|
||||
struct log_msg2_desc _desc = \
|
||||
|
@ -230,7 +233,8 @@ do { \
|
|||
if (_msg) { \
|
||||
CBPRINTF_STATIC_PACKAGE(_msg->data, _plen, _plen, \
|
||||
Z_LOG_MSG2_ALIGN_OFFSET, \
|
||||
0, __VA_ARGS__); \
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
z_log_msg2_finalize(_msg, (void *)_source, _desc, NULL); \
|
||||
} while (0)
|
||||
|
@ -333,6 +337,7 @@ do {\
|
|||
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__) \
|
||||
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
||||
_level, (uint8_t *)_data, _dlen,\
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
||||
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
||||
} while (0)
|
||||
|
@ -341,20 +346,22 @@ do {\
|
|||
_level, _data, _dlen, ...) \
|
||||
do { \
|
||||
Z_LOG_MSG2_STR_VAR(_fmt, ##__VA_ARGS__); \
|
||||
if (CBPRINTF_MUST_RUNTIME_PACKAGE(_cstr_cnt, 0, __VA_ARGS__)) { \
|
||||
if (CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
__VA_ARGS__)) { \
|
||||
LOG_MSG2_DBG("create runtime message\n");\
|
||||
z_log_msg2_runtime_create(_domain_id, (void *)_source, \
|
||||
_level, (uint8_t *)_data, _dlen,\
|
||||
CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(_cstr_cnt), \
|
||||
Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__));\
|
||||
_mode = Z_LOG_MSG2_MODE_RUNTIME; \
|
||||
} else if (IS_ENABLED(CONFIG_LOG_SPEED) && _try_0cpy && ((_dlen) == 0)) {\
|
||||
LOG_MSG2_DBG("create zero-copy message\n");\
|
||||
Z_LOG_MSG2_SIMPLE_CREATE(_domain_id, _source, \
|
||||
Z_LOG_MSG2_SIMPLE_CREATE(_cstr_cnt, _domain_id, _source, \
|
||||
_level, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
||||
_mode = Z_LOG_MSG2_MODE_ZERO_COPY; \
|
||||
} else { \
|
||||
LOG_MSG2_DBG("create on stack message\n");\
|
||||
Z_LOG_MSG2_STACK_CREATE(_domain_id, _source, _level, _data, \
|
||||
Z_LOG_MSG2_STACK_CREATE(_cstr_cnt, _domain_id, _source, _level, _data, \
|
||||
_dlen, Z_LOG_FMT_ARGS(_fmt, ##__VA_ARGS__)); \
|
||||
_mode = Z_LOG_MSG2_MODE_FROM_STACK; \
|
||||
} \
|
||||
|
@ -461,7 +468,8 @@ __syscall void z_log_msg2_static_create(const void *source,
|
|||
*/
|
||||
__syscall void z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
||||
uint8_t level, const void *data,
|
||||
size_t dlen, const char *fmt,
|
||||
size_t dlen, uint32_t package_flags,
|
||||
const char *fmt,
|
||||
va_list ap);
|
||||
|
||||
/** @brief Create message at runtime.
|
||||
|
@ -486,13 +494,14 @@ __syscall void z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|||
static inline void z_log_msg2_runtime_create(uint8_t domain_id,
|
||||
const void *source,
|
||||
uint8_t level, const void *data,
|
||||
size_t dlen, const char *fmt, ...)
|
||||
size_t dlen, uint32_t package_flags,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
z_log_msg2_runtime_vcreate(domain_id, source, level,
|
||||
data, dlen, fmt, ap);
|
||||
data, dlen, package_flags, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,27 +69,76 @@ extern "C" {
|
|||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Assume that const char pointer a pointing to read only (constant) strings.
|
||||
*
|
||||
* Flag is valid only for @ref CBPRINTF_STATIC_PACKAGE.
|
||||
*/
|
||||
#define CBPRINTF_PACKAGE_CONST_CHAR_RO BIT(0)
|
||||
|
||||
/** @brief Append locations (within the package) of read-only string pointers.`*/
|
||||
#define CBPRINTF_PACKAGE_ADD_RO_STR_POS BIT(1)
|
||||
|
||||
/** @brief Append locations (within the package) of read-write string pointers.
|
||||
*
|
||||
* When this flag is not used then read-write strings are appended to the package.
|
||||
*/
|
||||
#define CBPRINTF_PACKAGE_ADD_RW_STR_POS BIT(2)
|
||||
|
||||
#define Z_CBPRINTF_PACKAGE_FIRST_RO_STR_BITS 3
|
||||
#define Z_CBPRINTF_PACKAGE_FIRST_RO_STR_OFFSET 3
|
||||
#define Z_CBPRINTF_PACKAGE_FIRST_RO_STR_MASK BIT_MASK(Z_CBPRINTF_PACKAGE_FIRST_RO_STR_BITS)
|
||||
|
||||
/** @brief Indicate that @p n first string format arguments are char pointers to
|
||||
* read-honly location.
|
||||
*
|
||||
* Runtime algorithm (address analysis) is skipped for those strings.
|
||||
*
|
||||
* @param n Number of string arguments considered as read-only.
|
||||
*/
|
||||
#define CBPRINTF_PACKAGE_FIRST_RO_STR_CNT(n) \
|
||||
(n << Z_CBPRINTF_PACKAGE_FIRST_RO_STR_OFFSET)
|
||||
|
||||
/** @brief Get number of first format string arguments which are known to be read-only
|
||||
* string.
|
||||
*/
|
||||
#define Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(flags) \
|
||||
(((flags) >> Z_CBPRINTF_PACKAGE_FIRST_RO_STR_OFFSET) & Z_CBPRINTF_PACKAGE_FIRST_RO_STR_MASK)
|
||||
|
||||
/** @brief Append indexes of read-only string arguments in the package.
|
||||
*
|
||||
* When used, package contains locations of read-only string arguments. Package
|
||||
* with that information can be converted to fully self-contain package using
|
||||
* @ref cbprintf_fsc_package.
|
||||
*/
|
||||
#define CBPRINTF_PACKAGE_ADD_STRING_IDXS BIT(0)
|
||||
#define CBPRINTF_PACKAGE_ADD_STRING_IDXS \
|
||||
(CBPRINTF_PACKAGE_ADD_RO_STR_POS | CBPRINTF_PACKAGE_CONST_CHAR_RO)
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@defgroup CBPRINTF_MUST_RUNTIME_PACKAGE_FLAGS Package flags.
|
||||
/**@defgroup CBPRINTF_PACKAGE_COPY_FLAGS Package flags.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @brief Consider constant string pointers as pointing to fixed strings.
|
||||
/** @brief Append read-only strings from source package to destination package.
|
||||
*
|
||||
* When flag is set then const (w)char pointers arguments in the string does
|
||||
* not trigger runtime packaging.
|
||||
* If package was created with @ref CBPRINTF_PACKAGE_ADD_RO_STR_POS
|
||||
* or @ref CBPRINTF_PACKAGE_ADD_RW_STR_POS it contains arrays of indexes where
|
||||
* string address can be found in the package. When flag is set, read-only strings
|
||||
* are copied into destination package. Address of strings indicated as read-write
|
||||
* are also checked and if determined to be read-only they are also copied.
|
||||
*/
|
||||
#define CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR BIT(0)
|
||||
#define CBPRINTF_PACKAGE_COPY_RO_STR BIT(0)
|
||||
|
||||
/** @brief Append read-write strings from source package to destination package.
|
||||
*
|
||||
* If package was created with @ref CBPRINTF_PACKAGE_ADD_RW_STR_POS it contains
|
||||
* arrays of indexes where string address can be found in the package. When flag
|
||||
* is set, list of read-write strings is examined and if they are not determined
|
||||
* to be read-only, they are copied into the destination package.
|
||||
* If @ref CBPRINTF_PACKAGE_COPY_RO_STR is not set, remaining string locations
|
||||
* are considered as pointing to read-only location.
|
||||
*/
|
||||
#define CBPRINTF_PACKAGE_COPY_RW_STR BIT(1)
|
||||
/**@} */
|
||||
|
||||
/** @brief Signature for a cbprintf callback function.
|
||||
|
@ -141,20 +190,16 @@ typedef int (*cbvprintf_exteral_formatter_func)(cbprintf_cb out, void *ctx,
|
|||
*
|
||||
* @note By default any char pointers are considered to be pointing at transient
|
||||
* strings. This can be narrowed down to non const pointers by using
|
||||
* @ref CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR.
|
||||
*
|
||||
* @param skip number of read only string arguments in the parameter list. It
|
||||
* shall be non-zero if there are known read only string arguments present
|
||||
* in the string (e.g. function name prefix in the log message).
|
||||
* @ref CBPRINTF_PACKAGE_CONST_CHAR_RO.
|
||||
*
|
||||
* @param ... String with arguments.
|
||||
* @param flags option flags. See @ref CBPRINTF_MUST_RUNTIME_PACKAGE_FLAGS.
|
||||
* @param flags option flags. See @ref CBPRINTF_PACKAGE_FLAGS.
|
||||
*
|
||||
* @retval 1 if string must be packaged in run time.
|
||||
* @retval 0 string can be statically packaged.
|
||||
*/
|
||||
#define CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ... /* fmt, ... */) \
|
||||
Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, __VA_ARGS__)
|
||||
#define CBPRINTF_MUST_RUNTIME_PACKAGE(flags, ... /* fmt, ... */) \
|
||||
Z_CBPRINTF_MUST_RUNTIME_PACKAGE(flags, __VA_ARGS__)
|
||||
|
||||
/** @brief Statically package string.
|
||||
*
|
||||
|
@ -277,17 +322,61 @@ int cbvprintf_package(void *packaged,
|
|||
const char *format,
|
||||
va_list ap);
|
||||
|
||||
/** @brief Copy package with optional appending of strings.
|
||||
*
|
||||
* Copying may including appending strings used in the package to the package body.
|
||||
* If input package was created with @ref CBPRINTF_PACKAGE_ADD_RO_STR_POS or
|
||||
* @ref CBPRINTF_PACKAGE_ADD_RW_STR_POS, it contains information where strings
|
||||
* are located within the package. This information can be used to copy strings
|
||||
* into the output package.
|
||||
*
|
||||
* @param in_packaged Input package.
|
||||
*
|
||||
* @param in_len Input package length. If 0 package length will be retrieved
|
||||
* from the @p in_packaged
|
||||
*
|
||||
* @param[out] packaged Output package. If null only length of the output package
|
||||
* is calculated.
|
||||
*
|
||||
* @param len Available space in the location pointed by @p packaged. Not used when
|
||||
* @p packaged is null.
|
||||
*
|
||||
* @param flags Flags. See @ref CBPRINTF_PACKAGE_COPY_FLAGS.
|
||||
*
|
||||
* @param[in, out] strl if @p packaged is null, it is a pointer to the array where
|
||||
* @p strl_len first string lengths will is stored. If @p packaged is not null,
|
||||
* it contains legths of first @p strl_len strings. It can be used to optimize
|
||||
* copying so that string length is calculated only once (at length calculation
|
||||
* phase when @p packaged is null.
|
||||
*
|
||||
* @param strl_len Number of elements in @p strl array.
|
||||
*
|
||||
* @retval Positive Output package size.
|
||||
* @retval -ENOSPC if @p packaged was not null and the space required to store
|
||||
* exceed @p len.
|
||||
*/
|
||||
int cbprintf_package_copy(void *in_packaged,
|
||||
size_t in_len,
|
||||
void *packaged,
|
||||
size_t len,
|
||||
uint32_t flags,
|
||||
uint16_t *strl,
|
||||
size_t strl_len);
|
||||
|
||||
/** @brief Convert package to fully self-contained (fsc) package.
|
||||
*
|
||||
* By default, package does not contain read only strings. However, if needed
|
||||
* it may be converted to a fully self-contained package which contains all
|
||||
* strings. In order to allow such conversion, original package must be created
|
||||
* with @ref CBPRINTF_PACKAGE_ADD_STRING_IDXS flag. Such package will contain
|
||||
* necessary data to find read only strings in the package and copy them into
|
||||
* package body.
|
||||
* Package may not be self contain since strings by default are stored by address.
|
||||
* Package may be partially self-contained when transient (not read only) strings
|
||||
* are appended to the package. Such package can be decoded only when there is an
|
||||
* access to read-only strings.
|
||||
*
|
||||
* Fully self-contained has (fsc) contains all strings used in the package. A package
|
||||
* can be converted to fsc package if it was create with @ref CBPRINTF_PACKAGE_ADD_RO_STR_POS
|
||||
* flag. Such package will contain necessary data to find read only strings in
|
||||
* the package and copy them into the package body.
|
||||
*
|
||||
* @param in_packaged pointer to original package created with
|
||||
* @ref CBPRINTF_PACKAGE_ADD_STRING_IDXS.
|
||||
* @ref CBPRINTF_PACKAGE_ADD_RO_STR_POS.
|
||||
*
|
||||
* @param in_len @p in_packaged length.
|
||||
*
|
||||
|
@ -303,10 +392,15 @@ int cbvprintf_package(void *packaged,
|
|||
* exceed @p len.
|
||||
* @retval -EINVAL if @p in_packaged is null.
|
||||
*/
|
||||
int cbprintf_fsc_package(void *in_packaged,
|
||||
size_t in_len,
|
||||
void *packaged,
|
||||
size_t len);
|
||||
static inline int cbprintf_fsc_package(void *in_packaged,
|
||||
size_t in_len,
|
||||
void *packaged,
|
||||
size_t len)
|
||||
{
|
||||
return cbprintf_package_copy(in_packaged, in_len, packaged, len,
|
||||
CBPRINTF_PACKAGE_COPY_RO_STR |
|
||||
CBPRINTF_PACKAGE_COPY_RW_STR, NULL, 0);
|
||||
}
|
||||
|
||||
/** @brief Generate the output for a previously captured format
|
||||
* operation using an external formatter.
|
||||
|
|
|
@ -86,22 +86,36 @@ extern "C" {
|
|||
*/
|
||||
#ifdef __cplusplus
|
||||
#define Z_CBPRINTF_IS_PCHAR(x, flags) \
|
||||
z_cbprintf_cxx_is_pchar(x, flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR)
|
||||
z_cbprintf_cxx_is_pchar(x, (flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO)
|
||||
#else
|
||||
#define Z_CBPRINTF_IS_PCHAR(x, flags) \
|
||||
_Generic((x) + 0, \
|
||||
char * : 1, \
|
||||
const char * : (flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR) ? 0 : 1, \
|
||||
const char * : ((flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) ? 0 : 1, \
|
||||
volatile char * : 1, \
|
||||
const volatile char * : 1, \
|
||||
wchar_t * : 1, \
|
||||
const wchar_t * : (flags & CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR) ? 0 : 1, \
|
||||
const wchar_t * : ((flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) ? 0 : 1, \
|
||||
volatile wchar_t * : 1, \
|
||||
const volatile wchar_t * : 1, \
|
||||
default : \
|
||||
0)
|
||||
#endif
|
||||
|
||||
/* @brief Check if argument is a certain type of char pointer. What exectly is checked
|
||||
* depends on @p flags. If flags is 0 then 1 is returned if @p x is a char pointer.
|
||||
*
|
||||
* @param idx Argument index.
|
||||
* @param x Argument.
|
||||
* @param flags Flags. See @p CBPRINTF_PACKAGE_FLAGS.
|
||||
*
|
||||
* @retval 1 if @p x is char pointer meeting criteria identified by @p flags.
|
||||
* @retval 0 otherwise.
|
||||
*/
|
||||
#define Z_CBPRINTF_IS_X_PCHAR(idx, x, flags) \
|
||||
(idx < Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(flags) ? \
|
||||
0 : Z_CBPRINTF_IS_PCHAR(x, flags))
|
||||
|
||||
/** @brief Calculate number of char * or wchar_t * arguments in the arguments.
|
||||
*
|
||||
* @param fmt string.
|
||||
|
@ -111,31 +125,36 @@ extern "C" {
|
|||
* @return number of arguments which are char * or wchar_t *.
|
||||
*/
|
||||
#define Z_CBPRINTF_HAS_PCHAR_ARGS(flags, fmt, ...) \
|
||||
(FOR_EACH_FIXED_ARG(Z_CBPRINTF_IS_PCHAR, (+), flags, __VA_ARGS__))
|
||||
(FOR_EACH_IDX_FIXED_ARG(Z_CBPRINTF_IS_X_PCHAR, (+), flags, __VA_ARGS__))
|
||||
|
||||
#define Z_CBPRINTF_PCHAR_COUNT(flags, ...) \
|
||||
COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
|
||||
(0), \
|
||||
(Z_CBPRINTF_HAS_PCHAR_ARGS(flags, __VA_ARGS__)))
|
||||
|
||||
/**
|
||||
* @brief Check if formatted string must be packaged in runtime.
|
||||
*
|
||||
* @param skip number of char/wchar_t pointers in the argument list which are
|
||||
* accepted for static packaging.
|
||||
*
|
||||
* @param ... String with arguments (fmt, ...).
|
||||
*
|
||||
* @retval 1 if string must be packaged at runtime.
|
||||
* @retval 0 if string can be statically packaged.
|
||||
*/
|
||||
#if Z_C_GENERIC
|
||||
#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...) ({\
|
||||
#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(flags, ...) ({\
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
|
||||
int _rv = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), \
|
||||
(0), \
|
||||
(((Z_CBPRINTF_HAS_PCHAR_ARGS(flags, __VA_ARGS__) - skip) > 0))); \
|
||||
int _rv; \
|
||||
if ((flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS) { \
|
||||
_rv = 0; \
|
||||
} else { \
|
||||
_rv = Z_CBPRINTF_PCHAR_COUNT(flags, __VA_ARGS__) > 0 ? 1 : 0; \
|
||||
} \
|
||||
_Pragma("GCC diagnostic pop")\
|
||||
_rv; \
|
||||
})
|
||||
#else
|
||||
#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...) 1
|
||||
#define Z_CBPRINTF_MUST_RUNTIME_PACKAGE(flags, ...) 1
|
||||
#endif
|
||||
|
||||
/** @brief Get storage size for given argument.
|
||||
|
@ -260,8 +279,7 @@ extern "C" {
|
|||
*
|
||||
* @param _arg argument.
|
||||
*/
|
||||
#define Z_CBPRINTF_PACK_ARG2(_buf, _idx, _align_offset, _max, \
|
||||
_cfg_flags, _s_idx, _s_buf, _arg) \
|
||||
#define Z_CBPRINTF_PACK_ARG2(arg_idx, _buf, _idx, _align_offset, _max, _arg) \
|
||||
do { \
|
||||
BUILD_ASSERT(!((sizeof(double) < VA_STACK_ALIGN(long double)) && \
|
||||
Z_CBPRINTF_IS_LONGDOUBLE(_arg) && \
|
||||
|
@ -272,8 +290,25 @@ do { \
|
|||
_align_offset += sizeof(int); \
|
||||
} \
|
||||
uint32_t _arg_size = Z_CBPRINTF_ARG_SIZE(_arg); \
|
||||
if (Z_CBPRINTF_IS_PCHAR(_arg, 0)) { \
|
||||
_s_buf[_s_idx++] = _idx / sizeof(int); \
|
||||
uint32_t _loc = _idx / sizeof(int); \
|
||||
if (arg_idx < 1 + _fros_cnt) { \
|
||||
if (_ros_pos_en) { \
|
||||
_ros_pos_buf[_ros_pos_idx++] = _loc; \
|
||||
} \
|
||||
} else if (Z_CBPRINTF_IS_PCHAR(_arg, 0)) { \
|
||||
if (_cros_en) { \
|
||||
if (Z_CBPRINTF_IS_X_PCHAR(arg_idx, _arg, _flags)) { \
|
||||
if (_rws_pos_en) { \
|
||||
_rws_buffer[_rws_pos_idx++] = _loc; \
|
||||
} \
|
||||
} else { \
|
||||
if (_ros_pos_en) { \
|
||||
_ros_pos_buf[_ros_pos_idx++] = _loc; \
|
||||
} \
|
||||
} \
|
||||
} else if (_rws_pos_en) { \
|
||||
_rws_buffer[_rws_pos_idx++] = _idx / sizeof(int); \
|
||||
} \
|
||||
} \
|
||||
if (_buf && _idx < (int)_max) { \
|
||||
Z_CBPRINTF_STORE_ARG(&_buf[_idx], _arg); \
|
||||
|
@ -288,9 +323,8 @@ do { \
|
|||
*
|
||||
* @param arg argument.
|
||||
*/
|
||||
#define Z_CBPRINTF_PACK_ARG(arg) \
|
||||
Z_CBPRINTF_PACK_ARG2(_pbuf, _pkg_len, _pkg_offset, _pmax, _flags, \
|
||||
_s_cnt, _s_buffer, arg)
|
||||
#define Z_CBPRINTF_PACK_ARG(arg_idx, arg) \
|
||||
Z_CBPRINTF_PACK_ARG2(arg_idx, _pbuf, _pkg_len, _pkg_offset, _pmax, arg)
|
||||
|
||||
/** @brief Package descriptor.
|
||||
*
|
||||
|
@ -300,8 +334,9 @@ do { \
|
|||
*/
|
||||
struct z_cbprintf_desc {
|
||||
uint8_t len;
|
||||
uint8_t str_cnt;
|
||||
uint8_t ro_str_cnt;
|
||||
uint8_t str_cnt; /* Number of appended strings in the package. */
|
||||
uint8_t ro_str_cnt; /* Number of read-only strings, indexes appended to the package.*/
|
||||
uint8_t rw_str_cnt; /* Number of read-write strings, indexes appended to the package.*/
|
||||
};
|
||||
|
||||
/** @brief Package header. */
|
||||
|
@ -333,12 +368,12 @@ union z_cbprintf_hdr {
|
|||
* @param _align_offset Input buffer alignment offset in words. Where offset 0
|
||||
* means that buffer is aligned to CBPRINTF_PACKAGE_ALIGNMENT.
|
||||
*
|
||||
* @param _flags Option flags. See @ref CBPRINTF_PACKAGE_FLAGS.
|
||||
* @param flags Option flags. See @ref CBPRINTF_PACKAGE_FLAGS.
|
||||
*
|
||||
* @param ... String with variable list of arguments.
|
||||
*/
|
||||
#define Z_CBPRINTF_STATIC_PACKAGE_GENERIC(buf, _inlen, _outlen, _align_offset, \
|
||||
_flags, ... /* fmt, ... */) \
|
||||
flags, ... /* fmt, ... */) \
|
||||
do { \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wpointer-arith\"") \
|
||||
|
@ -352,15 +387,32 @@ do { \
|
|||
IF_ENABLED(CONFIG_CBPRINTF_STATIC_PACKAGE_CHECK_ALIGNMENT, \
|
||||
(__ASSERT(!((uintptr_t)buf & (CBPRINTF_PACKAGE_ALIGNMENT - 1)), \
|
||||
"Buffer must be aligned.");)) \
|
||||
bool str_idxs = _flags & CBPRINTF_PACKAGE_ADD_STRING_IDXS; \
|
||||
uint32_t _flags = flags; \
|
||||
bool _ros_pos_en = (_flags) & CBPRINTF_PACKAGE_ADD_RO_STR_POS; \
|
||||
bool _rws_pos_en = (_flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS; \
|
||||
bool _cros_en = (_flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO; \
|
||||
uint8_t *_pbuf = buf; \
|
||||
uint8_t _s_cnt = 0; \
|
||||
uint16_t _s_buffer[16]; \
|
||||
uint8_t _rws_pos_idx = 0; \
|
||||
uint8_t _ros_pos_idx = 0; \
|
||||
/* Variable holds count of all string pointer arguments. */ \
|
||||
uint8_t _alls_cnt = Z_CBPRINTF_PCHAR_COUNT(0, __VA_ARGS__); \
|
||||
uint8_t _fros_cnt = Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(_flags); \
|
||||
/* Variable holds count of non const string pointers. */ \
|
||||
uint8_t _rws_cnt = _cros_en ? \
|
||||
Z_CBPRINTF_PCHAR_COUNT(_flags, __VA_ARGS__) : _alls_cnt - _fros_cnt; \
|
||||
uint8_t _ros_cnt = 1 + _alls_cnt - _rws_cnt; \
|
||||
uint8_t _ros_pos_buf[_ros_pos_en ? _ros_cnt : 0]; \
|
||||
uint8_t _rws_buffer[_rws_cnt]; \
|
||||
size_t _pmax = (buf != NULL) ? _inlen : INT32_MAX; \
|
||||
int _pkg_len = 0; \
|
||||
int _total_len = 0; \
|
||||
int _pkg_offset = _align_offset; \
|
||||
union z_cbprintf_hdr *_len_loc; \
|
||||
/* If string has rw string arguments CBPRINTF_PACKAGE_ADD_RW_STR_POS is a must. */ \
|
||||
if (_rws_cnt && !((_flags) & CBPRINTF_PACKAGE_ADD_RW_STR_POS)) { \
|
||||
_outlen = -EINVAL; \
|
||||
break; \
|
||||
} \
|
||||
/* package starts with string address and field with length */ \
|
||||
if (_pmax < sizeof(union z_cbprintf_hdr)) { \
|
||||
_outlen = -ENOSPC; \
|
||||
|
@ -370,14 +422,21 @@ do { \
|
|||
_pkg_len += sizeof(union z_cbprintf_hdr); \
|
||||
_pkg_offset += sizeof(union z_cbprintf_hdr); \
|
||||
/* Pack remaining arguments */\
|
||||
FOR_EACH(Z_CBPRINTF_PACK_ARG, (;), __VA_ARGS__);\
|
||||
FOR_EACH_IDX(Z_CBPRINTF_PACK_ARG, (;), __VA_ARGS__);\
|
||||
_total_len = _pkg_len; \
|
||||
if (str_idxs) {\
|
||||
_total_len += _s_cnt; \
|
||||
if (_pbuf) { \
|
||||
for (int i = 0; i < _s_cnt; i++) { \
|
||||
_pbuf[_pkg_len + i] = _s_buffer[i]; \
|
||||
} \
|
||||
/* Append string indexes to the package. */ \
|
||||
if (_ros_pos_en) { \
|
||||
_total_len += sizeof(_ros_pos_buf); \
|
||||
} \
|
||||
_total_len += sizeof(_rws_buffer); \
|
||||
if (_pbuf) { \
|
||||
/* Append string locations. */ \
|
||||
uint8_t *_pbuf_loc = &_pbuf[_pkg_len]; \
|
||||
for (size_t i = 0; i < sizeof(_ros_pos_buf); i++) { \
|
||||
*_pbuf_loc++ = _ros_pos_buf[i]; \
|
||||
} \
|
||||
for (size_t i = 0; i < sizeof(_rws_buffer); i++) { \
|
||||
*_pbuf_loc++ = _rws_buffer[i]; \
|
||||
} \
|
||||
} \
|
||||
/* Store length */ \
|
||||
|
@ -388,7 +447,8 @@ do { \
|
|||
.desc = { \
|
||||
.len = (uint8_t)(_pkg_len / sizeof(int)), \
|
||||
.str_cnt = 0, \
|
||||
.ro_str_cnt = str_idxs ? _s_cnt : (uint8_t)0, \
|
||||
.ro_str_cnt = (uint8_t)sizeof(_ros_pos_buf), \
|
||||
.rw_str_cnt = (uint8_t)sizeof(_rws_buffer), \
|
||||
} \
|
||||
}; \
|
||||
*_len_loc = hdr; \
|
||||
|
|
|
@ -177,6 +177,62 @@ static int cbprintf_via_va_list(cbprintf_cb out,
|
|||
|
||||
#endif
|
||||
|
||||
static int z_strncpy(char *dst, const char *src, size_t num)
|
||||
{
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
dst[i] = src[i];
|
||||
if (src[i] == '\0') {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static size_t get_package_len(void *packaged)
|
||||
{
|
||||
__ASSERT_NO_MSG(packaged != NULL);
|
||||
|
||||
uint8_t *buf = packaged;
|
||||
uint8_t *start = buf;
|
||||
unsigned int args_size, s_nbr, ros_nbr;
|
||||
|
||||
args_size = buf[0] * sizeof(int);
|
||||
s_nbr = buf[1];
|
||||
ros_nbr = buf[2];
|
||||
|
||||
/* Move beyond args. */
|
||||
buf += args_size;
|
||||
|
||||
/* Move beyond read-only string indexes array. */
|
||||
buf += ros_nbr;
|
||||
|
||||
/* Move beyond strings appended to the package. */
|
||||
for (int i = 0; i < s_nbr; i++) {
|
||||
buf++;
|
||||
buf += strlen((const char *)buf) + 1;
|
||||
}
|
||||
|
||||
return (size_t)(uintptr_t)(buf - start);
|
||||
}
|
||||
|
||||
static int append_string(void *dst, size_t max, const char *str, uint16_t strl)
|
||||
{
|
||||
char *buf = dst;
|
||||
|
||||
if (dst == NULL) {
|
||||
return 1 + strlen(str);
|
||||
}
|
||||
|
||||
if (strl) {
|
||||
memcpy(dst, str, strl);
|
||||
|
||||
return strl;
|
||||
}
|
||||
|
||||
return z_strncpy(buf, str, max);
|
||||
}
|
||||
|
||||
int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
|
@ -202,6 +258,15 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags,
|
|||
unsigned int i;
|
||||
const char *s;
|
||||
bool parsing = false;
|
||||
/* Flag indicates that rw strings are stored as array with positions,
|
||||
* instead of appending them to the package.
|
||||
*/
|
||||
bool rws_pos_en = !!(flags & CBPRINTF_PACKAGE_ADD_RW_STR_POS);
|
||||
/* Get number of first read only strings present in the string.
|
||||
* There is always at least 1 (fmt) but flags can indicate more, e.g
|
||||
* fixed prefix appended to all strings.
|
||||
*/
|
||||
int fros_cnt = 1 + Z_CBPRINTF_PACKAGE_FIRST_RO_STR_CNT_GET(flags);
|
||||
|
||||
/* Buffer must be aligned at least to size of a pointer. */
|
||||
if ((uintptr_t)packaged % sizeof(void *)) {
|
||||
|
@ -413,21 +478,21 @@ process_string:
|
|||
*(const char **)buf = s;
|
||||
}
|
||||
|
||||
bool is_ro = ptr_in_rodata(s);
|
||||
bool do_all = !!(flags & CBPRINTF_PACKAGE_ADD_STRING_IDXS);
|
||||
bool is_ro = (fros_cnt-- > 0) ? true : ptr_in_rodata(s);
|
||||
bool do_ro = !!(flags & CBPRINTF_PACKAGE_ADD_RO_STR_POS);
|
||||
|
||||
if (is_ro && !do_all) {
|
||||
if (is_ro && !do_ro) {
|
||||
/* nothing to do */
|
||||
} else {
|
||||
uint32_t s_ptr_idx = BUF_OFFSET / sizeof(int);
|
||||
|
||||
/*
|
||||
* In the do_all case we must consider
|
||||
* In the do_ro case we must consider
|
||||
* room for possible STR_POS_RO_FLAG.
|
||||
* Otherwise the index range is 8 bits
|
||||
* and any overflow is caught later.
|
||||
*/
|
||||
if (do_all && s_ptr_idx > STR_POS_MASK) {
|
||||
if (do_ro && s_ptr_idx > STR_POS_MASK) {
|
||||
__ASSERT(false, "String with too many arguments");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -450,10 +515,10 @@ process_string:
|
|||
} else {
|
||||
s_rw_cnt++;
|
||||
}
|
||||
} else if (is_ro) {
|
||||
} else if (is_ro || rws_pos_en) {
|
||||
/*
|
||||
* Add only pointer position prefix
|
||||
* when counting read-only strings.
|
||||
* when counting strings.
|
||||
*/
|
||||
len += 1;
|
||||
} else {
|
||||
|
@ -520,9 +585,19 @@ process_string:
|
|||
/* Clear our buffer header. We made room for it initially. */
|
||||
*(char **)buf0 = NULL;
|
||||
|
||||
/* Record end of argument list and number of appended strings. */
|
||||
/* Record end of argument list. */
|
||||
buf0[0] = BUF_OFFSET / sizeof(int);
|
||||
buf0[1] = s_rw_cnt;
|
||||
|
||||
if (rws_pos_en) {
|
||||
/* Strings are appended, update location counter. */
|
||||
buf0[1] = 0;
|
||||
buf0[3] = s_rw_cnt;
|
||||
} else {
|
||||
/* Strings are appended, update append counter. */
|
||||
buf0[1] = s_rw_cnt;
|
||||
buf0[3] = 0;
|
||||
}
|
||||
|
||||
buf0[2] = s_ro_cnt;
|
||||
|
||||
/* Store strings pointer locations of read only strings. */
|
||||
|
@ -550,12 +625,17 @@ process_string:
|
|||
continue;
|
||||
}
|
||||
|
||||
/* retrieve the string pointer */
|
||||
s = *(char **)(buf0 + str_ptr_pos[i] * sizeof(int));
|
||||
/* clear the in-buffer pointer (less entropy if compressed) */
|
||||
*(char **)(buf0 + str_ptr_pos[i] * sizeof(int)) = NULL;
|
||||
/* find the string length including terminating '\0' */
|
||||
size = strlen(s) + 1;
|
||||
if (rws_pos_en) {
|
||||
size = 0;
|
||||
} else {
|
||||
/* retrieve the string pointer */
|
||||
s = *(char **)(buf0 + str_ptr_pos[i] * sizeof(int));
|
||||
/* clear the in-buffer pointer (less entropy if compressed) */
|
||||
*(char **)(buf0 + str_ptr_pos[i] * sizeof(int)) = NULL;
|
||||
/* find the string length including terminating '\0' */
|
||||
size = strlen(s) + 1;
|
||||
}
|
||||
|
||||
/* make sure it fits */
|
||||
if (BUF_OFFSET + 1 + size > len) {
|
||||
return -ENOSPC;
|
||||
|
@ -597,7 +677,7 @@ int cbpprintf_external(cbprintf_cb out,
|
|||
{
|
||||
uint8_t *buf = packaged;
|
||||
char *fmt, *s, **ps;
|
||||
unsigned int i, args_size, s_nbr, ros_nbr, s_idx;
|
||||
unsigned int i, args_size, s_nbr, ros_nbr, rws_nbr, s_idx;
|
||||
|
||||
if (buf == NULL) {
|
||||
return -EINVAL;
|
||||
|
@ -607,9 +687,10 @@ int cbpprintf_external(cbprintf_cb out,
|
|||
args_size = buf[0] * sizeof(int);
|
||||
s_nbr = buf[1];
|
||||
ros_nbr = buf[2];
|
||||
rws_nbr = buf[3];
|
||||
|
||||
/* Locate the string table */
|
||||
s = (char *)(buf + args_size + ros_nbr);
|
||||
s = (char *)(buf + args_size + ros_nbr + rws_nbr);
|
||||
|
||||
/*
|
||||
* Patch in string pointers.
|
||||
|
@ -634,64 +715,196 @@ int cbpprintf_external(cbprintf_cb out,
|
|||
return cbprintf_via_va_list(out, formatter, ctx, fmt, buf);
|
||||
}
|
||||
|
||||
int cbprintf_fsc_package(void *in_packaged,
|
||||
size_t in_len,
|
||||
void *packaged,
|
||||
size_t len)
|
||||
int cbprintf_package_copy(void *in_packaged,
|
||||
size_t in_len,
|
||||
void *packaged,
|
||||
size_t len,
|
||||
uint32_t flags,
|
||||
uint16_t *strl,
|
||||
size_t strl_len)
|
||||
{
|
||||
uint8_t *buf = in_packaged, *out = packaged;
|
||||
char **ps;
|
||||
unsigned int args_size, s_nbr, ros_nbr, s_idx;
|
||||
size_t out_len;
|
||||
size_t slen;
|
||||
__ASSERT_NO_MSG(in_packaged != NULL);
|
||||
|
||||
if (!buf) {
|
||||
return -EINVAL;
|
||||
}
|
||||
uint8_t *buf = in_packaged;
|
||||
uint32_t *buf32 = in_packaged;
|
||||
unsigned int args_size, ros_nbr, rws_nbr;
|
||||
bool rw_cpy;
|
||||
bool ro_cpy;
|
||||
|
||||
in_len != 0 ? in_len : get_package_len(in_packaged);
|
||||
|
||||
if (packaged && (len < in_len)) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* Retrieve the size of the arg list and number of strings. */
|
||||
args_size = buf[0] * sizeof(int);
|
||||
s_nbr = buf[1];
|
||||
ros_nbr = buf[2];
|
||||
/* Get number of RO string indexes in the package and check if copying
|
||||
* includes appending those strings.
|
||||
*/
|
||||
ros_nbr = buf[2];
|
||||
ro_cpy = ros_nbr &&
|
||||
(flags & CBPRINTF_PACKAGE_COPY_RO_STR) == CBPRINTF_PACKAGE_COPY_RO_STR;
|
||||
|
||||
out_len = in_len;
|
||||
/* Get number of RW string indexes in the package and check if copying
|
||||
* includes appending those strings.
|
||||
*/
|
||||
rws_nbr = buf[3];
|
||||
rw_cpy = rws_nbr > 0 &&
|
||||
(flags & CBPRINTF_PACKAGE_COPY_RW_STR) == CBPRINTF_PACKAGE_COPY_RW_STR;
|
||||
|
||||
if (packaged) {
|
||||
unsigned int rw_strs_len = in_len - (args_size + ros_nbr);
|
||||
|
||||
memcpy(out, buf, args_size);
|
||||
out[1] = s_nbr + ros_nbr;
|
||||
out[2] = 0;
|
||||
out += args_size;
|
||||
/* If flags are not set or appending request without rw string indexes
|
||||
* present is chosen, just do a simple copy (or length calculation).
|
||||
* Assuming that it is the most common case.
|
||||
*/
|
||||
if (!rw_cpy && !ro_cpy) {
|
||||
if (packaged) {
|
||||
memcpy(packaged, in_packaged, in_len);
|
||||
}
|
||||
|
||||
/* Append all strings that were already part of the package. */
|
||||
memcpy(out, &buf[args_size + ros_nbr], rw_strs_len);
|
||||
out += rw_strs_len;
|
||||
return in_len;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < ros_nbr; i++) {
|
||||
/* Get string address location */
|
||||
s_idx = buf[args_size + i];
|
||||
ps = (char **)(buf + s_idx * sizeof(int));
|
||||
/* If we got here, it means that coping will be more complex and will be
|
||||
* done with strings appending.
|
||||
* Retrieve the size of the arg list.
|
||||
*/
|
||||
args_size = buf[0] * sizeof(int);
|
||||
|
||||
/* Get string length */
|
||||
slen = strlen(*ps) + 1;
|
||||
out_len += slen;
|
||||
size_t out_len = in_len;
|
||||
|
||||
/* Copy string into the buffer (if provided) and enough space. */
|
||||
if (packaged) {
|
||||
if (out_len > len) {
|
||||
return -ENOSPC;
|
||||
/* Pointer to array with string locations. Array starts with read-only
|
||||
* string locations.
|
||||
*/
|
||||
uint8_t *str_pos = &buf[args_size];
|
||||
size_t strl_cnt = 0;
|
||||
|
||||
/* If null destination, just calculate output length. */
|
||||
if (packaged == NULL) {
|
||||
if (ro_cpy) {
|
||||
for (int i = 0; i < ros_nbr; i++) {
|
||||
const char *str = *(const char **)&buf32[*str_pos];
|
||||
int len = append_string(NULL, 0, str, 0);
|
||||
|
||||
/* If possible store calculated string length. */
|
||||
if (strl && strl_cnt < strl_len) {
|
||||
strl[strl_cnt++] = (uint16_t)len;
|
||||
}
|
||||
out_len += len;
|
||||
str_pos++;
|
||||
}
|
||||
*out++ = s_idx;
|
||||
memcpy(out, *ps, slen);
|
||||
out += slen;
|
||||
} else {
|
||||
str_pos += ros_nbr;
|
||||
}
|
||||
|
||||
/* Handle RW strings. */
|
||||
for (int i = 0; i < rws_nbr; i++) {
|
||||
const char *str = *(const char **)&buf32[*str_pos];
|
||||
bool is_ro = ptr_in_rodata(str);
|
||||
|
||||
if ((is_ro && flags & CBPRINTF_PACKAGE_COPY_RO_STR) ||
|
||||
(!is_ro && flags & CBPRINTF_PACKAGE_COPY_RW_STR)) {
|
||||
int len = append_string(NULL, 0, str, 0);
|
||||
|
||||
/* If possible store calculated string length. */
|
||||
if (strl && strl_cnt < strl_len) {
|
||||
strl[strl_cnt++] = (uint16_t)len;
|
||||
}
|
||||
out_len += len;
|
||||
}
|
||||
str_pos++;
|
||||
}
|
||||
|
||||
return out_len;
|
||||
}
|
||||
|
||||
uint8_t cpy_str_pos[16];
|
||||
uint8_t scpy_cnt;
|
||||
uint8_t *dst = packaged;
|
||||
uint8_t *dst_hdr = packaged;
|
||||
|
||||
memcpy(dst, in_packaged, args_size);
|
||||
dst += args_size;
|
||||
|
||||
/* If read-only strings shall be appended to the output package copy
|
||||
* their indexes to the local array, otherwise indicate that indexes
|
||||
* shall remain in the output package.
|
||||
*/
|
||||
if (ro_cpy) {
|
||||
memcpy(cpy_str_pos, str_pos, ros_nbr);
|
||||
scpy_cnt = ros_nbr;
|
||||
/* Read only string indexes removed from package. */
|
||||
dst_hdr[2] = 0;
|
||||
str_pos += ros_nbr;
|
||||
} else {
|
||||
scpy_cnt = 0;
|
||||
if (ros_nbr) {
|
||||
memcpy(dst, str_pos, ros_nbr);
|
||||
dst += ros_nbr;
|
||||
str_pos += ros_nbr;
|
||||
}
|
||||
}
|
||||
|
||||
return out_len;
|
||||
/* Go through read-write strings and identify which shall be appended.
|
||||
* Note that there may be read-only strings there. Use address evaluation
|
||||
* to determine if strings is read-only.
|
||||
*/
|
||||
for (int i = 0; i < rws_nbr; i++) {
|
||||
const char *str = *(const char **)&buf32[*str_pos];
|
||||
bool is_ro = ptr_in_rodata(str);
|
||||
|
||||
if ((is_ro && flags & CBPRINTF_PACKAGE_COPY_RO_STR) ||
|
||||
(!is_ro && flags & CBPRINTF_PACKAGE_COPY_RW_STR)) {
|
||||
cpy_str_pos[scpy_cnt++] = *str_pos;
|
||||
} else {
|
||||
*dst++ = *str_pos;
|
||||
}
|
||||
str_pos++;
|
||||
}
|
||||
|
||||
uint8_t out_str_pos_nbr = ros_nbr + rws_nbr - scpy_cnt;
|
||||
|
||||
/* Increment amount of strings appended to the package. */
|
||||
dst_hdr[1] += scpy_cnt;
|
||||
/* Update number of rw string locations in the package. */
|
||||
dst_hdr[3] = out_str_pos_nbr - dst_hdr[2];
|
||||
|
||||
/* Copy appended strings from source package to destination. */
|
||||
size_t strs_len = in_len - (args_size + ros_nbr + rws_nbr);
|
||||
|
||||
memcpy(dst, str_pos, strs_len);
|
||||
|
||||
dst += strs_len;
|
||||
|
||||
if (scpy_cnt == 0) {
|
||||
return dst - dst_hdr;
|
||||
}
|
||||
|
||||
/* Calculate remaining space in the buffer. */
|
||||
size_t rem = len - (args_size + strs_len + out_str_pos_nbr);
|
||||
|
||||
if (rem <= scpy_cnt) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
/* Append strings */
|
||||
for (int i = 0; i < scpy_cnt; i++) {
|
||||
uint8_t loc = cpy_str_pos[i];
|
||||
const char *str = *(const char **)&buf32[loc];
|
||||
int cpy_len;
|
||||
uint16_t str_len = strl ? strl[i] : 0;
|
||||
|
||||
*dst = loc;
|
||||
rem--;
|
||||
dst++;
|
||||
cpy_len = append_string(dst, rem, str, str_len);
|
||||
|
||||
if (cpy_len < 0) {
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
rem -= cpy_len;
|
||||
dst += cpy_len;
|
||||
}
|
||||
|
||||
return len - rem;
|
||||
}
|
||||
|
|
|
@ -399,7 +399,7 @@ void z_log_vprintk(const char *fmt, va_list ap)
|
|||
|
||||
if (!IS_ENABLED(CONFIG_LOG1)) {
|
||||
z_log_msg2_runtime_vcreate(CONFIG_LOG_DOMAIN_ID, NULL,
|
||||
LOG_LEVEL_INTERNAL_RAW_STRING, NULL, 0,
|
||||
LOG_LEVEL_INTERNAL_RAW_STRING, NULL, 0, 0,
|
||||
fmt, ap);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ static inline void z_vrfy_z_log_msg2_static_create(const void *source,
|
|||
|
||||
void z_impl_z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
||||
uint8_t level, const void *data, size_t dlen,
|
||||
const char *fmt, va_list ap)
|
||||
uint32_t package_flags, const char *fmt, va_list ap)
|
||||
{
|
||||
int plen;
|
||||
|
||||
|
@ -62,8 +62,8 @@ void z_impl_z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|||
va_list ap2;
|
||||
|
||||
va_copy(ap2, ap);
|
||||
plen = cbvprintf_package(NULL, Z_LOG_MSG2_ALIGN_OFFSET, 0,
|
||||
fmt, ap2);
|
||||
plen = cbvprintf_package(NULL, Z_LOG_MSG2_ALIGN_OFFSET,
|
||||
package_flags, fmt, ap2);
|
||||
__ASSERT_NO_MSG(plen >= 0);
|
||||
va_end(ap2);
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ void z_impl_z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|||
}
|
||||
|
||||
if (msg && fmt) {
|
||||
plen = cbvprintf_package(msg->data, (size_t)plen, 0, fmt, ap);
|
||||
plen = cbvprintf_package(msg->data, (size_t)plen, package_flags, fmt, ap);
|
||||
__ASSERT_NO_MSG(plen >= 0);
|
||||
}
|
||||
|
||||
|
@ -93,10 +93,10 @@ void z_impl_z_log_msg2_runtime_vcreate(uint8_t domain_id, const void *source,
|
|||
static inline void z_vrfy_z_log_msg2_runtime_vcreate(uint8_t domain_id,
|
||||
const void *source,
|
||||
uint8_t level, const void *data, size_t dlen,
|
||||
const char *fmt, va_list ap)
|
||||
uint32_t package_flags, const char *fmt, va_list ap)
|
||||
{
|
||||
return z_impl_z_log_msg2_runtime_vcreate(domain_id, source, level, data,
|
||||
dlen, fmt, ap);
|
||||
dlen, package_flags, fmt, ap);
|
||||
}
|
||||
#include <syscalls/z_log_msg2_runtime_vcreate_mrsh.c>
|
||||
#endif
|
||||
|
|
|
@ -57,7 +57,7 @@ static void unpack(const char *desc, struct out_buffer *buf,
|
|||
}
|
||||
|
||||
#define TEST_PACKAGING(flags, fmt, ...) do { \
|
||||
int must_runtime = CBPRINTF_MUST_RUNTIME_PACKAGE(0, flags, fmt, __VA_ARGS__); \
|
||||
int must_runtime = CBPRINTF_MUST_RUNTIME_PACKAGE(flags, fmt, __VA_ARGS__); \
|
||||
zassert_equal(must_runtime, !Z_C_GENERIC, NULL); \
|
||||
snprintfcb(compare_buf, sizeof(compare_buf), fmt, __VA_ARGS__); \
|
||||
printk("-----------------------------------------\n"); \
|
||||
|
@ -82,13 +82,13 @@ static void unpack(const char *desc, struct out_buffer *buf,
|
|||
struct out_buffer st_buf = { \
|
||||
.buf = static_buf, .idx = 0, .size = sizeof(static_buf) \
|
||||
}; \
|
||||
CBPRINTF_STATIC_PACKAGE(NULL, 0, len, ALIGN_OFFSET, 0, fmt, __VA_ARGS__); \
|
||||
CBPRINTF_STATIC_PACKAGE(NULL, 0, len, ALIGN_OFFSET, flags, fmt, __VA_ARGS__); \
|
||||
zassert_true(len > 0, "CBPRINTF_STATIC_PACKAGE() returned %d", len); \
|
||||
uint8_t __aligned(CBPRINTF_PACKAGE_ALIGNMENT) \
|
||||
package[len + ALIGN_OFFSET];\
|
||||
int outlen; \
|
||||
pkg = &package[ALIGN_OFFSET]; \
|
||||
CBPRINTF_STATIC_PACKAGE(pkg, len, outlen, ALIGN_OFFSET, 0, fmt, __VA_ARGS__);\
|
||||
CBPRINTF_STATIC_PACKAGE(pkg, len, outlen, ALIGN_OFFSET, flags, fmt, __VA_ARGS__);\
|
||||
zassert_equal(len, outlen, NULL); \
|
||||
dump("static", pkg, len); \
|
||||
unpack("static", &st_buf, pkg, len); \
|
||||
|
@ -123,19 +123,19 @@ void test_cbprintf_package(void)
|
|||
TEST_PACKAGING(0, "test %c %p", c, vp);
|
||||
|
||||
/* Runtime packaging is still possible when const strings are used. */
|
||||
TEST_PACKAGING(CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR,
|
||||
TEST_PACKAGING(CBPRINTF_PACKAGE_CONST_CHAR_RO,
|
||||
"test %s %s", str, (const char *)pstr);
|
||||
|
||||
/* When flag is set but argument is char * runtime packaging must be used. */
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR,
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
|
||||
"test %s %s", str, pstr);
|
||||
zassert_true(rv != 0, "Unexpected value %d", rv);
|
||||
|
||||
/* When const char * are used but flag is not used then runtime packaging must be used. */
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, 0, "test %s %s", str, (const char *)pstr);
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, "test %s %s", str, (const char *)pstr);
|
||||
zassert_true(rv != 0, "Unexpected value %d", rv);
|
||||
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(0, CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR,
|
||||
rv = CBPRINTF_MUST_RUNTIME_PACKAGE(CBPRINTF_PACKAGE_CONST_CHAR_RO,
|
||||
"test %s", (char *)str);
|
||||
zassert_true(rv != 0, "Unexpected value %d", rv);
|
||||
|
||||
|
|
|
@ -522,10 +522,10 @@ void test_log_msg2_create(void)
|
|||
level = 2;
|
||||
|
||||
z_log_msg2_runtime_create(domain, __log_current_const_data,
|
||||
level, &msg_data,
|
||||
level, &msg_data, 0,
|
||||
sizeof(msg_data), NULL);
|
||||
/* try z_log_msg2_static_create() */
|
||||
Z_LOG_MSG2_STACK_CREATE(domain, __log_current_const_data,
|
||||
Z_LOG_MSG2_STACK_CREATE(0, domain, __log_current_const_data,
|
||||
level, &msg_data,
|
||||
sizeof(msg_data), NULL);
|
||||
|
||||
|
@ -547,10 +547,10 @@ void test_log_msg2_create_user(void)
|
|||
level = 2;
|
||||
|
||||
z_log_msg2_runtime_create(domain, NULL,
|
||||
level, &msg_data,
|
||||
level, &msg_data, 0,
|
||||
sizeof(msg_data), test_msg_usr);
|
||||
/* try z_log_msg2_static_create() */
|
||||
Z_LOG_MSG2_STACK_CREATE(domain, NULL,
|
||||
Z_LOG_MSG2_STACK_CREATE(0, domain, NULL,
|
||||
level, &msg_data,
|
||||
sizeof(msg_data), test_msg_usr);
|
||||
|
||||
|
|
|
@ -198,7 +198,7 @@ void test_log_msg2_0_args_msg(void)
|
|||
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
|
||||
|
||||
z_log_msg2_runtime_create(domain, source,
|
||||
level, NULL, 0, TEST_MSG);
|
||||
level, NULL, 0, 0, TEST_MSG);
|
||||
|
||||
validate_base_message_set(source, domain, level,
|
||||
TEST_TIMESTAMP_INIT_VALUE,
|
||||
|
@ -231,7 +231,7 @@ void test_log_msg2_various_args(void)
|
|||
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
|
||||
|
||||
z_log_msg2_runtime_create(domain, (void *)source, level, NULL,
|
||||
0, TEST_MSG, s8, u, lld, str, lld, iarray);
|
||||
0, 0, TEST_MSG, s8, u, lld, str, lld, iarray);
|
||||
snprintfcb(str, sizeof(str), TEST_MSG, s8, u, lld, str, lld, iarray);
|
||||
|
||||
validate_base_message_set(source, domain, level,
|
||||
|
@ -258,7 +258,7 @@ void test_log_msg2_only_data(void)
|
|||
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
|
||||
|
||||
z_log_msg2_runtime_create(domain, (void *)source, level, array,
|
||||
sizeof(array), NULL);
|
||||
sizeof(array), 0, NULL);
|
||||
|
||||
validate_base_message_set(source, domain, level,
|
||||
TEST_TIMESTAMP_INIT_VALUE,
|
||||
|
@ -287,7 +287,7 @@ void test_log_msg2_string_and_data(void)
|
|||
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
|
||||
|
||||
z_log_msg2_runtime_create(domain, (void *)source, level, array,
|
||||
sizeof(array), TEST_MSG);
|
||||
sizeof(array), 0, TEST_MSG);
|
||||
|
||||
validate_base_message_set(source, domain, level,
|
||||
TEST_TIMESTAMP_INIT_VALUE,
|
||||
|
@ -323,7 +323,7 @@ void test_log_msg2_fp(void)
|
|||
TEST_MSG, i, lli, (double)f, &i, d, source);
|
||||
zassert_equal(mode, EXP_MODE(FROM_STACK), NULL);
|
||||
|
||||
z_log_msg2_runtime_create(domain, (void *)source, level, NULL, 0,
|
||||
z_log_msg2_runtime_create(domain, (void *)source, level, NULL, 0, 0,
|
||||
TEST_MSG, i, lli, (double)f, &i, d, source);
|
||||
snprintfcb(str, sizeof(str), TEST_MSG, i, lli, (double)f, &i, d, source);
|
||||
|
||||
|
@ -512,9 +512,7 @@ void test_mode_size_str_with_2strings(void)
|
|||
exp_len = sizeof(struct log_msg2_hdr) +
|
||||
/* package */4 * sizeof(const char *);
|
||||
if (TEST_LOG_MSG2_RW_STRINGS) {
|
||||
exp_len += strlen("sufix") + 2 /* null + header */ +
|
||||
strlen(prefix) + 2 /* null + header */+
|
||||
strlen(TEST_STR) + 2 /* null + header */;
|
||||
exp_len += strlen("sufix") + 2; /* null + header */
|
||||
}
|
||||
|
||||
exp_len = ROUND_UP(exp_len, Z_LOG_MSG2_ALIGNMENT) / sizeof(int);
|
||||
|
@ -554,7 +552,7 @@ void test_saturate(void)
|
|||
/* Message should not fit in and be dropped. */
|
||||
Z_LOG_MSG2_CREATE3(1, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
|
||||
Z_LOG_MSG2_CREATE3(0, mode, 0, 0, (void *)1, 2, NULL, 0, "test");
|
||||
z_log_msg2_runtime_create(0, (void *)1, 2, NULL, 0, "test");
|
||||
z_log_msg2_runtime_create(0, (void *)1, 2, NULL, 0, 0, "test");
|
||||
|
||||
zassert_equal(z_log_dropped_read_and_clear(), 3, "No dropped messages.");
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue