summaryrefslogtreecommitdiff
path: root/tools/objtool/include/objtool/trace.h
blob: 70b574366797b28a3c67bd1d89f87b2c7ce84774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (c) 2025, Oracle and/or its affiliates.
 */

#ifndef _TRACE_H
#define _TRACE_H

#include <objtool/check.h>
#include <objtool/disas.h>

#ifdef DISAS

extern bool trace;
extern int trace_depth;

#define TRACE(fmt, ...)						\
({	if (trace)						\
		fprintf(stderr, fmt, ##__VA_ARGS__);		\
})

/*
 * Print the instruction address and a message. The instruction
 * itself is not printed.
 */
#define TRACE_ADDR(insn, fmt, ...)				\
({								\
	if (trace) {						\
		disas_print_info(stderr, insn, trace_depth - 1, \
				 fmt "\n", ##__VA_ARGS__);	\
	}							\
})

/*
 * Print the instruction address, the instruction and a message.
 */
#define TRACE_INSN(insn, fmt, ...)				\
({								\
	if (trace) {						\
		disas_print_insn(stderr, objtool_disas_ctx,	\
				 insn, trace_depth - 1,		\
				 fmt, ##__VA_ARGS__);		\
		fprintf(stderr, "\n");				\
		insn->trace = 1;				\
	}							\
})

#define TRACE_INSN_STATE(insn, sprev, snext)			\
({								\
	if (trace)						\
		trace_insn_state(insn, sprev, snext);		\
})

#define TRACE_ALT_FMT(pfx, fmt) pfx "<%s.%lx> " fmt
#define TRACE_ALT_ARG(insn) disas_alt_type_name(insn), (insn)->offset

#define TRACE_ALT(insn, fmt, ...)				\
	TRACE_INSN(insn, TRACE_ALT_FMT("", fmt),		\
		   TRACE_ALT_ARG(insn), ##__VA_ARGS__)

#define TRACE_ALT_INFO(insn, pfx, fmt, ...)			\
	TRACE_ADDR(insn, TRACE_ALT_FMT(pfx, fmt),		\
		   TRACE_ALT_ARG(insn), ##__VA_ARGS__)

#define TRACE_ALT_INFO_NOADDR(insn, pfx, fmt, ...)		\
	TRACE_ADDR(NULL, TRACE_ALT_FMT(pfx, fmt),		\
		   TRACE_ALT_ARG(insn), ##__VA_ARGS__)

#define TRACE_ALT_BEGIN(insn, alt, alt_name)			\
({								\
	if (trace) {						\
		alt_name = disas_alt_name(alt);			\
		trace_alt_begin(insn, alt, alt_name);		\
	}							\
})

#define TRACE_ALT_END(insn, alt, alt_name)			\
({								\
	if (trace) {						\
		trace_alt_end(insn, alt, alt_name);		\
		free(alt_name);					\
	}							\
})

static inline void trace_enable(void)
{
	trace = true;
	trace_depth = 0;
}

static inline void trace_disable(void)
{
	trace = false;
}

static inline void trace_depth_inc(void)
{
	if (trace)
		trace_depth++;
}

static inline void trace_depth_dec(void)
{
	if (trace)
		trace_depth--;
}

void trace_insn_state(struct instruction *insn, struct insn_state *sprev,
		      struct insn_state *snext);
void trace_alt_begin(struct instruction *orig_insn, struct alternative *alt,
		     char *alt_name);
void trace_alt_end(struct instruction *orig_insn, struct alternative *alt,
		   char *alt_name);

#else /* DISAS */

#define TRACE(fmt, ...) ({})
#define TRACE_ADDR(insn, fmt, ...) ({})
#define TRACE_INSN(insn, fmt, ...) ({})
#define TRACE_INSN_STATE(insn, sprev, snext) ({})
#define TRACE_ALT(insn, fmt, ...) ({})
#define TRACE_ALT_INFO(insn, fmt, ...) ({})
#define TRACE_ALT_INFO_NOADDR(insn, fmt, ...) ({})
#define TRACE_ALT_BEGIN(insn, alt, alt_name) ({})
#define TRACE_ALT_END(insn, alt, alt_name) ({})


static inline void trace_enable(void) {}
static inline void trace_disable(void) {}
static inline void trace_depth_inc(void) {}
static inline void trace_depth_dec(void) {}
static inline void trace_alt_begin(struct instruction *orig_insn,
				   struct alternative *alt,
				   char *alt_name) {};
static inline void trace_alt_end(struct instruction *orig_insn,
				 struct alternative *alt,
				 char *alt_name) {};

#endif

#endif /* _TRACE_H */