The core file contains register's value. These APIs write registers to core file, and them will be called in the following patch.
Signed-off-by: Wen Congyang <we...@cn.fujitsu.com> --- Makefile.target | 1 + configure | 4 + cpu-all.h | 23 +++++ target-i386/arch_dump.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 target-i386/arch_dump.c diff --git a/Makefile.target b/Makefile.target index a87e678..cfd3113 100644 --- a/Makefile.target +++ b/Makefile.target @@ -210,6 +210,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o obj-$(CONFIG_VGA) += vga.o obj-y += memory.o savevm.o obj-y += memory_mapping.o +obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o LIBS+=-lz obj-i386-$(CONFIG_KVM) += hyperv.o diff --git a/configure b/configure index 61821fc..bcbd5d1 100755 --- a/configure +++ b/configure @@ -3662,6 +3662,10 @@ if test "$target_softmmu" = "yes" ; then if test "$smartcard_nss" = "yes" ; then echo "subdir-$target: subdir-libcacard" >> $config_host_mak fi + case "$target_arch2" in + i386|x86_64) + echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak + esac fi if test "$target_user_only" = "yes" ; then echo "CONFIG_USER_ONLY=y" >> $config_target_mak diff --git a/cpu-all.h b/cpu-all.h index 01c3c23..e476401 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -539,4 +539,27 @@ static inline bool cpu_paging_enabled(CPUState *env) } #endif +typedef int (*write_core_dump_function) + (target_phys_addr_t offset, void *buf, size_t size, void *opaque); +#if defined(CONFIG_HAVE_CORE_DUMP) +int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque); +int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque); +#else +static inline int cpu_write_elf64_note(write_core_dump_function f, + CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque) +{ + return -1; +} + +static inline int cpu_write_elf32_note(write_core_dump_function f, + CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque) +{ + return -1; +} +#endif + #endif /* CPU_ALL_H */ diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c new file mode 100644 index 0000000..3239c40 --- /dev/null +++ b/target-i386/arch_dump.c @@ -0,0 +1,249 @@ +/* + * i386 memory mapping + * + * Copyright Fujitsu, Corp. 2011 + * + * Authors: + * Wen Congyang <we...@cn.fujitsu.com> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "cpu.h" +#include "cpu-all.h" +#include "elf.h" + +#ifdef TARGET_X86_64 +typedef struct { + target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10; + target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax; + target_ulong rip, cs, eflags; + target_ulong rsp, ss; + target_ulong fs_base, gs_base; + target_ulong ds, es, fs, gs; +} x86_64_user_regs_struct; + +static int x86_64_write_elf64_note(write_core_dump_function f, CPUState *env, + int id, target_phys_addr_t *offset, + void *opaque) +{ + x86_64_user_regs_struct regs; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + regs.r15 = env->regs[15]; + regs.r14 = env->regs[14]; + regs.r13 = env->regs[13]; + regs.r12 = env->regs[12]; + regs.r11 = env->regs[11]; + regs.r10 = env->regs[10]; + regs.r9 = env->regs[9]; + regs.r8 = env->regs[8]; + regs.rbp = env->regs[R_EBP]; + regs.rsp = env->regs[R_ESP]; + regs.rdi = env->regs[R_EDI]; + regs.rsi = env->regs[R_ESI]; + regs.rdx = env->regs[R_EDX]; + regs.rcx = env->regs[R_ECX]; + regs.rbx = env->regs[R_EBX]; + regs.rax = env->regs[R_EAX]; + regs.rip = env->eip; + regs.eflags = env->eflags; + + regs.orig_rax = 0; /* FIXME */ + regs.cs = env->segs[R_CS].selector; + regs.ss = env->segs[R_SS].selector; + regs.fs_base = env->segs[R_FS].base; + regs.gs_base = env->segs[R_GS].base; + regs.ds = env->segs[R_DS].selector; + regs.es = env->segs[R_ES].selector; + regs.fs = env->segs[R_FS].selector; + regs.gs = env->segs[R_GS].selector; + + descsz = 336; /* sizeof(prstatus_t) is 336 on x86_64 box */ + note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + note->n_namesz = cpu_to_le32(name_size); + note->n_descsz = cpu_to_le32(descsz); + note->n_type = cpu_to_le32(NT_PRSTATUS); + buf = (char *)note; + buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf + 32, &id, 4); /* pr_pid */ + buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong); + memcpy(buf, ®s, sizeof(x86_64_user_regs_struct)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} +#endif + +typedef struct { + uint32_t ebx, ecx, edx, esi, edi, ebp, eax; + unsigned short ds, __ds, es, __es; + unsigned short fs, __fs, gs, __gs; + uint32_t orig_eax, eip; + unsigned short cs, __cs; + uint32_t eflags, esp; + unsigned short ss, __ss; +} x86_user_regs_struct; + +static int x86_write_elf64_note(write_core_dump_function f, CPUState *env, + int id, target_phys_addr_t *offset, + void *opaque) +{ + x86_user_regs_struct regs; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + regs.ebp = env->regs[R_EBP] & 0xffffffff; + regs.esp = env->regs[R_ESP] & 0xffffffff; + regs.edi = env->regs[R_EDI] & 0xffffffff; + regs.esi = env->regs[R_ESI] & 0xffffffff; + regs.edx = env->regs[R_EDX] & 0xffffffff; + regs.ecx = env->regs[R_ECX] & 0xffffffff; + regs.ebx = env->regs[R_EBX] & 0xffffffff; + regs.eax = env->regs[R_EAX] & 0xffffffff; + regs.eip = env->eip & 0xffffffff; + regs.eflags = env->eflags & 0xffffffff; + + regs.cs = env->segs[R_CS].selector; + regs.__cs = 0; + regs.ss = env->segs[R_SS].selector; + regs.__ss = 0; + regs.ds = env->segs[R_DS].selector; + regs.__ds = 0; + regs.es = env->segs[R_ES].selector; + regs.__es = 0; + regs.fs = env->segs[R_FS].selector; + regs.__fs = 0; + regs.gs = env->segs[R_GS].selector; + regs.__gs = 0; + + descsz = 144; /* sizeof(prstatus_t) is 144 on x86 box */ + note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + note->n_namesz = cpu_to_le32(name_size); + note->n_descsz = cpu_to_le32(descsz); + note->n_type = cpu_to_le32(NT_PRSTATUS); + buf = (char *)note; + buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf + 24, &id, 4); /* pr_pid */ + buf += descsz - sizeof(x86_user_regs_struct)-4; + memcpy(buf, ®s, sizeof(x86_user_regs_struct)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} + +int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque) +{ + int ret; +#ifdef TARGET_X86_64 + bool lma = !!(first_cpu->hflags & HF_LMA_MASK); + + if (lma) { + ret = x86_64_write_elf64_note(f, env, cpuid, offset, opaque); + } else { +#endif + ret = x86_write_elf64_note(f, env, cpuid, offset, opaque); +#ifdef TARGET_X86_64 + } +#endif + + return ret; +} + +int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, + target_phys_addr_t *offset, void *opaque) +{ + x86_user_regs_struct regs; + Elf32_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + regs.ebp = env->regs[R_EBP] & 0xffffffff; + regs.esp = env->regs[R_ESP] & 0xffffffff; + regs.edi = env->regs[R_EDI] & 0xffffffff; + regs.esi = env->regs[R_ESI] & 0xffffffff; + regs.edx = env->regs[R_EDX] & 0xffffffff; + regs.ecx = env->regs[R_ECX] & 0xffffffff; + regs.ebx = env->regs[R_EBX] & 0xffffffff; + regs.eax = env->regs[R_EAX] & 0xffffffff; + regs.eip = env->eip & 0xffffffff; + regs.eflags = env->eflags & 0xffffffff; + + regs.cs = env->segs[R_CS].selector; + regs.__cs = 0; + regs.ss = env->segs[R_SS].selector; + regs.__ss = 0; + regs.ds = env->segs[R_DS].selector; + regs.__ds = 0; + regs.es = env->segs[R_ES].selector; + regs.__es = 0; + regs.fs = env->segs[R_FS].selector; + regs.__fs = 0; + regs.gs = env->segs[R_GS].selector; + regs.__gs = 0; + + descsz = 144; /* sizeof(prstatus_t) is 144 on x86 box */ + note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz + 3) / 4) * 4; + note = g_malloc(note_size); + + memset(note, 0, note_size); + note->n_namesz = cpu_to_le32(name_size); + note->n_descsz = cpu_to_le32(descsz); + note->n_type = cpu_to_le32(NT_PRSTATUS); + buf = (char *)note; + buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf + 24, &cpuid, 4); /* pr_pid */ + buf += descsz - sizeof(x86_user_regs_struct)-4; + memcpy(buf, ®s, sizeof(x86_user_regs_struct)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} -- 1.7.1