aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre-Clément Tosi <ptosi@google.com>2023-04-03 17:13:28 +0100
committerPierre-Clément Tosi <ptosi@google.com>2023-04-13 09:25:59 +0100
commit597efcd89ce7feb31e73e80294fa81f3453b9f36 (patch)
tree061be807b5ce85bdebff64dbc1e93638411f2475
parenta26e69b29b7151c9851075e17dbd678ce9089928 (diff)
downloadavb-597efcd89ce7feb31e73e80294fa81f3453b9f36.tar.gz
sysdeps: Add support for vfprintf() logging
Introduce a build flag to make logging calls (avb_{debug,error,fatal}) use vfprintf(3) instead of printf(3), which greatly improves the probability of the call resulting in a single write(2), as opposed to our current implementation of avb_printv(), which calls fprintf(3) once per received argument. This is useful when stderr points to a file that is shared and/or format entries per write(2) call, such as /dev/kmsg. Note that client code passing the now deprecated NULL sentinel to the logging macros avb_{debug,error,fatal}() must NOT enable this feature. Test: - Reported-by: JeongHyeon Lee <jhs2.lee@samsung.com> Change-Id: I0f30d21939fca7ceb9e96ac7d443512fe7c301d9
-rw-r--r--libavb/avb_sysdeps.h7
-rw-r--r--libavb/avb_sysdeps_posix.c7
-rw-r--r--libavb/avb_util.h28
-rw-r--r--test/avb_sysdeps_posix_testing.cc7
4 files changed, 49 insertions, 0 deletions
diff --git a/libavb/avb_sysdeps.h b/libavb/avb_sysdeps.h
index cfc9355..b4a1e99 100644
--- a/libavb/avb_sysdeps.h
+++ b/libavb/avb_sysdeps.h
@@ -48,6 +48,7 @@ extern "C" {
*/
#define AVB_ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#define AVB_ATTR_PACKED __attribute__((packed))
+#define AVB_ATTR_PRINTF(x, y) __attribute__((format(printf, x, y)))
#define AVB_ATTR_NO_RETURN __attribute__((noreturn))
#define AVB_ATTR_SENTINEL __attribute__((__sentinel__))
@@ -99,6 +100,12 @@ void avb_print(const char* message);
*/
void avb_printv(const char* message, ...) AVB_ATTR_SENTINEL;
+/* Prints out a formatted string.
+ *
+ * Replaces avb_printv when AVB_USE_PRINTF_LOGS is enabled.
+ */
+void avb_printf(const char* fmt, ...) AVB_ATTR_PRINTF(1, 2);
+
/* Aborts the program or reboots the device. */
void avb_abort(void) AVB_ATTR_NO_RETURN;
diff --git a/libavb/avb_sysdeps_posix.c b/libavb/avb_sysdeps_posix.c
index e26c3ef..a954869 100644
--- a/libavb/avb_sysdeps_posix.c
+++ b/libavb/avb_sysdeps_posix.c
@@ -58,6 +58,13 @@ void avb_abort(void) {
abort();
}
+void avb_printf(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
void avb_print(const char* message) {
fprintf(stderr, "%s", message);
}
diff --git a/libavb/avb_util.h b/libavb/avb_util.h
index 671d39a..da638fc 100644
--- a/libavb/avb_util.h
+++ b/libavb/avb_util.h
@@ -35,9 +35,34 @@
extern "C" {
#endif
+#define AVB_CONCAT(x, y) x##y
#define AVB_STRINGIFY(x) #x
#define AVB_TO_STRING(x) AVB_STRINGIFY(x)
+#define AVB__COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, x, ...) x
+#define AVB_COUNT_ARGS(...) \
+ AVB__COUNT_ARGS(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0)
+
+#define AVB__REPEAT0(x)
+#define AVB__REPEAT1(x) x
+#define AVB__REPEAT2(x) AVB__REPEAT1(x) x
+#define AVB__REPEAT3(x) AVB__REPEAT2(x) x
+#define AVB__REPEAT4(x) AVB__REPEAT3(x) x
+#define AVB__REPEAT5(x) AVB__REPEAT4(x) x
+#define AVB__REPEAT6(x) AVB__REPEAT5(x) x
+#define AVB__REPEAT7(x) AVB__REPEAT6(x) x
+#define AVB__REPEAT(n, x) AVB_CONCAT(AVB__REPEAT, n)(x)
+#define AVB_REPEAT(n, x) AVB__REPEAT(n, x)
+
+#ifdef AVB_USE_PRINTF_LOGS
+#define AVB_LOG(level, message, ...) \
+ avb_printf("%s:%d: " level \
+ ": " AVB_REPEAT(AVB_COUNT_ARGS(message, ##__VA_ARGS__), "%s"), \
+ avb_basename(__FILE__), \
+ __LINE__, \
+ message, \
+ ##__VA_ARGS__)
+#else
#define AVB_LOG(level, message, ...) \
avb_printv(avb_basename(__FILE__), \
":", \
@@ -46,6 +71,7 @@ extern "C" {
message, \
##__VA_ARGS__, \
NULL)
+#endif
#ifdef AVB_ENABLE_DEBUG
/* Aborts the program if |expr| is false.
@@ -105,11 +131,13 @@ extern "C" {
avb_abort(); \
} while (0)
+#ifndef AVB_USE_PRINTF_LOGS
/* Deprecated legacy logging functions -- kept for client compatibility.
*/
#define avb_debugv(message, ...) avb_debug(message, ##__VA_ARGS__)
#define avb_errorv(message, ...) avb_error(message, ##__VA_ARGS__)
#define avb_fatalv(message, ...) avb_fatal(message, ##__VA_ARGS__)
+#endif
/* Converts a 16-bit unsigned integer from big-endian to host byte order. */
uint16_t avb_be16toh(uint16_t in) AVB_ATTR_WARN_UNUSED_RESULT;
diff --git a/test/avb_sysdeps_posix_testing.cc b/test/avb_sysdeps_posix_testing.cc
index 0a6ac13..6b1f210 100644
--- a/test/avb_sysdeps_posix_testing.cc
+++ b/test/avb_sysdeps_posix_testing.cc
@@ -77,6 +77,13 @@ void avb_printv(const char* message, ...) {
va_end(ap);
}
+void avb_printf(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
typedef struct {
size_t size;
base::debug::StackTrace stack_trace;