From 63c87031c8d701b0651287c6e681b3987284e886 Mon Sep 17 00:00:00 2001 Message-Id: <63c87031c8d701b0651287c6e681b3987284e886.1349774431.git.minovotn@redhat.com> In-Reply-To: References: From: Luiz Capitulino Date: Fri, 5 Oct 2012 17:46:22 +0200 Subject: [PATCH 10/21] target-i386: Add API to write elf notes to core file RH-Author: Luiz Capitulino Message-id: <1349459193-18226-9-git-send-email-lcapitulino@redhat.com> Patchwork-id: 42756 O-Subject: [RHEL6.4 qemu-kvm PATCH 08/19] target-i386: Add API to write elf notes to core file Bugzilla: 832458 RH-Acked-by: Marcelo Tosatti RH-Acked-by: Markus Armbruster RH-Acked-by: Paolo Bonzini From: Wen Congyang 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 Signed-off-by: Luiz Capitulino (cherry picked from commit 9fecbed0c03ddad63c27f1622e2002fdfc2f45e4) Conflicts: configure Signed-off-by: Luiz Capitulino --- Makefile.target | 1 + configure | 4 + cpu-all.h | 22 +++++ target-i386/arch_dump.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 target-i386/arch_dump.c Signed-off-by: Michal Novotny --- Makefile.target | 1 + configure | 4 + cpu-all.h | 22 +++++ target-i386/arch_dump.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 target-i386/arch_dump.c diff --git a/Makefile.target b/Makefile.target index 80f4536..26f0e93 100644 --- a/Makefile.target +++ b/Makefile.target @@ -216,6 +216,7 @@ obj-y += msix.o obj-$(CONFIG_ISA_MMIO) += isa_mmio.o obj-y += memory_mapping.o obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o +obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o LIBS+=-lz sound-obj-y = diff --git a/configure b/configure index 83c2e95..63b68e0 100755 --- a/configure +++ b/configure @@ -2904,6 +2904,10 @@ if test "$target_softmmu" = "yes" ; then echo "LIBS+=$libs_softmmu" >> $config_target_mak echo "HWDIR=../libhw$target_phys_bits" >> $config_target_mak echo "subdir-$target: subdir-libhw$target_phys_bits" >> $config_host_mak + 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 8f6b8f9..3baedb2 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -1121,4 +1121,26 @@ static inline bool cpu_paging_enabled(CPUArchState *env) } #endif +typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque); +#if defined(CONFIG_HAVE_CORE_DUMP) +int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env, + int cpuid, void *opaque); +int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env, + int cpuid, void *opaque); +#else +static inline int cpu_write_elf64_note(write_core_dump_function f, + CPUArchState *env, int cpuid, + void *opaque) +{ + return -1; +} + +static inline int cpu_write_elf32_note(write_core_dump_function f, + CPUArchState *env, int cpuid, + 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..d55c2ce --- /dev/null +++ b/target-i386/arch_dump.c @@ -0,0 +1,233 @@ +/* + * i386 memory mapping + * + * Copyright Fujitsu, Corp. 2011, 2012 + * + * Authors: + * Wen Congyang + * + * 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; + +typedef struct { + char pad1[32]; + uint32_t pid; + char pad2[76]; + x86_64_user_regs_struct regs; + char pad3[8]; +} x86_64_elf_prstatus; + +static int x86_64_write_elf64_note(write_core_dump_function f, + CPUArchState *env, int id, + 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 = sizeof(x86_64_elf_prstatus); + 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(note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + 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; + +typedef struct { + char pad1[24]; + uint32_t pid; + char pad2[44]; + x86_user_regs_struct regs; + char pad3[4]; +} x86_elf_prstatus; + +static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env, + int id) +{ + memset(prstatus, 0, sizeof(x86_elf_prstatus)); + prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff; + prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff; + prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff; + prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff; + prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff; + prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff; + prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff; + prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff; + prstatus->regs.eip = env->eip & 0xffffffff; + prstatus->regs.eflags = env->eflags & 0xffffffff; + + prstatus->regs.cs = env->segs[R_CS].selector; + prstatus->regs.ss = env->segs[R_SS].selector; + prstatus->regs.ds = env->segs[R_DS].selector; + prstatus->regs.es = env->segs[R_ES].selector; + prstatus->regs.fs = env->segs[R_FS].selector; + prstatus->regs.gs = env->segs[R_GS].selector; + + prstatus->pid = id; +} + +static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env, + int id, void *opaque) +{ + x86_elf_prstatus prstatus; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + x86_fill_elf_prstatus(&prstatus, env, id); + descsz = sizeof(x86_elf_prstatus); + 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, &prstatus, sizeof(prstatus)); + + ret = f(note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + return 0; +} + +int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env, + int cpuid, 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, opaque); + } else { +#endif + ret = x86_write_elf64_note(f, env, cpuid, opaque); +#ifdef TARGET_X86_64 + } +#endif + + return ret; +} + +int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env, + int cpuid, void *opaque) +{ + x86_elf_prstatus prstatus; + Elf32_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + x86_fill_elf_prstatus(&prstatus, env, cpuid); + descsz = sizeof(x86_elf_prstatus); + 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, &prstatus, sizeof(prstatus)); + + ret = f(note, note_size, opaque); + g_free(note); + if (ret < 0) { + return -1; + } + + return 0; +} -- 1.7.11.4