1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Copyright (c) 2025, Oracle and/or its affiliates.
4 */
5
6 #ifndef _TRACE_H
7 #define _TRACE_H
8
9 #include <objtool/check.h>
10 #include <objtool/disas.h>
11
12 #ifdef DISAS
13
14 extern bool trace;
15 extern int trace_depth;
16
17 #define TRACE(fmt, ...) \
18 ({ if (trace) \
19 fprintf(stderr, fmt, ##__VA_ARGS__); \
20 })
21
22 /*
23 * Print the instruction address and a message. The instruction
24 * itself is not printed.
25 */
26 #define TRACE_ADDR(insn, fmt, ...) \
27 ({ \
28 if (trace) { \
29 disas_print_info(stderr, insn, trace_depth - 1, \
30 fmt "\n", ##__VA_ARGS__); \
31 } \
32 })
33
34 /*
35 * Print the instruction address, the instruction and a message.
36 */
37 #define TRACE_INSN(insn, fmt, ...) \
38 ({ \
39 if (trace) { \
40 disas_print_insn(stderr, objtool_disas_ctx, \
41 insn, trace_depth - 1, \
42 fmt, ##__VA_ARGS__); \
43 fprintf(stderr, "\n"); \
44 insn->trace = 1; \
45 } \
46 })
47
48 #define TRACE_INSN_STATE(insn, sprev, snext) \
49 ({ \
50 if (trace) \
51 trace_insn_state(insn, sprev, snext); \
52 })
53
54 #define TRACE_ALT_FMT(pfx, fmt) pfx "<%s.%lx> " fmt
55 #define TRACE_ALT_ARG(insn) disas_alt_type_name(insn), (insn)->offset
56
57 #define TRACE_ALT(insn, fmt, ...) \
58 TRACE_INSN(insn, TRACE_ALT_FMT("", fmt), \
59 TRACE_ALT_ARG(insn), ##__VA_ARGS__)
60
61 #define TRACE_ALT_INFO(insn, pfx, fmt, ...) \
62 TRACE_ADDR(insn, TRACE_ALT_FMT(pfx, fmt), \
63 TRACE_ALT_ARG(insn), ##__VA_ARGS__)
64
65 #define TRACE_ALT_INFO_NOADDR(insn, pfx, fmt, ...) \
66 TRACE_ADDR(NULL, TRACE_ALT_FMT(pfx, fmt), \
67 TRACE_ALT_ARG(insn), ##__VA_ARGS__)
68
69 #define TRACE_ALT_BEGIN(insn, alt, alt_name) \
70 ({ \
71 if (trace) { \
72 alt_name = disas_alt_name(alt); \
73 trace_alt_begin(insn, alt, alt_name); \
74 } \
75 })
76
77 #define TRACE_ALT_END(insn, alt, alt_name) \
78 ({ \
79 if (trace) { \
80 trace_alt_end(insn, alt, alt_name); \
81 free(alt_name); \
82 } \
83 })
84
trace_enable(void)85 static inline void trace_enable(void)
86 {
87 trace = true;
88 trace_depth = 0;
89 }
90
trace_disable(void)91 static inline void trace_disable(void)
92 {
93 trace = false;
94 }
95
trace_depth_inc(void)96 static inline void trace_depth_inc(void)
97 {
98 if (trace)
99 trace_depth++;
100 }
101
trace_depth_dec(void)102 static inline void trace_depth_dec(void)
103 {
104 if (trace)
105 trace_depth--;
106 }
107
108 void trace_insn_state(struct instruction *insn, struct insn_state *sprev,
109 struct insn_state *snext);
110 void trace_alt_begin(struct instruction *orig_insn, struct alternative *alt,
111 char *alt_name);
112 void trace_alt_end(struct instruction *orig_insn, struct alternative *alt,
113 char *alt_name);
114
115 #else /* DISAS */
116
117 #define TRACE(fmt, ...) ({})
118 #define TRACE_ADDR(insn, fmt, ...) ({})
119 #define TRACE_INSN(insn, fmt, ...) ({})
120 #define TRACE_INSN_STATE(insn, sprev, snext) ({})
121 #define TRACE_ALT(insn, fmt, ...) ({})
122 #define TRACE_ALT_INFO(insn, fmt, ...) ({})
123 #define TRACE_ALT_INFO_NOADDR(insn, fmt, ...) ({})
124 #define TRACE_ALT_BEGIN(insn, alt, alt_name) ({})
125 #define TRACE_ALT_END(insn, alt, alt_name) ({})
126
127
trace_enable(void)128 static inline void trace_enable(void) {}
trace_disable(void)129 static inline void trace_disable(void) {}
trace_depth_inc(void)130 static inline void trace_depth_inc(void) {}
trace_depth_dec(void)131 static inline void trace_depth_dec(void) {}
trace_alt_begin(struct instruction * orig_insn,struct alternative * alt,char * alt_name)132 static inline void trace_alt_begin(struct instruction *orig_insn,
133 struct alternative *alt,
134 char *alt_name) {};
trace_alt_end(struct instruction * orig_insn,struct alternative * alt,char * alt_name)135 static inline void trace_alt_end(struct instruction *orig_insn,
136 struct alternative *alt,
137 char *alt_name) {};
138
139 #endif
140
141 #endif /* _TRACE_H */
142