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-2015 Julian Seward 11 jseward@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 */ 70static 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 */ 82static Bool should_dump(const NSegment *seg) 83{ 84 return may_dump(seg); // && seg->hasW; 85} 86 87static 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 112static 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 138struct note { 139 struct note *next; 140 ESZ(Nhdr) note; 141 HChar name[0]; 142}; 143 144static 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) 154static 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 177static void write_note(Int fd, const struct note *n) 178{ 179 VG_(write)(fd, &n->note, note_size(n)); 180} 181 182static void fill_prpsinfo(const ThreadState *tst, 183 struct vki_elf_prpsinfo *prpsinfo) 184{ 185 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo)); 186 187 switch(tst->status) { 188 case VgTs_Runnable: 189 case VgTs_Yielding: 190 prpsinfo->pr_sname = 'R'; 191 break; 192 193 case VgTs_WaitSys: 194 prpsinfo->pr_sname = 'S'; 195 break; 196 197 case VgTs_Zombie: 198 prpsinfo->pr_sname = 'Z'; 199 break; 200 201 case VgTs_Empty: 202 case VgTs_Init: 203 prpsinfo->pr_sname = '?'; 204 break; 205 } 206 207 prpsinfo->pr_uid = 0; 208 prpsinfo->pr_gid = 0; 209 210 VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), False); 211} 212 213static void fill_prstatus(const ThreadState *tst, 214 /*OUT*/struct vki_elf_prstatus *prs, 215 const vki_siginfo_t *si) 216{ 217 struct vki_user_regs_struct *regs; 218 const ThreadArchState* arch = &tst->arch; 219 220 VG_(memset)(prs, 0, sizeof(*prs)); 221 222 prs->pr_info.si_signo = si->si_signo; 223 prs->pr_info.si_code = si->si_code; 224 prs->pr_info.si_errno = 0; 225 226 prs->pr_cursig = si->si_signo; 227 228 prs->pr_pid = tst->os_state.lwpid; 229 prs->pr_ppid = 0; 230 prs->pr_pgrp = VG_(getpgrp)(); 231 prs->pr_sid = VG_(getpgrp)(); 232 233#if defined(VGP_s390x_linux) 234 /* prs->pr_reg has struct type. Need to take address. */ 235 regs = (struct vki_user_regs_struct *)&(prs->pr_reg); 236#else 237 regs = (struct vki_user_regs_struct *)prs->pr_reg; 238 vg_assert(sizeof(*regs) == sizeof(prs->pr_reg)); 239#endif 240 241#if defined(VGP_x86_linux) 242 regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex ); 243 regs->esp = arch->vex.guest_ESP; 244 regs->eip = arch->vex.guest_EIP; 245 246 regs->ebx = arch->vex.guest_EBX; 247 regs->ecx = arch->vex.guest_ECX; 248 regs->edx = arch->vex.guest_EDX; 249 regs->esi = arch->vex.guest_ESI; 250 regs->edi = arch->vex.guest_EDI; 251 regs->ebp = arch->vex.guest_EBP; 252 regs->eax = arch->vex.guest_EAX; 253 254 regs->cs = arch->vex.guest_CS; 255 regs->ds = arch->vex.guest_DS; 256 regs->ss = arch->vex.guest_SS; 257 regs->es = arch->vex.guest_ES; 258 regs->fs = arch->vex.guest_FS; 259 regs->gs = arch->vex.guest_GS; 260 261#elif defined(VGP_amd64_linux) 262 regs->eflags = LibVEX_GuestAMD64_get_rflags( &arch->vex ); 263 regs->rsp = arch->vex.guest_RSP; 264 regs->rip = arch->vex.guest_RIP; 265 266 regs->rbx = arch->vex.guest_RBX; 267 regs->rcx = arch->vex.guest_RCX; 268 regs->rdx = arch->vex.guest_RDX; 269 regs->rsi = arch->vex.guest_RSI; 270 regs->rdi = arch->vex.guest_RDI; 271 regs->rbp = arch->vex.guest_RBP; 272 regs->rax = arch->vex.guest_RAX; 273 regs->r8 = arch->vex.guest_R8; 274 regs->r9 = arch->vex.guest_R9; 275 regs->r10 = arch->vex.guest_R10; 276 regs->r11 = arch->vex.guest_R11; 277 regs->r12 = arch->vex.guest_R12; 278 regs->r13 = arch->vex.guest_R13; 279 regs->r14 = arch->vex.guest_R14; 280 regs->r15 = arch->vex.guest_R15; 281 282#elif defined(VGP_ppc32_linux) 283# define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 284 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 285 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 286 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 287 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 288# undef DO 289 290 regs->nip = arch->vex.guest_CIA; 291 regs->msr = 0xf032; /* pretty arbitrary */ 292 regs->orig_gpr3 = arch->vex.guest_GPR3; 293 regs->ctr = arch->vex.guest_CTR; 294 regs->link = arch->vex.guest_LR; 295 regs->xer = LibVEX_GuestPPC32_get_XER( &arch->vex ); 296 regs->ccr = LibVEX_GuestPPC32_get_CR( &arch->vex ); 297 regs->mq = 0; 298 regs->trap = 0; 299 regs->dar = 0; /* should be fault address? */ 300 regs->dsisr = 0; 301 regs->result = 0; 302 303#elif defined(VGP_ppc64be_linux) 304# define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 305 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 306 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 307 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 308 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 309# undef DO 310 311 regs->nip = arch->vex.guest_CIA; 312 regs->msr = 0xf032; /* pretty arbitrary */ 313 regs->orig_gpr3 = arch->vex.guest_GPR3; 314 regs->ctr = arch->vex.guest_CTR; 315 regs->link = arch->vex.guest_LR; 316 regs->xer = LibVEX_GuestPPC64_get_XER( &arch->vex ); 317 regs->ccr = LibVEX_GuestPPC64_get_CR( &arch->vex ); 318 /* regs->mq = 0; */ 319 regs->trap = 0; 320 regs->dar = 0; /* should be fault address? */ 321 regs->dsisr = 0; 322 regs->result = 0; 323 324#elif defined(VGP_ppc64le_linux) 325# define DO(n) regs->gpr[n] = arch->vex.guest_GPR##n 326 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 327 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 328 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 329 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 330# undef DO 331 332 regs->nip = arch->vex.guest_CIA; 333 regs->msr = 0xf033; /* pretty arbitrary */ 334 regs->orig_gpr3 = arch->vex.guest_GPR3; 335 regs->ctr = arch->vex.guest_CTR; 336 regs->link = arch->vex.guest_LR; 337 regs->xer = LibVEX_GuestPPC64_get_XER( &(arch->vex) ); 338 regs->ccr = LibVEX_GuestPPC64_get_CR( &(arch->vex) ); 339 /* regs->mq = 0; */ 340 regs->trap = 0; 341 regs->dar = 0; /* should be fault address? */ 342 regs->dsisr = 0; 343 regs->result = 0; 344 345#elif defined(VGP_arm_linux) 346 regs->ARM_r0 = arch->vex.guest_R0; 347 regs->ARM_r1 = arch->vex.guest_R1; 348 regs->ARM_r2 = arch->vex.guest_R2; 349 regs->ARM_r3 = arch->vex.guest_R3; 350 regs->ARM_r4 = arch->vex.guest_R4; 351 regs->ARM_r5 = arch->vex.guest_R5; 352 regs->ARM_r6 = arch->vex.guest_R6; 353 regs->ARM_r7 = arch->vex.guest_R7; 354 regs->ARM_r8 = arch->vex.guest_R8; 355 regs->ARM_r9 = arch->vex.guest_R9; 356 regs->ARM_r10 = arch->vex.guest_R10; 357 regs->ARM_fp = arch->vex.guest_R11; 358 regs->ARM_ip = arch->vex.guest_R12; 359 regs->ARM_sp = arch->vex.guest_R13; 360 regs->ARM_lr = arch->vex.guest_R14; 361 regs->ARM_pc = arch->vex.guest_R15T; 362 regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &arch->vex ); 363 364#elif defined(VGP_arm64_linux) 365 (void)arch; 366 I_die_here; 367 368#elif defined(VGP_s390x_linux) 369# define DO(n) regs->gprs[n] = arch->vex.guest_r##n 370 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 371 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 372# undef DO 373# define DO(n) regs->acrs[n] = arch->vex.guest_a##n 374 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 375 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 376# undef DO 377 regs->orig_gpr2 = arch->vex.guest_r2; 378 379#elif defined(VGP_mips32_linux) 380# define DO(n) regs->MIPS_r##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 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 384 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 385# undef DO 386 regs->MIPS_hi = arch->vex.guest_HI; 387 regs->MIPS_lo = arch->vex.guest_LO; 388 389#elif defined(VGP_mips64_linux) 390# define DO(n) regs->MIPS_r##n = arch->vex.guest_r##n 391 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 392 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 393 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 394 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 395# undef DO 396 regs->MIPS_hi = arch->vex.guest_HI; 397 regs->MIPS_lo = arch->vex.guest_LO; 398#elif defined(VGP_tilegx_linux) 399# define DO(n) regs->regs[n] = arch->vex.guest_r##n 400 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 401 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 402 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 403 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 404 DO(32); DO(33); DO(34); DO(35); DO(36); DO(37); DO(38); DO(39); 405 DO(40); DO(41); DO(42); DO(43); DO(44); DO(45); DO(46); DO(47); 406 DO(48); DO(49); DO(50); DO(51); DO(52); DO(53); DO(54); DO(55); 407 regs->pc = arch->vex.guest_pc; 408 regs->orig_r0 = arch->vex.guest_r0; 409#else 410# error Unknown ELF platform 411#endif 412} 413 414static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu) 415{ 416 __attribute__((unused)) 417 const ThreadArchState* arch = &tst->arch; 418 419#if defined(VGP_x86_linux) 420//:: static void fill_fpu(vki_elf_fpregset_t *fpu, const HChar *from) 421//:: { 422//:: if (VG_(have_ssestate)) { 423//:: UShort *to; 424//:: Int i; 425//:: 426//:: /* This is what the kernel does */ 427//:: VG_(memcpy)(fpu, from, 7*sizeof(long)); 428//:: 429//:: to = (UShort *)&fpu->st_space[0]; 430//:: from += 18 * sizeof(UShort); 431//:: 432//:: for (i = 0; i < 8; i++, to += 5, from += 8) 433//:: VG_(memcpy)(to, from, 5*sizeof(UShort)); 434//:: } else 435//:: VG_(memcpy)(fpu, from, sizeof(*fpu)); 436//:: } 437 438//:: fill_fpu(fpu, (const HChar *)&arch->m_sse); 439 440#elif defined(VGP_amd64_linux) 441//:: fpu->cwd = ?; 442//:: fpu->swd = ?; 443//:: fpu->twd = ?; 444//:: fpu->fop = ?; 445//:: fpu->rip = ?; 446//:: fpu->rdp = ?; 447//:: fpu->mxcsr = ?; 448//:: fpu->mxcsr_mask = ?; 449//:: fpu->st_space = ?; 450 451# define DO(n) VG_(memcpy)(fpu->xmm_space + n * 4, \ 452 &arch->vex.guest_YMM##n[0], 16) 453 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 454 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 455# undef DO 456 457 VG_(memset)(fpu->padding, 0, sizeof(fpu->padding)); 458 459#elif defined(VGP_ppc32_linux) 460 /* The guest state has the FPR fields declared as ULongs, so need 461 to fish out the values without converting them. 462 NOTE: The 32 FP registers map to the first 32 VSX registers.*/ 463# define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_VSR##n) 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 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 467 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 468# undef DO 469 470#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_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_arm_linux) || defined(VGP_tilegx_linux) 482 // umm ... 483 484#elif defined(VGP_arm64_linux) 485 I_die_here; 486 487#elif defined(VGP_s390x_linux) 488# define DO(n) fpu->fprs[n].ui = arch->vex.guest_f##n 489 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 490 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 491# undef DO 492#elif defined(VGP_mips32_linux) 493# define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_f##n) 494 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 495 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 496 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 497 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 498# undef DO 499#elif defined(VGP_mips32_linux) || defined(VGP_mips64_linux) 500# define DO(n) (*fpu)[n] = *(double*)(&arch->vex.guest_f##n) 501 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 502 DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15); 503 DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23); 504 DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31); 505# undef DO 506#else 507# error Unknown ELF platform 508#endif 509} 510 511#if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android) 512static void fill_xfpu(const ThreadState *tst, vki_elf_fpxregset_t *xfpu) 513{ 514 const ThreadArchState* arch = &tst->arch; 515 516//:: xfpu->cwd = ?; 517//:: xfpu->swd = ?; 518//:: xfpu->twd = ?; 519//:: xfpu->fop = ?; 520//:: xfpu->fip = ?; 521//:: xfpu->fcs = ?; 522//:: xfpu->foo = ?; 523//:: xfpu->fos = ?; 524//:: xfpu->mxcsr = ?; 525 xfpu->reserved = 0; 526//:: xfpu->st_space = ?; 527 528# define DO(n) VG_(memcpy)(xfpu->xmm_space + n * 4, &arch->vex.guest_XMM##n, sizeof(arch->vex.guest_XMM##n)) 529 DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7); 530# undef DO 531 532 VG_(memset)(xfpu->padding, 0, sizeof(xfpu->padding)); 533} 534#endif 535 536static 537void dump_one_thread(struct note **notelist, const vki_siginfo_t *si, ThreadId tid) 538{ 539 vki_elf_fpregset_t fpu; 540 struct vki_elf_prstatus prstatus; 541# if defined(VGP_x86_linux) && !defined(VGPV_x86_linux_android) 542 { 543 vki_elf_fpxregset_t xfpu; 544 fill_xfpu(&VG_(threads)[tid], &xfpu); 545 add_note(notelist, "LINUX", NT_PRXFPREG, &xfpu, sizeof(xfpu)); 546 } 547# endif 548 549 fill_fpu(&VG_(threads)[tid], &fpu); 550# if !defined(VGPV_arm_linux_android) \ 551 && !defined(VGPV_x86_linux_android) \ 552 && !defined(VGPV_mips32_linux_android) \ 553 && !defined(VGPV_arm64_linux_android) 554 add_note(notelist, "CORE", NT_FPREGSET, &fpu, sizeof(fpu)); 555# endif 556 557 fill_prstatus(&VG_(threads)[tid], &prstatus, si); 558# if !defined(VGPV_arm_linux_android) \ 559 && !defined(VGPV_x86_linux_android) \ 560 && !defined(VGPV_mips32_linux_android) \ 561 && !defined(VGPV_arm64_linux_android) 562 add_note(notelist, "CORE", NT_PRSTATUS, &prstatus, sizeof(prstatus)); 563# endif 564} 565 566static 567void make_elf_coredump(ThreadId tid, const vki_siginfo_t *si, ULong max_size) 568{ 569 HChar* buf = NULL; 570 const HChar *basename = "vgcore"; 571 const HChar *coreext = ""; 572 Int seq = 0; 573 Int core_fd; 574 NSegment const * seg; 575 ESZ(Ehdr) ehdr; 576 ESZ(Phdr) *phdrs; 577 Int num_phdrs; 578 Int i, idx; 579 UInt off; 580 struct note *notelist, *note; 581 UInt notesz; 582 struct vki_elf_prpsinfo prpsinfo; 583 Addr *seg_starts; 584 Int n_seg_starts; 585 586 if (VG_(clo_log_fname_expanded) != NULL) { 587 coreext = ".core"; 588 basename = VG_(expand_file_name)("--log-file", 589 VG_(clo_log_fname_expanded)); 590 } 591 592 vg_assert(coreext); 593 vg_assert(basename); 594 buf = VG_(malloc)( "coredump-elf.mec.1", 595 VG_(strlen)(coreext) + VG_(strlen)(basename) 596 + 100/*for the two %ds. */ ); 597 598 for(;;) { 599 Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC; 600 SysRes sres; 601 602 if (seq == 0) 603 VG_(sprintf)(buf, "%s%s.%d", 604 basename, coreext, VG_(getpid)()); 605 else 606 VG_(sprintf)(buf, "%s%s.%d.%d", 607 basename, coreext, VG_(getpid)(), seq); 608 seq++; 609 610# if defined(VKI_O_LARGEFILE) 611 oflags |= VKI_O_LARGEFILE; 612# endif 613 614 sres = VG_(open)(buf, oflags, VKI_S_IRUSR|VKI_S_IWUSR); 615 if (!sr_isError(sres)) { 616 core_fd = sr_Res(sres); 617 break; 618 } 619 620 if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST) 621 return; /* can't create file */ 622 } 623 624 /* Get the client segments */ 625 seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC, 626 &n_seg_starts); 627 628 /* First, count how many memory segments to dump */ 629 num_phdrs = 1; /* start with notes */ 630 for(i = 0; i < n_seg_starts; i++) { 631 if (!may_dump(VG_(am_find_nsegment(seg_starts[i])))) 632 continue; 633 634 num_phdrs++; 635 } 636 637 fill_ehdr(&ehdr, num_phdrs); 638 639 notelist = NULL; 640 641 /* Second, work out their layout */ 642 phdrs = VG_(malloc)("coredump-elf.mec.1", sizeof(*phdrs) * num_phdrs); 643 644 /* Add details for all threads except the one that faulted */ 645 for(i = 1; i < VG_N_THREADS; i++) { 646 647 if (VG_(threads)[i].status == VgTs_Empty) 648 continue; 649 650 if (i == tid) 651 continue; 652 653 dump_one_thread(¬elist, si, i); 654 } 655 656 /* Add details for the faulting thread. Note that because we are 657 adding to the head of a linked list this thread will actually 658 come out first in the core file, which seems to be how 659 debuggers determine that it is the faulting thread. */ 660 dump_one_thread(¬elist, si, tid); 661 662 fill_prpsinfo(&VG_(threads)[tid], &prpsinfo); 663# if !defined(VGPV_arm_linux_android) \ 664 && !defined(VGPV_x86_linux_android) \ 665 && !defined(VGPV_mips32_linux_android) \ 666 && !defined(VGPV_arm64_linux_android) 667 add_note(¬elist, "CORE", NT_PRPSINFO, &prpsinfo, sizeof(prpsinfo)); 668# endif 669 670 for (note = notelist, notesz = 0; note != NULL; note = note->next) 671 notesz += note_size(note); 672 673 off = sizeof(ehdr) + sizeof(*phdrs) * num_phdrs; 674 675 phdrs[0].p_type = PT_NOTE; 676 phdrs[0].p_offset = off; 677 phdrs[0].p_vaddr = 0; 678 phdrs[0].p_paddr = 0; 679 phdrs[0].p_filesz = notesz; 680 phdrs[0].p_memsz = 0; 681 phdrs[0].p_flags = 0; 682 phdrs[0].p_align = 0; 683 684 off += notesz; 685 686 off = VG_PGROUNDUP(off); 687 688 for(i = 0, idx = 1; i < n_seg_starts; i++) { 689 seg = VG_(am_find_nsegment(seg_starts[i])); 690 691 if (!may_dump(seg)) 692 continue; 693 694 fill_phdr(&phdrs[idx], seg, off, 695 (seg->end - seg->start + 1 + off) < max_size); 696 697 off += phdrs[idx].p_filesz; 698 699 idx++; 700 } 701 702 /* write everything out */ 703 VG_(write)(core_fd, &ehdr, sizeof(ehdr)); 704 VG_(write)(core_fd, phdrs, sizeof(*phdrs) * num_phdrs); 705 706 for(note = notelist; note != NULL; note = note->next) 707 write_note(core_fd, note); 708 709 VG_(lseek)(core_fd, phdrs[1].p_offset, VKI_SEEK_SET); 710 711 for(i = 0, idx = 1; i < n_seg_starts; i++) { 712 seg = VG_(am_find_nsegment(seg_starts[i])); 713 714 if (!should_dump(seg)) 715 continue; 716 717 if (phdrs[idx].p_filesz > 0) { 718 vg_assert(VG_(lseek)(core_fd, phdrs[idx].p_offset, VKI_SEEK_SET) 719 == phdrs[idx].p_offset); 720 vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz); 721 722 (void)VG_(write)(core_fd, (void *)seg->start, phdrs[idx].p_filesz); 723 } 724 idx++; 725 } 726 727 VG_(free)(seg_starts); 728 729 VG_(close)(core_fd); 730} 731 732void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, ULong max_size) 733{ 734 make_elf_coredump(tid, si, max_size); 735} 736 737#endif // defined(VGO_linux) 738 739/*--------------------------------------------------------------------*/ 740/*--- end ---*/ 741/*--------------------------------------------------------------------*/ 742