2023-02-08 18:12:00 +01:00
|
|
|
/* Simple Plugin API */
|
|
|
|
|
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
|
|
|
|
/* SPDX-License-Identifier: MIT */
|
2017-06-06 13:30:34 +02:00
|
|
|
|
2019-01-14 12:58:23 +01:00
|
|
|
#ifndef SPA_LOG_IMPL_H
|
|
|
|
|
#define SPA_LOG_IMPL_H
|
2017-06-06 13:30:34 +02:00
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2018-02-08 11:24:20 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
2019-06-21 13:31:34 +02:00
|
|
|
#include <spa/utils/type.h>
|
2017-11-10 13:36:14 +01:00
|
|
|
#include <spa/support/log.h>
|
2017-06-06 13:30:34 +02:00
|
|
|
|
2021-05-21 14:03:07 +10:00
|
|
|
/**
|
|
|
|
|
* \addtogroup spa_log
|
|
|
|
|
* \{
|
|
|
|
|
*/
|
|
|
|
|
|
2023-11-21 17:18:26 +01:00
|
|
|
static inline SPA_PRINTF_FUNC(7, 0) void spa_log_impl_logtv(void *object SPA_UNUSED,
|
2017-06-06 13:30:34 +02:00
|
|
|
enum spa_log_level level,
|
2021-09-14 14:49:03 +10:00
|
|
|
const struct spa_log_topic *topic,
|
2017-06-06 13:30:34 +02:00
|
|
|
const char *file,
|
|
|
|
|
int line,
|
|
|
|
|
const char *func,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
va_list args)
|
|
|
|
|
{
|
spa: support: log-impl: check the return value of `strrchr()`
Previously, the return value of `strrchr()` was not checked
in `spa_log_impl_logv()` which could cause a segmentation fault
in `snprintf()` if the `file` string argument does not contain
any directory separators ('/').
For example,
./build/spa/tools/spa-inspect ./build/spa/plugins/alsa/libspa-alsa.so
could run into this problem:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f1d505 in __strlen_avx2 () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff7f1d505 in __strlen_avx2 () from /usr/lib/libc.so.6
#1 0x00007ffff7e29408 in __vfprintf_internal () from /usr/lib/libc.so.6
#2 0x00007ffff7e3a19a in __vsnprintf_internal () from /usr/lib/libc.so.6
#3 0x00007ffff7e146f6 in snprintf () from /usr/lib/libc.so.6
#4 0x0000555555558818 in spa_log_impl_logv (object=<optimized out>, level=SPA_LOG_LEVEL_INFO,
file=0x7fffffffd4d0 "[I][", line=260, func=0x7ffff7ce8090 "error_node", fmt=<optimized out>,
args=0x7fffffffd920) at ../spa/include/spa/support/log-impl.h:49
#5 0x00007ffff7d8c69e in alsa_error_handler (file=<optimized out>, line=<optimized out>,
function=<optimized out>, err=<optimized out>, fmt=<optimized out>)
at ../spa/plugins/alsa/acp/alsa-util.c:866
#6 0x00007ffff7cd6a8f in ?? () from /usr/lib/libasound.so.2
#7 0x00007ffff7cdb55e in snd_use_case_mgr_open () from /usr/lib/libasound.so.2
#8 0x00007ffff7d8940f in pa_alsa_ucm_query_profiles (ucm=ucm@entry=0x55555556ba28, card_index=0)
at ../spa/plugins/alsa/acp/alsa-ucm.c:752
#9 0x00007ffff7d6e3c2 in acp_card_new (index=0, props=props@entry=0x7fffffffdc50)
at ../spa/plugins/alsa/acp/acp.c:1508
#10 0x00007ffff7d29b7a in impl_init (factory=<optimized out>, handle=0x55555556b540,
info=<optimized out>, support=<optimized out>, n_support=<optimized out>)
at ../spa/plugins/alsa/alsa-acp-device.c:963
#11 0x0000555555558429 in inspect_factory (factory=0x7ffff7daefa0 <spa_alsa_acp_device_factory>,
data=0x7fffffffdcf0) at ../spa/tools/spa-inspect.c:231
#12 main (argc=<optimized out>, argv=<optimized out>) at ../spa/tools/spa-inspect.c:309
as in that particular case, the filename was returned by libasound,
and it was just "parser.c".
Furthermore, separate the static variable from the rest, and apply
the `const` qualifier to the pointers in the `levels` array.
2021-04-07 15:32:51 +02:00
|
|
|
static const char * const levels[] = { "-", "E", "W", "I", "D", "T" };
|
|
|
|
|
|
|
|
|
|
const char *basename = strrchr(file, '/');
|
2021-09-14 14:49:03 +10:00
|
|
|
char text[512], location[1024];
|
|
|
|
|
char topicstr[32] = {0};
|
spa: support: log-impl: check the return value of `strrchr()`
Previously, the return value of `strrchr()` was not checked
in `spa_log_impl_logv()` which could cause a segmentation fault
in `snprintf()` if the `file` string argument does not contain
any directory separators ('/').
For example,
./build/spa/tools/spa-inspect ./build/spa/plugins/alsa/libspa-alsa.so
could run into this problem:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f1d505 in __strlen_avx2 () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff7f1d505 in __strlen_avx2 () from /usr/lib/libc.so.6
#1 0x00007ffff7e29408 in __vfprintf_internal () from /usr/lib/libc.so.6
#2 0x00007ffff7e3a19a in __vsnprintf_internal () from /usr/lib/libc.so.6
#3 0x00007ffff7e146f6 in snprintf () from /usr/lib/libc.so.6
#4 0x0000555555558818 in spa_log_impl_logv (object=<optimized out>, level=SPA_LOG_LEVEL_INFO,
file=0x7fffffffd4d0 "[I][", line=260, func=0x7ffff7ce8090 "error_node", fmt=<optimized out>,
args=0x7fffffffd920) at ../spa/include/spa/support/log-impl.h:49
#5 0x00007ffff7d8c69e in alsa_error_handler (file=<optimized out>, line=<optimized out>,
function=<optimized out>, err=<optimized out>, fmt=<optimized out>)
at ../spa/plugins/alsa/acp/alsa-util.c:866
#6 0x00007ffff7cd6a8f in ?? () from /usr/lib/libasound.so.2
#7 0x00007ffff7cdb55e in snd_use_case_mgr_open () from /usr/lib/libasound.so.2
#8 0x00007ffff7d8940f in pa_alsa_ucm_query_profiles (ucm=ucm@entry=0x55555556ba28, card_index=0)
at ../spa/plugins/alsa/acp/alsa-ucm.c:752
#9 0x00007ffff7d6e3c2 in acp_card_new (index=0, props=props@entry=0x7fffffffdc50)
at ../spa/plugins/alsa/acp/acp.c:1508
#10 0x00007ffff7d29b7a in impl_init (factory=<optimized out>, handle=0x55555556b540,
info=<optimized out>, support=<optimized out>, n_support=<optimized out>)
at ../spa/plugins/alsa/alsa-acp-device.c:963
#11 0x0000555555558429 in inspect_factory (factory=0x7ffff7daefa0 <spa_alsa_acp_device_factory>,
data=0x7fffffffdcf0) at ../spa/tools/spa-inspect.c:231
#12 main (argc=<optimized out>, argv=<optimized out>) at ../spa/tools/spa-inspect.c:309
as in that particular case, the filename was returned by libasound,
and it was just "parser.c".
Furthermore, separate the static variable from the rest, and apply
the `const` qualifier to the pointers in the `levels` array.
2021-04-07 15:32:51 +02:00
|
|
|
|
|
|
|
|
if (basename)
|
|
|
|
|
basename += 1; /* skip '/' */
|
|
|
|
|
else
|
|
|
|
|
basename = file; /* use whole string if no '/' is found */
|
2017-06-06 13:30:34 +02:00
|
|
|
|
2021-09-14 14:49:03 +10:00
|
|
|
if (topic && topic->topic)
|
|
|
|
|
snprintf(topicstr, sizeof(topicstr), " %s ", topic->topic);
|
|
|
|
|
vsnprintf(text, sizeof(text), fmt, args);
|
|
|
|
|
snprintf(location, sizeof(location), "[%s]%s[%s:%i %s()] %s\n",
|
|
|
|
|
levels[level],
|
|
|
|
|
topicstr,
|
|
|
|
|
basename, line, func, text);
|
|
|
|
|
fputs(location, stderr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline SPA_PRINTF_FUNC(7,8) void spa_log_impl_logt(void *object,
|
|
|
|
|
enum spa_log_level level,
|
|
|
|
|
const struct spa_log_topic *topic,
|
|
|
|
|
const char *file,
|
|
|
|
|
int line,
|
|
|
|
|
const char *func,
|
|
|
|
|
const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
spa_log_impl_logtv(object, level, topic, file, line, func, fmt, args);
|
|
|
|
|
va_end(args);
|
2017-06-06 13:30:34 +02:00
|
|
|
}
|
2021-09-14 14:49:03 +10:00
|
|
|
|
|
|
|
|
static inline SPA_PRINTF_FUNC(6, 0) void spa_log_impl_logv(void *object,
|
|
|
|
|
enum spa_log_level level,
|
|
|
|
|
const char *file,
|
|
|
|
|
int line,
|
|
|
|
|
const char *func,
|
|
|
|
|
const char *fmt,
|
|
|
|
|
va_list args)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
spa_log_impl_logtv(object, level, NULL, file, line, func, fmt, args);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-20 18:20:04 +01:00
|
|
|
static inline SPA_PRINTF_FUNC(6,7) void spa_log_impl_log(void *object,
|
2017-06-06 13:30:34 +02:00
|
|
|
enum spa_log_level level,
|
|
|
|
|
const char *file,
|
|
|
|
|
int line,
|
|
|
|
|
const char *func,
|
|
|
|
|
const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
2019-05-20 16:11:23 +02:00
|
|
|
spa_log_impl_logv(object, level, file, line, func, fmt, args);
|
2017-06-06 13:30:34 +02:00
|
|
|
va_end(args);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-21 17:18:26 +01:00
|
|
|
static inline void spa_log_impl_topic_init(void *object SPA_UNUSED, struct spa_log_topic *topic SPA_UNUSED)
|
2021-09-14 14:49:03 +10:00
|
|
|
{
|
|
|
|
|
/* noop */
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-06 13:30:34 +02:00
|
|
|
#define SPA_LOG_IMPL_DEFINE(name) \
|
|
|
|
|
struct { \
|
|
|
|
|
struct spa_log log; \
|
2019-05-20 16:11:23 +02:00
|
|
|
struct spa_log_methods methods; \
|
2017-06-06 13:30:34 +02:00
|
|
|
} name
|
|
|
|
|
|
2019-05-20 16:11:23 +02:00
|
|
|
#define SPA_LOG_IMPL_INIT(name) \
|
|
|
|
|
{ { { SPA_TYPE_INTERFACE_Log, SPA_VERSION_LOG, \
|
2022-09-01 17:02:44 -04:00
|
|
|
SPA_CALLBACKS_INIT(&(name).methods, &(name)) }, \
|
2019-05-20 16:11:23 +02:00
|
|
|
SPA_LOG_LEVEL_INFO, }, \
|
2021-09-29 17:03:26 +02:00
|
|
|
{ SPA_VERSION_LOG_METHODS, \
|
2019-05-20 16:11:23 +02:00
|
|
|
spa_log_impl_log, \
|
2021-09-14 14:49:03 +10:00
|
|
|
spa_log_impl_logv, \
|
|
|
|
|
spa_log_impl_logt, \
|
|
|
|
|
spa_log_impl_logtv, \
|
2024-03-21 17:28:50 +01:00
|
|
|
spa_log_impl_topic_init, \
|
2021-09-14 14:49:03 +10:00
|
|
|
} }
|
2017-06-06 13:30:34 +02:00
|
|
|
|
|
|
|
|
#define SPA_LOG_IMPL(name) \
|
2019-05-20 16:11:23 +02:00
|
|
|
SPA_LOG_IMPL_DEFINE(name) = SPA_LOG_IMPL_INIT(name)
|
2017-06-06 13:30:34 +02:00
|
|
|
|
2021-05-21 14:03:07 +10:00
|
|
|
/**
|
|
|
|
|
* \}
|
|
|
|
|
*/
|
|
|
|
|
|
2017-06-06 13:30:34 +02:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
} /* extern "C" */
|
|
|
|
|
#endif
|
2019-01-14 12:58:23 +01:00
|
|
|
#endif /* SPA_LOG_IMPL_H */
|