1 2/*--------------------------------------------------------------------*/ 3/*--- Dumping core on Solaris. coredump-solaris.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2013-2015 Ivo Raisr 11 ivosh@ivosh.net 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_solaris) 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_coredump.h" 38#include "pub_core_debuglog.h" 39#include "pub_core_libcassert.h" 40#include "pub_core_libcbase.h" 41#include "pub_core_libcfile.h" 42#include "pub_core_libcprint.h" 43#include "pub_core_libcproc.h" 44#include "pub_core_machine.h" 45#include "pub_core_mallocfree.h" 46#include "pub_core_options.h" 47#include "pub_core_syscall.h" 48#include "pub_core_threadstate.h" 49#include "pub_core_xarray.h" 50#include "pub_core_clientstate.h" 51 52typedef struct __attribute__ ((__packed__)) note { 53 struct note *next; 54 VKI_ESZ(Nhdr) nhdr; 55 HChar name[8]; 56 HChar data[0]; 57} note_t; 58 59static void add_note(note_t **list, UInt type, const void *data, 60 UInt datasz); 61 62/* If true, then this Segment may be mentioned in the core */ 63static Bool may_dump(const NSegment *seg) 64{ 65 if ((seg->kind == SkAnonC) || 66 (seg->kind == SkShmC) || 67 ((seg->kind == SkFileC) && 68 !VKI_S_ISCHR(seg->mode) && !VKI_S_ISBLK(seg->mode))) 69 return True; 70 71 return False; 72} 73 74/* If true, then this Segment's contents will be in the core */ 75static Bool should_dump(const NSegment *seg) 76{ 77 return may_dump(seg); 78} 79 80#if defined(SOLARIS_PRXREGSET_T) 81static Bool should_dump_xregs(const ThreadState *tst) 82{ 83#if defined(VGP_x86_solaris) 84 return False; 85#elif defined(VGP_amd64_solaris) 86 const ThreadArchState *arch = (const ThreadArchState *) &tst->arch; 87 88 /* Dump 256-bit wide %ymm only when their upper half is non-zero. */ 89 #define YMM_NON_ZERO(reg) \ 90 ((reg[4] != 0) || (reg[5] != 0) || (reg[6] != 0) || (reg[7] != 0)) 91 if (YMM_NON_ZERO(arch->vex.guest_YMM0) || 92 YMM_NON_ZERO(arch->vex.guest_YMM1) || 93 YMM_NON_ZERO(arch->vex.guest_YMM2) || 94 YMM_NON_ZERO(arch->vex.guest_YMM3) || 95 YMM_NON_ZERO(arch->vex.guest_YMM4) || 96 YMM_NON_ZERO(arch->vex.guest_YMM5) || 97 YMM_NON_ZERO(arch->vex.guest_YMM6) || 98 YMM_NON_ZERO(arch->vex.guest_YMM7) || 99 YMM_NON_ZERO(arch->vex.guest_YMM9) || 100 YMM_NON_ZERO(arch->vex.guest_YMM0) || 101 YMM_NON_ZERO(arch->vex.guest_YMM10) || 102 YMM_NON_ZERO(arch->vex.guest_YMM11) || 103 YMM_NON_ZERO(arch->vex.guest_YMM12) || 104 YMM_NON_ZERO(arch->vex.guest_YMM13) || 105 YMM_NON_ZERO(arch->vex.guest_YMM14) || 106 YMM_NON_ZERO(arch->vex.guest_YMM15)) 107 return True; 108 109 return False; 110 111 #undef YMM_NON_ZERO 112#else 113# error Unknown ELF platform 114#endif 115} 116#endif /* SOLARIS_PRXREGSET_T */ 117 118static void write_part(Int fd, const HChar *filename, 119 void *buf, SizeT buf_size, const HChar *part) 120{ 121 Int ret = VG_(write)(fd, buf, buf_size); 122 if (ret < 0) { 123 VG_(umsg)("Failed to write %s to coredump file %s, it may be " 124 "incomplete.\n", part, filename); 125 VG_(debugLog)(1, "coredump-solaris", "write_part: failed to write " 126 "%s to file %s. Buffer address=%p, length=%lu. " 127 "Error=%d.\n", part, filename, buf, buf_size, -ret); 128 } 129} 130 131/*====================================================================*/ 132/*=== Miscellaneous getters ===*/ 133/*====================================================================*/ 134 135static Int get_uid(void) 136{ 137 return sr_Res(VG_(do_syscall0)(SYS_getuid)); 138} 139 140static Int get_gid(void) 141{ 142 return sr_Res(VG_(do_syscall0)(SYS_getgid)); 143} 144 145static Int get_dmodel(void) 146{ 147#if defined(VGP_x86_solaris) 148 return PR_MODEL_ILP32; 149#elif defined(VGP_amd64_solaris) 150 return PR_MODEL_LP64; 151#else 152# error "Unknown platform" 153#endif 154} 155 156static vki_zoneid_t get_zoneid(void) 157{ 158 SysRes sres = VG_(do_syscall2)(SYS_zone, VKI_ZONE_LOOKUP, 159 (UWord) NULL); 160 if (sr_isError(sres)) 161 return 0; 162 163 return sr_Res(sres); 164} 165 166static UInt count_auxv(void) 167{ 168 UInt count = 1; 169 170 vki_auxv_t *auxv = (vki_auxv_t *) VG_(client_auxv); 171 while (auxv->a_type != VKI_AT_NULL) { 172 count += 1; 173 auxv++; 174 } 175 176 return count; 177} 178 179static Addr compute_stkbase(const ThreadState *tst) 180{ 181 return tst->client_stack_highest_byte + 1 182 - tst->client_stack_szB; 183} 184 185static Int get_wstat(const vki_siginfo_t *si) 186{ 187 return (si->si_signo & 0xff) | WCOREFLG; 188} 189 190/*====================================================================*/ 191/*=== Utility fillers ===*/ 192/*====================================================================*/ 193 194static void fill_platform(HChar *buf, UInt buf_size) 195{ 196 vg_assert(buf != NULL); 197 vg_assert(buf_size >= 1); 198 199 buf[0] = '\0'; 200 201 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_PLATFORM, 202 (UWord) buf, buf_size); 203} 204 205static void fill_zonename(HChar *buf, UInt buf_size) 206{ 207 vg_assert(buf != NULL); 208 vg_assert(buf_size >= 1); 209 210 buf[0] = '\0'; 211 212 VG_(do_syscall5)(SYS_zone, VKI_ZONE_GETATTR, get_zoneid(), 213 VKI_ZONE_ATTR_NAME, (UWord) buf, buf_size); 214} 215 216static void fill_thread_state(const ThreadState *tst, 217 HChar *state, HChar *sname) 218{ 219 switch (tst->status) { 220 case VgTs_Runnable: 221 case VgTs_Yielding: 222 *state = VKI_SRUN; 223 *sname = 'R'; 224 break; 225 226 case VgTs_WaitSys: 227 *state = VKI_SSLEEP; 228 *sname = 'S'; 229 break; 230 231 case VgTs_Zombie: 232 *state = VKI_SZOMB; 233 *sname = 'Z'; 234 break; 235 236 case VgTs_Empty: 237 case VgTs_Init: 238 *state = 0; 239 *sname = '?'; 240 break; 241 } 242} 243 244static void fill_siginfo(const vki_siginfo_t *si, vki_siginfo_t *di, 245 Short *signo) 246{ 247 di->si_signo = si->si_signo; 248 di->si_code = si->si_code; 249 di->si_errno = 0; 250 di->si_addr = si->si_addr; 251 *signo = si->si_signo; 252} 253 254static void fill_argv(Int *argc, Addr *argv) 255{ 256 Addr *ptr = (Addr *) VG_(get_initial_client_SP)(); 257 *argc = *ptr++; 258 *argv = (Addr) ptr; 259} 260 261static void fill_scheduling_class(HChar *buf, SizeT buf_size) 262{ 263 vg_assert(buf != NULL); 264 vg_assert(buf_size >= 1); 265 266 /* Valgrind currently schedules one thread at time which 267 resembles the default timeshare class. */ 268 VG_(strncpy)(buf, "TS", buf_size); 269} 270 271static void fill_regset(vki_prgregset_t *regs, const ThreadState *tst) 272{ 273 const ThreadArchState *arch = (const ThreadArchState *) &tst->arch; 274 275#if defined(VGP_x86_solaris) 276 (*regs)[VKI_EIP] = arch->vex.guest_EIP; 277 (*regs)[VKI_EAX] = arch->vex.guest_EAX; 278 (*regs)[VKI_EBX] = arch->vex.guest_EBX; 279 (*regs)[VKI_ECX] = arch->vex.guest_ECX; 280 (*regs)[VKI_EDX] = arch->vex.guest_EDX; 281 (*regs)[VKI_ESI] = arch->vex.guest_ESI; 282 (*regs)[VKI_EDI] = arch->vex.guest_EDI; 283 (*regs)[VKI_EBP] = arch->vex.guest_EBP; 284 (*regs)[VKI_UESP] = arch->vex.guest_ESP; 285 (*regs)[VKI_SS] = arch->vex.guest_SS; 286 (*regs)[VKI_CS] = arch->vex.guest_CS; 287 (*regs)[VKI_DS] = arch->vex.guest_DS; 288 (*regs)[VKI_ES] = arch->vex.guest_ES; 289 (*regs)[VKI_FS] = arch->vex.guest_FS; 290 (*regs)[VKI_GS] = arch->vex.guest_GS; 291 (*regs)[VKI_EFL] = LibVEX_GuestX86_get_eflags(&arch->vex); 292#elif defined(VGP_amd64_solaris) 293 (*regs)[VKI_REG_RIP] = arch->vex.guest_RIP; 294 (*regs)[VKI_REG_RAX] = arch->vex.guest_RAX; 295 (*regs)[VKI_REG_RBX] = arch->vex.guest_RBX; 296 (*regs)[VKI_REG_RCX] = arch->vex.guest_RCX; 297 (*regs)[VKI_REG_RDX] = arch->vex.guest_RDX; 298 (*regs)[VKI_REG_RBP] = arch->vex.guest_RBP; 299 (*regs)[VKI_REG_RSI] = arch->vex.guest_RSI; 300 (*regs)[VKI_REG_RDI] = arch->vex.guest_RDI; 301 (*regs)[VKI_REG_R8] = arch->vex.guest_R8; 302 (*regs)[VKI_REG_R9] = arch->vex.guest_R9; 303 (*regs)[VKI_REG_R10] = arch->vex.guest_R10; 304 (*regs)[VKI_REG_R11] = arch->vex.guest_R11; 305 (*regs)[VKI_REG_R12] = arch->vex.guest_R12; 306 (*regs)[VKI_REG_R13] = arch->vex.guest_R13; 307 (*regs)[VKI_REG_R14] = arch->vex.guest_R14; 308 (*regs)[VKI_REG_R15] = arch->vex.guest_R15; 309 (*regs)[VKI_REG_RSP] = arch->vex.guest_RSP; 310 (*regs)[VKI_REG_CS] = VKI_UCS_SEL; 311 (*regs)[VKI_REG_DS] = 0; 312 (*regs)[VKI_REG_ES] = 0; 313 (*regs)[VKI_REG_FS] = 0; 314 (*regs)[VKI_REG_GS] = 0; 315 (*regs)[VKI_REG_SS] = VKI_UDS_SEL; 316 (*regs)[VKI_REG_FSBASE] = arch->vex.guest_FS_CONST; 317 (*regs)[VKI_REG_GSBASE] = 0; 318 (*regs)[VKI_REG_RFL] = LibVEX_GuestAMD64_get_rflags(&arch->vex); 319#else 320# error "Unknown platform" 321#endif 322} 323 324static void fill_fpregset(vki_fpregset_t *fpu, const ThreadState *tst) 325{ 326 const ThreadArchState *arch = (const ThreadArchState *) &tst->arch; 327 328#if defined(VGP_x86_solaris) 329 VG_(memset)(fpu, 0, sizeof(*fpu)); 330 331 struct vki_fpchip_state *fs = &fpu->fp_reg_set.fpchip_state; 332 vg_assert(sizeof(fs->state) == 108); 333 334 LibVEX_GuestX86_get_x87(CONST_CAST(VexGuestX86State *, &arch->vex), 335 (UChar *) &fs->state); 336 337 /* SSE */ 338 UInt mxcsr = LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State *, 339 &arch->vex)); 340 fs->mxcsr = mxcsr; 341 342 /* XMM registers */ 343 #define COPY_OUT_XMM(dest, src) \ 344 do { \ 345 dest._l[0] = src[0]; \ 346 dest._l[1] = src[1]; \ 347 dest._l[2] = src[2]; \ 348 dest._l[3] = src[3]; \ 349 } while (0); 350 COPY_OUT_XMM(fs->xmm[0], arch->vex.guest_XMM0); 351 COPY_OUT_XMM(fs->xmm[1], arch->vex.guest_XMM1); 352 COPY_OUT_XMM(fs->xmm[2], arch->vex.guest_XMM2); 353 COPY_OUT_XMM(fs->xmm[3], arch->vex.guest_XMM3); 354 COPY_OUT_XMM(fs->xmm[4], arch->vex.guest_XMM4); 355 COPY_OUT_XMM(fs->xmm[5], arch->vex.guest_XMM5); 356 COPY_OUT_XMM(fs->xmm[6], arch->vex.guest_XMM6); 357 COPY_OUT_XMM(fs->xmm[7], arch->vex.guest_XMM7); 358 #undef COPY_OUT_XMM 359#elif defined(VGP_amd64_solaris) 360 VG_(memset)(fpu, 0, sizeof(*fpu)); 361 struct vki_fpchip_state *fs = &fpu->fp_reg_set.fpchip_state; 362 363 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */ 364 vg_assert(sizeof(*fs) >= 416); 365 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State *, &arch->vex), 366 (Addr) fs); 367#else 368# error Unknown platform 369#endif 370} 371 372/*====================================================================*/ 373/*=== Header fillers ===*/ 374/*====================================================================*/ 375 376static void fill_ehdr(VKI_ESZ(Ehdr) *ehdr, Int num_phdrs) 377{ 378 VG_(memset)(ehdr, 0, sizeof(*ehdr)); 379 380 VG_(memcpy)(ehdr->e_ident, VKI_ELFMAG, VKI_SELFMAG); 381 ehdr->e_ident[VKI_EI_CLASS] = VG_ELF_CLASS; 382 ehdr->e_ident[VKI_EI_DATA] = VG_ELF_DATA2XXX; 383 ehdr->e_ident[VKI_EI_VERSION] = VKI_EV_CURRENT; 384 385 ehdr->e_type = VKI_ET_CORE; 386 ehdr->e_machine = VG_ELF_MACHINE; 387 ehdr->e_version = VKI_EV_CURRENT; 388 ehdr->e_entry = 0; 389 ehdr->e_flags = 0; 390 ehdr->e_ehsize = sizeof(VKI_ESZ(Ehdr)); 391 392 ehdr->e_phoff = sizeof(VKI_ESZ(Ehdr)); 393 ehdr->e_phentsize = sizeof(VKI_ESZ(Phdr)); 394 395 /* If the count of program headers can't fit in the mere 16 bits 396 * shortsightedly allotted to them in the ELF header, we use the 397 * extended formats and put the real values in the section header 398 * at index 0. 399 */ 400 if (num_phdrs >= VKI_PN_XNUM) { 401 ehdr->e_phnum = VKI_PN_XNUM; 402 ehdr->e_shnum = 1; 403 ehdr->e_shoff = ehdr->e_phoff + ehdr->e_phentsize * num_phdrs; 404 ehdr->e_shentsize = sizeof(VKI_ESZ(Shdr)); 405 } else { 406 ehdr->e_phnum = num_phdrs; 407 ehdr->e_shnum = 0; 408 ehdr->e_shoff = 0; 409 ehdr->e_shentsize = 0; 410 } 411 412 ehdr->e_shstrndx = 0; 413} 414 415static void fill_phdr(VKI_ESZ(Phdr) *phdr, const NSegment *seg, UInt off, 416 Bool really_write) 417{ 418 SizeT len = seg->end - seg->start + 1; 419 420 really_write = really_write && should_dump(seg); 421 422 VG_(memset)(phdr, 0, sizeof(*phdr)); 423 424 phdr->p_type = PT_LOAD; 425 phdr->p_offset = off; 426 phdr->p_vaddr = seg->start; 427 phdr->p_paddr = 0; 428 phdr->p_filesz = really_write ? len : 0; 429 phdr->p_memsz = len; 430 phdr->p_flags = 0; 431 432 if (seg->hasR) 433 phdr->p_flags |= PF_R; 434 if (seg->hasW) 435 phdr->p_flags |= PF_W; 436 if (seg->hasX) 437 phdr->p_flags |= PF_X; 438 439 phdr->p_align = VKI_PAGE_SIZE; 440} 441 442/* Fills the section header at index zero when num_phdrs >= PN_XNUM. */ 443static void fill_zero_shdr(VKI_ESZ(Shdr) *shdr, UInt num_phdrs) 444{ 445 vg_assert(num_phdrs >= VKI_PN_XNUM); 446 447 VG_(memset)(shdr, 0, sizeof(*shdr)); 448 449 shdr->sh_name = 0; // STR_NONE 450 shdr->sh_info = num_phdrs; 451} 452 453static void fill_prpsinfo(vki_elf_prpsinfo_t *prpsinfo, 454 const ThreadState *tst, 455 const vki_siginfo_t *si) 456{ 457 VG_(memset)(prpsinfo, 0, sizeof(*prpsinfo)); 458 459 fill_thread_state(tst, &prpsinfo->pr_state, &prpsinfo->pr_sname); 460 prpsinfo->pr_uid = get_uid(); 461 prpsinfo->pr_gid = get_gid(); 462 prpsinfo->pr_pid = VG_(getpid)(); 463 prpsinfo->pr_ppid = VG_(getppid)(); 464 prpsinfo->pr_pgrp = VG_(getpgrp)(); 465 prpsinfo->pr_sid = VG_(getpgrp)(); 466 fill_scheduling_class(prpsinfo->pr_clname, sizeof(prpsinfo->pr_clname)); 467 VG_(client_fname)(prpsinfo->pr_fname, sizeof(prpsinfo->pr_fname), True); 468 VG_(client_cmd_and_args)(prpsinfo->pr_psargs, 469 sizeof(prpsinfo->pr_psargs)); 470 fill_argv(&prpsinfo->pr_argc, (Addr *) &prpsinfo->pr_argv); 471 prpsinfo->pr_envp = (char **) VG_(client_envp); 472 prpsinfo->pr_wstat = get_wstat(si); 473 prpsinfo->pr_euid = VG_(geteuid)(); 474 prpsinfo->pr_egid = VG_(getegid)(); 475 prpsinfo->pr_dmodel = get_dmodel(); 476} 477 478static void fill_prstatus(vki_elf_prstatus_t *prs, 479 const ThreadState *tst, 480 const vki_siginfo_t *si) 481{ 482 VG_(memset)(prs, 0, sizeof(*prs)); 483 484 prs->pr_flags = VKI_ELF_OLD_PR_PCINVAL; 485 fill_siginfo(si, &prs->pr_info, &prs->pr_cursig); 486 prs->pr_nlwp = VG_(count_living_threads)(); 487 prs->pr_sighold = tst->sig_mask; 488 prs->pr_pid = VG_(getpid)(); 489 prs->pr_ppid = VG_(getppid)(); 490 prs->pr_pgrp = VG_(getpgrp)(); 491 prs->pr_sid = VG_(getpgrp)(); 492 fill_scheduling_class(prs->pr_clname, sizeof(prs->pr_clname)); 493 prs->pr_who = tst->os_state.lwpid; 494 prs->pr_brkbase = (vki_caddr_t) VG_(brk_base); 495 prs->pr_brksize = VG_(brk_limit) - VG_(brk_base); 496 prs->pr_stkbase = (vki_caddr_t) compute_stkbase(tst); 497 prs->pr_stksize = tst->client_stack_szB; 498 fill_regset(&prs->pr_reg, tst); 499} 500 501static void fill_psinfo(vki_psinfo_t *psinfo, const ThreadState *tst, 502 const vki_siginfo_t *si) 503{ 504 VG_(memset)(psinfo, 0, sizeof(*psinfo)); 505 506 psinfo->pr_nlwp = VG_(count_living_threads)(); 507 psinfo->pr_uid = get_uid(); 508 psinfo->pr_gid = get_gid(); 509 psinfo->pr_pid = VG_(getpid)(); 510 psinfo->pr_ppid = VG_(getppid)(); 511 psinfo->pr_pgid = VG_(getpgrp)(); 512 psinfo->pr_sid = VG_(getpgrp)(); 513 psinfo->pr_euid = VG_(geteuid)(); 514 psinfo->pr_egid = VG_(getegid)(); 515 VG_(client_fname)(psinfo->pr_fname, sizeof(psinfo->pr_fname), True); 516 psinfo->pr_wstat = get_wstat(si); 517 VG_(client_cmd_and_args)(psinfo->pr_psargs, 518 sizeof(psinfo->pr_psargs)); 519 fill_argv(&psinfo->pr_argc, (Addr *) &psinfo->pr_argv); 520 psinfo->pr_envp = (uintptr_t) VG_(client_envp); 521 psinfo->pr_dmodel = get_dmodel(); 522 psinfo->pr_zoneid = get_zoneid(); 523 524 psinfo->pr_lwp.pr_lwpid = tst->os_state.lwpid; 525 fill_thread_state(tst, &psinfo->pr_lwp.pr_state, 526 &psinfo->pr_lwp.pr_sname); 527 fill_scheduling_class(psinfo->pr_lwp.pr_clname, 528 sizeof(psinfo->pr_lwp.pr_clname)); 529} 530 531static void fill_pstatus(vki_pstatus_t *pstatus, 532 const ThreadState *tst, 533 const vki_siginfo_t *si) 534{ 535 VG_(memset)(pstatus, 0, sizeof(*pstatus)); 536 537 pstatus->pr_flags = VKI_PR_PCINVAL; 538 pstatus->pr_nlwp = VG_(count_living_threads)(); 539 pstatus->pr_pid = VG_(getpid)(); 540 pstatus->pr_ppid = VG_(getppid)(); 541 pstatus->pr_pgid = VG_(getpgrp)(); 542 pstatus->pr_sid = VG_(getpgrp)(); 543 pstatus->pr_brkbase = (uintptr_t) VG_(brk_base); 544 pstatus->pr_brksize = VG_(brk_limit) - VG_(brk_base); 545 pstatus->pr_stkbase = (uintptr_t) compute_stkbase(tst); 546 pstatus->pr_stksize = tst->client_stack_szB; 547 pstatus->pr_dmodel = get_dmodel(); 548 pstatus->pr_zoneid = get_zoneid(); 549 550 pstatus->pr_lwp.pr_flags = VKI_PR_PCINVAL; 551 pstatus->pr_lwp.pr_lwpid = tst->os_state.lwpid; 552 fill_siginfo(si, &pstatus->pr_lwp.pr_info, 553 &pstatus->pr_lwp.pr_cursig); 554 pstatus->pr_lwp.pr_lwphold = tst->sig_mask; 555 fill_scheduling_class(pstatus->pr_lwp.pr_clname, 556 sizeof(pstatus->pr_lwp.pr_clname)); 557 fill_regset(&pstatus->pr_lwp.pr_reg, tst); 558 fill_fpregset(&pstatus->pr_lwp.pr_fpreg, tst); 559} 560 561#if defined(SOLARIS_PRXREGSET_T) 562static void fill_xregs(vki_prxregset_t *xregs, const ThreadState *tst) 563{ 564 const ThreadArchState *arch = (const ThreadArchState *) &tst->arch; 565 566#if defined(VGP_x86_solaris) 567 VG_(memset)(xregs, 0, sizeof(*xregs)); 568 xregs->pr_xsize = sizeof(xregs->pr_un.pr_xsave); 569 570 /* SSE */ 571 UInt mxcsr = LibVEX_GuestX86_get_mxcsr(CONST_CAST(VexGuestX86State *, 572 &arch->vex)); 573 xregs->pr_un.pr_xsave.pr_mxcsr = mxcsr; 574 575 /* XMM registers */ 576 #define COPY_OUT_XMM(dest, src) \ 577 do { \ 578 dest._l[0] = src[0]; \ 579 dest._l[1] = src[1]; \ 580 dest._l[2] = src[2]; \ 581 dest._l[3] = src[3]; \ 582 } while (0); 583 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[0], arch->vex.guest_XMM0); 584 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[1], arch->vex.guest_XMM1); 585 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[2], arch->vex.guest_XMM2); 586 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[3], arch->vex.guest_XMM3); 587 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[4], arch->vex.guest_XMM4); 588 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[5], arch->vex.guest_XMM5); 589 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[6], arch->vex.guest_XMM6); 590 COPY_OUT_XMM(xregs->pr_un.pr_xsave.pr_xmm[7], arch->vex.guest_XMM7); 591 #undef COPY_OUT_XMM 592 593#elif defined(VGP_amd64_solaris) 594 VG_(memset)(xregs, 0, sizeof(*xregs)); 595 xregs->pr_xsize = sizeof(xregs->pr_un.pr_xsave); 596 597 /* LibVEX_GuestAMD64_fxsave() requires at least 416 bytes. */ 598 vg_assert(sizeof(xregs->pr_un.pr_xsave) >= 416); 599 LibVEX_GuestAMD64_fxsave(CONST_CAST(VexGuestAMD64State *, &arch->vex), 600 (Addr) &xregs->pr_un.pr_xsave); 601#else 602# error "Unknown platform" 603#endif 604} 605#endif /* SOLARIS_PRXREGSET_T */ 606 607static void fill_utsname(struct vki_utsname *uts) 608{ 609 VG_(memset)(uts, 0, sizeof(*uts)); 610 611 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_SYSNAME, 612 (UWord) &uts->sysname, sizeof(uts->sysname)); 613 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_HOSTNAME, 614 (UWord) &uts->nodename, sizeof(uts->nodename)); 615 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_RELEASE, 616 (UWord) &uts->release, sizeof(uts->release)); 617 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_VERSION, 618 (UWord) &uts->version, sizeof(uts->version)); 619 VG_(do_syscall3)(SYS_systeminfo, VKI_SI_MACHINE, 620 (UWord) &uts->machine, sizeof(uts->machine)); 621} 622 623static vki_prcred_t *create_prcred(SizeT *size) 624{ 625 UInt group_list[VKI_NGROUPS_MAX]; 626 Int ngroups = VG_(getgroups)(VKI_NGROUPS_MAX, group_list); 627 if (ngroups == -1) 628 ngroups = 0; 629 630 *size = sizeof(vki_prcred_t) + (ngroups - 1) * sizeof(gid_t); 631 vki_prcred_t *prcred = VG_(malloc)("coredump-elf.cp.1", *size); 632 VG_(memset)(prcred, 0, *size); 633 634 prcred->pr_euid = VG_(geteuid)(); 635 prcred->pr_ruid = get_uid(); 636 prcred->pr_suid = prcred->pr_euid; 637 prcred->pr_egid = VG_(getegid)(); 638 prcred->pr_rgid = get_gid(); 639 prcred->pr_sgid = prcred->pr_egid; 640 prcred->pr_ngroups = ngroups; 641 642 UInt i; 643 for (i = 0; i < ngroups; i++) 644 prcred->pr_groups[i] = group_list[i]; 645 646 return prcred; 647} 648 649static void fill_core_content(vki_core_content_t *content) 650{ 651 *content = VKI_CC_CONTENT_STACK | VKI_CC_CONTENT_HEAP 652 | VKI_CC_CONTENT_SHANON | VKI_CC_CONTENT_TEXT 653 | VKI_CC_CONTENT_DATA | VKI_CC_CONTENT_RODATA 654 | VKI_CC_CONTENT_ANON | VKI_CC_CONTENT_SHM 655 | VKI_CC_CONTENT_ISM | VKI_CC_CONTENT_DISM; 656} 657 658static vki_prpriv_t *create_prpriv(SizeT *size) 659{ 660 Int fd = VG_(fd_open)("/proc/self/priv", O_RDONLY, 0); 661 if (fd < 0) 662 return NULL; 663 664 struct vg_stat stats; 665 if (VG_(fstat)(fd, &stats) != 0) { 666 VG_(close)(fd); 667 return NULL; 668 } 669 670 vki_prpriv_t *prpriv = VG_(malloc)("coredump-elf.cp.1", stats.size); 671 672 if (VG_(read)(fd, prpriv, stats.size) != stats.size) { 673 VG_(free)(prpriv); 674 VG_(close)(fd); 675 return NULL; 676 } 677 678 VG_(close)(fd); 679 *size = stats.size; 680 return prpriv; 681} 682 683static vki_priv_impl_info_t *create_priv_info(SizeT *size) 684{ 685 /* Size of the returned priv_impl_info_t is apriori unkown. */ 686 vki_priv_impl_info_t first_cut[100]; 687 SysRes sres = VG_(do_syscall5)(SYS_privsys, VKI_PRIVSYS_GETIMPLINFO, 688 0, 0, (UWord) first_cut, 689 sizeof(first_cut)); 690 if (sr_isError(sres)) 691 return NULL; 692 693 SizeT real_size = first_cut[0].priv_headersize 694 + first_cut[0].priv_globalinfosize; 695 vki_priv_impl_info_t *priv_info = VG_(malloc)("coredump-elf.cpi.1", 696 real_size); 697 698 if (real_size <= sizeof(first_cut)) { 699 /* if the first_cut was large enough */ 700 VG_(memcpy)(priv_info, first_cut, real_size); 701 } else { 702 /* otherwise repeat the syscall with buffer large enough */ 703 sres = VG_(do_syscall5)(SYS_privsys, VKI_PRIVSYS_GETIMPLINFO, 704 0, 0, (UWord) priv_info, real_size); 705 if (sr_isError(sres)) { 706 VG_(free)(priv_info); 707 return NULL; 708 } 709 } 710 711 *size = real_size; 712 return priv_info; 713} 714 715static void fill_lwpsinfo(vki_lwpsinfo_t *lwp, 716 const ThreadState *tst) 717{ 718 VG_(memset)(lwp, 0, sizeof(*lwp)); 719 720 lwp->pr_lwpid = tst->os_state.lwpid; 721 fill_thread_state(tst, &lwp->pr_state, &lwp->pr_sname); 722 fill_scheduling_class(lwp->pr_clname, sizeof(lwp->pr_clname)); 723} 724 725static void fill_lwpstatus(vki_lwpstatus_t *lwp, 726 const ThreadState *tst, 727 const vki_siginfo_t *si) 728{ 729 VG_(memset)(lwp, 0, sizeof(*lwp)); 730 731 lwp->pr_flags = VKI_PR_PCINVAL; 732 lwp->pr_lwpid = tst->os_state.lwpid; 733 fill_siginfo(si, &lwp->pr_info, &lwp->pr_cursig); 734 fill_scheduling_class(lwp->pr_clname, sizeof(lwp->pr_clname)); 735 fill_regset(&lwp->pr_reg, tst); 736 fill_fpregset(&lwp->pr_fpreg, tst); 737} 738 739static void fill_old_note_for_thread(note_t **notes, 740 const ThreadState *tst, 741 const vki_siginfo_t *si) 742{ 743 vki_elf_prstatus_t prstatus; 744 fill_prstatus(&prstatus, tst, si); 745 add_note(notes, VKI_NT_PRSTATUS, &prstatus, sizeof(vki_elf_prstatus_t)); 746 747 vki_fpregset_t fpu; 748 fill_fpregset(&fpu, tst); 749 add_note(notes, VKI_NT_PRFPREG, &fpu, sizeof(vki_fpregset_t)); 750 751#if defined(SOLARIS_PRXREGSET_T) 752 if (should_dump_xregs(tst)) { 753 vki_prxregset_t xregs; 754 fill_xregs(&xregs, tst); 755 add_note(notes, VKI_NT_PRXREG, &xregs, sizeof(vki_prxregset_t)); 756 } 757#endif /* SOLARIS_PRXREGSET_T */ 758} 759 760static void fill_new_note_for_thread(note_t **notes, 761 const ThreadState *tst, 762 const vki_siginfo_t *si) 763{ 764 vki_lwpsinfo_t lwpsinfo; 765 fill_lwpsinfo(&lwpsinfo, tst); 766 add_note(notes, VKI_NT_LWPSINFO, &lwpsinfo, sizeof(vki_lwpsinfo_t)); 767 768 vki_lwpstatus_t lwpstatus; 769 fill_lwpstatus(&lwpstatus, tst, si); 770 add_note(notes, VKI_NT_LWPSTATUS, &lwpstatus, sizeof(vki_lwpstatus_t)); 771 772#if defined(SOLARIS_PRXREGSET_T) 773 if (should_dump_xregs(tst)) { 774 vki_prxregset_t xregs; 775 fill_xregs(&xregs, tst); 776 add_note(notes, VKI_NT_PRXREG, &xregs, sizeof(vki_prxregset_t)); 777 } 778#endif /* SOLARIS_PRXREGSET_T */ 779} 780 781/*====================================================================*/ 782/*=== Note utility functions ===*/ 783/*====================================================================*/ 784 785static void add_note(note_t **list, UInt type, const void *data, 786 UInt datasz) 787{ 788 UInt note_size = sizeof(note_t) + VG_ROUNDUP(datasz, 4); 789 790 note_t *n = VG_(malloc)("coredump-elf.an.1", note_size); 791 792 VG_(memset)(n, 0, note_size); 793 n->nhdr.n_type = type; 794 n->nhdr.n_namesz = 5; 795 n->nhdr.n_descsz = VG_ROUNDUP(datasz, 4); 796 VG_(memcpy)(n->name, "CORE", 4); 797 VG_(memcpy)(n->data, data, datasz); 798 799 if (*list == NULL) { 800 *list = n; 801 return; 802 } 803 804 note_t *tail = *list; 805 while (tail->next != NULL) 806 tail = tail->next; 807 tail->next = n; 808} 809 810static UInt note_size(const note_t *note) 811{ 812 return sizeof(note_t) - sizeof(note_t *) + note->nhdr.n_descsz; 813} 814 815static UInt notes_size(const note_t *list) 816{ 817 UInt size = 0; 818 const note_t *note; 819 820 for (note = list; note != NULL; note = note->next) 821 size += note_size(note); 822 823 return size; 824} 825 826static void fill_notes_phdr(VKI_ESZ(Phdr) *phdr, UInt offset, 827 UInt size_of_notes) 828{ 829 phdr->p_type = PT_NOTE; 830 phdr->p_offset = offset; 831 phdr->p_vaddr = 0; 832 phdr->p_paddr = 0; 833 phdr->p_filesz = size_of_notes; 834 phdr->p_memsz = 0; 835 phdr->p_flags = PF_R; 836 phdr->p_align = 0; 837} 838 839static void write_notes(Int fd, const HChar *filename, 840 const note_t *list) 841{ 842 const note_t *note; 843 844 for (note = list; note != NULL; note = note->next) 845 write_part(fd, filename, CONST_CAST(void *, ¬e->nhdr), 846 note_size(note), "notes"); 847} 848 849static void free_notes(note_t *list) 850{ 851 while (list != NULL) { 852 note_t *next = list->next; 853 VG_(free)(list); 854 list = next; 855 } 856} 857 858/*====================================================================*/ 859/*=== Main coredump function ===*/ 860/*====================================================================*/ 861 862void VG_(make_coredump)(ThreadId tid, const vki_siginfo_t *si, 863 ULong max_size) 864{ 865 const HChar *basename = "vgcore"; 866 const HChar *coreext = ""; 867 Int core_fd; 868 869 if (VG_(clo_log_fname_expanded) != NULL) { 870 coreext = ".core"; 871 basename = VG_(expand_file_name)("--log-file", 872 VG_(clo_log_fname_expanded)); 873 } 874 875 vg_assert(coreext != NULL); 876 vg_assert(basename != NULL); 877 878 UInt filename_size = VG_(strlen)(coreext) + VG_(strlen)(basename) 879 + 100; /* for the two %d's */ 880 HChar *filename = VG_(malloc)("coredump-elf.mc.1", filename_size); 881 882 /* Try to come with a non-existent coredump filename. */ 883 UInt seq = 0; 884 for (;;) { 885 Int oflags = VKI_O_CREAT|VKI_O_WRONLY|VKI_O_EXCL|VKI_O_TRUNC; 886 887 if (seq == 0) 888 VG_(snprintf)(filename, filename_size, "%s%s.%d", 889 basename, coreext, VG_(getpid)()); 890 else 891 VG_(snprintf)(filename, filename_size, "%s%s.%d.%d", 892 basename, coreext, VG_(getpid)(), seq); 893 seq++; 894 895#ifdef VKI_O_LARGEFILE 896 oflags |= VKI_O_LARGEFILE; 897#endif 898 899 SysRes sres = VG_(open)(filename, oflags, 900 VKI_S_IRUSR|VKI_S_IWUSR); 901 if (!sr_isError(sres)) { 902 core_fd = sr_Res(sres); 903 break; 904 } 905 906 if (sr_isError(sres) && sr_Err(sres) != VKI_EEXIST) { 907 VG_(umsg)("Cannot create coredump file %s (%lu)\n", 908 filename, sr_Err(sres)); 909 VG_(free)(filename); 910 return; 911 } 912 } 913 914 /* Get the client segments. Free seg_starts after use. */ 915 Int n_seg_starts; 916 Addr *seg_starts = VG_(get_segment_starts)(SkFileC | SkAnonC | SkShmC, 917 &n_seg_starts); 918 919 /* Count how many memory segments to dump. */ 920 Int i; 921 UInt num_phdrs = 2; /* two CORE note sections */ 922 for (i = 0; i < n_seg_starts; i++) { 923 if (!may_dump(VG_(am_find_nsegment(seg_starts[i])))) 924 continue; 925 926 num_phdrs++; 927 } 928 929 VKI_ESZ(Ehdr) ehdr; 930 fill_ehdr(&ehdr, num_phdrs); 931 932 VKI_ESZ(Shdr) shdr; 933 if (ehdr.e_shnum > 0) 934 fill_zero_shdr(&shdr, num_phdrs); 935 UInt phdrs_size = num_phdrs * ehdr.e_phentsize; 936 937 /* Construct the old-style notes. */ 938 note_t *old_notes = NULL; 939 940 vki_elf_prpsinfo_t prpsinfo; 941 fill_prpsinfo(&prpsinfo, &VG_(threads)[tid], si); 942 add_note(&old_notes, VKI_NT_PRPSINFO, &prpsinfo, 943 sizeof(vki_elf_prpsinfo_t)); 944 945 HChar platform[256 + 1]; 946 fill_platform(platform, sizeof(platform)); 947 add_note(&old_notes, VKI_NT_PLATFORM, platform, 948 VG_(strlen)(platform) + 1); 949 950 add_note(&old_notes, VKI_NT_AUXV, VG_(client_auxv), 951 count_auxv() * sizeof(auxv_t)); 952 953 /* Add detail about the faulting thread as the first note. 954 This is how gdb determines which thread faulted. Note that 955 mdb does not need such aid. */ 956 fill_old_note_for_thread(&old_notes, &VG_(threads)[tid], si); 957 958 /* Now add details for all threads except the one that faulted. */ 959 ThreadId t_idx; 960 for (t_idx = 1; t_idx < VG_N_THREADS; t_idx++) 961 if ((VG_(threads)[t_idx].status != VgTs_Empty) && 962 (VG_(threads)[t_idx].status != VgTs_Zombie)) { 963 if (t_idx == tid) 964 continue; 965 966 fill_old_note_for_thread(&old_notes, &VG_(threads)[t_idx], si); 967 } 968 969 /* Construct the new-style notes. */ 970 note_t *new_notes = NULL; 971 vki_psinfo_t psinfo; 972 fill_psinfo(&psinfo, &VG_(threads)[tid], si); 973 add_note(&new_notes, VKI_NT_PSINFO, &psinfo, sizeof(vki_psinfo_t)); 974 975 vki_pstatus_t pstatus; 976 fill_pstatus(&pstatus, &VG_(threads)[tid], si); 977 add_note(&new_notes, VKI_NT_PSTATUS, &pstatus, sizeof(vki_pstatus_t)); 978 979 add_note(&new_notes, VKI_NT_PLATFORM, platform, 980 VG_(strlen)(platform) + 1); 981 982 add_note(&new_notes, VKI_NT_AUXV, VG_(client_auxv), 983 count_auxv() * sizeof(auxv_t)); 984 985 struct vki_utsname uts; 986 fill_utsname(&uts); 987 add_note(&new_notes, VKI_NT_UTSNAME, &uts, 988 sizeof(struct vki_utsname)); 989 990 SizeT prcred_size; 991 vki_prcred_t *prcred = create_prcred(&prcred_size); 992 if (prcred != NULL) { 993 add_note(&new_notes, VKI_NT_PRCRED, prcred, prcred_size); 994 VG_(free)(prcred); 995 } 996 997 vki_core_content_t core_content; 998 fill_core_content(&core_content); 999 add_note(&new_notes, VKI_NT_CONTENT, &core_content, 1000 sizeof(vki_core_content_t)); 1001 1002 SizeT priv_size; 1003 vki_prpriv_t *prpriv = create_prpriv(&priv_size); 1004 if (prpriv != NULL) { 1005 add_note(&new_notes, VKI_NT_PRPRIV, prpriv, priv_size); 1006 VG_(free)(prpriv); 1007 } 1008 1009 vki_priv_impl_info_t *priv_info = create_priv_info(&priv_size); 1010 if (priv_info != NULL) { 1011 add_note(&new_notes, VKI_NT_PRPRIVINFO, priv_info, priv_size); 1012 VG_(free)(priv_info); 1013 } 1014 1015 HChar zonename[VKI_ZONENAME_MAX + 1]; 1016 fill_zonename(zonename, sizeof(zonename)); 1017 add_note(&new_notes, VKI_NT_ZONENAME, zonename, 1018 VG_(strlen)(zonename) + 1); 1019 1020 /* Add detail about the faulting thread as the first note. 1021 This is how gdb determines which thread faulted. Note that 1022 mdb does not need such aid. */ 1023 fill_new_note_for_thread(&new_notes, &VG_(threads)[tid], si); 1024 1025 /* Now add details for all threads except the one that faulted. */ 1026 for (t_idx = 1; t_idx < VG_N_THREADS; t_idx++) { 1027 if ((VG_(threads)[t_idx].status != VgTs_Empty) && 1028 (VG_(threads)[t_idx].status != VgTs_Zombie)) { 1029 if (t_idx == tid) 1030 continue; 1031 1032 fill_new_note_for_thread(&new_notes, &VG_(threads)[t_idx], si); 1033 } 1034 } 1035 1036 VKI_ESZ(Phdr) *phdrs = VG_(malloc)("coredump-elf.mc.2", phdrs_size); 1037 1038 UInt size_of_notes = notes_size(old_notes); 1039 UInt offset = ehdr.e_ehsize + phdrs_size + 1040 (ehdr.e_shnum * ehdr.e_shentsize); 1041 1042 /* fill program header for old notes */ 1043 fill_notes_phdr(&phdrs[0], offset, size_of_notes); 1044 offset += size_of_notes; 1045 1046 size_of_notes = notes_size(new_notes); 1047 /* fill program header for new notes */ 1048 fill_notes_phdr(&phdrs[1], offset, size_of_notes); 1049 offset += size_of_notes; 1050 1051 /* fill program headers for segments */ 1052 UInt idx; 1053 for (i = 0, idx = 2; i < n_seg_starts; i++) { 1054 NSegment const *seg = VG_(am_find_nsegment(seg_starts[i])); 1055 1056 if (!may_dump(seg)) 1057 continue; 1058 1059 fill_phdr(&phdrs[idx], seg, offset, 1060 (seg->end - seg->start + 1 + offset) < max_size); 1061 1062 offset += phdrs[idx].p_filesz; 1063 1064 idx++; 1065 } 1066 1067 /* write everything out */ 1068 write_part(core_fd, filename, &ehdr, sizeof(ehdr), 1069 "elf headers"); 1070 write_part(core_fd, filename, phdrs, phdrs_size, 1071 "program headers"); 1072 if (ehdr.e_shnum > 0) 1073 write_part(core_fd, filename, &shdr, sizeof(shdr), 1074 "section headers"); 1075 write_notes(core_fd, filename, old_notes); 1076 write_notes(core_fd, filename, new_notes); 1077 1078 VG_(lseek)(core_fd, phdrs[2].p_offset, VKI_SEEK_SET); 1079 1080 for (i = 0, idx = 2; i < n_seg_starts; i++) { 1081 NSegment const *seg = VG_(am_find_nsegment(seg_starts[i])); 1082 1083 if (!should_dump(seg)) 1084 continue; 1085 1086 if (phdrs[idx].p_filesz > 0) { 1087 Off64T off = VG_(lseek)(core_fd, phdrs[idx].p_offset, 1088 VKI_SEEK_SET); 1089 vg_assert(off == phdrs[idx].p_offset); 1090 vg_assert(seg->end - seg->start + 1 >= phdrs[idx].p_filesz); 1091 1092 write_part(core_fd, filename, (void *) seg->start, 1093 phdrs[idx].p_filesz, "program segment"); 1094 } 1095 idx++; 1096 } 1097 1098 VG_(close)(core_fd); 1099 VG_(free)(filename); 1100 VG_(free)(phdrs); 1101 free_notes(old_notes); 1102 free_notes(new_notes); 1103 VG_(free)(seg_starts); 1104} 1105 1106#endif 1107 1108/*--------------------------------------------------------------------*/ 1109/*--- end ---*/ 1110/*--------------------------------------------------------------------*/ 1111