The core file has register's value. But it does not include all register. Store the cpu status into QEMU note, and the user can get more information from vmcore.
Signed-off-by: Wen Congyang <we...@cn.fujitsu.com> --- cpu-all.h | 20 ++++++ target-i386/arch_dump.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 0 deletions(-) diff --git a/cpu-all.h b/cpu-all.h index f7c6321..ad69269 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -540,6 +540,10 @@ 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); +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque); +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque); #else static inline int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid, @@ -554,6 +558,22 @@ static inline int cpu_write_elf32_note(write_core_dump_function f, { return -1; } + +static inline int cpu_write_elf64_qemunote(write_core_dump_function f, + CPUState *env, + target_phys_addr_t *offset, + void *opaque); +{ + return -1; +} + +static inline int cpu_write_elf32_qemunote(write_core_dump_function f, + CPUState *env, + 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 index 3239c40..560c8a3 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -247,3 +247,157 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, return 0; } + +struct QEMUCPUSegment { + uint32_t selector; + uint32_t limit; + uint32_t flags; + uint32_t pad; + uint64_t base; +}; + +typedef struct QEMUCPUSegment QEMUCPUSegment; + +struct QEMUCPUState { + uint32_t version; + uint32_t size; + uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; + uint64_t r8, r9, r10, r11, r12, r13, r14, r15; + uint64_t rip, rflags; + QEMUCPUSegment cs, ds, es, fs, gs, ss; + QEMUCPUSegment ldt, tr, gdt, idt; + uint64_t cr[5]; +}; + +typedef struct QEMUCPUState QEMUCPUState; + +static void copy_segment(QEMUCPUSegment *d, SegmentCache *s) +{ + d->pad = 0; + d->selector = s->selector; + d->limit = s->limit; + d->flags = s->flags; + d->base = s->base; +} + +static void qemu_get_cpustate(QEMUCPUState *s, CPUState *env) +{ + memset(s, 0, sizeof(QEMUCPUState)); + + s->version = 1; + s->size = sizeof(QEMUCPUState); + + s->rax = env->regs[R_EAX]; + s->rbx = env->regs[R_EBX]; + s->rcx = env->regs[R_ECX]; + s->rdx = env->regs[R_EDX]; + s->rsi = env->regs[R_ESI]; + s->rdi = env->regs[R_EDI]; + s->rsp = env->regs[R_ESP]; + s->rbp = env->regs[R_EBP]; +#ifdef TARGET_X86_64 + s->r8 = env->regs[8]; + s->r9 = env->regs[9]; + s->r10 = env->regs[10]; + s->r11 = env->regs[11]; + s->r12 = env->regs[12]; + s->r13 = env->regs[13]; + s->r14 = env->regs[14]; + s->r15 = env->regs[15]; +#endif + s->rip = env->eip; + s->rflags = env->eflags; + + copy_segment(&s->cs, &env->segs[R_CS]); + copy_segment(&s->ds, &env->segs[R_DS]); + copy_segment(&s->es, &env->segs[R_ES]); + copy_segment(&s->fs, &env->segs[R_FS]); + copy_segment(&s->gs, &env->segs[R_GS]); + copy_segment(&s->ss, &env->segs[R_SS]); + copy_segment(&s->ldt, &env->ldt); + copy_segment(&s->tr, &env->tr); + copy_segment(&s->gdt, &env->gdt); + copy_segment(&s->idt, &env->idt); + + s->cr[0] = env->cr[0]; + s->cr[1] = env->cr[1]; + s->cr[2] = env->cr[2]; + s->cr[3] = env->cr[3]; + s->cr[4] = env->cr[4]; +} + +int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque) +{ + QEMUCPUState state; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "QEMU"; + int ret; + + qemu_get_cpustate(&state, env); + + descsz = sizeof(state); + 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 = 0; + buf = (char *)note; + buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf, &state, sizeof(state)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} + +int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env, + target_phys_addr_t *offset, void *opaque) +{ + QEMUCPUState state; + Elf32_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "QEMU"; + int ret; + + qemu_get_cpustate(&state, env); + + descsz = sizeof(state); + 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 = 0; + buf = (char *)note; + buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + memcpy(buf, &state, sizeof(state)); + + ret = f(*offset, note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + *offset += note_size; + + return 0; +} -- 1.7.1