CHERIoT RTOS
A compartmentalised RTOS for CHERIoT hardware
Loading...
Searching...
No Matches
debug.h
1#pragma once
2#include <__debug.h>
3#include <__macro_map.h>
4#include <string.h>
5
6#ifndef __cplusplus
7
8/**
9 * Helper macro to convert the type of an argument to the corresponding
10 * `DebugFormatArgument` value.
11 *
12 * Should not be used directly.
13 */
14# define CHERIOT_DEBUG_MAP_ARGUMENT(x) \
15 {_Generic((x), \
16 double: ({ \
17 typeof(x) __tmp = (x); \
18 uintptr_t __return; \
19 memcpy(&__return, &__tmp, sizeof(double)); \
20 __return; \
21 }), \
22 float: ({ \
23 typeof(x) __tmp = (x); \
24 uintptr_t __return; \
25 memcpy(&__return, &__tmp, sizeof(float)); \
26 __return; \
27 }), \
28 default: (uintptr_t)(x)), \
29 _Generic((x), \
30 _Bool: DebugFormatArgumentBool, \
31 char: DebugFormatArgumentCharacter, \
32 short: DebugFormatArgumentSignedNumber32, \
33 unsigned short: DebugFormatArgumentUnsignedNumber32, \
34 int: DebugFormatArgumentSignedNumber32, \
35 float: DebugFormatArgumentFloat, \
36 double: DebugFormatArgumentDouble, \
37 unsigned int: DebugFormatArgumentUnsignedNumber32, \
38 signed long long: DebugFormatArgumentSignedNumber64, \
39 unsigned long long: DebugFormatArgumentUnsignedNumber64, \
40 char *: DebugFormatArgumentCString, \
41 default: DebugFormatArgumentPointer)}
42
43/**
44 * Helper to map a list of arguments to an initialiser for a
45 * `DebugFormatArgument` array.
46 *
47 * Should not be used directly.
48 */
49# define CHERIOT_DEBUG_MAP_ARGUMENTS(...) \
50 CHERIOT_MAP_LIST(CHERIOT_DEBUG_MAP_ARGUMENT, __VA_ARGS__)
51
52/**
53 * Macro that logs a message. The `context` argument is a string that is
54 * printed in magenta at the start of the line, followed by the format string.
55 * Each format argument is referenced with {} in the format string and is
56 * inserted in the output with the default rendering for that type.
57 */
58# define CHERIOT_DEBUG_LOG(context, msg, ...) \
59 do \
60 { \
61 struct DebugFormatArgument args[] = { \
62 __VA_OPT__(CHERIOT_DEBUG_MAP_ARGUMENTS(__VA_ARGS__))}; \
63 debug_log_message_write( \
64 context, \
65 msg, \
66 args, \
67 0 __VA_OPT__(+(sizeof(args) / sizeof(args[0])))); \
68 } while (0)
69
70/**
71 * Assert that `condition` is true, printing a message and aborting the
72 * compartment invocation if not.
73 */
74# define CHERIOT_INVARIANT(condition, msg, ...) \
75 do \
76 { \
77 if (!(condition)) \
78 { \
79 struct DebugFormatArgument args[] = { \
80 __VA_OPT__(CHERIOT_DEBUG_MAP_ARGUMENTS(__VA_ARGS__))}; \
81 debug_report_failure( \
82 "Invariant", \
83 __FILE__, \
84 __func__, \
85 __LINE__, \
86 msg, \
87 args, \
88 0 __VA_OPT__(+(sizeof(args) / sizeof(args[0])))); \
89 __builtin_trap(); \
90 } \
91 } while (0)
92
93#else
94# include <debug.hh>
95
96namespace
97{
98 template<typename... Args>
99 __always_inline void
100 cheriot_debug_log(const char *context, const char *msg, Args... args)
101 {
102 DebugFormatArgument arguments[sizeof...(Args)];
103 make_debug_arguments_list(arguments, args...);
104 debug_log_message_write(context, msg, arguments, sizeof...(Args));
105 }
106
107 template<typename... Args>
108 __always_inline void cheriot_invariant(bool condition,
109 const char *file,
110 const char *function,
111 int line,
112 const char *msg,
113 Args... args)
114 {
115 if (!condition)
116 {
117 DebugFormatArgument arguments[sizeof...(Args)];
118 make_debug_arguments_list(arguments, args...);
119 debug_report_failure("Invariant",
120 file,
121 function,
122 line,
123 msg,
124 arguments,
125 sizeof...(Args));
126 }
127 }
128} // namespace
129
130/**
131 * C++ version of `CHERIOT_DEBUG_LOG`. This uses the C++ helpers and so will
132 * pretty-print a richer set of types than the C version.
133 */
134# define CHERIOT_DEBUG_LOG(context, msg, ...) \
135 do \
136 { \
137 cheriot_debug_log(context, msg __VA_OPT__(, ) __VA_ARGS__); \
138 } while (0)
139
140/**
141 * C++ version of `CHERIOT_INVARIANT`. This uses the C++ helpers and so will
142 * pretty-print a richer set of types than the C version.
143 */
144# define CHERIOT_INVARIANT(condition, msg, ...) \
145 do \
146 { \
147 cheriot_invariant(condition, \
148 __FILE__, \
149 __func__, \
150 __LINE__, \
151 msg __VA_OPT__(, ) __VA_ARGS__); \
152 } while (0)
153
154#endif
C++ APIs for assertions, invariants, and writing formatted debug messages to a UART.
void make_debug_arguments_list(DebugFormatArgument *arguments, Args &...args)
Convert args into a type-erased array of DebugFormatArguments in arguments.
Definition debug.hh:544