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 26 typedef 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 35 typedef 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 43 static 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 107 typedef 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 117 typedef 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 125 static 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 150 static 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 182 int 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 203 int 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 242 struct QEMUCPUSegment { 243 uint32_t selector; 244 uint32_t limit; 245 uint32_t flags; 246 uint32_t pad; 247 uint64_t base; 248 }; 249 250 typedef struct QEMUCPUSegment QEMUCPUSegment; 251 252 struct 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 263 typedef struct QEMUCPUState QEMUCPUState; 264 265 static void copy_segment(QEMUCPUSegment *d, SegmentCache *s) 266 { 267 d->pad = 0; 268 d->selector = s->selector; 269 d->limit = s->limit; 270 d->flags = s->flags; 271 d->base = s->base; 272 } 273 274 static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env) 275 { 276 memset(s, 0, sizeof(QEMUCPUState)); 277 278 s->version = QEMUCPUSTATE_VERSION; 279 s->size = sizeof(QEMUCPUState); 280 281 s->rax = env->regs[R_EAX]; 282 s->rbx = env->regs[R_EBX]; 283 s->rcx = env->regs[R_ECX]; 284 s->rdx = env->regs[R_EDX]; 285 s->rsi = env->regs[R_ESI]; 286 s->rdi = env->regs[R_EDI]; 287 s->rsp = env->regs[R_ESP]; 288 s->rbp = env->regs[R_EBP]; 289 #ifdef TARGET_X86_64 290 s->r8 = env->regs[8]; 291 s->r9 = env->regs[9]; 292 s->r10 = env->regs[10]; 293 s->r11 = env->regs[11]; 294 s->r12 = env->regs[12]; 295 s->r13 = env->regs[13]; 296 s->r14 = env->regs[14]; 297 s->r15 = env->regs[15]; 298 #endif 299 s->rip = env->eip; 300 s->rflags = env->eflags; 301 302 copy_segment(&s->cs, &env->segs[R_CS]); 303 copy_segment(&s->ds, &env->segs[R_DS]); 304 copy_segment(&s->es, &env->segs[R_ES]); 305 copy_segment(&s->fs, &env->segs[R_FS]); 306 copy_segment(&s->gs, &env->segs[R_GS]); 307 copy_segment(&s->ss, &env->segs[R_SS]); 308 copy_segment(&s->ldt, &env->ldt); 309 copy_segment(&s->tr, &env->tr); 310 copy_segment(&s->gdt, &env->gdt); 311 copy_segment(&s->idt, &env->idt); 312 313 s->cr[0] = env->cr[0]; 314 s->cr[1] = env->cr[1]; 315 s->cr[2] = env->cr[2]; 316 s->cr[3] = env->cr[3]; 317 s->cr[4] = env->cr[4]; 318 } 319 320 static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, 321 CPUX86State *env, 322 void *opaque, 323 int type) 324 { 325 QEMUCPUState state; 326 Elf64_Nhdr *note64; 327 Elf32_Nhdr *note32; 328 void *note; 329 char *buf; 330 int descsz, note_size, name_size = 5, note_head_size; 331 const char *name = "QEMU"; 332 int ret; 333 334 qemu_get_cpustate(&state, env); 335 336 descsz = sizeof(state); 337 if (type == 0) { 338 note_head_size = sizeof(Elf32_Nhdr); 339 } else { 340 note_head_size = sizeof(Elf64_Nhdr); 341 } 342 note_size = (DIV_ROUND_UP(note_head_size, 4) + DIV_ROUND_UP(name_size, 4) + 343 DIV_ROUND_UP(descsz, 4)) * 4; 344 note = g_malloc0(note_size); 345 if (type == 0) { 346 note32 = note; 347 note32->n_namesz = cpu_to_le32(name_size); 348 note32->n_descsz = cpu_to_le32(descsz); 349 note32->n_type = 0; 350 } else { 351 note64 = note; 352 note64->n_namesz = cpu_to_le32(name_size); 353 note64->n_descsz = cpu_to_le32(descsz); 354 note64->n_type = 0; 355 } 356 buf = note; 357 buf += ROUND_UP(note_head_size, 4); 358 memcpy(buf, name, name_size); 359 buf += ROUND_UP(name_size, 4); 360 memcpy(buf, &state, sizeof(state)); 361 362 ret = f(note, note_size, opaque); 363 g_free(note); 364 if (ret < 0) { 365 return -1; 366 } 367 368 return 0; 369 } 370 371 int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs, 372 void *opaque) 373 { 374 X86CPU *cpu = X86_CPU(cs); 375 376 return cpu_write_qemu_note(f, &cpu->env, opaque, 1); 377 } 378 379 int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs, 380 void *opaque) 381 { 382 X86CPU *cpu = X86_CPU(cs); 383 384 return cpu_write_qemu_note(f, &cpu->env, opaque, 0); 385 } 386 387 int cpu_get_dump_info(ArchDumpInfo *info, 388 const GuestPhysBlockList *guest_phys_blocks) 389 { 390 bool lma = false; 391 GuestPhysBlock *block; 392 393 #ifdef TARGET_X86_64 394 X86CPU *first_x86_cpu = X86_CPU(first_cpu); 395 lma = first_cpu && (first_x86_cpu->env.hflags & HF_LMA_MASK); 396 #endif 397 398 if (lma) { 399 info->d_machine = EM_X86_64; 400 } else { 401 info->d_machine = EM_386; 402 } 403 info->d_endian = ELFDATA2LSB; 404 405 if (lma) { 406 info->d_class = ELFCLASS64; 407 } else { 408 info->d_class = ELFCLASS32; 409 410 QTAILQ_FOREACH(block, &guest_phys_blocks->head, next) { 411 if (block->target_end > UINT_MAX) { 412 /* The memory size is greater than 4G */ 413 info->d_class = ELFCLASS64; 414 break; 415 } 416 } 417 } 418 419 return 0; 420 } 421 422 ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) 423 { 424 int name_size = 5; /* "CORE" or "QEMU" */ 425 size_t elf_note_size = 0; 426 size_t qemu_note_size = 0; 427 int elf_desc_size = 0; 428 int qemu_desc_size = 0; 429 int note_head_size; 430 431 if (class == ELFCLASS32) { 432 note_head_size = sizeof(Elf32_Nhdr); 433 } else { 434 note_head_size = sizeof(Elf64_Nhdr); 435 } 436 437 if (machine == EM_386) { 438 elf_desc_size = sizeof(x86_elf_prstatus); 439 } 440 #ifdef TARGET_X86_64 441 else { 442 elf_desc_size = sizeof(x86_64_elf_prstatus); 443 } 444 #endif 445 qemu_desc_size = sizeof(QEMUCPUState); 446 447 elf_note_size = ELF_NOTE_SIZE(note_head_size, name_size, elf_desc_size); 448 qemu_note_size = ELF_NOTE_SIZE(note_head_size, name_size, qemu_desc_size); 449 450 return (elf_note_size + qemu_note_size) * nr_cpus; 451 } 452