xref: /qemu/target/i386/arch_dump.c (revision 65cb7129f4160c7e07a0da107f888ec73ae96776)
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"
16*32cad1ffSPhilippe Mathieu-Daudé #include "system/dump.h"
179fecbed0SWen Congyang #include "elf.h"
18*32cad1ffSPhilippe Mathieu-Daudé #include "system/memory_mapping.h"
199fecbed0SWen Congyang 
2018a1f0d7SMarc-André Lureau #define ELF_NOTE_SIZE(hdr_size, name_size, desc_size)   \
2118a1f0d7SMarc-André Lureau     ((DIV_ROUND_UP((hdr_size), 4)                       \
2218a1f0d7SMarc-André Lureau       + DIV_ROUND_UP((name_size), 4)                    \
2318a1f0d7SMarc-André Lureau       + DIV_ROUND_UP((desc_size), 4)) * 4)
2418a1f0d7SMarc-André Lureau 
259fecbed0SWen Congyang #ifdef TARGET_X86_64
269fecbed0SWen Congyang typedef struct {
279fecbed0SWen Congyang     target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
289fecbed0SWen Congyang     target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
299fecbed0SWen Congyang     target_ulong rip, cs, eflags;
309fecbed0SWen Congyang     target_ulong rsp, ss;
319fecbed0SWen Congyang     target_ulong fs_base, gs_base;
329fecbed0SWen Congyang     target_ulong ds, es, fs, gs;
339fecbed0SWen Congyang } x86_64_user_regs_struct;
349fecbed0SWen Congyang 
359fecbed0SWen Congyang typedef struct {
369fecbed0SWen Congyang     char pad1[32];
379fecbed0SWen Congyang     uint32_t pid;
389fecbed0SWen Congyang     char pad2[76];
399fecbed0SWen Congyang     x86_64_user_regs_struct regs;
409fecbed0SWen Congyang     char pad3[8];
419fecbed0SWen Congyang } x86_64_elf_prstatus;
429fecbed0SWen Congyang 
x86_64_write_elf64_note(WriteCoreDumpFunction f,CPUX86State * env,int id,DumpState * s)43c72bf468SJens Freimann static int x86_64_write_elf64_note(WriteCoreDumpFunction f,
44369ff018SAndreas Färber                                    CPUX86State *env, int id,
451af0006aSJanosch Frank                                    DumpState *s)
469fecbed0SWen Congyang {
479fecbed0SWen Congyang     x86_64_user_regs_struct regs;
489fecbed0SWen Congyang     Elf64_Nhdr *note;
499fecbed0SWen Congyang     char *buf;
509fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
519fecbed0SWen Congyang     const char *name = "CORE";
529fecbed0SWen Congyang     int ret;
539fecbed0SWen Congyang 
549fecbed0SWen Congyang     regs.r15 = env->regs[15];
559fecbed0SWen Congyang     regs.r14 = env->regs[14];
569fecbed0SWen Congyang     regs.r13 = env->regs[13];
579fecbed0SWen Congyang     regs.r12 = env->regs[12];
589fecbed0SWen Congyang     regs.r11 = env->regs[11];
599fecbed0SWen Congyang     regs.r10 = env->regs[10];
609fecbed0SWen Congyang     regs.r9  = env->regs[9];
619fecbed0SWen Congyang     regs.r8  = env->regs[8];
629fecbed0SWen Congyang     regs.rbp = env->regs[R_EBP];
639fecbed0SWen Congyang     regs.rsp = env->regs[R_ESP];
649fecbed0SWen Congyang     regs.rdi = env->regs[R_EDI];
659fecbed0SWen Congyang     regs.rsi = env->regs[R_ESI];
669fecbed0SWen Congyang     regs.rdx = env->regs[R_EDX];
679fecbed0SWen Congyang     regs.rcx = env->regs[R_ECX];
689fecbed0SWen Congyang     regs.rbx = env->regs[R_EBX];
699fecbed0SWen Congyang     regs.rax = env->regs[R_EAX];
709fecbed0SWen Congyang     regs.rip = env->eip;
719fecbed0SWen Congyang     regs.eflags = env->eflags;
729fecbed0SWen Congyang 
739fecbed0SWen Congyang     regs.orig_rax = 0; /* FIXME */
749fecbed0SWen Congyang     regs.cs = env->segs[R_CS].selector;
759fecbed0SWen Congyang     regs.ss = env->segs[R_SS].selector;
769fecbed0SWen Congyang     regs.fs_base = env->segs[R_FS].base;
779fecbed0SWen Congyang     regs.gs_base = env->segs[R_GS].base;
789fecbed0SWen Congyang     regs.ds = env->segs[R_DS].selector;
799fecbed0SWen Congyang     regs.es = env->segs[R_ES].selector;
809fecbed0SWen Congyang     regs.fs = env->segs[R_FS].selector;
819fecbed0SWen Congyang     regs.gs = env->segs[R_GS].selector;
829fecbed0SWen Congyang 
839fecbed0SWen Congyang     descsz = sizeof(x86_64_elf_prstatus);
8418a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
854be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
869fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
879fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
889fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
899fecbed0SWen Congyang     buf = (char *)note;
9017fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
919fecbed0SWen Congyang     memcpy(buf, name, name_size);
9217fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
939fecbed0SWen Congyang     memcpy(buf + 32, &id, 4); /* pr_pid */
949fecbed0SWen Congyang     buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
959fecbed0SWen Congyang     memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
969fecbed0SWen Congyang 
971af0006aSJanosch Frank     ret = f(note, note_size, s);
989fecbed0SWen Congyang     g_free(note);
999fecbed0SWen Congyang     if (ret < 0) {
1009fecbed0SWen Congyang         return -1;
1019fecbed0SWen Congyang     }
1029fecbed0SWen Congyang 
1039fecbed0SWen Congyang     return 0;
1049fecbed0SWen Congyang }
1059fecbed0SWen Congyang #endif
1069fecbed0SWen Congyang 
1079fecbed0SWen Congyang typedef struct {
1089fecbed0SWen Congyang     uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
1099fecbed0SWen Congyang     unsigned short ds, __ds, es, __es;
1109fecbed0SWen Congyang     unsigned short fs, __fs, gs, __gs;
1119fecbed0SWen Congyang     uint32_t orig_eax, eip;
1129fecbed0SWen Congyang     unsigned short cs, __cs;
1139fecbed0SWen Congyang     uint32_t eflags, esp;
1149fecbed0SWen Congyang     unsigned short ss, __ss;
1159fecbed0SWen Congyang } x86_user_regs_struct;
1169fecbed0SWen Congyang 
1179fecbed0SWen Congyang typedef struct {
1189fecbed0SWen Congyang     char pad1[24];
1199fecbed0SWen Congyang     uint32_t pid;
1209fecbed0SWen Congyang     char pad2[44];
1219fecbed0SWen Congyang     x86_user_regs_struct regs;
1229fecbed0SWen Congyang     char pad3[4];
1239fecbed0SWen Congyang } x86_elf_prstatus;
1249fecbed0SWen Congyang 
x86_fill_elf_prstatus(x86_elf_prstatus * prstatus,CPUX86State * env,int id)125369ff018SAndreas Färber static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env,
1269fecbed0SWen Congyang                                   int id)
1279fecbed0SWen Congyang {
1289fecbed0SWen Congyang     memset(prstatus, 0, sizeof(x86_elf_prstatus));
1299fecbed0SWen Congyang     prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
1309fecbed0SWen Congyang     prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
1319fecbed0SWen Congyang     prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
1329fecbed0SWen Congyang     prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
1339fecbed0SWen Congyang     prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
1349fecbed0SWen Congyang     prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
1359fecbed0SWen Congyang     prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
1369fecbed0SWen Congyang     prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
1379fecbed0SWen Congyang     prstatus->regs.eip = env->eip & 0xffffffff;
1389fecbed0SWen Congyang     prstatus->regs.eflags = env->eflags & 0xffffffff;
1399fecbed0SWen Congyang 
1409fecbed0SWen Congyang     prstatus->regs.cs = env->segs[R_CS].selector;
1419fecbed0SWen Congyang     prstatus->regs.ss = env->segs[R_SS].selector;
1429fecbed0SWen Congyang     prstatus->regs.ds = env->segs[R_DS].selector;
1439fecbed0SWen Congyang     prstatus->regs.es = env->segs[R_ES].selector;
1449fecbed0SWen Congyang     prstatus->regs.fs = env->segs[R_FS].selector;
1459fecbed0SWen Congyang     prstatus->regs.gs = env->segs[R_GS].selector;
1469fecbed0SWen Congyang 
1479fecbed0SWen Congyang     prstatus->pid = id;
1489fecbed0SWen Congyang }
1499fecbed0SWen Congyang 
x86_write_elf64_note(WriteCoreDumpFunction f,CPUX86State * env,int id,DumpState * s)150369ff018SAndreas Färber static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env,
1511af0006aSJanosch Frank                                 int id, DumpState *s)
1529fecbed0SWen Congyang {
1539fecbed0SWen Congyang     x86_elf_prstatus prstatus;
1549fecbed0SWen Congyang     Elf64_Nhdr *note;
1559fecbed0SWen Congyang     char *buf;
1569fecbed0SWen Congyang     int descsz, note_size, name_size = 5;
1579fecbed0SWen Congyang     const char *name = "CORE";
1589fecbed0SWen Congyang     int ret;
1599fecbed0SWen Congyang 
1609fecbed0SWen Congyang     x86_fill_elf_prstatus(&prstatus, env, id);
1619fecbed0SWen Congyang     descsz = sizeof(x86_elf_prstatus);
16218a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz);
1634be34d1eSMarkus Armbruster     note = g_malloc0(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;
16817fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf64_Nhdr), 4);
1699fecbed0SWen Congyang     memcpy(buf, name, name_size);
17017fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
1719fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
1729fecbed0SWen Congyang 
1731af0006aSJanosch Frank     ret = f(note, note_size, s);
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 
x86_cpu_write_elf64_note(WriteCoreDumpFunction f,CPUState * cs,int cpuid,DumpState * s)182c72bf468SJens Freimann int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
1831af0006aSJanosch Frank                              int cpuid, DumpState *s)
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) {
1921af0006aSJanosch Frank         ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, s);
1939fecbed0SWen Congyang     } else {
1949fecbed0SWen Congyang #endif
1951af0006aSJanosch Frank         ret = x86_write_elf64_note(f, &cpu->env, cpuid, s);
1969fecbed0SWen Congyang #ifdef TARGET_X86_64
1979fecbed0SWen Congyang     }
1989fecbed0SWen Congyang #endif
1999fecbed0SWen Congyang 
2009fecbed0SWen Congyang     return ret;
2019fecbed0SWen Congyang }
2029fecbed0SWen Congyang 
x86_cpu_write_elf32_note(WriteCoreDumpFunction f,CPUState * cs,int cpuid,DumpState * s)203c72bf468SJens Freimann int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
2041af0006aSJanosch Frank                              int cpuid, DumpState *s)
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);
21618a1f0d7SMarc-André Lureau     note_size = ELF_NOTE_SIZE(sizeof(Elf32_Nhdr), name_size, descsz);
2174be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
2189fecbed0SWen Congyang     note->n_namesz = cpu_to_le32(name_size);
2199fecbed0SWen Congyang     note->n_descsz = cpu_to_le32(descsz);
2209fecbed0SWen Congyang     note->n_type = cpu_to_le32(NT_PRSTATUS);
2219fecbed0SWen Congyang     buf = (char *)note;
22217fc7e93SMarc-André Lureau     buf += ROUND_UP(sizeof(Elf32_Nhdr), 4);
2239fecbed0SWen Congyang     memcpy(buf, name, name_size);
22417fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
2259fecbed0SWen Congyang     memcpy(buf, &prstatus, sizeof(prstatus));
2269fecbed0SWen Congyang 
2271af0006aSJanosch Frank     ret = f(note, note_size, s);
2289fecbed0SWen Congyang     g_free(note);
2299fecbed0SWen Congyang     if (ret < 0) {
2309fecbed0SWen Congyang         return -1;
2319fecbed0SWen Congyang     }
2329fecbed0SWen Congyang 
2339fecbed0SWen Congyang     return 0;
2349fecbed0SWen Congyang }
23590166b71SWen Congyang 
23690166b71SWen Congyang /*
23790166b71SWen Congyang  * please count up QEMUCPUSTATE_VERSION if you have changed definition of
23890166b71SWen Congyang  * QEMUCPUState, and modify the tools using this information accordingly.
23990166b71SWen Congyang  */
24090166b71SWen Congyang #define QEMUCPUSTATE_VERSION (1)
24190166b71SWen Congyang 
24290166b71SWen Congyang struct QEMUCPUSegment {
24390166b71SWen Congyang     uint32_t selector;
24490166b71SWen Congyang     uint32_t limit;
24590166b71SWen Congyang     uint32_t flags;
24690166b71SWen Congyang     uint32_t pad;
24790166b71SWen Congyang     uint64_t base;
24890166b71SWen Congyang };
24990166b71SWen Congyang 
25090166b71SWen Congyang typedef struct QEMUCPUSegment QEMUCPUSegment;
25190166b71SWen Congyang 
25290166b71SWen Congyang struct QEMUCPUState {
25390166b71SWen Congyang     uint32_t version;
25490166b71SWen Congyang     uint32_t size;
25590166b71SWen Congyang     uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
25690166b71SWen Congyang     uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
25790166b71SWen Congyang     uint64_t rip, rflags;
25890166b71SWen Congyang     QEMUCPUSegment cs, ds, es, fs, gs, ss;
25990166b71SWen Congyang     QEMUCPUSegment ldt, tr, gdt, idt;
26090166b71SWen Congyang     uint64_t cr[5];
26146fac17dSViktor Prutyanov     /*
26246fac17dSViktor Prutyanov      * Fields below are optional and are being added at the end without
26346fac17dSViktor Prutyanov      * changing the version. External tools may identify their presence
26446fac17dSViktor Prutyanov      * by checking 'size' field.
26546fac17dSViktor Prutyanov      */
26646fac17dSViktor Prutyanov     uint64_t kernel_gs_base;
26790166b71SWen Congyang };
26890166b71SWen Congyang 
26990166b71SWen Congyang typedef struct QEMUCPUState QEMUCPUState;
27090166b71SWen Congyang 
copy_segment(QEMUCPUSegment * d,SegmentCache * s)27190166b71SWen Congyang static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
27290166b71SWen Congyang {
27390166b71SWen Congyang     d->pad = 0;
27490166b71SWen Congyang     d->selector = s->selector;
27590166b71SWen Congyang     d->limit = s->limit;
27690166b71SWen Congyang     d->flags = s->flags;
27790166b71SWen Congyang     d->base = s->base;
27890166b71SWen Congyang }
27990166b71SWen Congyang 
qemu_get_cpustate(QEMUCPUState * s,CPUX86State * env)280369ff018SAndreas Färber static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env)
28190166b71SWen Congyang {
28290166b71SWen Congyang     memset(s, 0, sizeof(QEMUCPUState));
28390166b71SWen Congyang 
28490166b71SWen Congyang     s->version = QEMUCPUSTATE_VERSION;
28590166b71SWen Congyang     s->size = sizeof(QEMUCPUState);
28690166b71SWen Congyang 
28790166b71SWen Congyang     s->rax = env->regs[R_EAX];
28890166b71SWen Congyang     s->rbx = env->regs[R_EBX];
28990166b71SWen Congyang     s->rcx = env->regs[R_ECX];
29090166b71SWen Congyang     s->rdx = env->regs[R_EDX];
29190166b71SWen Congyang     s->rsi = env->regs[R_ESI];
29290166b71SWen Congyang     s->rdi = env->regs[R_EDI];
29390166b71SWen Congyang     s->rsp = env->regs[R_ESP];
29490166b71SWen Congyang     s->rbp = env->regs[R_EBP];
29590166b71SWen Congyang #ifdef TARGET_X86_64
29690166b71SWen Congyang     s->r8  = env->regs[8];
29790166b71SWen Congyang     s->r9  = env->regs[9];
29890166b71SWen Congyang     s->r10 = env->regs[10];
29990166b71SWen Congyang     s->r11 = env->regs[11];
30090166b71SWen Congyang     s->r12 = env->regs[12];
30190166b71SWen Congyang     s->r13 = env->regs[13];
30290166b71SWen Congyang     s->r14 = env->regs[14];
30390166b71SWen Congyang     s->r15 = env->regs[15];
30490166b71SWen Congyang #endif
30590166b71SWen Congyang     s->rip = env->eip;
30690166b71SWen Congyang     s->rflags = env->eflags;
30790166b71SWen Congyang 
30890166b71SWen Congyang     copy_segment(&s->cs, &env->segs[R_CS]);
30990166b71SWen Congyang     copy_segment(&s->ds, &env->segs[R_DS]);
31090166b71SWen Congyang     copy_segment(&s->es, &env->segs[R_ES]);
31190166b71SWen Congyang     copy_segment(&s->fs, &env->segs[R_FS]);
31290166b71SWen Congyang     copy_segment(&s->gs, &env->segs[R_GS]);
31390166b71SWen Congyang     copy_segment(&s->ss, &env->segs[R_SS]);
31490166b71SWen Congyang     copy_segment(&s->ldt, &env->ldt);
31590166b71SWen Congyang     copy_segment(&s->tr, &env->tr);
31690166b71SWen Congyang     copy_segment(&s->gdt, &env->gdt);
31790166b71SWen Congyang     copy_segment(&s->idt, &env->idt);
31890166b71SWen Congyang 
31990166b71SWen Congyang     s->cr[0] = env->cr[0];
32090166b71SWen Congyang     s->cr[1] = env->cr[1];
32190166b71SWen Congyang     s->cr[2] = env->cr[2];
32290166b71SWen Congyang     s->cr[3] = env->cr[3];
32390166b71SWen Congyang     s->cr[4] = env->cr[4];
32446fac17dSViktor Prutyanov 
32546fac17dSViktor Prutyanov #ifdef TARGET_X86_64
32646fac17dSViktor Prutyanov     s->kernel_gs_base = env->kernelgsbase;
32746fac17dSViktor Prutyanov #endif
32890166b71SWen Congyang }
32990166b71SWen Congyang 
cpu_write_qemu_note(WriteCoreDumpFunction f,CPUX86State * env,DumpState * s,int type)330c72bf468SJens Freimann static inline int cpu_write_qemu_note(WriteCoreDumpFunction f,
331369ff018SAndreas Färber                                       CPUX86State *env,
3321af0006aSJanosch Frank                                       DumpState *s,
33390166b71SWen Congyang                                       int type)
33490166b71SWen Congyang {
33590166b71SWen Congyang     QEMUCPUState state;
33690166b71SWen Congyang     Elf64_Nhdr *note64;
33790166b71SWen Congyang     Elf32_Nhdr *note32;
33890166b71SWen Congyang     void *note;
33990166b71SWen Congyang     char *buf;
34090166b71SWen Congyang     int descsz, note_size, name_size = 5, note_head_size;
34190166b71SWen Congyang     const char *name = "QEMU";
34290166b71SWen Congyang     int ret;
34390166b71SWen Congyang 
34490166b71SWen Congyang     qemu_get_cpustate(&state, env);
34590166b71SWen Congyang 
34690166b71SWen Congyang     descsz = sizeof(state);
34790166b71SWen Congyang     if (type == 0) {
34890166b71SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
34990166b71SWen Congyang     } else {
35090166b71SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
35190166b71SWen Congyang     }
352074d5afeSMarc-André Lureau     note_size = (DIV_ROUND_UP(note_head_size, 4) + DIV_ROUND_UP(name_size, 4) +
353074d5afeSMarc-André Lureau                 DIV_ROUND_UP(descsz, 4)) * 4;
3544be34d1eSMarkus Armbruster     note = g_malloc0(note_size);
35590166b71SWen Congyang     if (type == 0) {
35690166b71SWen Congyang         note32 = note;
35790166b71SWen Congyang         note32->n_namesz = cpu_to_le32(name_size);
35890166b71SWen Congyang         note32->n_descsz = cpu_to_le32(descsz);
35990166b71SWen Congyang         note32->n_type = 0;
36090166b71SWen Congyang     } else {
36190166b71SWen Congyang         note64 = note;
36290166b71SWen Congyang         note64->n_namesz = cpu_to_le32(name_size);
36390166b71SWen Congyang         note64->n_descsz = cpu_to_le32(descsz);
36490166b71SWen Congyang         note64->n_type = 0;
36590166b71SWen Congyang     }
36690166b71SWen Congyang     buf = note;
36717fc7e93SMarc-André Lureau     buf += ROUND_UP(note_head_size, 4);
36890166b71SWen Congyang     memcpy(buf, name, name_size);
36917fc7e93SMarc-André Lureau     buf += ROUND_UP(name_size, 4);
37090166b71SWen Congyang     memcpy(buf, &state, sizeof(state));
37190166b71SWen Congyang 
3721af0006aSJanosch Frank     ret = f(note, note_size, s);
37390166b71SWen Congyang     g_free(note);
37490166b71SWen Congyang     if (ret < 0) {
37590166b71SWen Congyang         return -1;
37690166b71SWen Congyang     }
37790166b71SWen Congyang 
37890166b71SWen Congyang     return 0;
37990166b71SWen Congyang }
38090166b71SWen Congyang 
x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,CPUState * cs,DumpState * s)381c72bf468SJens Freimann int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs,
3821af0006aSJanosch Frank                                  DumpState *s)
38390166b71SWen Congyang {
384c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
385c72bf468SJens Freimann 
3861af0006aSJanosch Frank     return cpu_write_qemu_note(f, &cpu->env, s, 1);
38790166b71SWen Congyang }
38890166b71SWen Congyang 
x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f,CPUState * cs,DumpState * s)389c72bf468SJens Freimann int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs,
3901af0006aSJanosch Frank                                  DumpState *s)
39190166b71SWen Congyang {
392c72bf468SJens Freimann     X86CPU *cpu = X86_CPU(cs);
393c72bf468SJens Freimann 
3941af0006aSJanosch Frank     return cpu_write_qemu_note(f, &cpu->env, s, 0);
39590166b71SWen Congyang }
39625ae9c1dSWen Congyang 
cpu_get_dump_info(ArchDumpInfo * info,const GuestPhysBlockList * guest_phys_blocks)39756c4bfb3SLaszlo Ersek int cpu_get_dump_info(ArchDumpInfo *info,
39856c4bfb3SLaszlo Ersek                       const GuestPhysBlockList *guest_phys_blocks)
39925ae9c1dSWen Congyang {
40025ae9c1dSWen Congyang     bool lma = false;
40156c4bfb3SLaszlo Ersek     GuestPhysBlock *block;
40225ae9c1dSWen Congyang 
40325ae9c1dSWen Congyang #ifdef TARGET_X86_64
404182735efSAndreas Färber     X86CPU *first_x86_cpu = X86_CPU(first_cpu);
405fd5d23baSIwona Kotlarska     lma = first_cpu && (first_x86_cpu->env.hflags & HF_LMA_MASK);
40625ae9c1dSWen Congyang #endif
40725ae9c1dSWen Congyang 
40825ae9c1dSWen Congyang     if (lma) {
40925ae9c1dSWen Congyang         info->d_machine = EM_X86_64;
41025ae9c1dSWen Congyang     } else {
41125ae9c1dSWen Congyang         info->d_machine = EM_386;
41225ae9c1dSWen Congyang     }
41325ae9c1dSWen Congyang     info->d_endian = ELFDATA2LSB;
41425ae9c1dSWen Congyang 
41525ae9c1dSWen Congyang     if (lma) {
41625ae9c1dSWen Congyang         info->d_class = ELFCLASS64;
41725ae9c1dSWen Congyang     } else {
41825ae9c1dSWen Congyang         info->d_class = ELFCLASS32;
41925ae9c1dSWen Congyang 
42056c4bfb3SLaszlo Ersek         QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) {
42156c4bfb3SLaszlo Ersek             if (block->target_end > UINT_MAX) {
42225ae9c1dSWen Congyang                 /* The memory size is greater than 4G */
42325ae9c1dSWen Congyang                 info->d_class = ELFCLASS64;
42425ae9c1dSWen Congyang                 break;
42525ae9c1dSWen Congyang             }
42625ae9c1dSWen Congyang         }
42725ae9c1dSWen Congyang     }
42825ae9c1dSWen Congyang 
42925ae9c1dSWen Congyang     return 0;
43025ae9c1dSWen Congyang }
4310038ffb0SWen Congyang 
cpu_get_note_size(int class,int machine,int nr_cpus)4324720bd05SPaolo Bonzini ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
4330038ffb0SWen Congyang {
4340038ffb0SWen Congyang     int name_size = 5; /* "CORE" or "QEMU" */
4350038ffb0SWen Congyang     size_t elf_note_size = 0;
4360038ffb0SWen Congyang     size_t qemu_note_size = 0;
4370038ffb0SWen Congyang     int elf_desc_size = 0;
4380038ffb0SWen Congyang     int qemu_desc_size = 0;
4390038ffb0SWen Congyang     int note_head_size;
4400038ffb0SWen Congyang 
4410038ffb0SWen Congyang     if (class == ELFCLASS32) {
4420038ffb0SWen Congyang         note_head_size = sizeof(Elf32_Nhdr);
4430038ffb0SWen Congyang     } else {
4440038ffb0SWen Congyang         note_head_size = sizeof(Elf64_Nhdr);
4450038ffb0SWen Congyang     }
4460038ffb0SWen Congyang 
4470038ffb0SWen Congyang     if (machine == EM_386) {
4480038ffb0SWen Congyang         elf_desc_size = sizeof(x86_elf_prstatus);
4490038ffb0SWen Congyang     }
4500038ffb0SWen Congyang #ifdef TARGET_X86_64
4510038ffb0SWen Congyang     else {
4520038ffb0SWen Congyang         elf_desc_size = sizeof(x86_64_elf_prstatus);
4530038ffb0SWen Congyang     }
4540038ffb0SWen Congyang #endif
4550038ffb0SWen Congyang     qemu_desc_size = sizeof(QEMUCPUState);
4560038ffb0SWen Congyang 
45718a1f0d7SMarc-André Lureau     elf_note_size = ELF_NOTE_SIZE(note_head_size, name_size, elf_desc_size);
45818a1f0d7SMarc-André Lureau     qemu_note_size = ELF_NOTE_SIZE(note_head_size, name_size, qemu_desc_size);
4590038ffb0SWen Congyang 
4600038ffb0SWen Congyang     return (elf_note_size + qemu_note_size) * nr_cpus;
4610038ffb0SWen Congyang }
462