142 lines
3.3 KiB
C
142 lines
3.3 KiB
C
/* 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 */
|