linux-user: Add guest memory layout to exception dump
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>
This commit is contained in:
parent
35a2c85f7d
commit
bd5ccd6108
@ -23,18 +23,9 @@
|
|||||||
#include "exec/log.h"
|
#include "exec/log.h"
|
||||||
#include "special-errno.h"
|
#include "special-errno.h"
|
||||||
|
|
||||||
#define EXCP_DUMP(env, fmt, ...) \
|
void target_exception_dump(CPUArchState *env, const char *fmt, int code);
|
||||||
do { \
|
#define EXCP_DUMP(env, fmt, code) \
|
||||||
CPUState *cs = env_cpu(env); \
|
target_exception_dump(env, fmt, code)
|
||||||
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_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs);
|
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -201,7 +201,6 @@ void cpu_loop(CPUX86State *env)
|
|||||||
{
|
{
|
||||||
CPUState *cs = env_cpu(env);
|
CPUState *cs = env_cpu(env);
|
||||||
int trapnr;
|
int trapnr;
|
||||||
abi_ulong pc;
|
|
||||||
abi_ulong ret;
|
abi_ulong ret;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -307,9 +306,8 @@ void cpu_loop(CPUX86State *env)
|
|||||||
cpu_exec_step_atomic(cs);
|
cpu_exec_step_atomic(cs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pc = env->segs[R_CS].base + env->eip;
|
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n",
|
||||||
EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n",
|
trapnr);
|
||||||
(long)pc, trapnr);
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
process_pending_signals(env);
|
process_pending_signals(env);
|
||||||
|
@ -183,6 +183,7 @@ struct file_clone_range {
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "fd-trans.h"
|
#include "fd-trans.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
|
#include "cpu_loop-common.h"
|
||||||
|
|
||||||
#ifndef CLONE_IO
|
#ifndef CLONE_IO
|
||||||
#define CLONE_IO 0x80000000 /* Clone io context */
|
#define CLONE_IO 0x80000000 /* Clone io context */
|
||||||
@ -8169,6 +8170,33 @@ static int is_proc_myself(const char *filename, const char *entry)
|
|||||||
return 0;
|
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 || \
|
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
|
||||||
defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
|
defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
|
||||||
static int is_proc(const char *filename, const char *entry)
|
static int is_proc(const char *filename, const char *entry)
|
||||||
|
Loading…
Reference in New Issue
Block a user