1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 /* 27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 28 * Copyright 2018 Joyent, Inc. 29 * Copyright (c) 2013 by Delphix. All rights reserved. 30 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 31 * Copyright 2024 Oxide Computer Company 32 * Copyright 2026 Carsten Grzemba 33 */ 34 35 #define _STRUCTURED_PROC 1 36 37 #include <assert.h> 38 #include <stdlib.h> 39 #include <ctype.h> 40 #include <string.h> 41 #include <strings.h> 42 #include <errno.h> 43 #include <procfs.h> 44 #include <priv.h> 45 #include <sys/elf.h> 46 #include <sys/machelf.h> 47 #include <sys/sysmacros.h> 48 #include <sys/systeminfo.h> 49 #include <sys/proc.h> 50 #include <sys/utsname.h> 51 #include <core_shstrtab.h> 52 53 #include "Pcontrol.h" 54 #include "P32ton.h" 55 #include "proc_fd.h" 56 57 typedef struct { 58 struct ps_prochandle *P; 59 int pgc_fd; 60 off64_t *pgc_poff; 61 off64_t *pgc_soff; 62 off64_t *pgc_doff; 63 core_content_t pgc_content; 64 void *pgc_chunk; 65 size_t pgc_chunksz; 66 67 shstrtab_t pgc_shstrtab; 68 } pgcore_t; 69 70 typedef struct { 71 int fd_fd; 72 off64_t *fd_doff; 73 } fditer_t; 74 75 static int 76 gc_pwrite64(int fd, const void *buf, size_t len, off64_t off) 77 { 78 int err; 79 80 err = pwrite64(fd, buf, len, off); 81 82 if (err < 0) 83 return (err); 84 85 /* 86 * We will take a page from ZFS's book here and use the otherwise 87 * unused EBADE to mean a short write. Typically this will actually 88 * result from ENOSPC or EDQUOT, but we can't be sure. 89 */ 90 if (err < len) { 91 errno = EBADE; 92 return (-1); 93 } 94 95 return (0); 96 } 97 98 int 99 Pgcore(struct ps_prochandle *P, const char *fname, core_content_t content) 100 { 101 int fd; 102 int err; 103 int saved_errno; 104 105 if ((fd = creat64(fname, 0666)) < 0) 106 return (-1); 107 108 if ((err = Pfgcore(P, fd, content)) != 0) { 109 saved_errno = errno; 110 (void) close(fd); 111 (void) unlink(fname); 112 errno = saved_errno; 113 return (err); 114 } 115 116 return (close(fd)); 117 } 118 119 static int 120 write_note(int fd, uint_t type, const void *desc, size_t descsz, off64_t *offp) 121 { 122 /* 123 * Note headers are the same regardless of the data model of the 124 * ELF file; we arbitrarily use Elf64_Nhdr here. 125 */ 126 struct { 127 Elf64_Nhdr nhdr; 128 char name[8]; 129 } n; 130 131 bzero(&n, sizeof (n)); 132 bcopy("CORE", n.name, 4); 133 n.nhdr.n_type = type; 134 n.nhdr.n_namesz = 5; 135 n.nhdr.n_descsz = roundup(descsz, 4); 136 137 if (gc_pwrite64(fd, &n, sizeof (n), *offp) != 0) 138 return (-1); 139 140 *offp += sizeof (n); 141 142 if (gc_pwrite64(fd, desc, n.nhdr.n_descsz, *offp) != 0) 143 return (-1); 144 145 *offp += n.nhdr.n_descsz; 146 147 return (0); 148 } 149 150 static int 151 per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) 152 { 153 pgcore_t *pgc = data; 154 struct ps_prochandle *P = pgc->P; 155 prlwpname_t name = { 0, "" }; 156 psinfo_t ps; 157 prxregset_t *xregs; 158 size_t size; 159 160 /* 161 * If lsp is NULL this indicates that this is a zombie LWP in 162 * which case we dump only the lwpsinfo_t structure and none of 163 * the other ancillary LWP state data. 164 */ 165 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 166 if (write_note(pgc->pgc_fd, NT_LWPSINFO, lip, 167 sizeof (lwpsinfo_t), pgc->pgc_doff) != 0) 168 return (1); 169 if (lsp == NULL) 170 return (0); 171 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, lsp, 172 sizeof (lwpstatus_t), pgc->pgc_doff) != 0) 173 return (1); 174 #ifdef _LP64 175 } else { 176 lwpsinfo32_t li32; 177 lwpstatus32_t ls32; 178 lwpsinfo_n_to_32(lip, &li32); 179 if (write_note(pgc->pgc_fd, NT_LWPSINFO, &li32, 180 sizeof (lwpsinfo32_t), pgc->pgc_doff) != 0) 181 return (1); 182 if (lsp == NULL) 183 return (0); 184 lwpstatus_n_to_32(lsp, &ls32); 185 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, &ls32, 186 sizeof (lwpstatus32_t), pgc->pgc_doff) != 0) 187 return (1); 188 #endif /* _LP64 */ 189 } 190 191 if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs, &size) == 0) { 192 if (write_note(pgc->pgc_fd, NT_PRXREG, xregs, size, 193 pgc->pgc_doff) != 0) 194 return (1); 195 196 Plwp_freexregs(P, xregs, size); 197 } 198 199 if (Plwp_getname(P, lsp->pr_lwpid, name.pr_lwpname, 200 sizeof (name.pr_lwpname)) == 0) { 201 name.pr_lwpid = lsp->pr_lwpid; 202 if (write_note(pgc->pgc_fd, NT_LWPNAME, &name, 203 sizeof (name), pgc->pgc_doff) != 0) 204 return (1); 205 } 206 207 if (!(lsp->pr_flags & PR_AGENT)) 208 return (0); 209 210 if (Plwp_getspymaster(P, lsp->pr_lwpid, &ps) != 0) 211 return (0); 212 213 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 214 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps, 215 sizeof (psinfo_t), pgc->pgc_doff) != 0) 216 return (1); 217 #ifdef _LP64 218 } else { 219 psinfo32_t ps32; 220 psinfo_n_to_32(&ps, &ps32); 221 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps32, 222 sizeof (psinfo32_t), pgc->pgc_doff) != 0) 223 return (1); 224 #endif /* _LP64 */ 225 } 226 227 228 return (0); 229 } 230 231 static int 232 iter_fd(void *data, const prfdinfo_t *fdinfo) 233 { 234 fditer_t *iter = data; 235 prfdinfo_core_t core; 236 int ret = 0; 237 238 if (proc_fdinfo_to_core(fdinfo, &core) != 0) 239 return (1); 240 241 ret = write_note(iter->fd_fd, NT_FDINFO, &core, 242 sizeof (core), iter->fd_doff); 243 244 if (ret != 0) 245 return (1); 246 return (0); 247 } 248 249 /* 250 * Look for sections that begin with the string '.debug_'. In particular, this 251 * will catch all DWARF related sections and it will catch those that different 252 * folks use that are not related to DWARF, but still begin with this prefix 253 * (e.g. .debug_gdb_scripts). Notably though, this does not catch something like 254 * stabs (though it could). This really is filtering based on the section name, 255 * less so intent. 256 */ 257 static boolean_t 258 is_debug_section(file_info_t *fptr, GElf_Shdr *shdr) 259 { 260 if (shdr->sh_name == 0 || shdr->sh_name > fptr->file_shstrsz) 261 return (B_FALSE); 262 263 if (strncmp(fptr->file_shstrs + shdr->sh_name, ".debug_", 264 strlen(".debug_")) != 0) { 265 return (B_FALSE); 266 } 267 268 return (B_TRUE); 269 } 270 271 static uint_t 272 count_debug(file_info_t *fptr) 273 { 274 uint_t count = 0; 275 Elf_Scn *scn = NULL; 276 277 if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) { 278 return (0); 279 } 280 281 while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) { 282 GElf_Shdr shdr; 283 284 if (gelf_getshdr(scn, &shdr) == NULL) 285 continue; 286 287 if (is_debug_section(fptr, &shdr)) 288 count++; 289 } 290 291 return (count); 292 } 293 294 static uint_t 295 count_sections(pgcore_t *pgc) 296 { 297 struct ps_prochandle *P = pgc->P; 298 file_info_t *fptr; 299 uint_t nshdrs = 0; 300 301 if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | 302 CC_CONTENT_DEBUG))) { 303 return (0); 304 } 305 306 for (fptr = list_head(&P->file_head); fptr != NULL; 307 fptr = list_next(&P->file_head, fptr)) { 308 int hit_symtab = 0; 309 310 Pbuild_file_symtab(P, fptr); 311 312 if ((pgc->pgc_content & CC_CONTENT_CTF) && 313 Pbuild_file_ctf(P, fptr) != NULL) { 314 sym_tbl_t *sym; 315 316 nshdrs++; 317 318 if (fptr->file_ctf_dyn) { 319 sym = &fptr->file_dynsym; 320 } else { 321 sym = &fptr->file_symtab; 322 hit_symtab = 1; 323 } 324 325 if (sym->sym_data_pri != NULL && sym->sym_symn != 0 && 326 sym->sym_strs != NULL) 327 nshdrs += 2; 328 } 329 330 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && 331 fptr->file_symtab.sym_data_pri != NULL && 332 fptr->file_symtab.sym_symn != 0 && 333 fptr->file_symtab.sym_strs != NULL) { 334 nshdrs += 2; 335 } 336 337 if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0) 338 nshdrs += count_debug(fptr); 339 } 340 341 return (nshdrs == 0 ? 0 : nshdrs + 2); 342 } 343 344 static int 345 write_shdr(pgcore_t *pgc, const char *name, uint_t type, ulong_t flags, 346 uintptr_t addr, ulong_t offset, size_t size, uint_t link, uint_t info, 347 uintptr_t addralign, uintptr_t entsize) 348 { 349 if (pgc->P->status.pr_dmodel == PR_MODEL_ILP32) { 350 Elf32_Shdr shdr; 351 352 bzero(&shdr, sizeof (shdr)); 353 if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) { 354 return (-1); 355 } 356 shdr.sh_type = type; 357 shdr.sh_flags = flags; 358 shdr.sh_addr = (Elf32_Addr)addr; 359 shdr.sh_offset = offset; 360 shdr.sh_size = size; 361 shdr.sh_link = link; 362 shdr.sh_info = info; 363 shdr.sh_addralign = addralign; 364 shdr.sh_entsize = entsize; 365 366 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 367 *pgc->pgc_soff) != 0) 368 return (-1); 369 370 *pgc->pgc_soff += sizeof (shdr); 371 #ifdef _LP64 372 } else { 373 Elf64_Shdr shdr; 374 375 bzero(&shdr, sizeof (shdr)); 376 if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) { 377 return (-1); 378 } 379 shdr.sh_type = type; 380 shdr.sh_flags = flags; 381 shdr.sh_addr = addr; 382 shdr.sh_offset = offset; 383 shdr.sh_size = size; 384 shdr.sh_link = link; 385 shdr.sh_info = info; 386 shdr.sh_addralign = addralign; 387 shdr.sh_entsize = entsize; 388 389 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 390 *pgc->pgc_soff) != 0) 391 return (-1); 392 393 *pgc->pgc_soff += sizeof (shdr); 394 #endif /* _LP64 */ 395 } 396 397 return (0); 398 } 399 400 static int 401 dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym) 402 { 403 sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab; 404 shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB; 405 shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB; 406 uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB; 407 size_t size; 408 uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr; 409 410 if (sym->sym_data_pri == NULL || sym->sym_symn == 0 || 411 sym->sym_strs == NULL) 412 return (0); 413 414 size = sym->sym_hdr_pri.sh_size; 415 if (gc_pwrite64(pgc->pgc_fd, sym->sym_data_pri->d_buf, size, 416 *pgc->pgc_doff) != 0) 417 return (-1); 418 419 if (write_shdr(pgc, shstrtab_data[symname], symtype, 0, addr, 420 *pgc->pgc_doff, size, index + 1, sym->sym_hdr_pri.sh_info, 421 sym->sym_hdr_pri.sh_addralign, sym->sym_hdr_pri.sh_entsize) != 0) 422 return (-1); 423 424 *pgc->pgc_doff += roundup(size, 8); 425 426 size = sym->sym_strhdr.sh_size; 427 if (gc_pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != 0) 428 return (-1); 429 430 if (write_shdr(pgc, shstrtab_data[strname], SHT_STRTAB, SHF_STRINGS, 431 addr, *pgc->pgc_doff, size, 0, 0, 1, 0) != 0) 432 return (-1); 433 434 *pgc->pgc_doff += roundup(size, 8); 435 436 return (0); 437 } 438 439 static int 440 dump_debug(pgcore_t *pgc, file_info_t *fptr, uint_t *indexp) 441 { 442 Elf_Scn *scn = NULL; 443 444 if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) { 445 return (0); 446 } 447 448 while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) { 449 GElf_Shdr shdr; 450 Elf_Data *data; 451 452 if (gelf_getshdr(scn, &shdr) == NULL) 453 continue; 454 455 if (!is_debug_section(fptr, &shdr)) 456 continue; 457 458 if ((data = elf_getdata(scn, NULL)) == NULL) { 459 return (-1); 460 } 461 462 if (gc_pwrite64(pgc->pgc_fd, data->d_buf, data->d_size, 463 *pgc->pgc_doff) != 0) 464 return (-1); 465 466 if (write_shdr(pgc, fptr->file_shstrs + shdr.sh_name, 467 shdr.sh_type, shdr.sh_flags, 468 fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff, 469 data->d_size, 0, shdr.sh_info, shdr.sh_addralign, 470 shdr.sh_entsize) != 0) { 471 return (-1); 472 } 473 474 *indexp = *indexp + 1; 475 *pgc->pgc_doff += roundup(data->d_size, 8); 476 } 477 478 return (0); 479 } 480 481 static int 482 dump_sections(pgcore_t *pgc) 483 { 484 struct ps_prochandle *P = pgc->P; 485 file_info_t *fptr; 486 uint_t index = 1; 487 488 if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | 489 CC_CONTENT_DEBUG))) { 490 return (0); 491 } 492 493 for (fptr = list_head(&P->file_head); fptr != NULL; 494 fptr = list_next(&P->file_head, fptr)) { 495 int hit_symtab = 0; 496 497 Pbuild_file_symtab(P, fptr); 498 499 if ((pgc->pgc_content & CC_CONTENT_CTF) && 500 Pbuild_file_ctf(P, fptr) != NULL) { 501 sym_tbl_t *sym; 502 uint_t dynsym; 503 uint_t symindex = 0; 504 505 /* 506 * Write the symtab out first so we can correctly 507 * set the sh_link field in the CTF section header. 508 * symindex will be 0 if there is no corresponding 509 * symbol table section. 510 */ 511 if (fptr->file_ctf_dyn) { 512 sym = &fptr->file_dynsym; 513 dynsym = 1; 514 } else { 515 sym = &fptr->file_symtab; 516 dynsym = 0; 517 hit_symtab = 1; 518 } 519 520 if (sym->sym_data_pri != NULL && sym->sym_symn != 0 && 521 sym->sym_strs != NULL) { 522 symindex = index; 523 if (dump_symtab(pgc, fptr, index, dynsym) != 0) 524 return (-1); 525 index += 2; 526 } 527 528 /* 529 * Write the CTF data that we've read out of the 530 * file itself into the core file. 531 */ 532 if (gc_pwrite64(pgc->pgc_fd, fptr->file_ctf_buf, 533 fptr->file_ctf_size, *pgc->pgc_doff) != 0) 534 return (-1); 535 536 if (write_shdr(pgc, shstrtab_data[STR_CTF], 537 SHT_PROGBITS, 0, fptr->file_map->map_pmap.pr_vaddr, 538 *pgc->pgc_doff, fptr->file_ctf_size, symindex, 0, 539 4, 0) != 0) 540 return (-1); 541 542 index++; 543 *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8); 544 } 545 546 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && 547 fptr->file_symtab.sym_data_pri != NULL && 548 fptr->file_symtab.sym_symn != 0 && 549 fptr->file_symtab.sym_strs != NULL) { 550 if (dump_symtab(pgc, fptr, index, 0) != 0) 551 return (-1); 552 index += 2; 553 } 554 555 if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0 && 556 dump_debug(pgc, fptr, &index) != 0) { 557 return (-1); 558 } 559 } 560 561 return (0); 562 } 563 564 /*ARGSUSED*/ 565 static int 566 dump_map(void *data, const prmap_t *pmp, const char *name) 567 { 568 pgcore_t *pgc = data; 569 struct ps_prochandle *P = pgc->P; 570 #ifdef _LP64 571 Elf64_Phdr phdr; 572 #else 573 Elf32_Phdr phdr; 574 #endif 575 size_t n; 576 577 bzero(&phdr, sizeof (phdr)); 578 phdr.p_type = PT_LOAD; 579 phdr.p_vaddr = pmp->pr_vaddr; 580 phdr.p_memsz = pmp->pr_size; 581 if (pmp->pr_mflags & MA_READ) 582 phdr.p_flags |= PF_R; 583 if (pmp->pr_mflags & MA_WRITE) 584 phdr.p_flags |= PF_W; 585 if (pmp->pr_mflags & MA_EXEC) 586 phdr.p_flags |= PF_X; 587 588 if (pmp->pr_vaddr + pmp->pr_size > P->status.pr_stkbase && 589 pmp->pr_vaddr < P->status.pr_stkbase + P->status.pr_stksize) { 590 if (!(pgc->pgc_content & CC_CONTENT_STACK)) 591 goto exclude; 592 593 } else if ((pmp->pr_mflags & MA_ANON) && 594 pmp->pr_vaddr + pmp->pr_size > P->status.pr_brkbase && 595 pmp->pr_vaddr < P->status.pr_brkbase + P->status.pr_brksize) { 596 if (!(pgc->pgc_content & CC_CONTENT_HEAP)) 597 goto exclude; 598 599 } else if (pmp->pr_mflags & MA_ISM) { 600 if (pmp->pr_mflags & MA_NORESERVE) { 601 if (!(pgc->pgc_content & CC_CONTENT_DISM)) 602 goto exclude; 603 } else { 604 if (!(pgc->pgc_content & CC_CONTENT_ISM)) 605 goto exclude; 606 } 607 608 } else if (pmp->pr_mflags & MA_SHM) { 609 if (!(pgc->pgc_content & CC_CONTENT_SHM)) 610 goto exclude; 611 612 } else if (pmp->pr_mflags & MA_SHARED) { 613 if (pmp->pr_mflags & MA_ANON) { 614 if (!(pgc->pgc_content & CC_CONTENT_SHANON)) 615 goto exclude; 616 } else { 617 if (!(pgc->pgc_content & CC_CONTENT_SHFILE)) 618 goto exclude; 619 } 620 621 } else if (pmp->pr_mflags & MA_ANON) { 622 if (!(pgc->pgc_content & CC_CONTENT_ANON)) 623 goto exclude; 624 625 } else if (phdr.p_flags == (PF_R | PF_X)) { 626 if (!(pgc->pgc_content & CC_CONTENT_TEXT)) 627 goto exclude; 628 629 } else if (phdr.p_flags == PF_R) { 630 if (!(pgc->pgc_content & CC_CONTENT_RODATA)) 631 goto exclude; 632 633 } else { 634 if (!(pgc->pgc_content & CC_CONTENT_DATA)) 635 goto exclude; 636 } 637 638 n = 0; 639 while (n < pmp->pr_size) { 640 size_t csz = MIN(pmp->pr_size - n, pgc->pgc_chunksz); 641 ssize_t ret; 642 643 /* 644 * If we happen to have a PROT_NONE mapping, don't try to read 645 * from the address space. 646 */ 647 if ((pmp->pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) == 0) { 648 bzero(pgc->pgc_chunk, csz); 649 ret = csz; 650 } else { 651 ret = Pread(P, pgc->pgc_chunk, csz, pmp->pr_vaddr + n); 652 } 653 654 /* 655 * If we can't read out part of the victim's address 656 * space for some reason ignore that failure and try to 657 * emit a partial core file without that mapping's data. 658 * As in the kernel, we mark these failures with the 659 * PF_SUNW_FAILURE flag and store the errno where the 660 * mapping would have been. 661 */ 662 if (ret != csz || gc_pwrite64(pgc->pgc_fd, pgc->pgc_chunk, csz, 663 *pgc->pgc_doff + n) != 0) { 664 int err = errno; 665 (void) gc_pwrite64(pgc->pgc_fd, &err, sizeof (err), 666 *pgc->pgc_doff); 667 *pgc->pgc_doff += roundup(sizeof (err), 8); 668 669 phdr.p_flags |= PF_SUNW_FAILURE; 670 (void) ftruncate64(pgc->pgc_fd, *pgc->pgc_doff); 671 goto exclude; 672 } 673 674 n += csz; 675 } 676 677 phdr.p_offset = *pgc->pgc_doff; 678 phdr.p_filesz = pmp->pr_size; 679 *pgc->pgc_doff += roundup(phdr.p_filesz, 8); 680 681 exclude: 682 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 683 if (gc_pwrite64(pgc->pgc_fd, &phdr, sizeof (phdr), 684 *pgc->pgc_poff) != 0) 685 return (1); 686 687 *pgc->pgc_poff += sizeof (phdr); 688 #ifdef _LP64 689 } else { 690 Elf32_Phdr phdr32; 691 692 bzero(&phdr32, sizeof (phdr32)); 693 phdr32.p_type = phdr.p_type; 694 phdr32.p_vaddr = (Elf32_Addr)phdr.p_vaddr; 695 phdr32.p_memsz = (Elf32_Word)phdr.p_memsz; 696 phdr32.p_flags = phdr.p_flags; 697 phdr32.p_offset = (Elf32_Off)phdr.p_offset; 698 phdr32.p_filesz = (Elf32_Word)phdr.p_filesz; 699 700 if (gc_pwrite64(pgc->pgc_fd, &phdr32, sizeof (phdr32), 701 *pgc->pgc_poff) != 0) 702 return (1); 703 704 *pgc->pgc_poff += sizeof (phdr32); 705 #endif /* _LP64 */ 706 } 707 708 return (0); 709 } 710 711 int 712 write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc) 713 { 714 off64_t off = *pgc->pgc_doff; 715 size_t size = 0; 716 shstrtab_t *s = &pgc->pgc_shstrtab; 717 718 if (shstrtab_size(s) == 1) 719 return (0); 720 721 /* 722 * Preemptively stick the name of the shstrtab in the string table. 723 */ 724 if (!shstrtab_ndx(&pgc->pgc_shstrtab, 725 shstrtab_data[STR_SHSTRTAB], NULL)) { 726 return (1); 727 } 728 size = shstrtab_size(s); 729 730 /* 731 * Dump all the strings that we used being sure we include the 732 * terminating null character. 733 */ 734 for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL; 735 ent = list_next(&s->sst_names, ent)) { 736 if (gc_pwrite64(pgc->pgc_fd, ent->sste_name, ent->sste_len, 737 off + ent->sste_offset) != 0) { 738 return (1); 739 } 740 } 741 742 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 743 Elf32_Shdr shdr; 744 745 bzero(&shdr, sizeof (shdr)); 746 if (!shstrtab_ndx(&pgc->pgc_shstrtab, 747 shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) { 748 return (1); 749 } 750 shdr.sh_size = size; 751 shdr.sh_offset = *pgc->pgc_doff; 752 shdr.sh_addralign = 1; 753 shdr.sh_flags = SHF_STRINGS; 754 shdr.sh_type = SHT_STRTAB; 755 756 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 757 *pgc->pgc_soff) != 0) 758 return (1); 759 760 *pgc->pgc_soff += sizeof (shdr); 761 #ifdef _LP64 762 } else { 763 Elf64_Shdr shdr; 764 765 bzero(&shdr, sizeof (shdr)); 766 if (!shstrtab_ndx(&pgc->pgc_shstrtab, 767 shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) { 768 return (1); 769 } 770 shdr.sh_size = size; 771 shdr.sh_offset = *pgc->pgc_doff; 772 shdr.sh_addralign = 1; 773 shdr.sh_flags = SHF_STRINGS; 774 shdr.sh_type = SHT_STRTAB; 775 776 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 777 *pgc->pgc_soff) != 0) 778 return (1); 779 780 *pgc->pgc_soff += sizeof (shdr); 781 #endif /* _LP64 */ 782 } 783 784 *pgc->pgc_doff += roundup(size, 8); 785 786 return (0); 787 } 788 789 /* 790 * Don't explicity stop the process; that's up to the consumer. 791 */ 792 #define NOTES_SECTIONS 1 793 int 794 Pfgcore(struct ps_prochandle *P, int fd, core_content_t content) 795 { 796 char plat[SYS_NMLN]; 797 char zonename[ZONENAME_MAX]; 798 int platlen = -1; 799 pgcore_t pgc; 800 off64_t poff, soff, doff, boff; 801 struct utsname uts; 802 uint_t nphdrs, nshdrs; 803 804 if (ftruncate64(fd, 0) != 0) 805 return (-1); 806 807 if (content == CC_CONTENT_INVALID) { 808 errno = EINVAL; 809 return (-1); 810 } 811 812 /* 813 * Cache the mappings and other useful data. 814 */ 815 (void) Prd_agent(P); 816 (void) Ppsinfo(P); 817 818 (void) memset(&pgc, 0, sizeof (pgc)); 819 pgc.P = P; 820 pgc.pgc_fd = fd; 821 pgc.pgc_poff = &poff; 822 pgc.pgc_soff = &soff; 823 pgc.pgc_doff = &doff; 824 pgc.pgc_content = content; 825 pgc.pgc_chunksz = PAGESIZE; 826 if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL) 827 return (-1); 828 829 if (!shstrtab_init(&pgc.pgc_shstrtab)) { 830 goto err; 831 } 832 833 /* 834 * There are a PT_NOTE program header for ancillary data, and 835 * one for each mapping. 836 */ 837 nphdrs = NOTES_SECTIONS + P->map_count; 838 nshdrs = count_sections(&pgc); 839 840 (void) Pplatform(P, plat, sizeof (plat)); 841 platlen = strlen(plat) + 1; 842 Preadauxvec(P); 843 (void) Puname(P, &uts); 844 if (Pzonename(P, zonename, sizeof (zonename)) == NULL) 845 zonename[0] = '\0'; 846 847 /* 848 * The core file contents may required zero section headers, but if we 849 * overflow the 16 bits allotted to the program header count in the ELF 850 * header, we'll need that program header at index zero. 851 */ 852 if (nshdrs == 0 && nphdrs >= PN_XNUM) 853 nshdrs = 1; 854 855 /* 856 * Set up the ELF header. 857 */ 858 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 859 Elf32_Ehdr ehdr; 860 861 bzero(&ehdr, sizeof (ehdr)); 862 ehdr.e_ident[EI_MAG0] = ELFMAG0; 863 ehdr.e_ident[EI_MAG1] = ELFMAG1; 864 ehdr.e_ident[EI_MAG2] = ELFMAG2; 865 ehdr.e_ident[EI_MAG3] = ELFMAG3; 866 ehdr.e_type = ET_CORE; 867 868 ehdr.e_ident[EI_CLASS] = ELFCLASS32; 869 #if defined(__sparc) 870 ehdr.e_machine = EM_SPARC; 871 ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 872 #elif defined(__i386) || defined(__amd64) 873 ehdr.e_machine = EM_386; 874 ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 875 #else 876 #error "unknown machine type" 877 #endif 878 ehdr.e_ident[EI_VERSION] = EV_CURRENT; 879 880 ehdr.e_version = EV_CURRENT; 881 ehdr.e_ehsize = sizeof (ehdr); 882 883 if (nphdrs >= PN_XNUM) 884 ehdr.e_phnum = PN_XNUM; 885 else 886 ehdr.e_phnum = (unsigned short)nphdrs; 887 888 ehdr.e_phentsize = sizeof (Elf32_Phdr); 889 ehdr.e_phoff = ehdr.e_ehsize; 890 891 if (nshdrs > 0) { 892 if (nshdrs >= SHN_LORESERVE) 893 ehdr.e_shnum = 0; 894 else 895 ehdr.e_shnum = (unsigned short)nshdrs; 896 897 if (nshdrs - 1 >= SHN_LORESERVE) 898 ehdr.e_shstrndx = SHN_XINDEX; 899 else 900 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); 901 902 ehdr.e_shentsize = sizeof (Elf32_Shdr); 903 ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; 904 } 905 906 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0) 907 goto err; 908 909 poff = ehdr.e_phoff; 910 soff = ehdr.e_shoff; 911 doff = boff = ehdr.e_ehsize + 912 ehdr.e_phentsize * nphdrs + 913 ehdr.e_shentsize * nshdrs; 914 915 #ifdef _LP64 916 } else { 917 Elf64_Ehdr ehdr; 918 919 bzero(&ehdr, sizeof (ehdr)); 920 ehdr.e_ident[EI_MAG0] = ELFMAG0; 921 ehdr.e_ident[EI_MAG1] = ELFMAG1; 922 ehdr.e_ident[EI_MAG2] = ELFMAG2; 923 ehdr.e_ident[EI_MAG3] = ELFMAG3; 924 ehdr.e_type = ET_CORE; 925 926 ehdr.e_ident[EI_CLASS] = ELFCLASS64; 927 #if defined(__sparc) 928 ehdr.e_machine = EM_SPARCV9; 929 ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 930 #elif defined(__i386) || defined(__amd64) 931 ehdr.e_machine = EM_AMD64; 932 ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 933 #else 934 #error "unknown machine type" 935 #endif 936 ehdr.e_ident[EI_VERSION] = EV_CURRENT; 937 938 ehdr.e_version = EV_CURRENT; 939 ehdr.e_ehsize = sizeof (ehdr); 940 941 if (nphdrs >= PN_XNUM) 942 ehdr.e_phnum = PN_XNUM; 943 else 944 ehdr.e_phnum = (unsigned short)nphdrs; 945 946 ehdr.e_phentsize = sizeof (Elf64_Phdr); 947 ehdr.e_phoff = ehdr.e_ehsize; 948 949 if (nshdrs > 0) { 950 if (nshdrs >= SHN_LORESERVE) 951 ehdr.e_shnum = 0; 952 else 953 ehdr.e_shnum = (unsigned short)nshdrs; 954 955 if (nshdrs - 1 >= SHN_LORESERVE) 956 ehdr.e_shstrndx = SHN_XINDEX; 957 else 958 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); 959 960 ehdr.e_shentsize = sizeof (Elf64_Shdr); 961 ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; 962 } 963 964 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0) 965 goto err; 966 967 poff = ehdr.e_phoff; 968 soff = ehdr.e_shoff; 969 doff = boff = ehdr.e_ehsize + 970 ehdr.e_phentsize * nphdrs + 971 ehdr.e_shentsize * nshdrs; 972 973 #endif /* _LP64 */ 974 } 975 976 /* 977 * Write the zero indexed section if it exists. 978 */ 979 if (nshdrs > 0 && write_shdr(&pgc, shstrtab_data[STR_NONE], 0, 0, 0, 0, 980 nshdrs >= SHN_LORESERVE ? nshdrs : 0, 981 nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0, 982 nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0) 983 goto err; 984 985 /* 986 * Construct the new-style note header and section. 987 */ 988 989 if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 990 if (write_note(fd, NT_PSINFO, &P->psinfo, sizeof (psinfo_t), 991 &doff) != 0) { 992 goto err; 993 } 994 if (write_note(fd, NT_PSTATUS, &P->status, sizeof (pstatus_t), 995 &doff) != 0) { 996 goto err; 997 } 998 if (write_note(fd, NT_AUXV, P->auxv, 999 P->nauxv * sizeof (P->auxv[0]), &doff) != 0) { 1000 goto err; 1001 } 1002 #ifdef _LP64 1003 } else { 1004 psinfo32_t pi32; 1005 pstatus32_t ps32; 1006 auxv32_t *av32; 1007 size_t size = sizeof (auxv32_t) * P->nauxv; 1008 int i; 1009 1010 psinfo_n_to_32(&P->psinfo, &pi32); 1011 if (write_note(fd, NT_PSINFO, &pi32, sizeof (psinfo32_t), 1012 &doff) != 0) { 1013 goto err; 1014 } 1015 pstatus_n_to_32(&P->status, &ps32); 1016 if (write_note(fd, NT_PSTATUS, &ps32, sizeof (pstatus32_t), 1017 &doff) != 0) { 1018 goto err; 1019 } 1020 if ((av32 = malloc(size)) == NULL) 1021 goto err; 1022 1023 for (i = 0; i < P->nauxv; i++) { 1024 auxv_n_to_32(&P->auxv[i], &av32[i]); 1025 } 1026 1027 if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) { 1028 free(av32); 1029 goto err; 1030 } 1031 1032 free(av32); 1033 #endif /* _LP64 */ 1034 } 1035 1036 if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0 || 1037 write_note(fd, NT_UTSNAME, &uts, sizeof (uts), &doff) != 0 || 1038 write_note(fd, NT_CONTENT, &content, sizeof (content), &doff) != 0) 1039 goto err; 1040 1041 { 1042 prcred_t cred, *cp; 1043 size_t size = sizeof (prcred_t); 1044 1045 if (Pcred(P, &cred, 0) != 0) 1046 goto err; 1047 1048 if (cred.pr_ngroups > 0) 1049 size += sizeof (gid_t) * (cred.pr_ngroups - 1); 1050 if ((cp = malloc(size)) == NULL) 1051 goto err; 1052 1053 if (Pcred(P, cp, cred.pr_ngroups) != 0 || 1054 write_note(fd, NT_PRCRED, cp, size, &doff) != 0) { 1055 free(cp); 1056 goto err; 1057 } 1058 1059 free(cp); 1060 } 1061 1062 { 1063 prpriv_t *ppriv = NULL; 1064 const priv_impl_info_t *pinfo; 1065 size_t pprivsz, pinfosz; 1066 1067 if (Ppriv(P, &ppriv) == -1) 1068 goto err; 1069 pprivsz = PRIV_PRPRIV_SIZE(ppriv); 1070 1071 if (write_note(fd, NT_PRPRIV, ppriv, pprivsz, &doff) != 0) { 1072 Ppriv_free(P, ppriv); 1073 goto err; 1074 } 1075 Ppriv_free(P, ppriv); 1076 1077 if ((pinfo = getprivimplinfo()) == NULL) 1078 goto err; 1079 pinfosz = PRIV_IMPL_INFO_SIZE(pinfo); 1080 1081 if (write_note(fd, NT_PRPRIVINFO, pinfo, pinfosz, &doff) != 0) 1082 goto err; 1083 } 1084 1085 if (write_note(fd, NT_ZONENAME, zonename, strlen(zonename) + 1, 1086 &doff) != 0) 1087 goto err; 1088 1089 { 1090 fditer_t iter; 1091 iter.fd_fd = fd; 1092 iter.fd_doff = &doff; 1093 1094 if (Pfdinfo_iter(P, iter_fd, &iter) != 0) 1095 goto err; 1096 } 1097 1098 1099 { 1100 prsecflags_t *psf = NULL; 1101 1102 if (Psecflags(P, &psf) != 0) 1103 goto err; 1104 1105 if (write_note(fd, NT_SECFLAGS, psf, 1106 sizeof (prsecflags_t), &doff) != 0) { 1107 Psecflags_free(psf); 1108 goto err; 1109 } 1110 1111 Psecflags_free(psf); 1112 } 1113 1114 { 1115 prcwd_t *cwd = NULL; 1116 1117 if (Pcwd(P, &cwd) != 0) 1118 goto err; 1119 1120 if (write_note(fd, NT_CWD, cwd, 1121 sizeof (prcwd_t), &doff) != 0) { 1122 Pcwd_free(cwd); 1123 goto err; 1124 } 1125 1126 Pcwd_free(cwd); 1127 } 1128 1129 #if defined(__i386) || defined(__amd64) 1130 /* CSTYLED */ 1131 { 1132 struct ssd *ldtp; 1133 size_t size; 1134 int nldt; 1135 1136 /* 1137 * Only dump out non-zero sized LDT notes. 1138 */ 1139 if ((nldt = Pldt(P, NULL, 0)) != 0) { 1140 size = sizeof (struct ssd) * nldt; 1141 if ((ldtp = malloc(size)) == NULL) 1142 goto err; 1143 1144 if (Pldt(P, ldtp, nldt) == -1 || 1145 write_note(fd, NT_LDT, ldtp, size, &doff) != 0) { 1146 free(ldtp); 1147 goto err; 1148 } 1149 1150 free(ldtp); 1151 } 1152 } 1153 #endif /* __i386 || __amd64 */ 1154 1155 if (Plwp_iter_all(P, per_lwp, &pgc) != 0) 1156 goto err; 1157 1158 if (P->status.pr_dmodel == PR_MODEL_ILP32) { 1159 Elf32_Phdr phdr; 1160 1161 bzero(&phdr, sizeof (phdr)); 1162 phdr.p_type = PT_NOTE; 1163 phdr.p_flags = PF_R; 1164 phdr.p_offset = (Elf32_Off)boff; 1165 phdr.p_filesz = doff - boff; 1166 boff = doff; 1167 1168 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) 1169 goto err; 1170 poff += sizeof (phdr); 1171 #ifdef _LP64 1172 } else { 1173 Elf64_Phdr phdr; 1174 1175 bzero(&phdr, sizeof (phdr)); 1176 phdr.p_type = PT_NOTE; 1177 phdr.p_flags = PF_R; 1178 phdr.p_offset = boff; 1179 phdr.p_filesz = doff - boff; 1180 boff = doff; 1181 1182 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0) 1183 goto err; 1184 poff += sizeof (phdr); 1185 #endif /* _LP64 */ 1186 } 1187 1188 /* 1189 * Construct the headers for each mapping and write out its data 1190 * if the content parameter indicates that it should be present 1191 * in the core file. 1192 */ 1193 if (Pmapping_iter(P, dump_map, &pgc) != 0) 1194 goto err; 1195 1196 if (dump_sections(&pgc) != 0) 1197 goto err; 1198 1199 if (write_shstrtab(P, &pgc) != 0) 1200 goto err; 1201 1202 free(pgc.pgc_chunk); 1203 shstrtab_fini(&pgc.pgc_shstrtab); 1204 1205 return (0); 1206 1207 err: 1208 /* 1209 * Wipe out anything we may have written if there was an error. 1210 */ 1211 (void) ftruncate64(fd, 0); 1212 free(pgc.pgc_chunk); 1213 shstrtab_fini(&pgc.pgc_shstrtab); 1214 1215 return (-1); 1216 } 1217 1218 static const char *content_str[] = { 1219 "stack", /* CC_CONTENT_STACK */ 1220 "heap", /* CC_CONTENT_HEAP */ 1221 "shfile", /* CC_CONTENT_SHFILE */ 1222 "shanon", /* CC_CONTENT_SHANON */ 1223 "text", /* CC_CONTENT_TEXT */ 1224 "data", /* CC_CONTENT_DATA */ 1225 "rodata", /* CC_CONTENT_RODATA */ 1226 "anon", /* CC_CONTENT_ANON */ 1227 "shm", /* CC_CONTENT_SHM */ 1228 "ism", /* CC_CONTENT_ISM */ 1229 "dism", /* CC_CONTENT_DISM */ 1230 "ctf", /* CC_CONTENT_CTF */ 1231 "symtab", /* CC_CONTENT_SYMTAB */ 1232 "debug" /* CC_CONTENT_DEBUG */ 1233 }; 1234 1235 static uint_t ncontent_str = sizeof (content_str) / sizeof (content_str[0]); 1236 1237 #define STREQ(a, b, n) (strlen(b) == (n) && strncmp(a, b, n) == 0) 1238 1239 int 1240 proc_str2content(const char *str, core_content_t *cp) 1241 { 1242 const char *cur = str; 1243 int add = 1; 1244 core_content_t mask, content = 0; 1245 1246 for (;;) { 1247 for (cur = str; isalpha(*cur); cur++) 1248 continue; 1249 1250 if (STREQ(str, "default", cur - str)) { 1251 mask = CC_CONTENT_DEFAULT; 1252 } else if (STREQ(str, "all", cur - str)) { 1253 mask = CC_CONTENT_ALL; 1254 } else if (STREQ(str, "none", cur - str)) { 1255 mask = 0; 1256 } else { 1257 int i = 0; 1258 1259 while (!STREQ(str, content_str[i], cur - str)) { 1260 i++; 1261 1262 if (i >= ncontent_str) 1263 return (-1); 1264 } 1265 1266 mask = (core_content_t)1 << i; 1267 } 1268 1269 if (add) 1270 content |= mask; 1271 else 1272 content &= ~mask; 1273 1274 switch (*cur) { 1275 case '\0': 1276 *cp = content; 1277 return (0); 1278 case '+': 1279 add = 1; 1280 break; 1281 case '-': 1282 add = 0; 1283 break; 1284 default: 1285 return (-1); 1286 } 1287 1288 str = cur + 1; 1289 } 1290 } 1291 1292 static int 1293 popc(core_content_t x) 1294 { 1295 int i; 1296 1297 for (i = 0; x != 0; i++) 1298 x &= x - 1; 1299 1300 return (i); 1301 } 1302 1303 int 1304 proc_content2str(core_content_t content, char *buf, size_t size) 1305 { 1306 int nonecnt, defcnt, allcnt; 1307 core_content_t mask, bit; 1308 int first; 1309 uint_t index; 1310 size_t n, tot = 0; 1311 1312 if (content == 0) 1313 return ((int)strlcpy(buf, "none", size)); 1314 1315 if (content & ~CC_CONTENT_ALL) 1316 return ((int)strlcpy(buf, "<invalid>", size)); 1317 1318 nonecnt = popc(content); 1319 defcnt = 1 + popc(content ^ CC_CONTENT_DEFAULT); 1320 allcnt = 1 + popc(content ^ CC_CONTENT_ALL); 1321 1322 if (defcnt <= nonecnt && defcnt <= allcnt) { 1323 mask = content ^ CC_CONTENT_DEFAULT; 1324 first = 0; 1325 tot += (n = strlcpy(buf, "default", size)); 1326 if (n > size) 1327 n = size; 1328 buf += n; 1329 size -= n; 1330 } else if (allcnt < nonecnt) { 1331 mask = content ^ CC_CONTENT_ALL; 1332 first = 0; 1333 tot += (n = strlcpy(buf, "all", size)); 1334 if (n > size) 1335 n = size; 1336 buf += n; 1337 size -= n; 1338 } else { 1339 mask = content; 1340 first = 1; 1341 } 1342 1343 while (mask != 0) { 1344 bit = mask ^ (mask & (mask - 1)); 1345 1346 if (!first) { 1347 if (size > 1) { 1348 *buf = (bit & content) ? '+' : '-'; 1349 buf++; 1350 size--; 1351 } 1352 1353 tot++; 1354 } 1355 index = popc(bit - 1); 1356 tot += (n = strlcpy(buf, content_str[index], size)); 1357 if (n > size) 1358 n = size; 1359 buf += n; 1360 size -= n; 1361 1362 mask ^= bit; 1363 first = 0; 1364 } 1365 1366 return ((int)tot); 1367 } 1368