/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (c) 2025, Oracle and/or its affiliates. */ #ifndef _TRACE_H #define _TRACE_H #include #include #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 */