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, ®s, 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