xref: /qemu/target/i386/arch_dump.c (revision 18a1f0d767852a7d6a000bffeb65d8825ae83a79)
19fecbed0SWen Congyang /*
29fecbed0SWen Congyang  * i386 memory mapping
39fecbed0SWen Congyang  *
49fecbed0SWen Congyang  * Copyright Fujitsu, Corp. 2011, 2012
59fecbed0SWen Congyang  *
69fecbed0SWen Congyang  * Authors:
79fecbed0SWen Congyang  *     Wen Congyang <wency@cn.fujitsu.com>
89fecbed0SWen Congyang  *
9fc0608acSStefan Weil  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10fc0608acSStefan Weil  * See the COPYING file in the top-level directory.
119fecbed0SWen Congyang  *
129fecbed0SWen Congyang  */
139fecbed0SWen Congyang 
14b6a0aa05SPeter Maydell #include "qemu/osdep.h"
159fecbed0SWen Congyang #include "cpu.h"
16022c62cbSPaolo Bonzini #include "exec/cpu-all.h"
179c17d615SPaolo Bonzini #include "sysemu/dump.h"
189fecbed0SWen Congyang #include "elf.h"
1956c4bfb3SLaszlo Ersek #include "sysemu/memory_mapping.h"
209fecbed0SWen Congyang 
21*18a1f0d7SMarc-André Lureau #define ELF_NOTE_SIZE(hdr_size, name_size, desc_size)   \
22*18a1f0d7SMarc-André Lureau     ((DIV_ROUND_UP((hdr_size), 4)                       \
23*18a1f0d7SMarc-André Lureau       + DIV_ROUND_UP((name_size), 4)                    \
24*18a1f0d7SMarc-André Lureau       + DIV_ROUND_UP((desc_size), 4)) * 4)
25*18a1f0d7SMarc-André Lureau 
269fecbed0SWen Congyang #ifdef TARGET_X86_64
279fecbed0SWen Congyang typedef struct {
289fecbed0SWen Congyang     target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
299fecbed0SWen Congyang     target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
309fecbed0SWen Congyang     target_ulong rip, cs, eflags;
319fecbed0SWen Congyang     target_ulong rsp, ss;
329fecbed0SWen Congyang     target_ulong fs_base, gs_base;
339fecbed0SWen Congyang     target_ulong ds, es, fs, gs;
349fecbed0SWen Congyang } x86_64_user_regs_struct;
359fecbed0SWen Congyang 
369fecbed0SWen Congyang typedef struct {
379fecbed0SWen Congyang     char pad1[32];
389fecbed0SWen Congyang     uint32_t pid;
399fecbed0SWen Congyang     char pad2[76];
409fecbed0SWen Congyang     x86_64_user_regs_struct regs;
419fecbed0SWen Congyang     char pad3[8];
429fecbed0SWen Congyang } x86_64_elf_prstatus;
439fecbed0SWen Congyang 
44c72bf468SJens Freimann static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
45369ff018SAndreas Färber                                    CPUX86State *env, int id,
469fecbed0SWen Congyang                                    void *opaque)
479fecbed0SWen Congyang {
489fecbed0SWen Congyang     x86_64_user_regs_struct regs;
499fecbed0SWen Congyang     Elf64_Nhdr *note;
509fecbed0SWen Congyang     char *buf;
519fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
529fecbed0SWen Congyang     const char *name = "CORE";
539fecbed0SWen Congyang     int ret;
549fecbed0SWen Congyang 
559fecbed0SWen Congyang     regs.r15 = env->regs[15];
569fecbed0SWen Congyang     regs.r14 = env->regs[14];
579fecbed0SWen Congyang     regs.r13 = env->regs[13];
589fecbed0SWen Congyang     regs.r12 = env->regs[12];
599fecbed0SWen Congyang     regs.r11 = env->regs[11];
609fecbed0SWen Congyang     regs.r10 = env->regs[10];
619fecbed0SWen Congyang     regs.r9  = env->regs[9];
629fecbed0SWen Congyang     regs.r8  = env->regs[8];
639fecbed0SWen Congyang     regs.rbp = env->regs[R_EBP];
649fecbed0SWen Congyang     regs.rsp = env->regs[R_ESP];
659fecbed0SWen Congyang     regs.rdi = env->regs[R_EDI];
669fecbed0SWen Congyang     regs.rsi = env->regs[R_ESI];
679fecbed0SWen Congyang     regs.rdx = env->regs[R_EDX];
689fecbed0SWen Congyang     regs.rcx = env->regs[R_ECX];
699fecbed0SWen Congyang     regs.rbx = env->regs[R_EBX];
709fecbed0SWen Congyang     regs.rax = env->regs[R_EAX];
719fecbed0SWen Congyang     regs.rip = env->eip;
729fecbed0SWen Congyang     regs.eflags = env->eflags;
739fecbed0SWen Congyang 
749fecbed0SWen Congyang     regs.orig_rax = 0; /* FIXME */
759fecbed0SWen Congyang     regs.cs = env->segs[R_CS].selector;
769fecbed0SWen Congyang     regs.ss = env->segs[R_SS].selector;
779fecbed0SWen Congyang     regs.fs_base = env->segs[R_FS].base;
789fecbed0SWen Congyang     regs.gs_base = env->segs[R_GS].base;
799fecbed0SWen Congyang     regs.ds = env->segs[R_DS].selector;
809fecbed0SWen Congyang     regs.es = env->segs[R_ES].selector;
819fecbed0SWen Congyang     regs.fs = env->segs[R_FS].selector;
829fecbed0SWen Congyang     regs.gs = env->segs[R_GS].selector;
839fecbed0SWen Congyang 
849fecbed0SWen Congyang     descsz = sizeof(x86_64_elf_prstatus);
85*18a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
864be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
879fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
889fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
899fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
909fecbed0SWen Congyang     buf = (char *)note;
9117fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
929fecbed0SWen Congyang     memcpy(buf, name, name_size);
9317fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
949fecbed0SWen Congyang     memcpy(buf + 32, &id, 4); /* pr_pid */
959fecbed0SWen Congyang     buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
969fecbed0SWen Congyang     memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
979fecbed0SWen Congyang 
989fecbed0SWen Congyang     ret = f(note, note_size, opaque);
999fecbed0SWen Congyang     g_free(note);
1009fecbed0SWen Congyang     if (ret < 0) {
1019fecbed0SWen Congyang         return -1;
1029fecbed0SWen Congyang     }
1039fecbed0SWen Congyang 
1049fecbed0SWen Congyang     return 0;
1059fecbed0SWen Congyang }
1069fecbed0SWen Congyang #endif
1079fecbed0SWen Congyang 
1089fecbed0SWen Congyang typedef struct {
1099fecbed0SWen Congyang     uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
1109fecbed0SWen Congyang     unsigned short ds, __ds, es, __es;
1119fecbed0SWen Congyang     unsigned short fs, __fs, gs, __gs;
1129fecbed0SWen Congyang     uint32_t orig_eax, eip;
1139fecbed0SWen Congyang     unsigned short cs, __cs;
1149fecbed0SWen Congyang     uint32_t eflags, esp;
1159fecbed0SWen Congyang     unsigned short ss, __ss;
1169fecbed0SWen Congyang } x86_user_regs_struct;
1179fecbed0SWen Congyang 
1189fecbed0SWen Congyang typedef struct {
1199fecbed0SWen Congyang     char pad1[24];
1209fecbed0SWen Congyang     uint32_t pid;
1219fecbed0SWen Congyang     char pad2[44];
1229fecbed0SWen Congyang     x86_user_regs_struct regs;
1239fecbed0SWen Congyang     char pad3[4];
1249fecbed0SWen Congyang } x86_elf_prstatus;
1259fecbed0SWen Congyang 
126369ff018SAndreas Färber static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
1279fecbed0SWen Congyang                                   int id)
1289fecbed0SWen Congyang {
1299fecbed0SWen Congyang     memset(prstatus, 0, sizeof(x86_elf_prstatus));
1309fecbed0SWen Congyang     prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
1319fecbed0SWen Congyang     prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
1329fecbed0SWen Congyang     prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
1339fecbed0SWen Congyang     prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
1349fecbed0SWen Congyang     prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
1359fecbed0SWen Congyang     prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
1369fecbed0SWen Congyang     prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
1379fecbed0SWen Congyang     prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
1389fecbed0SWen Congyang     prstatus->regs.eip = env->eip & 0xffffffff;
1399fecbed0SWen Congyang     prstatus->regs.eflags = env->eflags & 0xffffffff;
1409fecbed0SWen Congyang 
1419fecbed0SWen Congyang     prstatus->regs.cs = env->segs[R_CS].selector;
1429fecbed0SWen Congyang     prstatus->regs.ss = env->segs[R_SS].selector;
1439fecbed0SWen Congyang     prstatus->regs.ds = env->segs[R_DS].selector;
1449fecbed0SWen Congyang     prstatus->regs.es = env->segs[R_ES].selector;
1459fecbed0SWen Congyang     prstatus->regs.fs = env->segs[R_FS].selector;
1469fecbed0SWen Congyang     prstatus->regs.gs = env->segs[R_GS].selector;
1479fecbed0SWen Congyang 
1489fecbed0SWen Congyang     prstatus->pid = id;
1499fecbed0SWen Congyang }
1509fecbed0SWen Congyang 
151369ff018SAndreas Färber static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
1529fecbed0SWen Congyang                                 int id, void *opaque)
1539fecbed0SWen Congyang {
1549fecbed0SWen Congyang     x86_elf_prstatus prstatus;
1559fecbed0SWen Congyang     Elf64_Nhdr *note;
1569fecbed0SWen Congyang     char *buf;
1579fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
1589fecbed0SWen Congyang     const char *name = "CORE";
1599fecbed0SWen Congyang     int ret;
1609fecbed0SWen Congyang 
1619fecbed0SWen Congyang     x86_fill_elf_prstatus(&prstatus, env, id);
1629fecbed0SWen Congyang     descsz = sizeof(x86_elf_prstatus);
163*18a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
1644be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
1659fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
1669fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
1679fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
1689fecbed0SWen Congyang     buf = (char *)note;
16917fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
1709fecbed0SWen Congyang     memcpy(buf, name, name_size);
17117fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
1729fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
1739fecbed0SWen Congyang 
1749fecbed0SWen Congyang     ret = f(note, note_size, opaque);
1759fecbed0SWen Congyang     g_free(note);
1769fecbed0SWen Congyang     if (ret < 0) {
1779fecbed0SWen Congyang         return -1;
1789fecbed0SWen Congyang     }
1799fecbed0SWen Congyang 
1809fecbed0SWen Congyang     return 0;
1819fecbed0SWen Congyang }
1829fecbed0SWen Congyang 
183c72bf468SJens Freimann int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
1849fecbed0SWen Congyang                              int cpuid, void *opaque)
1859fecbed0SWen Congyang {
186c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
1879fecbed0SWen Congyang     int ret;
1889fecbed0SWen Congyang #ifdef TARGET_X86_64
189182735efSAndreas Färber     X86CPU *first_x86_cpu = X86_CPU(first_cpu);
190182735efSAndreas Färber     bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
1919fecbed0SWen Congyang 
1929fecbed0SWen Congyang     if (lma) {
193c72bf468SJens Freimann         ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
1949fecbed0SWen Congyang     } else {
1959fecbed0SWen Congyang #endif
196c72bf468SJens Freimann         ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
1979fecbed0SWen Congyang #ifdef TARGET_X86_64
1989fecbed0SWen Congyang     }
1999fecbed0SWen Congyang #endif
2009fecbed0SWen Congyang 
2019fecbed0SWen Congyang     return ret;
2029fecbed0SWen Congyang }
2039fecbed0SWen Congyang 
204c72bf468SJens Freimann int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
2059fecbed0SWen Congyang                              int cpuid, void *opaque)
2069fecbed0SWen Congyang {
207c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
2089fecbed0SWen Congyang     x86_elf_prstatus prstatus;
2099fecbed0SWen Congyang     Elf32_Nhdr *note;
2109fecbed0SWen Congyang     char *buf;
2119fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
2129fecbed0SWen Congyang     const char *name = "CORE";
2139fecbed0SWen Congyang     int ret;
2149fecbed0SWen Congyang 
215c72bf468SJens Freimann     x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
2169fecbed0SWen Congyang     descsz = sizeof(x86_elf_prstatus);
217*18a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf32_Nhdr), name_size, descsz);
2184be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
2199fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
2209fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
2219fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
2229fecbed0SWen Congyang     buf = (char *)note;
22317fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf32_Nhdr), 4);
2249fecbed0SWen Congyang     memcpy(buf, name, name_size);
22517fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
2269fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
2279fecbed0SWen Congyang 
2289fecbed0SWen Congyang     ret = f(note, note_size, opaque);
2299fecbed0SWen Congyang     g_free(note);
2309fecbed0SWen Congyang     if (ret < 0) {
2319fecbed0SWen Congyang         return -1;
2329fecbed0SWen Congyang     }
2339fecbed0SWen Congyang 
2349fecbed0SWen Congyang     return 0;
2359fecbed0SWen Congyang }
23690166b71SWen Congyang 
23790166b71SWen Congyang /*
23890166b71SWen Congyang  * please count up QEMUCPUSTATE_VERSION if you have changed definition of
23990166b71SWen Congyang  * QEMUCPUState, and modify the tools using this information accordingly.
24090166b71SWen Congyang  */
24190166b71SWen Congyang #define QEMUCPUSTATE_VERSION (1)
24290166b71SWen Congyang 
24390166b71SWen Congyang struct QEMUCPUSegment {
24490166b71SWen Congyang     uint32_t selector;
24590166b71SWen Congyang     uint32_t limit;
24690166b71SWen Congyang     uint32_t flags;
24790166b71SWen Congyang     uint32_t pad;
24890166b71SWen Congyang     uint64_t base;
24990166b71SWen Congyang };
25090166b71SWen Congyang 
25190166b71SWen Congyang typedef struct QEMUCPUSegment QEMUCPUSegment;
25290166b71SWen Congyang 
25390166b71SWen Congyang struct QEMUCPUState {
25490166b71SWen Congyang     uint32_t version;
25590166b71SWen Congyang     uint32_t size;
25690166b71SWen Congyang     uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
25790166b71SWen Congyang     uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
25890166b71SWen Congyang     uint64_t rip, rflags;
25990166b71SWen Congyang     QEMUCPUSegment cs, ds, es, fs, gs, ss;
26090166b71SWen Congyang     QEMUCPUSegment ldt, tr, gdt, idt;
26190166b71SWen Congyang     uint64_t cr[5];
26290166b71SWen Congyang };
26390166b71SWen Congyang 
26490166b71SWen Congyang typedef struct QEMUCPUState QEMUCPUState;
26590166b71SWen Congyang 
26690166b71SWen Congyang static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
26790166b71SWen Congyang {
26890166b71SWen Congyang     d->pad = 0;
26990166b71SWen Congyang     d->selector = s->selector;
27090166b71SWen Congyang     d->limit = s->limit;
27190166b71SWen Congyang     d->flags = s->flags;
27290166b71SWen Congyang     d->base = s->base;
27390166b71SWen Congyang }
27490166b71SWen Congyang 
275369ff018SAndreas Färber static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
27690166b71SWen Congyang {
27790166b71SWen Congyang     memset(s, 0, sizeof(QEMUCPUState));
27890166b71SWen Congyang 
27990166b71SWen Congyang     s->version = QEMUCPUSTATE_VERSION;
28090166b71SWen Congyang     s->size = sizeof(QEMUCPUState);
28190166b71SWen Congyang 
28290166b71SWen Congyang     s->rax = env->regs[R_EAX];
28390166b71SWen Congyang     s->rbx = env->regs[R_EBX];
28490166b71SWen Congyang     s->rcx = env->regs[R_ECX];
28590166b71SWen Congyang     s->rdx = env->regs[R_EDX];
28690166b71SWen Congyang     s->rsi = env->regs[R_ESI];
28790166b71SWen Congyang     s->rdi = env->regs[R_EDI];
28890166b71SWen Congyang     s->rsp = env->regs[R_ESP];
28990166b71SWen Congyang     s->rbp = env->regs[R_EBP];
29090166b71SWen Congyang #ifdef TARGET_X86_64
29190166b71SWen Congyang     s->r8  = env->regs[8];
29290166b71SWen Congyang     s->r9  = env->regs[9];
29390166b71SWen Congyang     s->r10 = env->regs[10];
29490166b71SWen Congyang     s->r11 = env->regs[11];
29590166b71SWen Congyang     s->r12 = env->regs[12];
29690166b71SWen Congyang     s->r13 = env->regs[13];
29790166b71SWen Congyang     s->r14 = env->regs[14];
29890166b71SWen Congyang     s->r15 = env->regs[15];
29990166b71SWen Congyang #endif
30090166b71SWen Congyang     s->rip = env->eip;
30190166b71SWen Congyang     s->rflags = env->eflags;
30290166b71SWen Congyang 
30390166b71SWen Congyang     copy_segment(&s->cs, &env->segs[R_CS]);
30490166b71SWen Congyang     copy_segment(&s->ds, &env->segs[R_DS]);
30590166b71SWen Congyang     copy_segment(&s->es, &env->segs[R_ES]);
30690166b71SWen Congyang     copy_segment(&s->fs, &env->segs[R_FS]);
30790166b71SWen Congyang     copy_segment(&s->gs, &env->segs[R_GS]);
30890166b71SWen Congyang     copy_segment(&s->ss, &env->segs[R_SS]);
30990166b71SWen Congyang     copy_segment(&s->ldt, &env->ldt);
31090166b71SWen Congyang     copy_segment(&s->tr, &env->tr);
31190166b71SWen Congyang     copy_segment(&s->gdt, &env->gdt);
31290166b71SWen Congyang     copy_segment(&s->idt, &env->idt);
31390166b71SWen Congyang 
31490166b71SWen Congyang     s->cr[0] = env->cr[0];
31590166b71SWen Congyang     s->cr[1] = env->cr[1];
31690166b71SWen Congyang     s->cr[2] = env->cr[2];
31790166b71SWen Congyang     s->cr[3] = env->cr[3];
31890166b71SWen Congyang     s->cr[4] = env->cr[4];
31990166b71SWen Congyang }
32090166b71SWen Congyang 
321c72bf468SJens Freimann static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
322369ff018SAndreas Färber                                       CPUX86State *env,
32390166b71SWen Congyang                                       void *opaque,
32490166b71SWen Congyang                                       int type)
32590166b71SWen Congyang {
32690166b71SWen Congyang     QEMUCPUState state;
32790166b71SWen Congyang     Elf64_Nhdr *note64;
32890166b71SWen Congyang     Elf32_Nhdr *note32;
32990166b71SWen Congyang     void *note;
33090166b71SWen Congyang     char *buf;
33190166b71SWen Congyang     int descsz, note_size, name_size = 5, note_head_size;
33290166b71SWen Congyang     const char *name = "QEMU";
33390166b71SWen Congyang     int ret;
33490166b71SWen Congyang 
33590166b71SWen Congyang     qemu_get_cpustate(&state, env);
33690166b71SWen Congyang 
33790166b71SWen Congyang     descsz = sizeof(state);
33890166b71SWen Congyang     if (type == 0) {
33990166b71SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
34090166b71SWen Congyang     } else {
34190166b71SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
34290166b71SWen Congyang     }
343074d5afeSMarc-André Lureau     note_size = (DIV_ROUND_UP(note_head_size, 4) + DIV_ROUND_UP(name_size, 4) +
344074d5afeSMarc-André Lureau                 DIV_ROUND_UP(descsz, 4)) * 4;
3454be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
34690166b71SWen Congyang     if (type == 0) {
34790166b71SWen Congyang         note32 = note;
34890166b71SWen Congyang         note32->n_namesz = cpu_to_le32(name_size);
34990166b71SWen Congyang         note32->n_descsz = cpu_to_le32(descsz);
35090166b71SWen Congyang         note32->n_type = 0;
35190166b71SWen Congyang     } else {
35290166b71SWen Congyang         note64 = note;
35390166b71SWen Congyang         note64->n_namesz = cpu_to_le32(name_size);
35490166b71SWen Congyang         note64->n_descsz = cpu_to_le32(descsz);
35590166b71SWen Congyang         note64->n_type = 0;
35690166b71SWen Congyang     }
35790166b71SWen Congyang     buf = note;
35817fc7e93SMarc-André Lureau     buf += ROUND_UP(note_head_size, 4);
35990166b71SWen Congyang     memcpy(buf, name, name_size);
36017fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
36190166b71SWen Congyang     memcpy(buf, &state, sizeof(state));
36290166b71SWen Congyang 
36390166b71SWen Congyang     ret = f(note, note_size, opaque);
36490166b71SWen Congyang     g_free(note);
36590166b71SWen Congyang     if (ret < 0) {
36690166b71SWen Congyang         return -1;
36790166b71SWen Congyang     }
36890166b71SWen Congyang 
36990166b71SWen Congyang     return 0;
37090166b71SWen Congyang }
37190166b71SWen Congyang 
372c72bf468SJens Freimann int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
37390166b71SWen Congyang                                  void *opaque)
37490166b71SWen Congyang {
375c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
376c72bf468SJens Freimann 
377c72bf468SJens Freimann     return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
37890166b71SWen Congyang }
37990166b71SWen Congyang 
380c72bf468SJens Freimann int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
38190166b71SWen Congyang                                  void *opaque)
38290166b71SWen Congyang {
383c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
384c72bf468SJens Freimann 
385c72bf468SJens Freimann     return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
38690166b71SWen Congyang }
38725ae9c1dSWen Congyang 
38856c4bfb3SLaszlo Ersek int cpu_get_dump_info(ArchDumpInfo *info,
38956c4bfb3SLaszlo Ersek                       const GuestPhysBlockList *guest_phys_blocks)
39025ae9c1dSWen Congyang {
39125ae9c1dSWen Congyang     bool lma = false;
39256c4bfb3SLaszlo Ersek     GuestPhysBlock *block;
39325ae9c1dSWen Congyang 
39425ae9c1dSWen Congyang #ifdef TARGET_X86_64
395182735efSAndreas Färber     X86CPU *first_x86_cpu = X86_CPU(first_cpu);
396fd5d23baSIwona Kotlarska     lma = first_cpu && (first_x86_cpu->env.hflags & HF_LMA_MASK);
39725ae9c1dSWen Congyang #endif
39825ae9c1dSWen Congyang 
39925ae9c1dSWen Congyang     if (lma) {
40025ae9c1dSWen Congyang         info->d_machine = EM_X86_64;
40125ae9c1dSWen Congyang     } else {
40225ae9c1dSWen Congyang         info->d_machine = EM_386;
40325ae9c1dSWen Congyang     }
40425ae9c1dSWen Congyang     info->d_endian = ELFDATA2LSB;
40525ae9c1dSWen Congyang 
40625ae9c1dSWen Congyang     if (lma) {
40725ae9c1dSWen Congyang         info->d_class = ELFCLASS64;
40825ae9c1dSWen Congyang     } else {
40925ae9c1dSWen Congyang         info->d_class = ELFCLASS32;
41025ae9c1dSWen Congyang 
41156c4bfb3SLaszlo Ersek         QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
41256c4bfb3SLaszlo Ersek             if (block->target_end > UINT_MAX) {
41325ae9c1dSWen Congyang                 /* The memory size is greater than 4G */
41425ae9c1dSWen Congyang                 info->d_class = ELFCLASS64;
41525ae9c1dSWen Congyang                 break;
41625ae9c1dSWen Congyang             }
41725ae9c1dSWen Congyang         }
41825ae9c1dSWen Congyang     }
41925ae9c1dSWen Congyang 
42025ae9c1dSWen Congyang     return 0;
42125ae9c1dSWen Congyang }
4220038ffb0SWen Congyang 
4234720bd05SPaolo Bonzini ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
4240038ffb0SWen Congyang {
4250038ffb0SWen Congyang     int name_size = 5; /* "CORE" or "QEMU" */
4260038ffb0SWen Congyang     size_t elf_note_size = 0;
4270038ffb0SWen Congyang     size_t qemu_note_size = 0;
4280038ffb0SWen Congyang     int elf_desc_size = 0;
4290038ffb0SWen Congyang     int qemu_desc_size = 0;
4300038ffb0SWen Congyang     int note_head_size;
4310038ffb0SWen Congyang 
4320038ffb0SWen Congyang     if (class == ELFCLASS32) {
4330038ffb0SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
4340038ffb0SWen Congyang     } else {
4350038ffb0SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
4360038ffb0SWen Congyang     }
4370038ffb0SWen Congyang 
4380038ffb0SWen Congyang     if (machine == EM_386) {
4390038ffb0SWen Congyang         elf_desc_size = sizeof(x86_elf_prstatus);
4400038ffb0SWen Congyang     }
4410038ffb0SWen Congyang #ifdef TARGET_X86_64
4420038ffb0SWen Congyang     else {
4430038ffb0SWen Congyang         elf_desc_size = sizeof(x86_64_elf_prstatus);
4440038ffb0SWen Congyang     }
4450038ffb0SWen Congyang #endif
4460038ffb0SWen Congyang     qemu_desc_size = sizeof(QEMUCPUState);
4470038ffb0SWen Congyang 
448*18a1f0d7SMarc-André Lureau     elf_note_size = ELF_NOTE_SIZE(note_head_size, name_size, elf_desc_size);
449*18a1f0d7SMarc-André Lureau     qemu_note_size = ELF_NOTE_SIZE(note_head_size, name_size, qemu_desc_size);
4500038ffb0SWen Congyang 
4510038ffb0SWen Congyang     return (elf_note_size + qemu_note_size) * nr_cpus;
4520038ffb0SWen Congyang }
453