xref: /qemu/target/i386/arch_dump.c (revision 369ff018fee40ffb8f6721e5d7f6b56bea74176c)
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 
149fecbed0SWen Congyang #include "cpu.h"
15022c62cbSPaolo Bonzini #include "exec/cpu-all.h"
169c17d615SPaolo Bonzini #include "sysemu/dump.h"
179fecbed0SWen Congyang #include "elf.h"
189fecbed0SWen Congyang 
199fecbed0SWen Congyang #ifdef TARGET_X86_64
209fecbed0SWen Congyang typedef struct {
219fecbed0SWen Congyang     target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
229fecbed0SWen Congyang     target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
239fecbed0SWen Congyang     target_ulong rip, cs, eflags;
249fecbed0SWen Congyang     target_ulong rsp, ss;
259fecbed0SWen Congyang     target_ulong fs_base, gs_base;
269fecbed0SWen Congyang     target_ulong ds, es, fs, gs;
279fecbed0SWen Congyang } x86_64_user_regs_struct;
289fecbed0SWen Congyang 
299fecbed0SWen Congyang typedef struct {
309fecbed0SWen Congyang     char pad1[32];
319fecbed0SWen Congyang     uint32_t pid;
329fecbed0SWen Congyang     char pad2[76];
339fecbed0SWen Congyang     x86_64_user_regs_struct regs;
349fecbed0SWen Congyang     char pad3[8];
359fecbed0SWen Congyang } x86_64_elf_prstatus;
369fecbed0SWen Congyang 
37c72bf468SJens Freimann static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
38369ff018SAndreas Färber                                    CPUX86State *env, int id,
399fecbed0SWen Congyang                                    void *opaque)
409fecbed0SWen Congyang {
419fecbed0SWen Congyang     x86_64_user_regs_struct regs;
429fecbed0SWen Congyang     Elf64_Nhdr *note;
439fecbed0SWen Congyang     char *buf;
449fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
459fecbed0SWen Congyang     const char *name = "CORE";
469fecbed0SWen Congyang     int ret;
479fecbed0SWen Congyang 
489fecbed0SWen Congyang     regs.r15 = env->regs[15];
499fecbed0SWen Congyang     regs.r14 = env->regs[14];
509fecbed0SWen Congyang     regs.r13 = env->regs[13];
519fecbed0SWen Congyang     regs.r12 = env->regs[12];
529fecbed0SWen Congyang     regs.r11 = env->regs[11];
539fecbed0SWen Congyang     regs.r10 = env->regs[10];
549fecbed0SWen Congyang     regs.r9  = env->regs[9];
559fecbed0SWen Congyang     regs.r8  = env->regs[8];
569fecbed0SWen Congyang     regs.rbp = env->regs[R_EBP];
579fecbed0SWen Congyang     regs.rsp = env->regs[R_ESP];
589fecbed0SWen Congyang     regs.rdi = env->regs[R_EDI];
599fecbed0SWen Congyang     regs.rsi = env->regs[R_ESI];
609fecbed0SWen Congyang     regs.rdx = env->regs[R_EDX];
619fecbed0SWen Congyang     regs.rcx = env->regs[R_ECX];
629fecbed0SWen Congyang     regs.rbx = env->regs[R_EBX];
639fecbed0SWen Congyang     regs.rax = env->regs[R_EAX];
649fecbed0SWen Congyang     regs.rip = env->eip;
659fecbed0SWen Congyang     regs.eflags = env->eflags;
669fecbed0SWen Congyang 
679fecbed0SWen Congyang     regs.orig_rax = 0; /* FIXME */
689fecbed0SWen Congyang     regs.cs = env->segs[R_CS].selector;
699fecbed0SWen Congyang     regs.ss = env->segs[R_SS].selector;
709fecbed0SWen Congyang     regs.fs_base = env->segs[R_FS].base;
719fecbed0SWen Congyang     regs.gs_base = env->segs[R_GS].base;
729fecbed0SWen Congyang     regs.ds = env->segs[R_DS].selector;
739fecbed0SWen Congyang     regs.es = env->segs[R_ES].selector;
749fecbed0SWen Congyang     regs.fs = env->segs[R_FS].selector;
759fecbed0SWen Congyang     regs.gs = env->segs[R_GS].selector;
769fecbed0SWen Congyang 
779fecbed0SWen Congyang     descsz = sizeof(x86_64_elf_prstatus);
789fecbed0SWen Congyang     note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
799fecbed0SWen Congyang                 (descsz + 3) / 4) * 4;
809fecbed0SWen Congyang     note = g_malloc(note_size);
819fecbed0SWen Congyang 
829fecbed0SWen Congyang     memset(note, 0, note_size);
839fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
849fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
859fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
869fecbed0SWen Congyang     buf = (char *)note;
879fecbed0SWen Congyang     buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
889fecbed0SWen Congyang     memcpy(buf, name, name_size);
899fecbed0SWen Congyang     buf += ((name_size + 3) / 4) * 4;
909fecbed0SWen Congyang     memcpy(buf + 32, &id, 4); /* pr_pid */
919fecbed0SWen Congyang     buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
929fecbed0SWen Congyang     memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
939fecbed0SWen Congyang 
949fecbed0SWen Congyang     ret = f(note, note_size, opaque);
959fecbed0SWen Congyang     g_free(note);
969fecbed0SWen Congyang     if (ret < 0) {
979fecbed0SWen Congyang         return -1;
989fecbed0SWen Congyang     }
999fecbed0SWen Congyang 
1009fecbed0SWen Congyang     return 0;
1019fecbed0SWen Congyang }
1029fecbed0SWen Congyang #endif
1039fecbed0SWen Congyang 
1049fecbed0SWen Congyang typedef struct {
1059fecbed0SWen Congyang     uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
1069fecbed0SWen Congyang     unsigned short ds, __ds, es, __es;
1079fecbed0SWen Congyang     unsigned short fs, __fs, gs, __gs;
1089fecbed0SWen Congyang     uint32_t orig_eax, eip;
1099fecbed0SWen Congyang     unsigned short cs, __cs;
1109fecbed0SWen Congyang     uint32_t eflags, esp;
1119fecbed0SWen Congyang     unsigned short ss, __ss;
1129fecbed0SWen Congyang } x86_user_regs_struct;
1139fecbed0SWen Congyang 
1149fecbed0SWen Congyang typedef struct {
1159fecbed0SWen Congyang     char pad1[24];
1169fecbed0SWen Congyang     uint32_t pid;
1179fecbed0SWen Congyang     char pad2[44];
1189fecbed0SWen Congyang     x86_user_regs_struct regs;
1199fecbed0SWen Congyang     char pad3[4];
1209fecbed0SWen Congyang } x86_elf_prstatus;
1219fecbed0SWen Congyang 
122369ff018SAndreas Färber static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
1239fecbed0SWen Congyang                                   int id)
1249fecbed0SWen Congyang {
1259fecbed0SWen Congyang     memset(prstatus, 0, sizeof(x86_elf_prstatus));
1269fecbed0SWen Congyang     prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
1279fecbed0SWen Congyang     prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
1289fecbed0SWen Congyang     prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
1299fecbed0SWen Congyang     prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
1309fecbed0SWen Congyang     prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
1319fecbed0SWen Congyang     prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
1329fecbed0SWen Congyang     prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
1339fecbed0SWen Congyang     prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
1349fecbed0SWen Congyang     prstatus->regs.eip = env->eip & 0xffffffff;
1359fecbed0SWen Congyang     prstatus->regs.eflags = env->eflags & 0xffffffff;
1369fecbed0SWen Congyang 
1379fecbed0SWen Congyang     prstatus->regs.cs = env->segs[R_CS].selector;
1389fecbed0SWen Congyang     prstatus->regs.ss = env->segs[R_SS].selector;
1399fecbed0SWen Congyang     prstatus->regs.ds = env->segs[R_DS].selector;
1409fecbed0SWen Congyang     prstatus->regs.es = env->segs[R_ES].selector;
1419fecbed0SWen Congyang     prstatus->regs.fs = env->segs[R_FS].selector;
1429fecbed0SWen Congyang     prstatus->regs.gs = env->segs[R_GS].selector;
1439fecbed0SWen Congyang 
1449fecbed0SWen Congyang     prstatus->pid = id;
1459fecbed0SWen Congyang }
1469fecbed0SWen Congyang 
147369ff018SAndreas Färber static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
1489fecbed0SWen Congyang                                 int id, void *opaque)
1499fecbed0SWen Congyang {
1509fecbed0SWen Congyang     x86_elf_prstatus prstatus;
1519fecbed0SWen Congyang     Elf64_Nhdr *note;
1529fecbed0SWen Congyang     char *buf;
1539fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
1549fecbed0SWen Congyang     const char *name = "CORE";
1559fecbed0SWen Congyang     int ret;
1569fecbed0SWen Congyang 
1579fecbed0SWen Congyang     x86_fill_elf_prstatus(&prstatus, env, id);
1589fecbed0SWen Congyang     descsz = sizeof(x86_elf_prstatus);
1599fecbed0SWen Congyang     note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
1609fecbed0SWen Congyang                 (descsz + 3) / 4) * 4;
1619fecbed0SWen Congyang     note = g_malloc(note_size);
1629fecbed0SWen Congyang 
1639fecbed0SWen Congyang     memset(note, 0, note_size);
1649fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
1659fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
1669fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
1679fecbed0SWen Congyang     buf = (char *)note;
1689fecbed0SWen Congyang     buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
1699fecbed0SWen Congyang     memcpy(buf, name, name_size);
1709fecbed0SWen Congyang     buf += ((name_size + 3) / 4) * 4;
1719fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
1729fecbed0SWen Congyang 
1739fecbed0SWen Congyang     ret = f(note, note_size, opaque);
1749fecbed0SWen Congyang     g_free(note);
1759fecbed0SWen Congyang     if (ret < 0) {
1769fecbed0SWen Congyang         return -1;
1779fecbed0SWen Congyang     }
1789fecbed0SWen Congyang 
1799fecbed0SWen Congyang     return 0;
1809fecbed0SWen Congyang }
1819fecbed0SWen Congyang 
182c72bf468SJens Freimann int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
1839fecbed0SWen Congyang                              int cpuid, void *opaque)
1849fecbed0SWen Congyang {
185c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
1869fecbed0SWen Congyang     int ret;
1879fecbed0SWen Congyang #ifdef TARGET_X86_64
188182735efSAndreas Färber     X86CPU *first_x86_cpu = X86_CPU(first_cpu);
189182735efSAndreas Färber     bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
1909fecbed0SWen Congyang 
1919fecbed0SWen Congyang     if (lma) {
192c72bf468SJens Freimann         ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque);
1939fecbed0SWen Congyang     } else {
1949fecbed0SWen Congyang #endif
195c72bf468SJens Freimann         ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque);
1969fecbed0SWen Congyang #ifdef TARGET_X86_64
1979fecbed0SWen Congyang     }
1989fecbed0SWen Congyang #endif
1999fecbed0SWen Congyang 
2009fecbed0SWen Congyang     return ret;
2019fecbed0SWen Congyang }
2029fecbed0SWen Congyang 
203c72bf468SJens Freimann int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
2049fecbed0SWen Congyang                              int cpuid, void *opaque)
2059fecbed0SWen Congyang {
206c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
2079fecbed0SWen Congyang     x86_elf_prstatus prstatus;
2089fecbed0SWen Congyang     Elf32_Nhdr *note;
2099fecbed0SWen Congyang     char *buf;
2109fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
2119fecbed0SWen Congyang     const char *name = "CORE";
2129fecbed0SWen Congyang     int ret;
2139fecbed0SWen Congyang 
214c72bf468SJens Freimann     x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid);
2159fecbed0SWen Congyang     descsz = sizeof(x86_elf_prstatus);
2169fecbed0SWen Congyang     note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
2179fecbed0SWen Congyang                 (descsz + 3) / 4) * 4;
2189fecbed0SWen Congyang     note = g_malloc(note_size);
2199fecbed0SWen Congyang 
2209fecbed0SWen Congyang     memset(note, 0, note_size);
2219fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
2229fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
2239fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
2249fecbed0SWen Congyang     buf = (char *)note;
2259fecbed0SWen Congyang     buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
2269fecbed0SWen Congyang     memcpy(buf, name, name_size);
2279fecbed0SWen Congyang     buf += ((name_size + 3) / 4) * 4;
2289fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
2299fecbed0SWen Congyang 
2309fecbed0SWen Congyang     ret = f(note, note_size, opaque);
2319fecbed0SWen Congyang     g_free(note);
2329fecbed0SWen Congyang     if (ret < 0) {
2339fecbed0SWen Congyang         return -1;
2349fecbed0SWen Congyang     }
2359fecbed0SWen Congyang 
2369fecbed0SWen Congyang     return 0;
2379fecbed0SWen Congyang }
23890166b71SWen Congyang 
23990166b71SWen Congyang /*
24090166b71SWen Congyang  * please count up QEMUCPUSTATE_VERSION if you have changed definition of
24190166b71SWen Congyang  * QEMUCPUState, and modify the tools using this information accordingly.
24290166b71SWen Congyang  */
24390166b71SWen Congyang #define QEMUCPUSTATE_VERSION (1)
24490166b71SWen Congyang 
24590166b71SWen Congyang struct QEMUCPUSegment {
24690166b71SWen Congyang     uint32_t selector;
24790166b71SWen Congyang     uint32_t limit;
24890166b71SWen Congyang     uint32_t flags;
24990166b71SWen Congyang     uint32_t pad;
25090166b71SWen Congyang     uint64_t base;
25190166b71SWen Congyang };
25290166b71SWen Congyang 
25390166b71SWen Congyang typedef struct QEMUCPUSegment QEMUCPUSegment;
25490166b71SWen Congyang 
25590166b71SWen Congyang struct QEMUCPUState {
25690166b71SWen Congyang     uint32_t version;
25790166b71SWen Congyang     uint32_t size;
25890166b71SWen Congyang     uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
25990166b71SWen Congyang     uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
26090166b71SWen Congyang     uint64_t rip, rflags;
26190166b71SWen Congyang     QEMUCPUSegment cs, ds, es, fs, gs, ss;
26290166b71SWen Congyang     QEMUCPUSegment ldt, tr, gdt, idt;
26390166b71SWen Congyang     uint64_t cr[5];
26490166b71SWen Congyang };
26590166b71SWen Congyang 
26690166b71SWen Congyang typedef struct QEMUCPUState QEMUCPUState;
26790166b71SWen Congyang 
26890166b71SWen Congyang static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
26990166b71SWen Congyang {
27090166b71SWen Congyang     d->pad = 0;
27190166b71SWen Congyang     d->selector = s->selector;
27290166b71SWen Congyang     d->limit = s->limit;
27390166b71SWen Congyang     d->flags = s->flags;
27490166b71SWen Congyang     d->base = s->base;
27590166b71SWen Congyang }
27690166b71SWen Congyang 
277369ff018SAndreas Färber static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
27890166b71SWen Congyang {
27990166b71SWen Congyang     memset(s, 0, sizeof(QEMUCPUState));
28090166b71SWen Congyang 
28190166b71SWen Congyang     s->version = QEMUCPUSTATE_VERSION;
28290166b71SWen Congyang     s->size = sizeof(QEMUCPUState);
28390166b71SWen Congyang 
28490166b71SWen Congyang     s->rax = env->regs[R_EAX];
28590166b71SWen Congyang     s->rbx = env->regs[R_EBX];
28690166b71SWen Congyang     s->rcx = env->regs[R_ECX];
28790166b71SWen Congyang     s->rdx = env->regs[R_EDX];
28890166b71SWen Congyang     s->rsi = env->regs[R_ESI];
28990166b71SWen Congyang     s->rdi = env->regs[R_EDI];
29090166b71SWen Congyang     s->rsp = env->regs[R_ESP];
29190166b71SWen Congyang     s->rbp = env->regs[R_EBP];
29290166b71SWen Congyang #ifdef TARGET_X86_64
29390166b71SWen Congyang     s->r8  = env->regs[8];
29490166b71SWen Congyang     s->r9  = env->regs[9];
29590166b71SWen Congyang     s->r10 = env->regs[10];
29690166b71SWen Congyang     s->r11 = env->regs[11];
29790166b71SWen Congyang     s->r12 = env->regs[12];
29890166b71SWen Congyang     s->r13 = env->regs[13];
29990166b71SWen Congyang     s->r14 = env->regs[14];
30090166b71SWen Congyang     s->r15 = env->regs[15];
30190166b71SWen Congyang #endif
30290166b71SWen Congyang     s->rip = env->eip;
30390166b71SWen Congyang     s->rflags = env->eflags;
30490166b71SWen Congyang 
30590166b71SWen Congyang     copy_segment(&s->cs, &env->segs[R_CS]);
30690166b71SWen Congyang     copy_segment(&s->ds, &env->segs[R_DS]);
30790166b71SWen Congyang     copy_segment(&s->es, &env->segs[R_ES]);
30890166b71SWen Congyang     copy_segment(&s->fs, &env->segs[R_FS]);
30990166b71SWen Congyang     copy_segment(&s->gs, &env->segs[R_GS]);
31090166b71SWen Congyang     copy_segment(&s->ss, &env->segs[R_SS]);
31190166b71SWen Congyang     copy_segment(&s->ldt, &env->ldt);
31290166b71SWen Congyang     copy_segment(&s->tr, &env->tr);
31390166b71SWen Congyang     copy_segment(&s->gdt, &env->gdt);
31490166b71SWen Congyang     copy_segment(&s->idt, &env->idt);
31590166b71SWen Congyang 
31690166b71SWen Congyang     s->cr[0] = env->cr[0];
31790166b71SWen Congyang     s->cr[1] = env->cr[1];
31890166b71SWen Congyang     s->cr[2] = env->cr[2];
31990166b71SWen Congyang     s->cr[3] = env->cr[3];
32090166b71SWen Congyang     s->cr[4] = env->cr[4];
32190166b71SWen Congyang }
32290166b71SWen Congyang 
323c72bf468SJens Freimann static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
324369ff018SAndreas Färber                                       CPUX86State *env,
32590166b71SWen Congyang                                       void *opaque,
32690166b71SWen Congyang                                       int type)
32790166b71SWen Congyang {
32890166b71SWen Congyang     QEMUCPUState state;
32990166b71SWen Congyang     Elf64_Nhdr *note64;
33090166b71SWen Congyang     Elf32_Nhdr *note32;
33190166b71SWen Congyang     void *note;
33290166b71SWen Congyang     char *buf;
33390166b71SWen Congyang     int descsz, note_size, name_size = 5, note_head_size;
33490166b71SWen Congyang     const char *name = "QEMU";
33590166b71SWen Congyang     int ret;
33690166b71SWen Congyang 
33790166b71SWen Congyang     qemu_get_cpustate(&state, env);
33890166b71SWen Congyang 
33990166b71SWen Congyang     descsz = sizeof(state);
34090166b71SWen Congyang     if (type == 0) {
34190166b71SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
34290166b71SWen Congyang     } else {
34390166b71SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
34490166b71SWen Congyang     }
34590166b71SWen Congyang     note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
34690166b71SWen Congyang                 (descsz + 3) / 4) * 4;
34790166b71SWen Congyang     note = g_malloc(note_size);
34890166b71SWen Congyang 
34990166b71SWen Congyang     memset(note, 0, note_size);
35090166b71SWen Congyang     if (type == 0) {
35190166b71SWen Congyang         note32 = note;
35290166b71SWen Congyang         note32->n_namesz = cpu_to_le32(name_size);
35390166b71SWen Congyang         note32->n_descsz = cpu_to_le32(descsz);
35490166b71SWen Congyang         note32->n_type = 0;
35590166b71SWen Congyang     } else {
35690166b71SWen Congyang         note64 = note;
35790166b71SWen Congyang         note64->n_namesz = cpu_to_le32(name_size);
35890166b71SWen Congyang         note64->n_descsz = cpu_to_le32(descsz);
35990166b71SWen Congyang         note64->n_type = 0;
36090166b71SWen Congyang     }
36190166b71SWen Congyang     buf = note;
36290166b71SWen Congyang     buf += ((note_head_size + 3) / 4) * 4;
36390166b71SWen Congyang     memcpy(buf, name, name_size);
36490166b71SWen Congyang     buf += ((name_size + 3) / 4) * 4;
36590166b71SWen Congyang     memcpy(buf, &state, sizeof(state));
36690166b71SWen Congyang 
36790166b71SWen Congyang     ret = f(note, note_size, opaque);
36890166b71SWen Congyang     g_free(note);
36990166b71SWen Congyang     if (ret < 0) {
37090166b71SWen Congyang         return -1;
37190166b71SWen Congyang     }
37290166b71SWen Congyang 
37390166b71SWen Congyang     return 0;
37490166b71SWen Congyang }
37590166b71SWen Congyang 
376c72bf468SJens Freimann int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
37790166b71SWen Congyang                                  void *opaque)
37890166b71SWen Congyang {
379c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
380c72bf468SJens Freimann 
381c72bf468SJens Freimann     return cpu_write_qemu_note(f, &cpu->env, opaque, 1);
38290166b71SWen Congyang }
38390166b71SWen Congyang 
384c72bf468SJens Freimann int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
38590166b71SWen Congyang                                  void *opaque)
38690166b71SWen Congyang {
387c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
388c72bf468SJens Freimann 
389c72bf468SJens Freimann     return cpu_write_qemu_note(f, &cpu->env, opaque, 0);
39090166b71SWen Congyang }
39125ae9c1dSWen Congyang 
39225ae9c1dSWen Congyang int cpu_get_dump_info(ArchDumpInfo *info)
39325ae9c1dSWen Congyang {
39425ae9c1dSWen Congyang     bool lma = false;
39525ae9c1dSWen Congyang     RAMBlock *block;
39625ae9c1dSWen Congyang 
39725ae9c1dSWen Congyang #ifdef TARGET_X86_64
398182735efSAndreas Färber     X86CPU *first_x86_cpu = X86_CPU(first_cpu);
399182735efSAndreas Färber 
400182735efSAndreas Färber     lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK);
40125ae9c1dSWen Congyang #endif
40225ae9c1dSWen Congyang 
40325ae9c1dSWen Congyang     if (lma) {
40425ae9c1dSWen Congyang         info->d_machine = EM_X86_64;
40525ae9c1dSWen Congyang     } else {
40625ae9c1dSWen Congyang         info->d_machine = EM_386;
40725ae9c1dSWen Congyang     }
40825ae9c1dSWen Congyang     info->d_endian = ELFDATA2LSB;
40925ae9c1dSWen Congyang 
41025ae9c1dSWen Congyang     if (lma) {
41125ae9c1dSWen Congyang         info->d_class = ELFCLASS64;
41225ae9c1dSWen Congyang     } else {
41325ae9c1dSWen Congyang         info->d_class = ELFCLASS32;
41425ae9c1dSWen Congyang 
415a3161038SPaolo Bonzini         QTAILQ_FOREACH(block, &ram_list.blocks, next) {
41625ae9c1dSWen Congyang             if (block->offset + block->length > UINT_MAX) {
41725ae9c1dSWen Congyang                 /* The memory size is greater than 4G */
41825ae9c1dSWen Congyang                 info->d_class = ELFCLASS64;
41925ae9c1dSWen Congyang                 break;
42025ae9c1dSWen Congyang             }
42125ae9c1dSWen Congyang         }
42225ae9c1dSWen Congyang     }
42325ae9c1dSWen Congyang 
42425ae9c1dSWen Congyang     return 0;
42525ae9c1dSWen Congyang }
4260038ffb0SWen Congyang 
4274720bd05SPaolo Bonzini ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
4280038ffb0SWen Congyang {
4290038ffb0SWen Congyang     int name_size = 5; /* "CORE" or "QEMU" */
4300038ffb0SWen Congyang     size_t elf_note_size = 0;
4310038ffb0SWen Congyang     size_t qemu_note_size = 0;
4320038ffb0SWen Congyang     int elf_desc_size = 0;
4330038ffb0SWen Congyang     int qemu_desc_size = 0;
4340038ffb0SWen Congyang     int note_head_size;
4350038ffb0SWen Congyang 
4360038ffb0SWen Congyang     if (class == ELFCLASS32) {
4370038ffb0SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
4380038ffb0SWen Congyang     } else {
4390038ffb0SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
4400038ffb0SWen Congyang     }
4410038ffb0SWen Congyang 
4420038ffb0SWen Congyang     if (machine == EM_386) {
4430038ffb0SWen Congyang         elf_desc_size = sizeof(x86_elf_prstatus);
4440038ffb0SWen Congyang     }
4450038ffb0SWen Congyang #ifdef TARGET_X86_64
4460038ffb0SWen Congyang     else {
4470038ffb0SWen Congyang         elf_desc_size = sizeof(x86_64_elf_prstatus);
4480038ffb0SWen Congyang     }
4490038ffb0SWen Congyang #endif
4500038ffb0SWen Congyang     qemu_desc_size = sizeof(QEMUCPUState);
4510038ffb0SWen Congyang 
4520038ffb0SWen Congyang     elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
4530038ffb0SWen Congyang                      (elf_desc_size + 3) / 4) * 4;
4540038ffb0SWen Congyang     qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
4550038ffb0SWen Congyang                       (qemu_desc_size + 3) / 4) * 4;
4560038ffb0SWen Congyang 
4570038ffb0SWen Congyang     return (elf_note_size + qemu_note_size) * nr_cpus;
4580038ffb0SWen Congyang }
459