From 35e24960e2af30ded0fe586f4944192ee4b0536d Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 18 Jun 2024 16:21:01 -0700 Subject: [PATCH] Disassemble instructions using current CPU state While this means we have to allocate a temporary buffer for the textual trace format, I don't see another workaround for the fact that we print the instruction disassembly after the instruction has executed and therefore has modified state (such as env->thumb) that affects the disassembly of instructions. Fixes: https://github.com/CTSRD-CHERI/qemu/issues/255 --- accel/tcg/log_instr.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/accel/tcg/log_instr.c b/accel/tcg/log_instr.c index edffa5d87a..0fecab44a2 100644 --- a/accel/tcg/log_instr.c +++ b/accel/tcg/log_instr.c @@ -121,6 +121,7 @@ typedef struct cpu_log_instr_info { /* Generic instruction opcode buffer */ int insn_size; char insn_bytes[TARGET_MAX_INSN_SIZE]; + char *insn_disas_text; /* Only needed for text output format. */ #define cpu_log_iinfo_endzero mem /* * For now we allow multiple accesses to be tied to one instruction. @@ -349,8 +350,9 @@ static void emit_text_entry(CPUArchState *env, cpu_log_instr_info_t *iinfo) rcu_read_lock(); logfile = qatomic_rcu_read(&qemu_logfile); if (logfile) { - target_disas_buf(logfile->fd, env_cpu(env), iinfo->insn_bytes, - sizeof(iinfo->insn_bytes), iinfo->pc, 1); + fprintf(logfile->fd, "%s", iinfo->insn_disas_text); + free(iinfo->insn_disas_text); + iinfo->insn_disas_text = NULL; } rcu_read_unlock(); @@ -1058,6 +1060,18 @@ void qemu_log_instr(CPUArchState *env, target_ulong pc, const char *insn, iinfo->pc = pc; iinfo->insn_size = size; memcpy(iinfo->insn_bytes, insn, size); + if (qemu_log_instr_format == QLI_FMT_TEXT) { + /* + * We have to diassemble now, since instruction side-effects could + * change the CPU execution mode. + */ + size_t disas_len = 0; + FILE *stream = open_memstream(&iinfo->insn_disas_text, &disas_len); + target_disas_buf(stream, env_cpu(env), iinfo->insn_bytes, + iinfo->insn_size, iinfo->pc, 1); + fclose(stream); + /* Allocated buffer is freed in log_instr_emit(). */ + } } void qemu_log_instr_asid(CPUArchState *env, uint16_t asid)