Skip to content

Commit

Permalink
linux-user: Add guest memory layout to exception dump
Browse files Browse the repository at this point in the history
When the emulation stops with a hard exception it's very useful for
debugging purposes to dump the current guest memory layout (for an
example see /proc/self/maps) beside the CPU registers.

The open_self_maps() function provides such a memory dump, but since
it's located in the syscall.c file, various changes (add #includes, make
this function externally visible, ...) are needed to be able to call it
from the existing EXCP_DUMP() macro.

This patch takes another approach by re-defining EXCP_DUMP() to call
target_exception_dump(), which is in syscall.c, consolidates the log
print functions and allows to add the call to dump the memory layout.

Beside a reduced code footprint, this approach keeps the changes across
the various callers minimal, and keeps EXCP_DUMP() highlighted as
important macro/function.

Signed-off-by: Helge Deller <deller@gmx.de>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <Y1bzAWbw07WBKPxw@p100>
[lv: remove pc declaration and setting]
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
  • Loading branch information
hdeller authored and vivier committed Oct 25, 2022
1 parent 35a2c85 commit bd5ccd6
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 16 deletions.
15 changes: 3 additions & 12 deletions linux-user/cpu_loop-common.h
Expand Up @@ -23,18 +23,9 @@
#include "exec/log.h"
#include "special-errno.h"

#define EXCP_DUMP(env, fmt, ...) \
do { \
CPUState *cs = env_cpu(env); \
fprintf(stderr, fmt , ## __VA_ARGS__); \
fprintf(stderr, "Failing executable: %s\n", exec_path); \
cpu_dump_state(cs, stderr, 0); \
if (qemu_log_separate()) { \
qemu_log(fmt, ## __VA_ARGS__); \
qemu_log("Failing executable: %s\n", exec_path); \
log_cpu_state(cs, 0); \
} \
} while (0)
void target_exception_dump(CPUArchState *env, const char *fmt, int code);
#define EXCP_DUMP(env, fmt, code) \
target_exception_dump(env, fmt, code)

void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs);
#endif
6 changes: 2 additions & 4 deletions linux-user/i386/cpu_loop.c
Expand Up @@ -201,7 +201,6 @@ void cpu_loop(CPUX86State *env)
{
CPUState *cs = env_cpu(env);
int trapnr;
abi_ulong pc;
abi_ulong ret;

for(;;) {
Expand Down Expand Up @@ -307,9 +306,8 @@ void cpu_loop(CPUX86State *env)
cpu_exec_step_atomic(cs);
break;
default:
pc = env->segs[R_CS].base + env->eip;
EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
(long)pc, trapnr);
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
trapnr);
abort();
}
process_pending_signals(env);
Expand Down
28 changes: 28 additions & 0 deletions linux-user/syscall.c
Expand Up @@ -183,6 +183,7 @@ struct file_clone_range {
#include "qapi/error.h"
#include "fd-trans.h"
#include "tcg/tcg.h"
#include "cpu_loop-common.h"

#ifndef CLONE_IO
#define CLONE_IO 0x80000000 /* Clone io context */
Expand Down Expand Up @@ -8169,6 +8170,33 @@ static int is_proc_myself(const char *filename, const char *entry)
return 0;
}

static void excp_dump_file(FILE *logfile, CPUArchState *env,
const char *fmt, int code)
{
if (logfile) {
CPUState *cs = env_cpu(env);

fprintf(logfile, fmt, code);
fprintf(logfile, "Failing executable: %s\n", exec_path);
cpu_dump_state(cs, logfile, 0);
open_self_maps(env, fileno(logfile));
}
}

void target_exception_dump(CPUArchState *env, const char *fmt, int code)
{
/* dump to console */
excp_dump_file(stderr, env, fmt, code);

/* dump to log file */
if (qemu_log_separate()) {
FILE *logfile = qemu_log_trylock();

excp_dump_file(logfile, env, fmt, code);
qemu_log_unlock(logfile);
}
}

#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
static int is_proc(const char *filename, const char *entry)
Expand Down

0 comments on commit bd5ccd6

Please sign in to comment.