logging: Add basic userspace support
This commit adds basic userspace support to the logging subsystem. With this change, the following API could be called from user mode: - LOG_*() - LOG_INST_*(), - LOG_HEXDUMP_*(), - LOG_HEXDUMP_INST_*(), - LOG_PANIC(), LOG_PROCESS(), - log_printk(), log_generic(), log_buffrered_cnt(), - log_filter_set(NULL, ...) With userspace disabled, the logger behavior and performance is not affected. With userspace enabled, the calls from kernel space have an additional overhead introduced by _is_user_context(). The logger behavior changes when it is called from the user context. All strings logged using LOG_*() and LOG_INST_*() API from userspace are rendered in place for security reasons and then placed in log_strdup() memory pool, which should be large enough to hold bursts of log messages. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com> Signed-off-by: Piotr Zięcik <piotr.ziecik@nordicsemi.no>
This commit is contained in:
parent
78eb718396
commit
892ab4e356
7 changed files with 399 additions and 43 deletions
|
@ -8,10 +8,11 @@
|
|||
|
||||
#include <logging/log_msg.h>
|
||||
#include <logging/log_instance.h>
|
||||
#include <sys/util.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <syscall.h>
|
||||
#include <sys/util.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -162,9 +163,11 @@ extern "C" {
|
|||
|
||||
#define Z_LOG_INTERNAL_X(N, ...) UTIL_CAT(_LOG_INTERNAL_, N)(__VA_ARGS__)
|
||||
|
||||
#define __LOG_INTERNAL(_src_level, ...) \
|
||||
#define __LOG_INTERNAL(is_user_context, _src_level, ...) \
|
||||
do { \
|
||||
if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
|
||||
if (is_user_context) { \
|
||||
log_from_user(_src_level, __VA_ARGS__); \
|
||||
} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
|
||||
log_string_sync(_src_level, __VA_ARGS__); \
|
||||
} else { \
|
||||
Z_LOG_INTERNAL_X(Z_LOG_NARGS_POSTFIX(__VA_ARGS__), \
|
||||
|
@ -212,8 +215,11 @@ extern "C" {
|
|||
/******************************************************************************/
|
||||
#define __LOG(_level, _id, _filter, ...) \
|
||||
do { \
|
||||
bool is_user_context = _is_user_context(); \
|
||||
\
|
||||
if (Z_LOG_CONST_LEVEL_CHECK(_level) && \
|
||||
(_level <= LOG_RUNTIME_FILTER(_filter))) { \
|
||||
(is_user_context || \
|
||||
(_level <= LOG_RUNTIME_FILTER(_filter)))) { \
|
||||
struct log_msg_ids src_level = { \
|
||||
.level = _level, \
|
||||
.domain_id = CONFIG_LOG_DOMAIN_ID, \
|
||||
|
@ -221,10 +227,11 @@ extern "C" {
|
|||
}; \
|
||||
\
|
||||
if ((BIT(_level) & LOG_FUNCTION_PREFIX_MASK) != 0U) {\
|
||||
__LOG_INTERNAL(src_level, \
|
||||
Z_LOG_STR(__VA_ARGS__)); \
|
||||
__LOG_INTERNAL(is_user_context, src_level, \
|
||||
Z_LOG_STR(__VA_ARGS__)); \
|
||||
} else { \
|
||||
__LOG_INTERNAL(src_level, __VA_ARGS__); \
|
||||
__LOG_INTERNAL(is_user_context, src_level, \
|
||||
__VA_ARGS__); \
|
||||
} \
|
||||
} else if (false) { \
|
||||
/* Arguments checker present but never evaluated.*/ \
|
||||
|
@ -254,15 +261,21 @@ extern "C" {
|
|||
/******************************************************************************/
|
||||
#define __LOG_HEXDUMP(_level, _id, _filter, _data, _length, _str) \
|
||||
do { \
|
||||
bool is_user_context = _is_user_context(); \
|
||||
\
|
||||
if (Z_LOG_CONST_LEVEL_CHECK(_level) && \
|
||||
(_level <= LOG_RUNTIME_FILTER(_filter))) { \
|
||||
(is_user_context || \
|
||||
(_level <= LOG_RUNTIME_FILTER(_filter)))) { \
|
||||
struct log_msg_ids src_level = { \
|
||||
.level = _level, \
|
||||
.source_id = _id, \
|
||||
.domain_id = CONFIG_LOG_DOMAIN_ID \
|
||||
}; \
|
||||
\
|
||||
if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
|
||||
if (is_user_context) { \
|
||||
log_hexdump_from_user(src_level, _str, \
|
||||
_data, _length); \
|
||||
} else if (IS_ENABLED(CONFIG_LOG_IMMEDIATE)) { \
|
||||
log_hexdump_sync(src_level, _str, \
|
||||
_data, _length); \
|
||||
} else { \
|
||||
|
@ -526,6 +539,15 @@ void log_hexdump_sync(struct log_msg_ids src_level, const char *metadata,
|
|||
*/
|
||||
void log_generic(struct log_msg_ids src_level, const char *fmt, va_list ap);
|
||||
|
||||
/**
|
||||
* @brief Writes a generic log message to the log from user mode.
|
||||
*
|
||||
* @note This function is intended to be used internally
|
||||
* by the logging subsystem.
|
||||
*/
|
||||
void log_generic_from_user(struct log_msg_ids src_level,
|
||||
const char *fmt, va_list ap);
|
||||
|
||||
/** @brief Check if address belongs to the memory pool used for transient.
|
||||
*
|
||||
* @param buf Buffer.
|
||||
|
@ -559,6 +581,42 @@ u32_t log_get_strdup_longest_string(void);
|
|||
*/
|
||||
void log_dropped(void);
|
||||
|
||||
/** @brief Log a message from user mode context.
|
||||
*
|
||||
* @note This function is intended to be used internally
|
||||
* by the logging subsystem.
|
||||
*
|
||||
* @param src_level Log identification.
|
||||
* @param fmt String to format.
|
||||
* @param ... Variable list of arguments.
|
||||
*/
|
||||
void __printf_like(2, 3) log_from_user(struct log_msg_ids src_level,
|
||||
const char *fmt, ...);
|
||||
|
||||
|
||||
/* Internal function used by log_from_user(). */
|
||||
__syscall void z_log_string_from_user(u32_t src_level_val, const char *str);
|
||||
|
||||
/** @brief Log binary data (displayed as hexdump) from user mode conext.
|
||||
*
|
||||
* @note This function is intended to be used internally
|
||||
* by the logging subsystem.
|
||||
*
|
||||
* @param src_level Log identification.
|
||||
* @param metadata Raw string associated with the data.
|
||||
* @param data Data.
|
||||
* @param len Data length.
|
||||
*/
|
||||
void log_hexdump_from_user(struct log_msg_ids src_level, const char *metadata,
|
||||
const u8_t *data, u32_t len);
|
||||
|
||||
/* Internal function used by log_hexdump_from_user(). */
|
||||
__syscall void z_log_hexdump_from_user(u32_t src_level_val,
|
||||
const char *metadata,
|
||||
const u8_t *data, u32_t len);
|
||||
|
||||
#include <syscalls/log_core.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -75,7 +75,7 @@ int log_set_timestamp_func(timestamp_get_t timestamp_getter, u32_t freq);
|
|||
* are flushed after switching to panic mode. In panic mode, all log
|
||||
* messages must be processed in the context of the call.
|
||||
*/
|
||||
void log_panic(void);
|
||||
__syscall void log_panic(void);
|
||||
|
||||
/**
|
||||
* @brief Process one pending log message.
|
||||
|
@ -85,14 +85,14 @@ void log_panic(void);
|
|||
* @retval true There is more messages pending to be processed.
|
||||
* @retval false No messages pending.
|
||||
*/
|
||||
bool log_process(bool bypass);
|
||||
__syscall bool log_process(bool bypass);
|
||||
|
||||
/**
|
||||
* @brief Return number of buffered log messages.
|
||||
*
|
||||
* @return Number of currently buffered log messages.
|
||||
*/
|
||||
u32_t log_buffered_cnt(void);
|
||||
__syscall u32_t log_buffered_cnt(void);
|
||||
|
||||
/** @brief Get number of independent logger sources (modules and instances)
|
||||
*
|
||||
|
@ -144,10 +144,10 @@ u32_t log_filter_get(struct log_backend const *const backend,
|
|||
* @return Actual level set which may be limited by compiled level. If filter
|
||||
* was set for all backends then maximal level that was set is returned.
|
||||
*/
|
||||
u32_t log_filter_set(struct log_backend const *const backend,
|
||||
u32_t domain_id,
|
||||
u32_t src_id,
|
||||
u32_t level);
|
||||
__syscall u32_t log_filter_set(struct log_backend const *const backend,
|
||||
u32_t domain_id,
|
||||
u32_t src_id,
|
||||
u32_t level);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -179,6 +179,8 @@ void log_backend_disable(struct log_backend const *const backend);
|
|||
#define LOG_PROCESS() false
|
||||
#endif
|
||||
|
||||
#include <syscalls/log_ctrl.h>
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue