1 2 /*--------------------------------------------------------------------*/ 3 /*--- Dumping core. coredump-elf.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2013 Julian Seward 11 jseward (at) acm.org 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #if defined(VGO_linux) 32 33 #include "pub_core_basics.h" 34 #include "pub_core_vki.h" 35 #include "pub_core_aspacehl.h" 36 #include "pub_core_aspacemgr.h" 37 #include "pub_core_libcbase.h" 38 #include "pub_core_machine.h" 39 #include "pub_core_coredump.h" 40 #include "pub_core_libcprint.h" 41 #include "pub_core_libcfile.h" // VG_(close) et al 42 #include "pub_core_libcproc.h" // VG_(geteuid), VG_(getegid) 43 #include "pub_core_libcassert.h" // VG_(exit), vg_assert 44 #include "pub_core_mallocfree.h" // VG_(malloc), VG_(free) 45 #include "pub_core_threadstate.h" 46 #include "pub_core_xarray.h" 47 #include "pub_core_clientstate.h" 48 #include "pub_core_options.h" 49 50 /* 51 Dump core 52 53 Generate a standard ELF core file corresponding to the client state 54 at the time of a crash. 55 */ 56 #include <elf.h> 57 #ifndef NT_PRXFPREG 58 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ 59 #endif /* NT_PRXFPREG */ 60 61 #if VG_WORDSIZE == 8 62 #define ESZ(x) Elf64_##x 63 #elif VG_WORDSIZE == 4 64 #define ESZ(x) Elf32_##x 65 #else 66 #error VG_WORDSIZE needs to ==4 or ==8 67 #endif 68 69 /* If true, then this Segment may be mentioned in the core */ 70 static Bool may_dump(const NSegment *seg) 71 { 72 if (seg->kind == SkAnonC || 73 seg->kind == SkShmC || 74 (seg->kind == SkFileC && 75 !VKI_S_ISCHR(seg->mode) && !VKI_S_ISBLK(seg->mode))) 76 return True; 77 78 return False; 79 } 80 81 /* If true, then this Segment's contents will be in the core */ 82 static Bool should_dump(const NSegment *seg) 83 { 84 return may_dump(seg); // && seg->hasW; 85 } 86 87 static void fill_ehdr(ESZ(Ehdr) *ehdr, Int num_phdrs) 88 { 89 VG_(memset)(ehdr, 0, sizeof(*ehdr)); 90 91 VG_(memcpy)(ehdr->e_ident, ELFMAG, SELFMAG); 92 ehdr->e_ident[EI_CLASS] = VG_ELF_CLASS; 93 ehdr->e_ident[EI_DATA] = VG_ELF_DATA2XXX; 94 ehdr->e_ident[EI_VERSION] = EV_CURRENT; 95 96 ehdr->e_type = ET_CORE; 97 ehdr->e_machine = VG_ELF_MACHINE; 98 ehdr->e_version = EV_CURRENT; 99 ehdr->e_entry = 0; 100 ehdr->e_phoff = sizeof(ESZ(Ehdr)); 101 ehdr->e_shoff = 0; 102 ehdr->e_flags = 0; 103 ehdr->e_ehsize = sizeof(ESZ(Ehdr)); 104 ehdr->e_phentsize = sizeof(ESZ(Phdr)); 105 ehdr->e_phnum = num_phdrs; 106 ehdr->e_shentsize = 0; 107 ehdr->e_shnum = 0; 108 ehdr->e_shstrndx = 0; 109 110 } 111 112 static void fill_phdr(ESZ(Phdr) *phdr, const NSegment *seg, UInt off, Bool write) 113 { 114 SizeT len = seg->end - seg->start + 1; 115 116 write = write && should_dump(seg); 117 118 VG_(memset)(phdr, 0, sizeof(*phdr)); 119 120 phdr->p_type = PT_LOAD; 121 phdr->p_offset = off; 122 phdr->p_vaddr = seg->start; 123 phdr->p_paddr = 0; 124 phdr->p_filesz = write ? len : 0; 125 phdr->p_memsz = len; 126 phdr->p_flags = 0; 127 128 if (seg->hasR) 129 phdr->p_flags |= PF_R; 130 if (seg->hasW) 131 phdr->p_flags |= PF_W; 132 if (seg->hasX) 133 phdr->p_flags |= PF_X; 134 135 phdr->p_align = VKI_PAGE_SIZE; 136 } 137 138 struct note { 139 struct note *next; 140 ESZ(Nhdr) note; 141 HChar name[0]; 142 }; 143 144 static UInt note_size(const struct note *n) 145 { 146 return sizeof(ESZ(Nhdr)) + VG_ROUNDUP(VG_(strlen)(n->name)+1, 4) 147 + VG_ROUNDUP(n->note.n_descsz, 4); 148 } 149 150 #if !defined(VGPV_arm_linux_android) \ 151 && !defined(VGPV_x86_linux_android) \ 152 && !defined(VGPV_mips32_linux_android) \ 153 && !defined(VGPV_arm64_linux_android) 154 static void add_note(struct note **list, const HChar *name, UInt type, 155 const void *data, UInt datasz) 156 { 157 Int namelen = VG_(strlen)(name)+1; 158 Int notelen = sizeof(struct note) + 159 VG_ROUNDUP(namelen, 4) + 160 VG_ROUNDUP(datasz, 4); 161 struct note *n = VG_(malloc)("coredump-elf.an.1", notelen); 162 163 VG_(memset)(n, 0, notelen); 164 165 n->next = *list; 166 *list = n; 167 168 n->note.n_type = type; 169 n->note.n_namesz = namelen; 170 n->note.n_descsz = datasz; 171 172 VG_(memcpy)(n->name, name, namelen); 173 VG_(memcpy)(n->name+VG_ROUNDUP(namelen,4), data, datasz); 174 } 175 #endif /* !defined(VGPV_*_linux_android) */ 176 177 static void write_note(Int fd, const struct note *n) 178 { 179 VG_(write)(fd, &n->note, note_size(n)); 180 } 181 182 static void fill_prpsinfo(const ThreadState *tst, 183 struct vki_elf_prpsinfo *prpsinfo) 184 { 185 const HChar *name; 186 187 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo)); 188 189 switch(tst->status) { 190 case VgTs_Runnable: 191 case VgTs_Yielding: 192 prpsinfo->pr_sname = 'R'; 193 break; 194 195 case VgTs_WaitSys: 196 prpsinfo->pr_sname = 'S'; 197 break; 198 199 case VgTs_Zombie: 200 prpsinfo->pr_sname = 'Z'; 201 break; 202 203 case VgTs_Empty: 204 case VgTs_Init: 205 prpsinfo->pr_sname = '?'; 206 break; 207 } 208 209 prpsinfo->pr_uid = 0; 210 prpsinfo->pr_gid = 0; 211 212 if (VG_(resolve_filename)(VG_(cl_exec_fd), &name)) { 213 const HChar *n = name + VG_(strlen)(name) - 1; 214 215 while (n > name && *n != '/') 216 n--; 217 if (n != name) 218 n++; 219 220 VG_(strncpy)(prpsinfo->pr_fname, n, sizeof(prpsinfo->pr_fname)); 221 } 222 } 223 224 static void fill_prstatus(const ThreadState *tst, 225 /*OUT*/struct vki_elf_prstatus *prs, 226 const vki_siginfo_t *si) 227 { 228 struct vki_user_regs_struct *regs; 229 const ThreadArchState* arch = &tst->arch; 230 231 VG_(memset)(prs, 0, sizeof(*prs)); 232 233 prs->pr_info.si_signo = si->si_signo; 234 prs->pr_info.si_code = si->si_code; 235 prs->pr_info.si_errno = 0; 236 237 prs->pr_cursig = si->si_signo; 238 239 prs->pr_pid = tst->os_state.lwpid; 240 prs->pr_ppid = 0; 241 prs->pr_pgrp = VG_(getpgrp)(); 242 prs->pr_sid = VG_(getpgrp)(); 243 244 #if defined(VGP_s390x_linux) 245 /* prs->pr_reg has struct type. Need to take address. */ 246 regs = (struct vki_user_regs_struct *)&(prs->pr_reg); 247 #else 248 regs = (struct vki_user_regs_struct *)prs->pr_reg; 249 vg_assert(sizeof(*regs) == sizeof(prs->pr_reg)); 250 #endif 251 252 #if defined(VGP_x86_linux) 253 regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex ); 254 regs->esp = arch->vex.guest_ESP; 255 regs->eip = arch->vex.guest_EIP; 256 257 regs->ebx = arch->vex.guest_EBX; 258 regs->ecx = arch->vex.guest_ECX; 259 regs->edx = arch->vex.guest_EDX; 260 regs->esi = arch->vex.guest_ESI; 261 regs->edi = arch->vex.guest_EDI; 262 regs->ebp = arch->vex.guest_EBP; 263 regs->eax = arch->vex.guest_EAX; 264 265 regs->cs = arch->vex.guest_CS; 266 regs->ds = arch->vex.guest_DS; 267 regs->ss = arch->vex.guest_SS; 268 regs->es = arch->vex.guest_ES; 269 regs->fs = arch->vex.guest_FS; 270 regs->gs = arch->vex.guest_GS; 271 272 #elif defined(VGP_amd64_linux) 273 regs->eflags = LibVEX_GuestAMD64_get_rflags( &arch->vex ); 274 regs->rsp = arch->vex.guest_RSP; 275 regs->rip = arch->vex.guest_RIP; 276 277 regs->rbx = arch->vex.guest_RBX; 278 regs->rcx = arch->vex.guest_RCX; 279 regs->rdx = arch->vex.guest_RDX; 280 regs->rsi = arch->vex.guest_RSI; 281 regs->rdi = arch->vex.guest_RDI; 282 regs->rbp = arch->vex.guest_RBP; 283 regs->rax = arch->vex.guest_RAX; 284 regs->r8 = arch->vex.guest_R8; 285 regs->r9 = arch->vex.guest_R9; 286 regs->r10 = arch->vex.guest_R10; 287 regs->r11 = arch->vex.guest_R11; 288 regs->r12 = arch->vex.guest_R12; 289 regs->r13 = arch->vex.guest_R13; 290 regs->r14 = arch->vex.guest_R14; 291 regs->r15 = arch->vex.guest_R15; 292 293 #elif defined(VGP_ppc32_linux) 294 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 295 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 296 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 297 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 298 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 299 # undef DO 300 301 regs->nip = arch->vex.guest_CIA; 302 regs->msr = 0xf032; /* pretty arbitrary */ 303 regs->orig_gpr3 = arch->vex.guest_GPR3; 304 regs->ctr = arch->vex.guest_CTR; 305 regs->link = arch->vex.guest_LR; 306 regs->xer = LibVEX_GuestPPC32_get_XER( &arch->vex ); 307 regs->ccr = LibVEX_GuestPPC32_get_CR( &arch->vex ); 308 regs->mq = 0; 309 regs->trap = 0; 310 regs->dar = 0; /* should be fault address? */ 311 regs->dsisr = 0; 312 regs->result = 0; 313 314 #elif defined(VGP_ppc64be_linux) 315 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 316 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 317 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 318 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 319 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 320 # undef DO 321 322 regs->nip = arch->vex.guest_CIA; 323 regs->msr = 0xf032; /* pretty arbitrary */ 324 regs->orig_gpr3 = arch->vex.guest_GPR3; 325 regs->ctr = arch->vex.guest_CTR; 326 regs->link = arch->vex.guest_LR; 327 regs->xer = LibVEX_GuestPPC64_get_XER( &arch->vex ); 328 regs->ccr = LibVEX_GuestPPC64_get_CR( &arch->vex ); 329 /* regs->mq = 0; */ 330 regs->trap = 0; 331 regs->dar = 0; /* should be fault address? */ 332 regs->dsisr = 0; 333 regs->result = 0; 334 335 #elif defined(VGP_ppc64le_linux) 336 # define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 337 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 338 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 339 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 340 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 341 # undef DO 342 343 regs->nip = arch->vex.guest_CIA; 344 regs->msr = 0xf033; /* pretty arbitrary */ 345 regs->orig_gpr3 = arch->vex.guest_GPR3; 346 regs->ctr = arch->vex.guest_CTR; 347 regs->link = arch->vex.guest_LR; 348 regs->xer = LibVEX_GuestPPC64_get_XER( &(arch->vex) ); 349 regs->ccr = LibVEX_GuestPPC64_get_CR( &(arch->vex) ); 350 /* regs->mq = 0; */ 351 regs->trap = 0; 352 regs->dar = 0; /* should be fault address? */ 353 regs->dsisr = 0; 354 regs->result = 0; 355 356 #elif defined(VGP_arm_linux) 357 regs->ARM_r0 = arch->vex.guest_R0; 358 regs->ARM_r1 = arch->vex.guest_R1; 359 regs->ARM_r2 = arch->vex.guest_R2; 360 regs->ARM_r3 = arch->vex.guest_R3; 361 regs->ARM_r4 = arch->vex.guest_R4; 362 regs->ARM_r5 = arch->vex.guest_R5; 363 regs->ARM_r6 = arch->vex.guest_R6; 364 regs->ARM_r7 = arch->vex.guest_R7; 365 regs->ARM_r8 = arch->vex.guest_R8; 366 regs->ARM_r9 = arch->vex.guest_R9; 367 regs->ARM_r10 = arch->vex.guest_R10; 368 regs->ARM_fp = arch->vex.guest_R11; 369 regs->ARM_ip = arch->vex.guest_R12; 370 regs->ARM_sp = arch->vex.guest_R13; 371 regs->ARM_lr = arch->vex.guest_R14; 372 regs->ARM_pc = arch->vex.guest_R15T; 373 regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &arch->vex ); 374 375 #elif defined(VGP_arm64_linux) 376 (void)arch; 377 I_die_here; 378 379 #elif defined(VGP_s390x_linux) 380 # define DO(n) regs->gprs[n] = arch->vex.guest_r##n 381 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 382 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 383 # undef DO 384 # define DO(n) regs->acrs[n] = arch->vex.guest_a##n 385 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 386 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 387 # undef DO 388 regs->orig_gpr2 = arch->vex.guest_r2; 389 390 #elif defined(VGP_mips32_linux) 391 # define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n 392 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 393 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 394 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 395 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 396 # undef DO 397 regs->MIPS_hi = arch->vex.guest_HI; 398 regs->MIPS_lo = arch->vex.guest_LO; 399 400 #elif defined(VGP_mips64_linux) 401 # define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n 402 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 403 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 404 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 405 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 406 # undef DO 407 regs->MIPS_hi = arch->vex.guest_HI; 408 regs->MIPS_lo = arch->vex.guest_LO; 409 #elif defined(VGP_tilegx_linux) 410 # define DO(n) regs->regs[n] = arch->vex.guest_r##n 411 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 412 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 413 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 414 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 415 DO(32); DO(33); DO(34); DO(35); DO(36); DO(37); DO(38); DO(39); 416 DO(40); DO(41); DO(42); DO(43); DO(44); DO(45); DO(46); DO(47); 417 DO(48); DO(49); DO(50); DO(51); DO(52); DO(53); DO(54); DO(55); 418 regs->pc = arch->vex.guest_pc; 419 regs->orig_r0 = arch->vex.guest_r0; 420 #else 421 # error Unknown ELF platform 422 #endif 423 } 424 425 static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) 426 { 427 __attribute__((unused)) 428 const ThreadArchState* arch = &tst->arch; 429 430 #if defined(VGP_x86_linux) 431 //:: static void fill_fpu(vki_elf_fpregset_t *fpu, const HChar *from) 432 //:: { 433 //:: if (VG_(have_ssestate)) { 434 //:: UShort *to; 435 //:: Int i; 436 //:: 437 //:: /* This is what the kernel does */ 438 //:: VG_(memcpy)(fpu, from, 7*sizeof(long)); 439 //:: 440 //:: to = (UShort *)&fpu->st_space[0]; 441 //:: from += 18 * sizeof(UShort); 442 //:: 443 //:: for (i = 0; i < 8; i++, to += 5, from += 8) 444 //:: VG_(memcpy)(to, from, 5*sizeof(UShort)); 445 //:: } else 446 //:: VG_(memcpy)(fpu, from, sizeof(*fpu)); 447 //:: } 448 449 //:: fill_fpu(fpu, (const HChar *)&arch->m_sse); 450 451 #elif defined(VGP_amd64_linux) 452 //:: fpu->cwd = ?; 453 //:: fpu->swd = ?; 454 //:: fpu->twd = ?; 455 //:: fpu->fop = ?; 456 //:: fpu->rip = ?; 457 //:: fpu->rdp = ?; 458 //:: fpu->mxcsr = ?; 459 //:: fpu->mxcsr_mask = ?; 460 //:: fpu->st_space = ?; 461 462 # define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \ 463 &arch->vex.guest_YMM##n[0], 16) 464 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 465 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 466 # undef DO 467 468 VG_(memset)(fpu->padding, 0, sizeof(fpu->padding)); 469 470 #elif defined(VGP_ppc32_linux) 471 /* The guest state has the FPR fields declared as ULongs, so need 472 to fish out the values without converting them. 473 NOTE: The 32 FP registers map to the first 32 VSX registers.*/ 474 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n) 475 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 476 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 477 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 478 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 479 # undef DO 480 481 #elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) 482 /* The guest state has the FPR fields declared as ULongs, so need 483 to fish out the values without converting them. 484 NOTE: The 32 FP registers map to the first 32 VSX registers.*/ 485 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n) 486 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 487 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 488 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 489 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 490 # undef DO 491 492 #elif defined(VGP_arm_linux) || defined(VGP_tilegx_linux) 493 // umm ... 494 495 #elif defined(VGP_arm64_linux) 496 I_die_here; 497 498 #elif defined(VGP_s390x_linux) 499 # define DO(n) fpu->fprs[n].ui = arch->vex.guest_f##n 500 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 501 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 502 # undef DO 503 #elif defined(VGP_mips32_linux) 504 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_f##n) 505 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 506 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 507 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 508 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 509 # undef DO 510 #elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) 511 # define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_f##n) 512 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 513 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 514 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 515 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 516 # undef DO 517 #else 518 # error Unknown ELF platform 519 #endif 520 } 521 522 #if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android) 523 static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu) 524 { 525 const ThreadArchState* arch = &tst->arch; 526 527 //:: xfpu->cwd = ?; 528 //:: xfpu->swd = ?; 529 //:: xfpu->twd = ?; 530 //:: xfpu->fop = ?; 531 //:: xfpu->fip = ?; 532 //:: xfpu->fcs = ?; 533 //:: xfpu->foo = ?; 534 //:: xfpu->fos = ?; 535 //:: xfpu->mxcsr = ?; 536 xfpu->reserved = 0; 537 //:: xfpu->st_space = ?; 538 539 # define DO(n) VG_(memcpy)(xfpu->xmm_space + n * 4, &arch->vex.guest_XMM##n, sizeof(arch->vex.guest_XMM##n)) 540 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 541 # undef DO 542 543 VG_(memset)(xfpu->padding, 0, sizeof(xfpu->padding)); 544 } 545 #endif 546 547 static 548 void dump_one_thread(struct note **notelist, const vki_siginfo_t *si, ThreadId tid) 549 { 550 vki_elf_fpregset_t fpu; 551 struct vki_elf_prstatus prstatus; 552 # if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android) 553 { 554 vki_elf_fpxregset_t xfpu; 555 fill_xfpu(&VG_(threads)[tid], &xfpu); 556 add_note(notelist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu)); 557 } 558 # endif 559 560 fill_fpu(&VG_(threads)[tid], &fpu); 561 # if !defined(VGPV_arm_linux_android) \ 562 && !defined(VGPV_x86_linux_android) \ 563 && !defined(VGPV_mips32_linux_android) \ 564 && !defined(VGPV_arm64_linux_android) 565 add_note(notelist, "CORE", NT_FPREGSET, &fpu, sizeof(fpu)); 566 # endif 567 568 fill_prstatus(&VG_(threads)[tid], &prstatus, si); 569 # if !defined(VGPV_arm_linux_android) \ 570 && !defined(VGPV_x86_linux_android) \ 571 && !defined(VGPV_mips32_linux_android) \ 572 && !defined(VGPV_arm64_linux_android) 573 add_note(notelist, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus)); 574 # endif 575 } 576 577 static 578 void make_elf_coredump(ThreadId tid, const vki_siginfo_t *si, ULong max_size) 579 { 580 HChar* buf = NULL; 581 const HChar *basename = "vgcore"; 582 const HChar *coreext = ""; 583 Int seq = 0; 584 Int core_fd; 585 NSegment const * seg; 586 ESZ(Ehdr) ehdr; 587 ESZ(Phdr) *phdrs; 588 Int num_phdrs; 589 Int i, idx; 590 UInt off; 591 struct note *notelist, *note; 592 UInt notesz; 593 struct vki_elf_prpsinfo prpsinfo; 594 Addr *seg_starts; 595 Int n_seg_starts; 596 597 if (VG_(clo_log_fname_expanded) != NULL) { 598 coreext = ".core"; 599 basename = VG_(expand_file_name)("--log-file", 600 VG_(clo_log_fname_expanded)); 601 } 602 603 vg_assert(coreext); 604 vg_assert(basename); 605 buf = VG_(malloc)( "coredump-elf.mec.1", 606 VG_(strlen)(coreext) + VG_(strlen)(basename) 607 + 100/*for the two %ds. */ ); 608 609 for(;;) { 610 Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC; 611 SysRes sres; 612 613 if (seq == 0) 614 VG_(sprintf)(buf, "%s%s.%d", 615 basename, coreext, VG_(getpid)()); 616 else 617 VG_(sprintf)(buf, "%s%s.%d.%d", 618 basename, coreext, VG_(getpid)(), seq); 619 seq++; 620 621 # if defined(VKI_O_LARGEFILE) 622 oflags |= VKI_O_LARGEFILE; 623 # endif 624 625 sres = VG_(open)(buf, oflags, VKI_S_IRUSR|VKI_S_IWUSR); 626 if (!sr_isError(sres)) { 627 core_fd = sr_Res(sres); 628 break; 629 } 630 631 if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST) 632 return; /* can't create file */ 633 } 634 635 /* Get the client segments */ 636 seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC, 637 &n_seg_starts); 638 639 /* First, count how many memory segments to dump */ 640 num_phdrs = 1; /* start with notes */ 641 for(i = 0; i < n_seg_starts; i++) { 642 if (!may_dump(VG_(am_find_nsegment(seg_starts[i])))) 643 continue; 644 645 num_phdrs++; 646 } 647 648 fill_ehdr(&ehdr, num_phdrs); 649 650 notelist = NULL; 651 652 /* Second, work out their layout */ 653 phdrs = VG_(malloc)("coredump-elf.mec.1", sizeof(*phdrs) * num_phdrs); 654 655 /* Add details for all threads except the one that faulted */ 656 for(i = 1; i < VG_N_THREADS; i++) { 657 658 if (VG_(threads)[i].status == VgTs_Empty) 659 continue; 660 661 if (i == tid) 662 continue; 663 664 dump_one_thread(¬elist, si, i); 665 } 666 667 /* Add details for the faulting thread. Note that because we are 668 adding to the head of a linked list this thread will actually 669 come out first in the core file, which seems to be how 670 debuggers determine that it is the faulting thread. */ 671 dump_one_thread(¬elist, si, tid); 672 673 fill_prpsinfo(&VG_(threads)[tid], &prpsinfo); 674 # if !defined(VGPV_arm_linux_android) \ 675 && !defined(VGPV_x86_linux_android) \ 676 && !defined(VGPV_mips32_linux_android) \ 677 && !defined(VGPV_arm64_linux_android) 678 add_note(¬elist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); 679 # endif 680 681 for (note = notelist, notesz = 0; note != NULL; note = note->next) 682 notesz += note_size(note); 683 684 off = sizeof(ehdr) + sizeof(*phdrs) * num_phdrs; 685 686 phdrs[0].p_type = PT_NOTE; 687 phdrs[0].p_offset = off; 688 phdrs[0].p_vaddr = 0; 689 phdrs[0].p_paddr = 0; 690 phdrs[0].p_filesz = notesz; 691 phdrs[0].p_memsz = 0; 692 phdrs[0].p_flags = 0; 693 phdrs[0].p_align = 0; 694 695 off += notesz; 696 697 off = VG_PGROUNDUP(off); 698 699 for(i = 0, idx = 1; i < n_seg_starts; i++) { 700 seg = VG_(am_find_nsegment(seg_starts[i])); 701 702 if (!may_dump(seg)) 703 continue; 704 705 fill_phdr(&phdrs[idx], seg, off, 706 (seg->end - seg->start + 1 + off) < max_size); 707 708 off += phdrs[idx].p_filesz; 709 710 idx++; 711 } 712 713 /* write everything out */ 714 VG_(write)(core_fd, &ehdr, sizeof(ehdr)); 715 VG_(write)(core_fd, phdrs, sizeof(*phdrs) * num_phdrs); 716 717 for(note = notelist; note != NULL; note = note->next) 718 write_note(core_fd, note); 719 720 VG_(lseek)(core_fd, phdrs[1].p_offset, VKI_SEEK_SET); 721 722 for(i = 0, idx = 1; i < n_seg_starts; i++) { 723 seg = VG_(am_find_nsegment(seg_starts[i])); 724 725 if (!should_dump(seg)) 726 continue; 727 728 if (phdrs[idx].p_filesz > 0) { 729 vg_assert(VG_(lseek)(core_fd, phdrs[idx].p_offset, VKI_SEEK_SET) 730 == phdrs[idx].p_offset); 731 vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz); 732 733 (void)VG_(write)(core_fd, (void *)seg->start, phdrs[idx].p_filesz); 734 } 735 idx++; 736 } 737 738 VG_(free)(seg_starts); 739 740 VG_(close)(core_fd); 741 } 742 743 void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, ULong max_size) 744 { 745 make_elf_coredump(tid, si, max_size); 746 } 747 748 #endif // defined(VGO_linux) 749 750 /*--------------------------------------------------------------------*/ 751 /*--- end ---*/ 752 /*--------------------------------------------------------------------*/ 753