xref: /linux/tools/objtool/include/objtool/trace.h (revision 63e6995005be8ceb8a1d56a18df1a1a40c28356d)
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