arch_dump.c (12838B)
1/* 2 * i386 memory mapping 3 * 4 * Copyright Fujitsu, Corp. 2011, 2012 5 * 6 * Authors: 7 * Wen Congyang <wency@cn.fujitsu.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 * 12 */ 13 14#include "qemu/osdep.h" 15#include "cpu.h" 16#include "sysemu/dump.h" 17#include "elf.h" 18#include "sysemu/memory_mapping.h" 19 20#define ELF_NOTE_SIZE(hdr_size, name_size, desc_size) \ 21 ((DIV_ROUND_UP((hdr_size), 4) \ 22 + DIV_ROUND_UP((name_size), 4) \ 23 + DIV_ROUND_UP((desc_size), 4)) * 4) 24 25#ifdef TARGET_X86_64 26typedef struct { 27 target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10; 28 target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax; 29 target_ulong rip, cs, eflags; 30 target_ulong rsp, ss; 31 target_ulong fs_base, gs_base; 32 target_ulong ds, es, fs, gs; 33} x86_64_user_regs_struct; 34 35typedef struct { 36 char pad1[32]; 37 uint32_t pid; 38 char pad2[76]; 39 x86_64_user_regs_struct regs; 40 char pad3[8]; 41} x86_64_elf_prstatus; 42 43static int x86_64_write_elf64_note(WriteCoreDumpFunction f, 44 CPUX86State *env, int id, 45 void *opaque) 46{ 47 x86_64_user_regs_struct regs; 48 Elf64_Nhdr *note; 49 char *buf; 50 int descsz, note_size, name_size = 5; 51 const char *name = "CORE"; 52 int ret; 53 54 regs.r15 = env->regs[15]; 55 regs.r14 = env->regs[14]; 56 regs.r13 = env->regs[13]; 57 regs.r12 = env->regs[12]; 58 regs.r11 = env->regs[11]; 59 regs.r10 = env->regs[10]; 60 regs.r9 = env->regs[9]; 61 regs.r8 = env->regs[8]; 62 regs.rbp = env->regs[R_EBP]; 63 regs.rsp = env->regs[R_ESP]; 64 regs.rdi = env->regs[R_EDI]; 65 regs.rsi = env->regs[R_ESI]; 66 regs.rdx = env->regs[R_EDX]; 67 regs.rcx = env->regs[R_ECX]; 68 regs.rbx = env->regs[R_EBX]; 69 regs.rax = env->regs[R_EAX]; 70 regs.rip = env->eip; 71 regs.eflags = env->eflags; 72 73 regs.orig_rax = 0; /* FIXME */ 74 regs.cs = env->segs[R_CS].selector; 75 regs.ss = env->segs[R_SS].selector; 76 regs.fs_base = env->segs[R_FS].base; 77 regs.gs_base = env->segs[R_GS].base; 78 regs.ds = env->segs[R_DS].selector; 79 regs.es = env->segs[R_ES].selector; 80 regs.fs = env->segs[R_FS].selector; 81 regs.gs = env->segs[R_GS].selector; 82 83 descsz = sizeof(x86_64_elf_prstatus); 84 note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz); 85 note = g_malloc0(note_size); 86 note->n_namesz = cpu_to_le32(name_size); 87 note->n_descsz = cpu_to_le32(descsz); 88 note->n_type = cpu_to_le32(NT_PRSTATUS); 89 buf = (char *)note; 90 buf += ROUND_UP(sizeof(Elf64_Nhdr), 4); 91 memcpy(buf, name, name_size); 92 buf += ROUND_UP(name_size, 4); 93 memcpy(buf + 32, &id, 4); /* pr_pid */ 94 buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong); 95 memcpy(buf, ®s, sizeof(x86_64_user_regs_struct)); 96 97 ret = f(note, note_size, opaque); 98 g_free(note); 99 if (ret < 0) { 100 return -1; 101 } 102 103 return 0; 104} 105#endif 106 107typedef struct { 108 uint32_t ebx, ecx, edx, esi, edi, ebp, eax; 109 unsigned short ds, __ds, es, __es; 110 unsigned short fs, __fs, gs, __gs; 111 uint32_t orig_eax, eip; 112 unsigned short cs, __cs; 113 uint32_t eflags, esp; 114 unsigned short ss, __ss; 115} x86_user_regs_struct; 116 117typedef struct { 118 char pad1[24]; 119 uint32_t pid; 120 char pad2[44]; 121 x86_user_regs_struct regs; 122 char pad3[4]; 123} x86_elf_prstatus; 124 125static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env, 126 int id) 127{ 128 memset(prstatus, 0, sizeof(x86_elf_prstatus)); 129 prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff; 130 prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff; 131 prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff; 132 prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff; 133 prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff; 134 prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff; 135 prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff; 136 prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff; 137 prstatus->regs.eip = env->eip & 0xffffffff; 138 prstatus->regs.eflags = env->eflags & 0xffffffff; 139 140 prstatus->regs.cs = env->segs[R_CS].selector; 141 prstatus->regs.ss = env->segs[R_SS].selector; 142 prstatus->regs.ds = env->segs[R_DS].selector; 143 prstatus->regs.es = env->segs[R_ES].selector; 144 prstatus->regs.fs = env->segs[R_FS].selector; 145 prstatus->regs.gs = env->segs[R_GS].selector; 146 147 prstatus->pid = id; 148} 149 150static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, 151 int id, void *opaque) 152{ 153 x86_elf_prstatus prstatus; 154 Elf64_Nhdr *note; 155 char *buf; 156 int descsz, note_size, name_size = 5; 157 const char *name = "CORE"; 158 int ret; 159 160 x86_fill_elf_prstatus(&prstatus, env, id); 161 descsz = sizeof(x86_elf_prstatus); 162 note_size = ELF_NOTE_SIZE(sizeof(Elf64_Nhdr), name_size, descsz); 163 note = g_malloc0(note_size); 164 note->n_namesz = cpu_to_le32(name_size); 165 note->n_descsz = cpu_to_le32(descsz); 166 note->n_type = cpu_to_le32(NT_PRSTATUS); 167 buf = (char *)note; 168 buf += ROUND_UP(sizeof(Elf64_Nhdr), 4); 169 memcpy(buf, name, name_size); 170 buf += ROUND_UP(name_size, 4); 171 memcpy(buf, &prstatus, sizeof(prstatus)); 172 173 ret = f(note, note_size, opaque); 174 g_free(note); 175 if (ret < 0) { 176 return -1; 177 } 178 179 return 0; 180} 181 182int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, 183 int cpuid, void *opaque) 184{ 185 X86CPU *cpu = X86_CPU(cs); 186 int ret; 187#ifdef TARGET_X86_64 188 X86CPU *first_x86_cpu = X86_CPU(first_cpu); 189 bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK); 190 191 if (lma) { 192 ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque); 193 } else { 194#endif 195 ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque); 196#ifdef TARGET_X86_64 197 } 198#endif 199 200 return ret; 201} 202 203int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, 204 int cpuid, void *opaque) 205{ 206 X86CPU *cpu = X86_CPU(cs); 207 x86_elf_prstatus prstatus; 208 Elf32_Nhdr *note; 209 char *buf; 210 int descsz, note_size, name_size = 5; 211 const char *name = "CORE"; 212 int ret; 213 214 x86_fill_elf_prstatus(&prstatus, &cpu->env, cpuid); 215 descsz = sizeof(x86_elf_prstatus); 216 note_size = ELF_NOTE_SIZE(sizeof(Elf32_Nhdr), name_size, descsz); 217 note = g_malloc0(note_size); 218 note->n_namesz = cpu_to_le32(name_size); 219 note->n_descsz = cpu_to_le32(descsz); 220 note->n_type = cpu_to_le32(NT_PRSTATUS); 221 buf = (char *)note; 222 buf += ROUND_UP(sizeof(Elf32_Nhdr), 4); 223 memcpy(buf, name, name_size); 224 buf += ROUND_UP(name_size, 4); 225 memcpy(buf, &prstatus, sizeof(prstatus)); 226 227 ret = f(note, note_size, opaque); 228 g_free(note); 229 if (ret < 0) { 230 return -1; 231 } 232 233 return 0; 234} 235 236/* 237 * please count up QEMUCPUSTATE_VERSION if you have changed definition of 238 * QEMUCPUState, and modify the tools using this information accordingly. 239 */ 240#define QEMUCPUSTATE_VERSION (1) 241 242struct QEMUCPUSegment { 243 uint32_t selector; 244 uint32_t limit; 245 uint32_t flags; 246 uint32_t pad; 247 uint64_t base; 248}; 249 250typedef struct QEMUCPUSegment QEMUCPUSegment; 251 252struct QEMUCPUState { 253 uint32_t version; 254 uint32_t size; 255 uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; 256 uint64_t r8, r9, r10, r11, r12, r13, r14, r15; 257 uint64_t rip, rflags; 258 QEMUCPUSegment cs, ds, es, fs, gs, ss; 259 QEMUCPUSegment ldt, tr, gdt, idt; 260 uint64_t cr[5]; 261 /* 262 * Fields below are optional and are being added at the end without 263 * changing the version. External tools may identify their presence 264 * by checking 'size' field. 265 */ 266 uint64_t kernel_gs_base; 267}; 268 269typedef struct QEMUCPUState QEMUCPUState; 270 271static void copy_segment(QEMUCPUSegment *d, SegmentCache *s) 272{ 273 d->pad = 0; 274 d->selector = s->selector; 275 d->limit = s->limit; 276 d->flags = s->flags; 277 d->base = s->base; 278} 279 280static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env) 281{ 282 memset(s, 0, sizeof(QEMUCPUState)); 283 284 s->version = QEMUCPUSTATE_VERSION; 285 s->size = sizeof(QEMUCPUState); 286 287 s->rax = env->regs[R_EAX]; 288 s->rbx = env->regs[R_EBX]; 289 s->rcx = env->regs[R_ECX]; 290 s->rdx = env->regs[R_EDX]; 291 s->rsi = env->regs[R_ESI]; 292 s->rdi = env->regs[R_EDI]; 293 s->rsp = env->regs[R_ESP]; 294 s->rbp = env->regs[R_EBP]; 295#ifdef TARGET_X86_64 296 s->r8 = env->regs[8]; 297 s->r9 = env->regs[9]; 298 s->r10 = env->regs[10]; 299 s->r11 = env->regs[11]; 300 s->r12 = env->regs[12]; 301 s->r13 = env->regs[13]; 302 s->r14 = env->regs[14]; 303 s->r15 = env->regs[15]; 304#endif 305 s->rip = env->eip; 306 s->rflags = env->eflags; 307 308 copy_segment(&s->cs, &env->segs[R_CS]); 309 copy_segment(&s->ds, &env->segs[R_DS]); 310 copy_segment(&s->es, &env->segs[R_ES]); 311 copy_segment(&s->fs, &env->segs[R_FS]); 312 copy_segment(&s->gs, &env->segs[R_GS]); 313 copy_segment(&s->ss, &env->segs[R_SS]); 314 copy_segment(&s->ldt, &env->ldt); 315 copy_segment(&s->tr, &env->tr); 316 copy_segment(&s->gdt, &env->gdt); 317 copy_segment(&s->idt, &env->idt); 318 319 s->cr[0] = env->cr[0]; 320 s->cr[1] = env->cr[1]; 321 s->cr[2] = env->cr[2]; 322 s->cr[3] = env->cr[3]; 323 s->cr[4] = env->cr[4]; 324 325#ifdef TARGET_X86_64 326 s->kernel_gs_base = env->kernelgsbase; 327#endif 328} 329 330static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, 331 CPUX86State *env, 332 void *opaque, 333 int type) 334{ 335 QEMUCPUState state; 336 Elf64_Nhdr *note64; 337 Elf32_Nhdr *note32; 338 void *note; 339 char *buf; 340 int descsz, note_size, name_size = 5, note_head_size; 341 const char *name = "QEMU"; 342 int ret; 343 344 qemu_get_cpustate(&state, env); 345 346 descsz = sizeof(state); 347 if (type == 0) { 348 note_head_size = sizeof(Elf32_Nhdr); 349 } else { 350 note_head_size = sizeof(Elf64_Nhdr); 351 } 352 note_size = (DIV_ROUND_UP(note_head_size, 4) + DIV_ROUND_UP(name_size, 4) + 353 DIV_ROUND_UP(descsz, 4)) * 4; 354 note = g_malloc0(note_size); 355 if (type == 0) { 356 note32 = note; 357 note32->n_namesz = cpu_to_le32(name_size); 358 note32->n_descsz = cpu_to_le32(descsz); 359 note32->n_type = 0; 360 } else { 361 note64 = note; 362 note64->n_namesz = cpu_to_le32(name_size); 363 note64->n_descsz = cpu_to_le32(descsz); 364 note64->n_type = 0; 365 } 366 buf = note; 367 buf += ROUND_UP(note_head_size, 4); 368 memcpy(buf, name, name_size); 369 buf += ROUND_UP(name_size, 4); 370 memcpy(buf, &state, sizeof(state)); 371 372 ret = f(note, note_size, opaque); 373 g_free(note); 374 if (ret < 0) { 375 return -1; 376 } 377 378 return 0; 379} 380 381int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs, 382 void *opaque) 383{ 384 X86CPU *cpu = X86_CPU(cs); 385 386 return cpu_write_qemu_note(f, &cpu->env, opaque, 1); 387} 388 389int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs, 390 void *opaque) 391{ 392 X86CPU *cpu = X86_CPU(cs); 393 394 return cpu_write_qemu_note(f, &cpu->env, opaque, 0); 395} 396 397int cpu_get_dump_info(ArchDumpInfo *info, 398 const GuestPhysBlockList *guest_phys_blocks) 399{ 400 bool lma = false; 401 GuestPhysBlock *block; 402 403#ifdef TARGET_X86_64 404 X86CPU *first_x86_cpu = X86_CPU(first_cpu); 405 lma = first_cpu && (first_x86_cpu->env.hflags & HF_LMA_MASK); 406#endif 407 408 if (lma) { 409 info->d_machine = EM_X86_64; 410 } else { 411 info->d_machine = EM_386; 412 } 413 info->d_endian = ELFDATA2LSB; 414 415 if (lma) { 416 info->d_class = ELFCLASS64; 417 } else { 418 info->d_class = ELFCLASS32; 419 420 QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) { 421 if (block->target_end > UINT_MAX) { 422 /* The memory size is greater than 4G */ 423 info->d_class = ELFCLASS64; 424 break; 425 } 426 } 427 } 428 429 return 0; 430} 431 432ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) 433{ 434 int name_size = 5; /* "CORE" or "QEMU" */ 435 size_t elf_note_size = 0; 436 size_t qemu_note_size = 0; 437 int elf_desc_size = 0; 438 int qemu_desc_size = 0; 439 int note_head_size; 440 441 if (class == ELFCLASS32) { 442 note_head_size = sizeof(Elf32_Nhdr); 443 } else { 444 note_head_size = sizeof(Elf64_Nhdr); 445 } 446 447 if (machine == EM_386) { 448 elf_desc_size = sizeof(x86_elf_prstatus); 449 } 450#ifdef TARGET_X86_64 451 else { 452 elf_desc_size = sizeof(x86_64_elf_prstatus); 453 } 454#endif 455 qemu_desc_size = sizeof(QEMUCPUState); 456 457 elf_note_size = ELF_NOTE_SIZE(note_head_size, name_size, elf_desc_size); 458 qemu_note_size = ELF_NOTE_SIZE(note_head_size, name_size, qemu_desc_size); 459 460 return (elf_note_size + qemu_note_size) * nr_cpus; 461}