17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 2340c00cd7Sahl * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <ctype.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <strings.h> 337c478bd9Sstevel@tonic-gate #include <errno.h> 347c478bd9Sstevel@tonic-gate #include <procfs.h> 357c478bd9Sstevel@tonic-gate #include <priv.h> 367c478bd9Sstevel@tonic-gate #include <sys/elf.h> 377c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 387c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 397c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 407c478bd9Sstevel@tonic-gate #include <sys/proc.h> 417c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <sys/old_procfs.h> 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #include "Pcontrol.h" 467c478bd9Sstevel@tonic-gate #include "P32ton.h" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate typedef enum { 49*30da1432Sahl STR_NONE, 507c478bd9Sstevel@tonic-gate STR_CTF, 517c478bd9Sstevel@tonic-gate STR_SYMTAB, 527c478bd9Sstevel@tonic-gate STR_DYNSYM, 537c478bd9Sstevel@tonic-gate STR_STRTAB, 547c478bd9Sstevel@tonic-gate STR_DYNSTR, 557c478bd9Sstevel@tonic-gate STR_SHSTRTAB, 567c478bd9Sstevel@tonic-gate STR_NUM 577c478bd9Sstevel@tonic-gate } shstrtype_t; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static const char *shstrtab_data[] = { 60*30da1432Sahl "", 617c478bd9Sstevel@tonic-gate ".SUNW_ctf", 627c478bd9Sstevel@tonic-gate ".symtab", 637c478bd9Sstevel@tonic-gate ".dynsym", 647c478bd9Sstevel@tonic-gate ".strtab", 657c478bd9Sstevel@tonic-gate ".dynstr", 667c478bd9Sstevel@tonic-gate ".shstrtab" 677c478bd9Sstevel@tonic-gate }; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate typedef struct shstrtab { 707c478bd9Sstevel@tonic-gate int sst_ndx[STR_NUM]; 717c478bd9Sstevel@tonic-gate int sst_cur; 727c478bd9Sstevel@tonic-gate } shstrtab_t; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate typedef struct { 757c478bd9Sstevel@tonic-gate struct ps_prochandle *P; 767c478bd9Sstevel@tonic-gate int pgc_fd; 777c478bd9Sstevel@tonic-gate off64_t *pgc_poff; 787c478bd9Sstevel@tonic-gate off64_t *pgc_soff; 797c478bd9Sstevel@tonic-gate off64_t *pgc_doff; 807c478bd9Sstevel@tonic-gate core_content_t pgc_content; 817c478bd9Sstevel@tonic-gate void *pgc_chunk; 827c478bd9Sstevel@tonic-gate size_t pgc_chunksz; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate shstrtab_t pgc_shstrtab; 857c478bd9Sstevel@tonic-gate } pgcore_t; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static void 887c478bd9Sstevel@tonic-gate shstrtab_init(shstrtab_t *s) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate bzero(&s->sst_ndx, sizeof (s->sst_ndx)); 917c478bd9Sstevel@tonic-gate s->sst_cur = 1; 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate static int 957c478bd9Sstevel@tonic-gate shstrtab_ndx(shstrtab_t *s, shstrtype_t type) 967c478bd9Sstevel@tonic-gate { 977c478bd9Sstevel@tonic-gate int ret; 987c478bd9Sstevel@tonic-gate 99*30da1432Sahl if ((ret = s->sst_ndx[type]) != 0 || type == STR_NONE) 1007c478bd9Sstevel@tonic-gate return (ret); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate ret = s->sst_ndx[type] = s->sst_cur; 1037c478bd9Sstevel@tonic-gate s->sst_cur += strlen(shstrtab_data[type]) + 1; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate return (ret); 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate static size_t 1097c478bd9Sstevel@tonic-gate shstrtab_size(const shstrtab_t *s) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate return (s->sst_cur); 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate int 1157c478bd9Sstevel@tonic-gate Pgcore(struct ps_prochandle *P, const char *fname, core_content_t content) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate int fd; 1187c478bd9Sstevel@tonic-gate int err; 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate if ((fd = creat64(fname, 0666)) < 0) 1217c478bd9Sstevel@tonic-gate return (-1); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate if ((err = Pfgcore(P, fd, content)) != 0) { 1247c478bd9Sstevel@tonic-gate (void) close(fd); 1257c478bd9Sstevel@tonic-gate (void) unlink(fname); 1267c478bd9Sstevel@tonic-gate return (err); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate return (close(fd)); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate /* 1337c478bd9Sstevel@tonic-gate * Since we don't want to use the old-school procfs interfaces, we use the 1347c478bd9Sstevel@tonic-gate * new-style data structures we already have to construct the old-style 1357c478bd9Sstevel@tonic-gate * data structures. We include these data structures in core files for 1367c478bd9Sstevel@tonic-gate * backward compatability. 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate static void 1407c478bd9Sstevel@tonic-gate mkprstatus(struct ps_prochandle *P, const lwpstatus_t *lsp, 1417c478bd9Sstevel@tonic-gate const lwpsinfo_t *lip, prstatus_t *psp) 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate bzero(psp, sizeof (*psp)); 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_STOPPED) 1467c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0001; 1477c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ISTOP) 1487c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0002; 1497c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_DSTOP) 1507c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0004; 1517c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASLEEP) 1527c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0008; 1537c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_FORK) 1547c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0010; 1557c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_RLC) 1567c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0020; 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set; 1597c478bd9Sstevel@tonic-gate * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_PCINVAL) 1627c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0080; 1637c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ISSYS) 1647c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0100; 1657c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_STEP) 1667c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0200; 1677c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_KLC) 1687c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0400; 1697c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASYNC) 1707c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0800; 1717c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_PTRACE) 1727c478bd9Sstevel@tonic-gate psp->pr_flags = 0x1000; 1737c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_MSACCT) 1747c478bd9Sstevel@tonic-gate psp->pr_flags = 0x2000; 1757c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_BPTADJ) 1767c478bd9Sstevel@tonic-gate psp->pr_flags = 0x4000; 1777c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASLWP) 1787c478bd9Sstevel@tonic-gate psp->pr_flags = 0x8000; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate psp->pr_why = lsp->pr_why; 1817c478bd9Sstevel@tonic-gate psp->pr_what = lsp->pr_what; 1827c478bd9Sstevel@tonic-gate psp->pr_info = lsp->pr_info; 1837c478bd9Sstevel@tonic-gate psp->pr_cursig = lsp->pr_cursig; 1847c478bd9Sstevel@tonic-gate psp->pr_nlwp = P->status.pr_nlwp; 1857c478bd9Sstevel@tonic-gate psp->pr_sigpend = P->status.pr_sigpend; 1867c478bd9Sstevel@tonic-gate psp->pr_sighold = lsp->pr_lwphold; 1877c478bd9Sstevel@tonic-gate psp->pr_altstack = lsp->pr_altstack; 1887c478bd9Sstevel@tonic-gate psp->pr_action = lsp->pr_action; 1897c478bd9Sstevel@tonic-gate psp->pr_pid = P->status.pr_pid; 1907c478bd9Sstevel@tonic-gate psp->pr_ppid = P->status.pr_ppid; 1917c478bd9Sstevel@tonic-gate psp->pr_pgrp = P->status.pr_pgid; 1927c478bd9Sstevel@tonic-gate psp->pr_sid = P->status.pr_sid; 1937c478bd9Sstevel@tonic-gate psp->pr_utime = P->status.pr_utime; 1947c478bd9Sstevel@tonic-gate psp->pr_stime = P->status.pr_stime; 1957c478bd9Sstevel@tonic-gate psp->pr_cutime = P->status.pr_cutime; 1967c478bd9Sstevel@tonic-gate psp->pr_cstime = P->status.pr_cstime; 1977c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname)); 1987c478bd9Sstevel@tonic-gate psp->pr_syscall = lsp->pr_syscall; 1997c478bd9Sstevel@tonic-gate psp->pr_nsysarg = lsp->pr_nsysarg; 2007c478bd9Sstevel@tonic-gate bcopy(lsp->pr_sysarg, psp->pr_sysarg, sizeof (psp->pr_sysarg)); 2017c478bd9Sstevel@tonic-gate psp->pr_who = lsp->pr_lwpid; 2027c478bd9Sstevel@tonic-gate psp->pr_lwppend = lsp->pr_lwppend; 2037c478bd9Sstevel@tonic-gate psp->pr_oldcontext = (ucontext_t *)lsp->pr_oldcontext; 2047c478bd9Sstevel@tonic-gate psp->pr_brkbase = (caddr_t)P->status.pr_brkbase; 2057c478bd9Sstevel@tonic-gate psp->pr_brksize = P->status.pr_brksize; 2067c478bd9Sstevel@tonic-gate psp->pr_stkbase = (caddr_t)P->status.pr_stkbase; 2077c478bd9Sstevel@tonic-gate psp->pr_stksize = P->status.pr_stksize; 2087c478bd9Sstevel@tonic-gate psp->pr_processor = (short)lip->pr_onpro; 2097c478bd9Sstevel@tonic-gate psp->pr_bind = (short)lip->pr_bindpro; 2107c478bd9Sstevel@tonic-gate psp->pr_instr = lsp->pr_instr; 2117c478bd9Sstevel@tonic-gate bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg)); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate static void 2157c478bd9Sstevel@tonic-gate mkprpsinfo(struct ps_prochandle *P, prpsinfo_t *psp) 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate bzero(psp, sizeof (*psp)); 2187c478bd9Sstevel@tonic-gate psp->pr_state = P->psinfo.pr_lwp.pr_state; 2197c478bd9Sstevel@tonic-gate psp->pr_sname = P->psinfo.pr_lwp.pr_sname; 2207c478bd9Sstevel@tonic-gate psp->pr_zomb = (psp->pr_state == SZOMB); 2217c478bd9Sstevel@tonic-gate psp->pr_nice = P->psinfo.pr_lwp.pr_nice; 2227c478bd9Sstevel@tonic-gate psp->pr_flag = P->psinfo.pr_lwp.pr_flag; 2237c478bd9Sstevel@tonic-gate psp->pr_uid = P->psinfo.pr_uid; 2247c478bd9Sstevel@tonic-gate psp->pr_gid = P->psinfo.pr_gid; 2257c478bd9Sstevel@tonic-gate psp->pr_pid = P->psinfo.pr_pid; 2267c478bd9Sstevel@tonic-gate psp->pr_ppid = P->psinfo.pr_ppid; 2277c478bd9Sstevel@tonic-gate psp->pr_pgrp = P->psinfo.pr_pgid; 2287c478bd9Sstevel@tonic-gate psp->pr_sid = P->psinfo.pr_sid; 2297c478bd9Sstevel@tonic-gate psp->pr_addr = (caddr_t)P->psinfo.pr_addr; 2307c478bd9Sstevel@tonic-gate psp->pr_size = P->psinfo.pr_size; 2317c478bd9Sstevel@tonic-gate psp->pr_rssize = P->psinfo.pr_rssize; 2327c478bd9Sstevel@tonic-gate psp->pr_wchan = (caddr_t)P->psinfo.pr_lwp.pr_wchan; 2337c478bd9Sstevel@tonic-gate psp->pr_start = P->psinfo.pr_start; 2347c478bd9Sstevel@tonic-gate psp->pr_time = P->psinfo.pr_time; 2357c478bd9Sstevel@tonic-gate psp->pr_pri = P->psinfo.pr_lwp.pr_pri; 2367c478bd9Sstevel@tonic-gate psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri; 2377c478bd9Sstevel@tonic-gate psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu; 2387c478bd9Sstevel@tonic-gate psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev); 2397c478bd9Sstevel@tonic-gate psp->pr_lttydev = P->psinfo.pr_ttydev; 2407c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname, 2417c478bd9Sstevel@tonic-gate sizeof (psp->pr_clname)); 2427c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_fname, P->psinfo.pr_fname, 2437c478bd9Sstevel@tonic-gate sizeof (psp->pr_fname)); 2447c478bd9Sstevel@tonic-gate bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs, 2457c478bd9Sstevel@tonic-gate sizeof (psp->pr_psargs)); 2467c478bd9Sstevel@tonic-gate psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall; 2477c478bd9Sstevel@tonic-gate psp->pr_ctime = P->psinfo.pr_ctime; 2487c478bd9Sstevel@tonic-gate psp->pr_bysize = psp->pr_size * PAGESIZE; 2497c478bd9Sstevel@tonic-gate psp->pr_byrssize = psp->pr_rssize * PAGESIZE; 2507c478bd9Sstevel@tonic-gate psp->pr_argc = P->psinfo.pr_argc; 2517c478bd9Sstevel@tonic-gate psp->pr_argv = (char **)P->psinfo.pr_argv; 2527c478bd9Sstevel@tonic-gate psp->pr_envp = (char **)P->psinfo.pr_envp; 2537c478bd9Sstevel@tonic-gate psp->pr_wstat = P->psinfo.pr_wstat; 2547c478bd9Sstevel@tonic-gate psp->pr_pctcpu = P->psinfo.pr_pctcpu; 2557c478bd9Sstevel@tonic-gate psp->pr_pctmem = P->psinfo.pr_pctmem; 2567c478bd9Sstevel@tonic-gate psp->pr_euid = P->psinfo.pr_euid; 2577c478bd9Sstevel@tonic-gate psp->pr_egid = P->psinfo.pr_egid; 2587c478bd9Sstevel@tonic-gate psp->pr_aslwpid = 0; 2597c478bd9Sstevel@tonic-gate psp->pr_dmodel = P->psinfo.pr_dmodel; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate #ifdef _LP64 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate static void 2657c478bd9Sstevel@tonic-gate mkprstatus32(struct ps_prochandle *P, const lwpstatus_t *lsp, 2667c478bd9Sstevel@tonic-gate const lwpsinfo_t *lip, prstatus32_t *psp) 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate bzero(psp, sizeof (*psp)); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_STOPPED) 2717c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0001; 2727c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ISTOP) 2737c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0002; 2747c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_DSTOP) 2757c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0004; 2767c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASLEEP) 2777c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0008; 2787c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_FORK) 2797c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0010; 2807c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_RLC) 2817c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0020; 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set; 2847c478bd9Sstevel@tonic-gate * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_PCINVAL) 2877c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0080; 2887c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ISSYS) 2897c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0100; 2907c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_STEP) 2917c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0200; 2927c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_KLC) 2937c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0400; 2947c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASYNC) 2957c478bd9Sstevel@tonic-gate psp->pr_flags = 0x0800; 2967c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_PTRACE) 2977c478bd9Sstevel@tonic-gate psp->pr_flags = 0x1000; 2987c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_MSACCT) 2997c478bd9Sstevel@tonic-gate psp->pr_flags = 0x2000; 3007c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_BPTADJ) 3017c478bd9Sstevel@tonic-gate psp->pr_flags = 0x4000; 3027c478bd9Sstevel@tonic-gate if (lsp->pr_flags & PR_ASLWP) 3037c478bd9Sstevel@tonic-gate psp->pr_flags = 0x8000; 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate psp->pr_why = lsp->pr_why; 3067c478bd9Sstevel@tonic-gate psp->pr_what = lsp->pr_what; 3077c478bd9Sstevel@tonic-gate siginfo_n_to_32(&lsp->pr_info, &psp->pr_info); 3087c478bd9Sstevel@tonic-gate psp->pr_cursig = lsp->pr_cursig; 3097c478bd9Sstevel@tonic-gate psp->pr_nlwp = P->status.pr_nlwp; 3107c478bd9Sstevel@tonic-gate psp->pr_sigpend = P->status.pr_sigpend; 3117c478bd9Sstevel@tonic-gate psp->pr_sighold = lsp->pr_lwphold; 3127c478bd9Sstevel@tonic-gate stack_n_to_32(&lsp->pr_altstack, &psp->pr_altstack); 3137c478bd9Sstevel@tonic-gate sigaction_n_to_32(&lsp->pr_action, &psp->pr_action); 3147c478bd9Sstevel@tonic-gate psp->pr_pid = P->status.pr_pid; 3157c478bd9Sstevel@tonic-gate psp->pr_ppid = P->status.pr_ppid; 3167c478bd9Sstevel@tonic-gate psp->pr_pgrp = P->status.pr_pgid; 3177c478bd9Sstevel@tonic-gate psp->pr_sid = P->status.pr_sid; 3187c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->status.pr_utime, &psp->pr_utime); 3197c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->status.pr_stime, &psp->pr_stime); 3207c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->status.pr_cutime, &psp->pr_cutime); 3217c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->status.pr_cstime, &psp->pr_cstime); 3227c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname)); 3237c478bd9Sstevel@tonic-gate psp->pr_syscall = lsp->pr_syscall; 3247c478bd9Sstevel@tonic-gate psp->pr_nsysarg = lsp->pr_nsysarg; 3257c478bd9Sstevel@tonic-gate bcopy(lsp->pr_sysarg, psp->pr_sysarg, 3267c478bd9Sstevel@tonic-gate sizeof (psp->pr_sysarg)); psp->pr_who = lsp->pr_lwpid; 3277c478bd9Sstevel@tonic-gate psp->pr_lwppend = lsp->pr_lwppend; 3287c478bd9Sstevel@tonic-gate psp->pr_oldcontext = (caddr32_t)lsp->pr_oldcontext; 3297c478bd9Sstevel@tonic-gate psp->pr_brkbase = (caddr32_t)P->status.pr_brkbase; 3307c478bd9Sstevel@tonic-gate psp->pr_brksize = P->status.pr_brksize; 3317c478bd9Sstevel@tonic-gate psp->pr_stkbase = (caddr32_t)P->status.pr_stkbase; 3327c478bd9Sstevel@tonic-gate psp->pr_stksize = P->status.pr_stksize; 3337c478bd9Sstevel@tonic-gate psp->pr_processor = (short)lip->pr_onpro; 3347c478bd9Sstevel@tonic-gate psp->pr_bind = (short)lip->pr_bindpro; 3357c478bd9Sstevel@tonic-gate psp->pr_instr = lsp->pr_instr; 3367c478bd9Sstevel@tonic-gate bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg)); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate static void 3407c478bd9Sstevel@tonic-gate mkprpsinfo32(struct ps_prochandle *P, prpsinfo32_t *psp) 3417c478bd9Sstevel@tonic-gate { 3427c478bd9Sstevel@tonic-gate bzero(psp, sizeof (*psp)); 3437c478bd9Sstevel@tonic-gate psp->pr_state = P->psinfo.pr_lwp.pr_state; 3447c478bd9Sstevel@tonic-gate psp->pr_sname = P->psinfo.pr_lwp.pr_sname; 3457c478bd9Sstevel@tonic-gate psp->pr_zomb = (psp->pr_state == SZOMB); 3467c478bd9Sstevel@tonic-gate psp->pr_nice = P->psinfo.pr_lwp.pr_nice; 3477c478bd9Sstevel@tonic-gate psp->pr_flag = P->psinfo.pr_lwp.pr_flag; 3487c478bd9Sstevel@tonic-gate psp->pr_uid = P->psinfo.pr_uid; 3497c478bd9Sstevel@tonic-gate psp->pr_gid = P->psinfo.pr_gid; 3507c478bd9Sstevel@tonic-gate psp->pr_pid = P->psinfo.pr_pid; 3517c478bd9Sstevel@tonic-gate psp->pr_ppid = P->psinfo.pr_ppid; 3527c478bd9Sstevel@tonic-gate psp->pr_pgrp = P->psinfo.pr_pgid; 3537c478bd9Sstevel@tonic-gate psp->pr_sid = P->psinfo.pr_sid; 3547c478bd9Sstevel@tonic-gate psp->pr_addr = (caddr32_t)P->psinfo.pr_addr; 3557c478bd9Sstevel@tonic-gate psp->pr_size = P->psinfo.pr_size; 3567c478bd9Sstevel@tonic-gate psp->pr_rssize = P->psinfo.pr_rssize; 3577c478bd9Sstevel@tonic-gate psp->pr_wchan = (caddr32_t)P->psinfo.pr_lwp.pr_wchan; 3587c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->psinfo.pr_start, &psp->pr_start); 3597c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->psinfo.pr_time, &psp->pr_time); 3607c478bd9Sstevel@tonic-gate psp->pr_pri = P->psinfo.pr_lwp.pr_pri; 3617c478bd9Sstevel@tonic-gate psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri; 3627c478bd9Sstevel@tonic-gate psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu; 3637c478bd9Sstevel@tonic-gate psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev); 3647c478bd9Sstevel@tonic-gate psp->pr_lttydev = prcmpldev(P->psinfo.pr_ttydev); 3657c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname, 3667c478bd9Sstevel@tonic-gate sizeof (psp->pr_clname)); 3677c478bd9Sstevel@tonic-gate (void) strncpy(psp->pr_fname, P->psinfo.pr_fname, 3687c478bd9Sstevel@tonic-gate sizeof (psp->pr_fname)); 3697c478bd9Sstevel@tonic-gate bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs, 3707c478bd9Sstevel@tonic-gate sizeof (psp->pr_psargs)); 3717c478bd9Sstevel@tonic-gate psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall; 3727c478bd9Sstevel@tonic-gate timestruc_n_to_32(&P->psinfo.pr_ctime, &psp->pr_ctime); 3737c478bd9Sstevel@tonic-gate psp->pr_bysize = psp->pr_size * PAGESIZE; 3747c478bd9Sstevel@tonic-gate psp->pr_byrssize = psp->pr_rssize * PAGESIZE; 3757c478bd9Sstevel@tonic-gate psp->pr_argc = P->psinfo.pr_argc; 3767c478bd9Sstevel@tonic-gate psp->pr_argv = (caddr32_t)P->psinfo.pr_argv; 3777c478bd9Sstevel@tonic-gate psp->pr_envp = (caddr32_t)P->psinfo.pr_envp; 3787c478bd9Sstevel@tonic-gate psp->pr_wstat = P->psinfo.pr_wstat; 3797c478bd9Sstevel@tonic-gate psp->pr_pctcpu = P->psinfo.pr_pctcpu; 3807c478bd9Sstevel@tonic-gate psp->pr_pctmem = P->psinfo.pr_pctmem; 3817c478bd9Sstevel@tonic-gate psp->pr_euid = P->psinfo.pr_euid; 3827c478bd9Sstevel@tonic-gate psp->pr_egid = P->psinfo.pr_egid; 3837c478bd9Sstevel@tonic-gate psp->pr_aslwpid = 0; 3847c478bd9Sstevel@tonic-gate psp->pr_dmodel = P->psinfo.pr_dmodel; 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate static int 3907c478bd9Sstevel@tonic-gate write_note(int fd, uint_t type, const void *desc, size_t descsz, off64_t *offp) 3917c478bd9Sstevel@tonic-gate { 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * Note headers are the same regardless of the data model of the 3947c478bd9Sstevel@tonic-gate * ELF file; we arbitrarily use Elf64_Nhdr here. 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate struct { 3977c478bd9Sstevel@tonic-gate Elf64_Nhdr nhdr; 3987c478bd9Sstevel@tonic-gate char name[8]; 3997c478bd9Sstevel@tonic-gate } n; 4007c478bd9Sstevel@tonic-gate 4017c478bd9Sstevel@tonic-gate bzero(&n, sizeof (n)); 4027c478bd9Sstevel@tonic-gate bcopy("CORE", n.name, 4); 4037c478bd9Sstevel@tonic-gate n.nhdr.n_type = type; 4047c478bd9Sstevel@tonic-gate n.nhdr.n_namesz = 5; 4057c478bd9Sstevel@tonic-gate n.nhdr.n_descsz = roundup(descsz, 4); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate if (pwrite64(fd, &n, sizeof (n), *offp) != sizeof (n)) 4087c478bd9Sstevel@tonic-gate return (-1); 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate *offp += sizeof (n); 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate if (pwrite64(fd, desc, n.nhdr.n_descsz, *offp) != n.nhdr.n_descsz) 4137c478bd9Sstevel@tonic-gate return (-1); 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate *offp += n.nhdr.n_descsz; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate return (0); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate static int 4217c478bd9Sstevel@tonic-gate old_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate pgcore_t *pgc = data; 4247c478bd9Sstevel@tonic-gate struct ps_prochandle *P = pgc->P; 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 4277c478bd9Sstevel@tonic-gate * Legacy core files don't contain information about zombie LWPs. 4287c478bd9Sstevel@tonic-gate * We use Plwp_iter_all() so that we get the lwpsinfo_t structure 4297c478bd9Sstevel@tonic-gate * more cheaply. 4307c478bd9Sstevel@tonic-gate */ 4317c478bd9Sstevel@tonic-gate if (lsp == NULL) 4327c478bd9Sstevel@tonic-gate return (0); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 4357c478bd9Sstevel@tonic-gate prstatus_t prstatus; 4367c478bd9Sstevel@tonic-gate mkprstatus(P, lsp, lip, &prstatus); 4377c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_PRSTATUS, &prstatus, 4387c478bd9Sstevel@tonic-gate sizeof (prstatus_t), pgc->pgc_doff) != 0) 4397c478bd9Sstevel@tonic-gate return (0); 4407c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_PRFPREG, &lsp->pr_fpreg, 4417c478bd9Sstevel@tonic-gate sizeof (prfpregset_t), pgc->pgc_doff) != 0) 4427c478bd9Sstevel@tonic-gate return (1); 4437c478bd9Sstevel@tonic-gate #ifdef _LP64 4447c478bd9Sstevel@tonic-gate } else { 4457c478bd9Sstevel@tonic-gate prstatus32_t pr32; 4467c478bd9Sstevel@tonic-gate prfpregset32_t pf32; 4477c478bd9Sstevel@tonic-gate mkprstatus32(P, lsp, lip, &pr32); 4487c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_PRSTATUS, &pr32, 4497c478bd9Sstevel@tonic-gate sizeof (prstatus32_t), pgc->pgc_doff) != 0) 4507c478bd9Sstevel@tonic-gate return (1); 4517c478bd9Sstevel@tonic-gate prfpregset_n_to_32(&lsp->pr_fpreg, &pf32); 4527c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_PRFPREG, &pf32, 4537c478bd9Sstevel@tonic-gate sizeof (prfpregset32_t), pgc->pgc_doff) != 0) 4547c478bd9Sstevel@tonic-gate return (1); 4557c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate #ifdef sparc 4597c478bd9Sstevel@tonic-gate { 4607c478bd9Sstevel@tonic-gate prxregset_t xregs; 4617c478bd9Sstevel@tonic-gate if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0 && 4627c478bd9Sstevel@tonic-gate write_note(pgc->pgc_fd, NT_PRXREG, &xregs, 4637c478bd9Sstevel@tonic-gate sizeof (prxregset_t), pgc->pgc_doff) != 0) 4647c478bd9Sstevel@tonic-gate return (1); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate #endif /* sparc */ 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate } 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate static int 4727c478bd9Sstevel@tonic-gate new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) 4737c478bd9Sstevel@tonic-gate { 4747c478bd9Sstevel@tonic-gate pgcore_t *pgc = data; 4757c478bd9Sstevel@tonic-gate struct ps_prochandle *P = pgc->P; 4767c478bd9Sstevel@tonic-gate 4777c478bd9Sstevel@tonic-gate /* 4787c478bd9Sstevel@tonic-gate * If lsp is NULL this indicates that this is a zombie LWP in 4797c478bd9Sstevel@tonic-gate * which case we dump only the lwpsinfo_t structure and none of 4807c478bd9Sstevel@tonic-gate * the other ancillary LWP state data. 4817c478bd9Sstevel@tonic-gate */ 4827c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 4837c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_LWPSINFO, lip, 4847c478bd9Sstevel@tonic-gate sizeof (lwpsinfo_t), pgc->pgc_doff) != 0) 4857c478bd9Sstevel@tonic-gate return (1); 4867c478bd9Sstevel@tonic-gate if (lsp == NULL) 4877c478bd9Sstevel@tonic-gate return (0); 4887c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_LWPSTATUS, lsp, 4897c478bd9Sstevel@tonic-gate sizeof (lwpstatus_t), pgc->pgc_doff) != 0) 4907c478bd9Sstevel@tonic-gate return (1); 4917c478bd9Sstevel@tonic-gate #ifdef _LP64 4927c478bd9Sstevel@tonic-gate } else { 4937c478bd9Sstevel@tonic-gate lwpsinfo32_t li32; 4947c478bd9Sstevel@tonic-gate lwpstatus32_t ls32; 4957c478bd9Sstevel@tonic-gate lwpsinfo_n_to_32(lip, &li32); 4967c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_LWPSINFO, &li32, 4977c478bd9Sstevel@tonic-gate sizeof (lwpsinfo32_t), pgc->pgc_doff) != 0) 4987c478bd9Sstevel@tonic-gate return (1); 4997c478bd9Sstevel@tonic-gate if (lsp == NULL) 5007c478bd9Sstevel@tonic-gate return (0); 5017c478bd9Sstevel@tonic-gate lwpstatus_n_to_32(lsp, &ls32); 5027c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_LWPSTATUS, &ls32, 5037c478bd9Sstevel@tonic-gate sizeof (lwpstatus32_t), pgc->pgc_doff) != 0) 5047c478bd9Sstevel@tonic-gate return (1); 5057c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 5087c478bd9Sstevel@tonic-gate #ifdef sparc 5097c478bd9Sstevel@tonic-gate { 5107c478bd9Sstevel@tonic-gate prxregset_t xregs; 5117c478bd9Sstevel@tonic-gate gwindows_t gwins; 5127c478bd9Sstevel@tonic-gate size_t size; 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0) { 5157c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_PRXREG, &xregs, 5167c478bd9Sstevel@tonic-gate sizeof (prxregset_t), pgc->pgc_doff) != 0) 5177c478bd9Sstevel@tonic-gate return (1); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (Plwp_getgwindows(P, lsp->pr_lwpid, &gwins) == 0 && 5217c478bd9Sstevel@tonic-gate gwins.wbcnt > 0) { 5227c478bd9Sstevel@tonic-gate size = sizeof (gwins) - sizeof (gwins.wbuf) + 5237c478bd9Sstevel@tonic-gate gwins.wbcnt * sizeof (gwins.wbuf[0]); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_GWINDOWS, &gwins, size, 5267c478bd9Sstevel@tonic-gate pgc->pgc_doff) != 0) 5277c478bd9Sstevel@tonic-gate return (1); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate #ifdef __sparcv9 5327c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_LP64) { 5337c478bd9Sstevel@tonic-gate asrset_t asrs; 5347c478bd9Sstevel@tonic-gate if (Plwp_getasrs(P, lsp->pr_lwpid, asrs) == 0) { 5357c478bd9Sstevel@tonic-gate if (write_note(pgc->pgc_fd, NT_ASRS, &asrs, 5367c478bd9Sstevel@tonic-gate sizeof (asrset_t), pgc->pgc_doff) != 0) 5377c478bd9Sstevel@tonic-gate return (1); 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate #endif /* __sparcv9 */ 5417c478bd9Sstevel@tonic-gate #endif /* sparc */ 5427c478bd9Sstevel@tonic-gate 5437c478bd9Sstevel@tonic-gate return (0); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate static uint_t 5477c478bd9Sstevel@tonic-gate count_sections(pgcore_t *pgc) 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate struct ps_prochandle *P = pgc->P; 5507c478bd9Sstevel@tonic-gate file_info_t *fptr; 5517c478bd9Sstevel@tonic-gate uint_t cnt; 5527c478bd9Sstevel@tonic-gate uint_t nshdrs = 0; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB))) 5557c478bd9Sstevel@tonic-gate return (0); 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate fptr = list_next(&P->file_head); 5587c478bd9Sstevel@tonic-gate for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) { 5597c478bd9Sstevel@tonic-gate int hit_symtab = 0; 5607c478bd9Sstevel@tonic-gate 5617c478bd9Sstevel@tonic-gate Pbuild_file_symtab(P, fptr); 5627c478bd9Sstevel@tonic-gate 5637c478bd9Sstevel@tonic-gate if ((pgc->pgc_content & CC_CONTENT_CTF) && 5647c478bd9Sstevel@tonic-gate Pbuild_file_ctf(P, fptr) != NULL) { 5657c478bd9Sstevel@tonic-gate sym_tbl_t *sym; 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate nshdrs++; 5687c478bd9Sstevel@tonic-gate 5697c478bd9Sstevel@tonic-gate if (fptr->file_ctf_dyn) { 5707c478bd9Sstevel@tonic-gate sym = &fptr->file_dynsym; 5717c478bd9Sstevel@tonic-gate } else { 5727c478bd9Sstevel@tonic-gate sym = &fptr->file_symtab; 5737c478bd9Sstevel@tonic-gate hit_symtab = 1; 5747c478bd9Sstevel@tonic-gate } 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate if (sym->sym_data != NULL && sym->sym_symn != 0 && 5777c478bd9Sstevel@tonic-gate sym->sym_strs != NULL) 5787c478bd9Sstevel@tonic-gate nshdrs += 2; 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && 5827c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_data != NULL && 5837c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_symn != 0 && 5847c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_strs != NULL) { 5857c478bd9Sstevel@tonic-gate nshdrs += 2; 5867c478bd9Sstevel@tonic-gate } 5877c478bd9Sstevel@tonic-gate } 5887c478bd9Sstevel@tonic-gate 5897c478bd9Sstevel@tonic-gate return (nshdrs == 0 ? 0 : nshdrs + 2); 5907c478bd9Sstevel@tonic-gate } 5917c478bd9Sstevel@tonic-gate 5927c478bd9Sstevel@tonic-gate static int 5937c478bd9Sstevel@tonic-gate write_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags, 5947c478bd9Sstevel@tonic-gate uintptr_t addr, ulong_t offset, size_t size, uint_t link, uint_t info, 5957c478bd9Sstevel@tonic-gate uintptr_t addralign, uintptr_t entsize) 5967c478bd9Sstevel@tonic-gate { 5977c478bd9Sstevel@tonic-gate if (pgc->P->status.pr_dmodel == PR_MODEL_ILP32) { 5987c478bd9Sstevel@tonic-gate Elf32_Shdr shdr; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate bzero(&shdr, sizeof (shdr)); 6017c478bd9Sstevel@tonic-gate shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name); 6027c478bd9Sstevel@tonic-gate shdr.sh_type = type; 6037c478bd9Sstevel@tonic-gate shdr.sh_flags = flags; 6047c478bd9Sstevel@tonic-gate shdr.sh_addr = (Elf32_Addr)addr; 6057c478bd9Sstevel@tonic-gate shdr.sh_offset = offset; 6067c478bd9Sstevel@tonic-gate shdr.sh_size = size; 6077c478bd9Sstevel@tonic-gate shdr.sh_link = link; 6087c478bd9Sstevel@tonic-gate shdr.sh_info = info; 6097c478bd9Sstevel@tonic-gate shdr.sh_addralign = addralign; 6107c478bd9Sstevel@tonic-gate shdr.sh_entsize = entsize; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 6137c478bd9Sstevel@tonic-gate *pgc->pgc_soff) != sizeof (shdr)) 6147c478bd9Sstevel@tonic-gate return (-1); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate *pgc->pgc_soff += sizeof (shdr); 6177c478bd9Sstevel@tonic-gate #ifdef _LP64 6187c478bd9Sstevel@tonic-gate } else { 6197c478bd9Sstevel@tonic-gate Elf64_Shdr shdr; 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate bzero(&shdr, sizeof (shdr)); 6227c478bd9Sstevel@tonic-gate shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name); 6237c478bd9Sstevel@tonic-gate shdr.sh_type = type; 6247c478bd9Sstevel@tonic-gate shdr.sh_flags = flags; 6257c478bd9Sstevel@tonic-gate shdr.sh_addr = addr; 6267c478bd9Sstevel@tonic-gate shdr.sh_offset = offset; 6277c478bd9Sstevel@tonic-gate shdr.sh_size = size; 6287c478bd9Sstevel@tonic-gate shdr.sh_link = link; 6297c478bd9Sstevel@tonic-gate shdr.sh_info = info; 6307c478bd9Sstevel@tonic-gate shdr.sh_addralign = addralign; 6317c478bd9Sstevel@tonic-gate shdr.sh_entsize = entsize; 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 6347c478bd9Sstevel@tonic-gate *pgc->pgc_soff) != sizeof (shdr)) 6357c478bd9Sstevel@tonic-gate return (-1); 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate *pgc->pgc_soff += sizeof (shdr); 6387c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate return (0); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate static int 6457c478bd9Sstevel@tonic-gate dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym) 6467c478bd9Sstevel@tonic-gate { 6477c478bd9Sstevel@tonic-gate sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab; 6487c478bd9Sstevel@tonic-gate shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB; 6497c478bd9Sstevel@tonic-gate shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB; 6507c478bd9Sstevel@tonic-gate uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB; 6517c478bd9Sstevel@tonic-gate size_t size; 6527c478bd9Sstevel@tonic-gate uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr; 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate if (sym->sym_data == NULL || sym->sym_symn == 0 || 6557c478bd9Sstevel@tonic-gate sym->sym_strs == NULL) 6567c478bd9Sstevel@tonic-gate return (0); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate size = sym->sym_hdr.sh_size; 6597c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, sym->sym_data->d_buf, size, 6607c478bd9Sstevel@tonic-gate *pgc->pgc_doff) != size) 6617c478bd9Sstevel@tonic-gate return (-1); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size, 6647c478bd9Sstevel@tonic-gate index + 1, sym->sym_hdr.sh_info, sym->sym_hdr.sh_addralign, 6657c478bd9Sstevel@tonic-gate sym->sym_hdr.sh_entsize) != 0) 6667c478bd9Sstevel@tonic-gate return (-1); 6677c478bd9Sstevel@tonic-gate 6687c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(size, 8); 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate size = sym->sym_strhdr.sh_size; 6717c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != size) 6727c478bd9Sstevel@tonic-gate return (-1); 6737c478bd9Sstevel@tonic-gate 6747c478bd9Sstevel@tonic-gate if (write_shdr(pgc, strname, SHT_STRTAB, SHF_STRINGS, addr, 6757c478bd9Sstevel@tonic-gate *pgc->pgc_doff, size, 0, 0, 1, 0) != 0) 6767c478bd9Sstevel@tonic-gate return (-1); 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(size, 8); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate return (0); 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate static int 6847c478bd9Sstevel@tonic-gate dump_sections(pgcore_t *pgc) 6857c478bd9Sstevel@tonic-gate { 6867c478bd9Sstevel@tonic-gate struct ps_prochandle *P = pgc->P; 6877c478bd9Sstevel@tonic-gate file_info_t *fptr; 6887c478bd9Sstevel@tonic-gate uint_t cnt; 6897c478bd9Sstevel@tonic-gate uint_t index = 1; 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB))) 6927c478bd9Sstevel@tonic-gate return (0); 6937c478bd9Sstevel@tonic-gate 6947c478bd9Sstevel@tonic-gate fptr = list_next(&P->file_head); 6957c478bd9Sstevel@tonic-gate for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) { 6967c478bd9Sstevel@tonic-gate int hit_symtab = 0; 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate Pbuild_file_symtab(P, fptr); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if ((pgc->pgc_content & CC_CONTENT_CTF) && 7017c478bd9Sstevel@tonic-gate Pbuild_file_ctf(P, fptr) != NULL) { 7027c478bd9Sstevel@tonic-gate sym_tbl_t *sym; 7037c478bd9Sstevel@tonic-gate uint_t dynsym; 7047c478bd9Sstevel@tonic-gate uint_t symindex = 0; 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * Write the symtab out first so we can correctly 7087c478bd9Sstevel@tonic-gate * set the sh_link field in the CTF section header. 7097c478bd9Sstevel@tonic-gate * symindex will be 0 if there is no corresponding 7107c478bd9Sstevel@tonic-gate * symbol table section. 7117c478bd9Sstevel@tonic-gate */ 7127c478bd9Sstevel@tonic-gate if (fptr->file_ctf_dyn) { 7137c478bd9Sstevel@tonic-gate sym = &fptr->file_dynsym; 7147c478bd9Sstevel@tonic-gate dynsym = 1; 7157c478bd9Sstevel@tonic-gate } else { 7167c478bd9Sstevel@tonic-gate sym = &fptr->file_symtab; 7177c478bd9Sstevel@tonic-gate dynsym = 0; 7187c478bd9Sstevel@tonic-gate hit_symtab = 1; 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if (sym->sym_data != NULL && sym->sym_symn != 0 && 7227c478bd9Sstevel@tonic-gate sym->sym_strs != NULL) { 7237c478bd9Sstevel@tonic-gate symindex = index; 7247c478bd9Sstevel@tonic-gate if (dump_symtab(pgc, fptr, index, dynsym) != 0) 7257c478bd9Sstevel@tonic-gate return (-1); 7267c478bd9Sstevel@tonic-gate index += 2; 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * Write the CTF data that we've read out of the 7317c478bd9Sstevel@tonic-gate * file itself into the core file. 7327c478bd9Sstevel@tonic-gate */ 7337c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, fptr->file_ctf_buf, 7347c478bd9Sstevel@tonic-gate fptr->file_ctf_size, *pgc->pgc_doff) != 7357c478bd9Sstevel@tonic-gate fptr->file_ctf_size) 7367c478bd9Sstevel@tonic-gate return (-1); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate if (write_shdr(pgc, STR_CTF, SHT_PROGBITS, 0, 7397c478bd9Sstevel@tonic-gate fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff, 7407c478bd9Sstevel@tonic-gate fptr->file_ctf_size, symindex, 0, 4, 0) != 0) 7417c478bd9Sstevel@tonic-gate return (-1); 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate index++; 7447c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8); 7457c478bd9Sstevel@tonic-gate } 7467c478bd9Sstevel@tonic-gate 7477c478bd9Sstevel@tonic-gate if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && 7487c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_data != NULL && 7497c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_symn != 0 && 7507c478bd9Sstevel@tonic-gate fptr->file_symtab.sym_strs != NULL) { 7517c478bd9Sstevel@tonic-gate if (dump_symtab(pgc, fptr, index, 0) != 0) 7527c478bd9Sstevel@tonic-gate return (-1); 7537c478bd9Sstevel@tonic-gate index += 2; 7547c478bd9Sstevel@tonic-gate } 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate return (0); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7617c478bd9Sstevel@tonic-gate static int 7627c478bd9Sstevel@tonic-gate dump_map(void *data, const prmap_t *pmp, const char *name) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate pgcore_t *pgc = data; 7657c478bd9Sstevel@tonic-gate struct ps_prochandle *P = pgc->P; 7667c478bd9Sstevel@tonic-gate #ifdef _LP64 7677c478bd9Sstevel@tonic-gate Elf64_Phdr phdr; 7687c478bd9Sstevel@tonic-gate #else 7697c478bd9Sstevel@tonic-gate Elf32_Phdr phdr; 7707c478bd9Sstevel@tonic-gate #endif 7717c478bd9Sstevel@tonic-gate size_t n; 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate bzero(&phdr, sizeof (phdr)); 7747c478bd9Sstevel@tonic-gate phdr.p_type = PT_LOAD; 7757c478bd9Sstevel@tonic-gate phdr.p_vaddr = pmp->pr_vaddr; 7767c478bd9Sstevel@tonic-gate phdr.p_memsz = pmp->pr_size; 7777c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_READ) 7787c478bd9Sstevel@tonic-gate phdr.p_flags |= PF_R; 7797c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_WRITE) 7807c478bd9Sstevel@tonic-gate phdr.p_flags |= PF_W; 7817c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_EXEC) 7827c478bd9Sstevel@tonic-gate phdr.p_flags |= PF_X; 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate if (pmp->pr_vaddr + pmp->pr_size > P->status.pr_stkbase && 7857c478bd9Sstevel@tonic-gate pmp->pr_vaddr < P->status.pr_stkbase + P->status.pr_stksize) { 7867c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_STACK)) 7877c478bd9Sstevel@tonic-gate goto exclude; 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate } else if ((pmp->pr_mflags & MA_ANON) && 7907c478bd9Sstevel@tonic-gate pmp->pr_vaddr + pmp->pr_size > P->status.pr_brkbase && 7917c478bd9Sstevel@tonic-gate pmp->pr_vaddr < P->status.pr_brkbase + P->status.pr_brksize) { 7927c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_HEAP)) 7937c478bd9Sstevel@tonic-gate goto exclude; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_ISM) { 7967c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_NORESERVE) { 7977c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_DISM)) 7987c478bd9Sstevel@tonic-gate goto exclude; 7997c478bd9Sstevel@tonic-gate } else { 8007c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_ISM)) 8017c478bd9Sstevel@tonic-gate goto exclude; 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_SHM) { 8057c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_SHM)) 8067c478bd9Sstevel@tonic-gate goto exclude; 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_SHARED) { 8097c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_ANON) { 8107c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_SHANON)) 8117c478bd9Sstevel@tonic-gate goto exclude; 8127c478bd9Sstevel@tonic-gate } else { 8137c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_SHFILE)) 8147c478bd9Sstevel@tonic-gate goto exclude; 8157c478bd9Sstevel@tonic-gate } 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_ANON) { 8187c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_ANON)) 8197c478bd9Sstevel@tonic-gate goto exclude; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate } else if (phdr.p_flags == (PF_R | PF_X)) { 8227c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_TEXT)) 8237c478bd9Sstevel@tonic-gate goto exclude; 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate } else if (phdr.p_flags == PF_R) { 8267c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_RODATA)) 8277c478bd9Sstevel@tonic-gate goto exclude; 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate } else { 8307c478bd9Sstevel@tonic-gate if (!(pgc->pgc_content & CC_CONTENT_DATA)) 8317c478bd9Sstevel@tonic-gate goto exclude; 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate n = 0; 8357c478bd9Sstevel@tonic-gate while (n < pmp->pr_size) { 8367c478bd9Sstevel@tonic-gate size_t csz = MIN(pmp->pr_size - n, pgc->pgc_chunksz); 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate /* 8397c478bd9Sstevel@tonic-gate * If we can't read out part of the victim's address 8407c478bd9Sstevel@tonic-gate * space for some reason ignore that failure and try to 8417c478bd9Sstevel@tonic-gate * emit a partial core file without that mapping's data. 8427c478bd9Sstevel@tonic-gate * As in the kernel, we mark these failures with the 8437c478bd9Sstevel@tonic-gate * PF_SUNW_FAILURE flag and store the errno where the 8447c478bd9Sstevel@tonic-gate * mapping would have been. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate if (Pread(P, pgc->pgc_chunk, csz, pmp->pr_vaddr + n) != csz || 8477c478bd9Sstevel@tonic-gate pwrite64(pgc->pgc_fd, pgc->pgc_chunk, csz, 8487c478bd9Sstevel@tonic-gate *pgc->pgc_doff + n) != csz) { 8497c478bd9Sstevel@tonic-gate int err = errno; 8507c478bd9Sstevel@tonic-gate (void) pwrite64(pgc->pgc_fd, &err, sizeof (err), 8517c478bd9Sstevel@tonic-gate *pgc->pgc_doff); 8527c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(sizeof (err), 8); 8537c478bd9Sstevel@tonic-gate 8547c478bd9Sstevel@tonic-gate phdr.p_flags |= PF_SUNW_FAILURE; 8557c478bd9Sstevel@tonic-gate (void) ftruncate64(pgc->pgc_fd, *pgc->pgc_doff); 8567c478bd9Sstevel@tonic-gate goto exclude; 8577c478bd9Sstevel@tonic-gate } 8587c478bd9Sstevel@tonic-gate 8597c478bd9Sstevel@tonic-gate n += csz; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate phdr.p_offset = *pgc->pgc_doff; 8637c478bd9Sstevel@tonic-gate phdr.p_filesz = pmp->pr_size; 8647c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(phdr.p_filesz, 8); 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate exclude: 8677c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 8687c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &phdr, sizeof (phdr), 8697c478bd9Sstevel@tonic-gate *pgc->pgc_poff) != sizeof (phdr)) 8707c478bd9Sstevel@tonic-gate return (1); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate *pgc->pgc_poff += sizeof (phdr); 8737c478bd9Sstevel@tonic-gate #ifdef _LP64 8747c478bd9Sstevel@tonic-gate } else { 8757c478bd9Sstevel@tonic-gate Elf32_Phdr phdr32; 8767c478bd9Sstevel@tonic-gate 8777c478bd9Sstevel@tonic-gate bzero(&phdr32, sizeof (phdr32)); 8787c478bd9Sstevel@tonic-gate phdr32.p_type = phdr.p_type; 8797c478bd9Sstevel@tonic-gate phdr32.p_vaddr = (Elf32_Addr)phdr.p_vaddr; 8807c478bd9Sstevel@tonic-gate phdr32.p_memsz = (Elf32_Word)phdr.p_memsz; 8817c478bd9Sstevel@tonic-gate phdr32.p_flags = phdr.p_flags; 8827c478bd9Sstevel@tonic-gate phdr32.p_offset = (Elf32_Off)phdr.p_offset; 8837c478bd9Sstevel@tonic-gate phdr32.p_filesz = (Elf32_Word)phdr.p_filesz; 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &phdr32, sizeof (phdr32), 8867c478bd9Sstevel@tonic-gate *pgc->pgc_poff) != sizeof (phdr32)) 8877c478bd9Sstevel@tonic-gate return (1); 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate *pgc->pgc_poff += sizeof (phdr32); 8907c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate return (0); 8947c478bd9Sstevel@tonic-gate } 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate int 8977c478bd9Sstevel@tonic-gate write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc) 8987c478bd9Sstevel@tonic-gate { 8997c478bd9Sstevel@tonic-gate off64_t off = *pgc->pgc_doff; 9007c478bd9Sstevel@tonic-gate size_t size = 0; 9017c478bd9Sstevel@tonic-gate shstrtab_t *s = &pgc->pgc_shstrtab; 9027c478bd9Sstevel@tonic-gate int i, ndx; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate if (shstrtab_size(s) == 1) 9057c478bd9Sstevel@tonic-gate return (0); 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate /* 9087c478bd9Sstevel@tonic-gate * Preemptively stick the name of the shstrtab in the string table. 9097c478bd9Sstevel@tonic-gate */ 9107c478bd9Sstevel@tonic-gate (void) shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); 9117c478bd9Sstevel@tonic-gate size = shstrtab_size(s); 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * Dump all the strings that we used being sure we include the 9157c478bd9Sstevel@tonic-gate * terminating null character. 9167c478bd9Sstevel@tonic-gate */ 9177c478bd9Sstevel@tonic-gate for (i = 0; i < STR_NUM; i++) { 918*30da1432Sahl if ((ndx = s->sst_ndx[i]) != 0 || i == STR_NONE) { 9197c478bd9Sstevel@tonic-gate const char *str = shstrtab_data[i]; 9207c478bd9Sstevel@tonic-gate size_t len = strlen(str) + 1; 9217c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, str, len, off + ndx) != len) 9227c478bd9Sstevel@tonic-gate return (1); 9237c478bd9Sstevel@tonic-gate } 9247c478bd9Sstevel@tonic-gate } 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_ILP32) { 9277c478bd9Sstevel@tonic-gate Elf32_Shdr shdr; 9287c478bd9Sstevel@tonic-gate 9297c478bd9Sstevel@tonic-gate bzero(&shdr, sizeof (shdr)); 9307c478bd9Sstevel@tonic-gate shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); 9317c478bd9Sstevel@tonic-gate shdr.sh_size = size; 9327c478bd9Sstevel@tonic-gate shdr.sh_offset = *pgc->pgc_doff; 9337c478bd9Sstevel@tonic-gate shdr.sh_addralign = 1; 9347c478bd9Sstevel@tonic-gate shdr.sh_flags = SHF_STRINGS; 9357c478bd9Sstevel@tonic-gate shdr.sh_type = SHT_STRTAB; 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 9387c478bd9Sstevel@tonic-gate *pgc->pgc_soff) != sizeof (shdr)) 9397c478bd9Sstevel@tonic-gate return (1); 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate *pgc->pgc_soff += sizeof (shdr); 9427c478bd9Sstevel@tonic-gate #ifdef _LP64 9437c478bd9Sstevel@tonic-gate } else { 9447c478bd9Sstevel@tonic-gate Elf64_Shdr shdr; 9457c478bd9Sstevel@tonic-gate 9467c478bd9Sstevel@tonic-gate bzero(&shdr, sizeof (shdr)); 9477c478bd9Sstevel@tonic-gate shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); 9487c478bd9Sstevel@tonic-gate shdr.sh_size = size; 9497c478bd9Sstevel@tonic-gate shdr.sh_offset = *pgc->pgc_doff; 9507c478bd9Sstevel@tonic-gate shdr.sh_addralign = 1; 9517c478bd9Sstevel@tonic-gate shdr.sh_flags = SHF_STRINGS; 9527c478bd9Sstevel@tonic-gate shdr.sh_type = SHT_STRTAB; 9537c478bd9Sstevel@tonic-gate 9547c478bd9Sstevel@tonic-gate if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), 9557c478bd9Sstevel@tonic-gate *pgc->pgc_soff) != sizeof (shdr)) 9567c478bd9Sstevel@tonic-gate return (1); 9577c478bd9Sstevel@tonic-gate 9587c478bd9Sstevel@tonic-gate *pgc->pgc_soff += sizeof (shdr); 9597c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 9607c478bd9Sstevel@tonic-gate } 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate *pgc->pgc_doff += roundup(size, 8); 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate return (0); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate /* 9687c478bd9Sstevel@tonic-gate * Don't explicity stop the process; that's up to the consumer. 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate int 9717c478bd9Sstevel@tonic-gate Pfgcore(struct ps_prochandle *P, int fd, core_content_t content) 9727c478bd9Sstevel@tonic-gate { 9737c478bd9Sstevel@tonic-gate char plat[SYS_NMLN]; 9747c478bd9Sstevel@tonic-gate char zonename[ZONENAME_MAX]; 9757c478bd9Sstevel@tonic-gate int platlen = -1; 9767c478bd9Sstevel@tonic-gate pgcore_t pgc; 9777c478bd9Sstevel@tonic-gate off64_t poff, soff, doff, boff; 9787c478bd9Sstevel@tonic-gate struct utsname uts; 9797c478bd9Sstevel@tonic-gate uint_t nphdrs, nshdrs; 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate if (ftruncate64(fd, 0) != 0) 9827c478bd9Sstevel@tonic-gate return (-1); 9837c478bd9Sstevel@tonic-gate 9847c478bd9Sstevel@tonic-gate if (content == CC_CONTENT_INVALID) { 9857c478bd9Sstevel@tonic-gate errno = EINVAL; 9867c478bd9Sstevel@tonic-gate return (-1); 9877c478bd9Sstevel@tonic-gate } 9887c478bd9Sstevel@tonic-gate 9897c478bd9Sstevel@tonic-gate /* 9907c478bd9Sstevel@tonic-gate * Cache the mappings and other useful data. 9917c478bd9Sstevel@tonic-gate */ 9927c478bd9Sstevel@tonic-gate (void) Prd_agent(P); 9937c478bd9Sstevel@tonic-gate (void) Ppsinfo(P); 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate pgc.P = P; 9967c478bd9Sstevel@tonic-gate pgc.pgc_fd = fd; 9977c478bd9Sstevel@tonic-gate pgc.pgc_poff = &poff; 9987c478bd9Sstevel@tonic-gate pgc.pgc_soff = &soff; 9997c478bd9Sstevel@tonic-gate pgc.pgc_doff = &doff; 10007c478bd9Sstevel@tonic-gate pgc.pgc_content = content; 10017c478bd9Sstevel@tonic-gate pgc.pgc_chunksz = PAGESIZE; 10027c478bd9Sstevel@tonic-gate if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL) 10037c478bd9Sstevel@tonic-gate return (-1); 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate shstrtab_init(&pgc.pgc_shstrtab); 10067c478bd9Sstevel@tonic-gate 10077c478bd9Sstevel@tonic-gate /* 10087c478bd9Sstevel@tonic-gate * There are two PT_NOTE program headers for ancillary data, and 10097c478bd9Sstevel@tonic-gate * one for each mapping. 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate nphdrs = 2 + P->map_count; 10127c478bd9Sstevel@tonic-gate nshdrs = count_sections(&pgc); 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate (void) Pplatform(P, plat, sizeof (plat)); 10157c478bd9Sstevel@tonic-gate platlen = strlen(plat) + 1; 10167c478bd9Sstevel@tonic-gate Preadauxvec(P); 10177c478bd9Sstevel@tonic-gate (void) Puname(P, &uts); 10187c478bd9Sstevel@tonic-gate if (Pzonename(P, zonename, sizeof (zonename)) == NULL) 10197c478bd9Sstevel@tonic-gate zonename[0] = '\0'; 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 1022*30da1432Sahl * The core file contents may required zero section headers, but if we 1023*30da1432Sahl * overflow the 16 bits allotted to the program header count in the ELF 1024*30da1432Sahl * header, we'll need that program header at index zero. 1025*30da1432Sahl */ 1026*30da1432Sahl if (nshdrs == 0 && nphdrs >= PN_XNUM) 1027*30da1432Sahl nshdrs = 1; 1028*30da1432Sahl 1029*30da1432Sahl /* 10307c478bd9Sstevel@tonic-gate * Set up the ELF header. 10317c478bd9Sstevel@tonic-gate */ 10327c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_ILP32) { 10337c478bd9Sstevel@tonic-gate Elf32_Ehdr ehdr; 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate bzero(&ehdr, sizeof (ehdr)); 10367c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG0] = ELFMAG0; 10377c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG1] = ELFMAG1; 10387c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG2] = ELFMAG2; 10397c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG3] = ELFMAG3; 10407c478bd9Sstevel@tonic-gate ehdr.e_type = ET_CORE; 10417c478bd9Sstevel@tonic-gate 10427c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_CLASS] = ELFCLASS32; 10437c478bd9Sstevel@tonic-gate #if defined(__sparc) 10447c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_SPARC; 10457c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 10467c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64) 10477c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_386; 10487c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 10497c478bd9Sstevel@tonic-gate #else 10507c478bd9Sstevel@tonic-gate #error "unknown machine type" 10517c478bd9Sstevel@tonic-gate #endif 10527c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_VERSION] = EV_CURRENT; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate ehdr.e_version = EV_CURRENT; 10557c478bd9Sstevel@tonic-gate ehdr.e_ehsize = sizeof (ehdr); 1056*30da1432Sahl 1057*30da1432Sahl if (nphdrs >= PN_XNUM) 1058*30da1432Sahl ehdr.e_phnum = PN_XNUM; 1059*30da1432Sahl else 10607c478bd9Sstevel@tonic-gate ehdr.e_phnum = (unsigned short)nphdrs; 1061*30da1432Sahl 1062*30da1432Sahl ehdr.e_phentsize = sizeof (Elf32_Phdr); 10637c478bd9Sstevel@tonic-gate ehdr.e_phoff = ehdr.e_ehsize; 10647c478bd9Sstevel@tonic-gate 1065*30da1432Sahl if (nshdrs > 0) { 1066*30da1432Sahl if (nshdrs >= SHN_LORESERVE) 1067*30da1432Sahl ehdr.e_shnum = 0; 1068*30da1432Sahl else 10697c478bd9Sstevel@tonic-gate ehdr.e_shnum = (unsigned short)nshdrs; 1070*30da1432Sahl 1071*30da1432Sahl if (nshdrs - 1 >= SHN_LORESERVE) 1072*30da1432Sahl ehdr.e_shstrndx = SHN_XINDEX; 1073*30da1432Sahl else 1074*30da1432Sahl ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); 1075*30da1432Sahl 1076*30da1432Sahl ehdr.e_shentsize = sizeof (Elf32_Shdr); 1077*30da1432Sahl ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; 10787c478bd9Sstevel@tonic-gate } 10797c478bd9Sstevel@tonic-gate 10807c478bd9Sstevel@tonic-gate if (pwrite64(fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) 10817c478bd9Sstevel@tonic-gate goto err; 10827c478bd9Sstevel@tonic-gate 10837c478bd9Sstevel@tonic-gate poff = ehdr.e_phoff; 1084*30da1432Sahl soff = ehdr.e_shoff; 10857c478bd9Sstevel@tonic-gate doff = boff = ehdr.e_ehsize + 1086*30da1432Sahl ehdr.e_phentsize * nphdrs + 1087*30da1432Sahl ehdr.e_shentsize * nshdrs; 10887c478bd9Sstevel@tonic-gate 10897c478bd9Sstevel@tonic-gate #ifdef _LP64 10907c478bd9Sstevel@tonic-gate } else { 10917c478bd9Sstevel@tonic-gate Elf64_Ehdr ehdr; 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate bzero(&ehdr, sizeof (ehdr)); 10947c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG0] = ELFMAG0; 10957c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG1] = ELFMAG1; 10967c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG2] = ELFMAG2; 10977c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_MAG3] = ELFMAG3; 10987c478bd9Sstevel@tonic-gate ehdr.e_type = ET_CORE; 10997c478bd9Sstevel@tonic-gate 11007c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_CLASS] = ELFCLASS64; 11017c478bd9Sstevel@tonic-gate #if defined(__sparc) 11027c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_SPARCV9; 11037c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2MSB; 11047c478bd9Sstevel@tonic-gate #elif defined(__i386) || defined(__amd64) 11057c478bd9Sstevel@tonic-gate ehdr.e_machine = EM_AMD64; 11067c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_DATA] = ELFDATA2LSB; 11077c478bd9Sstevel@tonic-gate #else 11087c478bd9Sstevel@tonic-gate #error "unknown machine type" 11097c478bd9Sstevel@tonic-gate #endif 11107c478bd9Sstevel@tonic-gate ehdr.e_ident[EI_VERSION] = EV_CURRENT; 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate ehdr.e_version = EV_CURRENT; 11137c478bd9Sstevel@tonic-gate ehdr.e_ehsize = sizeof (ehdr); 1114*30da1432Sahl 1115*30da1432Sahl if (nphdrs >= PN_XNUM) 1116*30da1432Sahl ehdr.e_phnum = PN_XNUM; 1117*30da1432Sahl else 11187c478bd9Sstevel@tonic-gate ehdr.e_phnum = (unsigned short)nphdrs; 1119*30da1432Sahl 1120*30da1432Sahl ehdr.e_phentsize = sizeof (Elf64_Phdr); 11217c478bd9Sstevel@tonic-gate ehdr.e_phoff = ehdr.e_ehsize; 11227c478bd9Sstevel@tonic-gate 1123*30da1432Sahl if (nshdrs > 0) { 1124*30da1432Sahl if (nshdrs >= SHN_LORESERVE) 1125*30da1432Sahl ehdr.e_shnum = 0; 1126*30da1432Sahl else 11277c478bd9Sstevel@tonic-gate ehdr.e_shnum = (unsigned short)nshdrs; 1128*30da1432Sahl 1129*30da1432Sahl if (nshdrs - 1 >= SHN_LORESERVE) 1130*30da1432Sahl ehdr.e_shstrndx = SHN_XINDEX; 1131*30da1432Sahl else 1132*30da1432Sahl ehdr.e_shstrndx = (unsigned short)(nshdrs - 1); 1133*30da1432Sahl 1134*30da1432Sahl ehdr.e_shentsize = sizeof (Elf64_Shdr); 1135*30da1432Sahl ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs; 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate if (pwrite64(fd, &ehdr, sizeof (ehdr), 0) != sizeof (ehdr)) 11397c478bd9Sstevel@tonic-gate goto err; 11407c478bd9Sstevel@tonic-gate 11417c478bd9Sstevel@tonic-gate poff = ehdr.e_phoff; 1142*30da1432Sahl soff = ehdr.e_shoff; 1143*30da1432Sahl doff = boff = ehdr.e_ehsize + 1144*30da1432Sahl ehdr.e_phentsize * nphdrs + 1145*30da1432Sahl ehdr.e_shentsize * nshdrs; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 11487c478bd9Sstevel@tonic-gate } 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* 1151*30da1432Sahl * Write the zero indexed section if it exists. 1152*30da1432Sahl */ 1153*30da1432Sahl if (nshdrs > 0 && write_shdr(&pgc, STR_NONE, 0, 0, 0, 0, 1154*30da1432Sahl nshdrs >= SHN_LORESERVE ? nshdrs : 0, 1155*30da1432Sahl nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0, 1156*30da1432Sahl nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0) 1157*30da1432Sahl goto err; 1158*30da1432Sahl 1159*30da1432Sahl /* 11607c478bd9Sstevel@tonic-gate * Construct the old-style note header and section. 11617c478bd9Sstevel@tonic-gate */ 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 11647c478bd9Sstevel@tonic-gate prpsinfo_t prpsinfo; 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate mkprpsinfo(P, &prpsinfo); 11677c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PRPSINFO, &prpsinfo, sizeof (prpsinfo_t), 11687c478bd9Sstevel@tonic-gate &doff) != 0) { 11697c478bd9Sstevel@tonic-gate goto err; 11707c478bd9Sstevel@tonic-gate } 11717c478bd9Sstevel@tonic-gate if (write_note(fd, NT_AUXV, P->auxv, 11727c478bd9Sstevel@tonic-gate P->nauxv * sizeof (P->auxv[0]), &doff) != 0) { 11737c478bd9Sstevel@tonic-gate goto err; 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate #ifdef _LP64 11767c478bd9Sstevel@tonic-gate } else { 11777c478bd9Sstevel@tonic-gate prpsinfo32_t pi32; 11787c478bd9Sstevel@tonic-gate auxv32_t *av32; 11797c478bd9Sstevel@tonic-gate size_t size = sizeof (auxv32_t) * P->nauxv; 11807c478bd9Sstevel@tonic-gate int i; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate mkprpsinfo32(P, &pi32); 11837c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PRPSINFO, &pi32, sizeof (prpsinfo32_t), 11847c478bd9Sstevel@tonic-gate &doff) != 0) { 11857c478bd9Sstevel@tonic-gate goto err; 11867c478bd9Sstevel@tonic-gate } 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate if ((av32 = malloc(size)) == NULL) 11897c478bd9Sstevel@tonic-gate goto err; 11907c478bd9Sstevel@tonic-gate 11917c478bd9Sstevel@tonic-gate for (i = 0; i < P->nauxv; i++) { 11927c478bd9Sstevel@tonic-gate auxv_n_to_32(&P->auxv[i], &av32[i]); 11937c478bd9Sstevel@tonic-gate } 11947c478bd9Sstevel@tonic-gate 11957c478bd9Sstevel@tonic-gate if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) { 11967c478bd9Sstevel@tonic-gate free(av32); 11977c478bd9Sstevel@tonic-gate goto err; 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate free(av32); 12017c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate 12047c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0) 12057c478bd9Sstevel@tonic-gate goto err; 12067c478bd9Sstevel@tonic-gate 12077c478bd9Sstevel@tonic-gate if (Plwp_iter_all(P, old_per_lwp, &pgc) != 0) 12087c478bd9Sstevel@tonic-gate goto err; 12097c478bd9Sstevel@tonic-gate 12107c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_ILP32) { 12117c478bd9Sstevel@tonic-gate Elf32_Phdr phdr; 12127c478bd9Sstevel@tonic-gate 12137c478bd9Sstevel@tonic-gate bzero(&phdr, sizeof (phdr)); 12147c478bd9Sstevel@tonic-gate phdr.p_type = PT_NOTE; 12157c478bd9Sstevel@tonic-gate phdr.p_flags = PF_R; 12167c478bd9Sstevel@tonic-gate phdr.p_offset = (Elf32_Off)boff; 12177c478bd9Sstevel@tonic-gate phdr.p_filesz = doff - boff; 12187c478bd9Sstevel@tonic-gate boff = doff; 12197c478bd9Sstevel@tonic-gate 12207c478bd9Sstevel@tonic-gate if (pwrite64(fd, &phdr, sizeof (phdr), poff) != sizeof (phdr)) 12217c478bd9Sstevel@tonic-gate goto err; 12227c478bd9Sstevel@tonic-gate poff += sizeof (phdr); 12237c478bd9Sstevel@tonic-gate #ifdef _LP64 12247c478bd9Sstevel@tonic-gate } else { 12257c478bd9Sstevel@tonic-gate Elf64_Phdr phdr; 12267c478bd9Sstevel@tonic-gate 12277c478bd9Sstevel@tonic-gate bzero(&phdr, sizeof (phdr)); 12287c478bd9Sstevel@tonic-gate phdr.p_type = PT_NOTE; 12297c478bd9Sstevel@tonic-gate phdr.p_flags = PF_R; 12307c478bd9Sstevel@tonic-gate phdr.p_offset = boff; 12317c478bd9Sstevel@tonic-gate phdr.p_filesz = doff - boff; 12327c478bd9Sstevel@tonic-gate boff = doff; 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate if (pwrite64(fd, &phdr, sizeof (phdr), poff) != sizeof (phdr)) 12357c478bd9Sstevel@tonic-gate goto err; 12367c478bd9Sstevel@tonic-gate poff += sizeof (phdr); 12377c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate /* 12417c478bd9Sstevel@tonic-gate * Construct the new-style note header and section. 12427c478bd9Sstevel@tonic-gate */ 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_NATIVE) { 12457c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PSINFO, &P->psinfo, sizeof (psinfo_t), 12467c478bd9Sstevel@tonic-gate &doff) != 0) { 12477c478bd9Sstevel@tonic-gate goto err; 12487c478bd9Sstevel@tonic-gate } 12497c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PSTATUS, &P->status, sizeof (pstatus_t), 12507c478bd9Sstevel@tonic-gate &doff) != 0) { 12517c478bd9Sstevel@tonic-gate goto err; 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate if (write_note(fd, NT_AUXV, P->auxv, 12547c478bd9Sstevel@tonic-gate P->nauxv * sizeof (P->auxv[0]), &doff) != 0) { 12557c478bd9Sstevel@tonic-gate goto err; 12567c478bd9Sstevel@tonic-gate } 12577c478bd9Sstevel@tonic-gate #ifdef _LP64 12587c478bd9Sstevel@tonic-gate } else { 12597c478bd9Sstevel@tonic-gate psinfo32_t pi32; 12607c478bd9Sstevel@tonic-gate pstatus32_t ps32; 12617c478bd9Sstevel@tonic-gate auxv32_t *av32; 12627c478bd9Sstevel@tonic-gate size_t size = sizeof (auxv32_t) * P->nauxv; 12637c478bd9Sstevel@tonic-gate int i; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate psinfo_n_to_32(&P->psinfo, &pi32); 12667c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PSINFO, &pi32, sizeof (psinfo32_t), 12677c478bd9Sstevel@tonic-gate &doff) != 0) { 12687c478bd9Sstevel@tonic-gate goto err; 12697c478bd9Sstevel@tonic-gate } 12707c478bd9Sstevel@tonic-gate pstatus_n_to_32(&P->status, &ps32); 12717c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PSTATUS, &ps32, sizeof (pstatus32_t), 12727c478bd9Sstevel@tonic-gate &doff) != 0) { 12737c478bd9Sstevel@tonic-gate goto err; 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate if ((av32 = malloc(size)) == NULL) 12767c478bd9Sstevel@tonic-gate goto err; 12777c478bd9Sstevel@tonic-gate 12787c478bd9Sstevel@tonic-gate for (i = 0; i < P->nauxv; i++) { 12797c478bd9Sstevel@tonic-gate auxv_n_to_32(&P->auxv[i], &av32[i]); 12807c478bd9Sstevel@tonic-gate } 12817c478bd9Sstevel@tonic-gate 12827c478bd9Sstevel@tonic-gate if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) { 12837c478bd9Sstevel@tonic-gate free(av32); 12847c478bd9Sstevel@tonic-gate goto err; 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate free(av32); 12887c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 12897c478bd9Sstevel@tonic-gate } 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0 || 12927c478bd9Sstevel@tonic-gate write_note(fd, NT_UTSNAME, &uts, sizeof (uts), &doff) != 0 || 12937c478bd9Sstevel@tonic-gate write_note(fd, NT_CONTENT, &content, sizeof (content), &doff) != 0) 12947c478bd9Sstevel@tonic-gate goto err; 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate { 12977c478bd9Sstevel@tonic-gate prcred_t cred, *cp; 12987c478bd9Sstevel@tonic-gate size_t size = sizeof (prcred_t); 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate if (Pcred(P, &cred, 0) != 0) 13017c478bd9Sstevel@tonic-gate goto err; 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate if (cred.pr_ngroups > 0) 13047c478bd9Sstevel@tonic-gate size += sizeof (gid_t) * (cred.pr_ngroups - 1); 13057c478bd9Sstevel@tonic-gate if ((cp = malloc(size)) == NULL) 13067c478bd9Sstevel@tonic-gate goto err; 13077c478bd9Sstevel@tonic-gate 13087c478bd9Sstevel@tonic-gate if (Pcred(P, cp, cred.pr_ngroups) != 0 || 13097c478bd9Sstevel@tonic-gate write_note(fd, NT_PRCRED, cp, size, &doff) != 0) { 13107c478bd9Sstevel@tonic-gate free(cp); 13117c478bd9Sstevel@tonic-gate goto err; 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate 13147c478bd9Sstevel@tonic-gate free(cp); 13157c478bd9Sstevel@tonic-gate } 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate { 13187c478bd9Sstevel@tonic-gate prpriv_t *ppriv; 13197c478bd9Sstevel@tonic-gate const priv_impl_info_t *pinfo; 13207c478bd9Sstevel@tonic-gate size_t pprivsz, pinfosz; 13217c478bd9Sstevel@tonic-gate 13227c478bd9Sstevel@tonic-gate if ((ppriv = proc_get_priv(P->pid)) == NULL) 13237c478bd9Sstevel@tonic-gate goto err; 13247c478bd9Sstevel@tonic-gate pprivsz = PRIV_PRPRIV_SIZE(ppriv); 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PRPRIV, ppriv, pprivsz, &doff) != 0) { 13277c478bd9Sstevel@tonic-gate free(ppriv); 13287c478bd9Sstevel@tonic-gate goto err; 13297c478bd9Sstevel@tonic-gate } 13307c478bd9Sstevel@tonic-gate free(ppriv); 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate if ((pinfo = getprivimplinfo()) == NULL) 13337c478bd9Sstevel@tonic-gate goto err; 13347c478bd9Sstevel@tonic-gate pinfosz = PRIV_IMPL_INFO_SIZE(pinfo); 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate if (write_note(fd, NT_PRPRIVINFO, pinfo, pinfosz, &doff) != 0) 13377c478bd9Sstevel@tonic-gate goto err; 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate if (write_note(fd, NT_ZONENAME, zonename, strlen(zonename) + 1, 13417c478bd9Sstevel@tonic-gate &doff) != 0) 13427c478bd9Sstevel@tonic-gate goto err; 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 13457c478bd9Sstevel@tonic-gate /* CSTYLED */ 13467c478bd9Sstevel@tonic-gate { 13477c478bd9Sstevel@tonic-gate struct ssd *ldtp; 13487c478bd9Sstevel@tonic-gate size_t size; 13497c478bd9Sstevel@tonic-gate int nldt; 13507c478bd9Sstevel@tonic-gate 135140c00cd7Sahl /* 135240c00cd7Sahl * Only dump out non-zero sized LDT notes. 135340c00cd7Sahl */ 135440c00cd7Sahl if ((nldt = Pldt(P, NULL, 0)) != 0) { 13557c478bd9Sstevel@tonic-gate size = sizeof (struct ssd) * nldt; 13567c478bd9Sstevel@tonic-gate if ((ldtp = malloc(size)) == NULL) 13577c478bd9Sstevel@tonic-gate goto err; 13587c478bd9Sstevel@tonic-gate 13597c478bd9Sstevel@tonic-gate if (Pldt(P, ldtp, nldt) == -1 || 13607c478bd9Sstevel@tonic-gate write_note(fd, NT_LDT, ldtp, size, &doff) != 0) { 13617c478bd9Sstevel@tonic-gate free(ldtp); 13627c478bd9Sstevel@tonic-gate goto err; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate free(ldtp); 13667c478bd9Sstevel@tonic-gate } 136740c00cd7Sahl } 13687c478bd9Sstevel@tonic-gate #endif /* __i386 || __amd64 */ 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate if (Plwp_iter_all(P, new_per_lwp, &pgc) != 0) 13717c478bd9Sstevel@tonic-gate goto err; 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate if (P->status.pr_dmodel == PR_MODEL_ILP32) { 13747c478bd9Sstevel@tonic-gate Elf32_Phdr phdr; 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate bzero(&phdr, sizeof (phdr)); 13777c478bd9Sstevel@tonic-gate phdr.p_type = PT_NOTE; 13787c478bd9Sstevel@tonic-gate phdr.p_flags = PF_R; 13797c478bd9Sstevel@tonic-gate phdr.p_offset = (Elf32_Off)boff; 13807c478bd9Sstevel@tonic-gate phdr.p_filesz = doff - boff; 13817c478bd9Sstevel@tonic-gate boff = doff; 13827c478bd9Sstevel@tonic-gate 13837c478bd9Sstevel@tonic-gate if (pwrite64(fd, &phdr, sizeof (phdr), poff) != sizeof (phdr)) 13847c478bd9Sstevel@tonic-gate goto err; 13857c478bd9Sstevel@tonic-gate poff += sizeof (phdr); 13867c478bd9Sstevel@tonic-gate #ifdef _LP64 13877c478bd9Sstevel@tonic-gate } else { 13887c478bd9Sstevel@tonic-gate Elf64_Phdr phdr; 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate bzero(&phdr, sizeof (phdr)); 13917c478bd9Sstevel@tonic-gate phdr.p_type = PT_NOTE; 13927c478bd9Sstevel@tonic-gate phdr.p_flags = PF_R; 13937c478bd9Sstevel@tonic-gate phdr.p_offset = boff; 13947c478bd9Sstevel@tonic-gate phdr.p_filesz = doff - boff; 13957c478bd9Sstevel@tonic-gate boff = doff; 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate if (pwrite64(fd, &phdr, sizeof (phdr), poff) != sizeof (phdr)) 13987c478bd9Sstevel@tonic-gate goto err; 13997c478bd9Sstevel@tonic-gate poff += sizeof (phdr); 14007c478bd9Sstevel@tonic-gate #endif /* _LP64 */ 14017c478bd9Sstevel@tonic-gate } 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate /* 14047c478bd9Sstevel@tonic-gate * Construct the headers for each mapping and write out its data 14057c478bd9Sstevel@tonic-gate * if the content parameter indicates that it should be present 14067c478bd9Sstevel@tonic-gate * in the core file. 14077c478bd9Sstevel@tonic-gate */ 14087c478bd9Sstevel@tonic-gate if (Pmapping_iter(P, dump_map, &pgc) != 0) 14097c478bd9Sstevel@tonic-gate goto err; 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate if (dump_sections(&pgc) != 0) 14127c478bd9Sstevel@tonic-gate goto err; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate if (write_shstrtab(P, &pgc) != 0) 14157c478bd9Sstevel@tonic-gate goto err; 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate free(pgc.pgc_chunk); 14187c478bd9Sstevel@tonic-gate 14197c478bd9Sstevel@tonic-gate return (0); 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate err: 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate * Wipe out anything we may have written if there was an error. 14247c478bd9Sstevel@tonic-gate */ 14257c478bd9Sstevel@tonic-gate (void) ftruncate64(fd, 0); 14267c478bd9Sstevel@tonic-gate free(pgc.pgc_chunk); 14277c478bd9Sstevel@tonic-gate return (-1); 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate static const char *content_str[] = { 14317c478bd9Sstevel@tonic-gate "stack", /* CC_CONTENT_STACK */ 14327c478bd9Sstevel@tonic-gate "heap", /* CC_CONTENT_HEAP */ 14337c478bd9Sstevel@tonic-gate "shfile", /* CC_CONTENT_SHFILE */ 14347c478bd9Sstevel@tonic-gate "shanon", /* CC_CONTENT_SHANON */ 14357c478bd9Sstevel@tonic-gate "text", /* CC_CONTENT_TEXT */ 14367c478bd9Sstevel@tonic-gate "data", /* CC_CONTENT_DATA */ 14377c478bd9Sstevel@tonic-gate "rodata", /* CC_CONTENT_RODATA */ 14387c478bd9Sstevel@tonic-gate "anon", /* CC_CONTENT_ANON */ 14397c478bd9Sstevel@tonic-gate "shm", /* CC_CONTENT_SHM */ 14407c478bd9Sstevel@tonic-gate "ism", /* CC_CONTENT_ISM */ 14417c478bd9Sstevel@tonic-gate "dism", /* CC_CONTENT_DISM */ 14427c478bd9Sstevel@tonic-gate "ctf", /* CC_CONTENT_CTF */ 14437c478bd9Sstevel@tonic-gate "symtab", /* CC_CONTENT_SYMTAB */ 14447c478bd9Sstevel@tonic-gate }; 14457c478bd9Sstevel@tonic-gate 14467c478bd9Sstevel@tonic-gate static uint_t ncontent_str = sizeof (content_str) / sizeof (content_str[0]); 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate #define STREQ(a, b, n) (strlen(b) == (n) && strncmp(a, b, n) == 0) 14497c478bd9Sstevel@tonic-gate 14507c478bd9Sstevel@tonic-gate int 14517c478bd9Sstevel@tonic-gate proc_str2content(const char *str, core_content_t *cp) 14527c478bd9Sstevel@tonic-gate { 14537c478bd9Sstevel@tonic-gate const char *cur = str; 14547c478bd9Sstevel@tonic-gate int add = 1; 14557c478bd9Sstevel@tonic-gate core_content_t mask, content = 0; 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate for (;;) { 14587c478bd9Sstevel@tonic-gate for (cur = str; isalpha(*cur); cur++) 14597c478bd9Sstevel@tonic-gate continue; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate if (STREQ(str, "default", cur - str)) { 14627c478bd9Sstevel@tonic-gate mask = CC_CONTENT_DEFAULT; 14637c478bd9Sstevel@tonic-gate } else if (STREQ(str, "all", cur - str)) { 14647c478bd9Sstevel@tonic-gate mask = CC_CONTENT_ALL; 14657c478bd9Sstevel@tonic-gate } else if (STREQ(str, "none", cur - str)) { 14667c478bd9Sstevel@tonic-gate mask = 0; 14677c478bd9Sstevel@tonic-gate } else { 14687c478bd9Sstevel@tonic-gate int i = 0; 14697c478bd9Sstevel@tonic-gate 14707c478bd9Sstevel@tonic-gate while (!STREQ(str, content_str[i], cur - str)) { 14717c478bd9Sstevel@tonic-gate i++; 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate if (i >= ncontent_str) 14747c478bd9Sstevel@tonic-gate return (-1); 14757c478bd9Sstevel@tonic-gate } 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate mask = (core_content_t)1 << i; 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate if (add) 14817c478bd9Sstevel@tonic-gate content |= mask; 14827c478bd9Sstevel@tonic-gate else 14837c478bd9Sstevel@tonic-gate content &= ~mask; 14847c478bd9Sstevel@tonic-gate 14857c478bd9Sstevel@tonic-gate switch (*cur) { 14867c478bd9Sstevel@tonic-gate case '\0': 14877c478bd9Sstevel@tonic-gate *cp = content; 14887c478bd9Sstevel@tonic-gate return (0); 14897c478bd9Sstevel@tonic-gate case '+': 14907c478bd9Sstevel@tonic-gate add = 1; 14917c478bd9Sstevel@tonic-gate break; 14927c478bd9Sstevel@tonic-gate case '-': 14937c478bd9Sstevel@tonic-gate add = 0; 14947c478bd9Sstevel@tonic-gate break; 14957c478bd9Sstevel@tonic-gate default: 14967c478bd9Sstevel@tonic-gate return (-1); 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate str = cur + 1; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate } 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate static int 15047c478bd9Sstevel@tonic-gate popc(core_content_t x) 15057c478bd9Sstevel@tonic-gate { 15067c478bd9Sstevel@tonic-gate int i; 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate for (i = 0; x != 0; i++) 15097c478bd9Sstevel@tonic-gate x &= x - 1; 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate return (i); 15127c478bd9Sstevel@tonic-gate } 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate int 15157c478bd9Sstevel@tonic-gate proc_content2str(core_content_t content, char *buf, size_t size) 15167c478bd9Sstevel@tonic-gate { 15177c478bd9Sstevel@tonic-gate int nonecnt, defcnt, allcnt; 15187c478bd9Sstevel@tonic-gate core_content_t mask, bit; 15197c478bd9Sstevel@tonic-gate int first; 15207c478bd9Sstevel@tonic-gate uint_t index; 15217c478bd9Sstevel@tonic-gate size_t n, tot = 0; 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate if (content == 0) 15247c478bd9Sstevel@tonic-gate return ((int)strlcpy(buf, "none", size)); 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate if (content & ~CC_CONTENT_ALL) 15277c478bd9Sstevel@tonic-gate return ((int)strlcpy(buf, "<invalid>", size)); 15287c478bd9Sstevel@tonic-gate 15297c478bd9Sstevel@tonic-gate nonecnt = popc(content); 15307c478bd9Sstevel@tonic-gate defcnt = 1 + popc(content ^ CC_CONTENT_DEFAULT); 15317c478bd9Sstevel@tonic-gate allcnt = 1 + popc(content ^ CC_CONTENT_ALL); 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if (defcnt <= nonecnt && defcnt <= allcnt) { 15347c478bd9Sstevel@tonic-gate mask = content ^ CC_CONTENT_DEFAULT; 15357c478bd9Sstevel@tonic-gate first = 0; 15367c478bd9Sstevel@tonic-gate tot += (n = strlcpy(buf, "default", size)); 15377c478bd9Sstevel@tonic-gate if (n > size) 15387c478bd9Sstevel@tonic-gate n = size; 15397c478bd9Sstevel@tonic-gate buf += n; 15407c478bd9Sstevel@tonic-gate size -= n; 15417c478bd9Sstevel@tonic-gate } else if (allcnt < nonecnt) { 15427c478bd9Sstevel@tonic-gate mask = content ^ CC_CONTENT_ALL; 15437c478bd9Sstevel@tonic-gate first = 0; 15447c478bd9Sstevel@tonic-gate tot += (n = strlcpy(buf, "all", size)); 15457c478bd9Sstevel@tonic-gate if (n > size) 15467c478bd9Sstevel@tonic-gate n = size; 15477c478bd9Sstevel@tonic-gate buf += n; 15487c478bd9Sstevel@tonic-gate size -= n; 15497c478bd9Sstevel@tonic-gate } else { 15507c478bd9Sstevel@tonic-gate mask = content; 15517c478bd9Sstevel@tonic-gate first = 1; 15527c478bd9Sstevel@tonic-gate } 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate while (mask != 0) { 15557c478bd9Sstevel@tonic-gate bit = mask ^ (mask & (mask - 1)); 15567c478bd9Sstevel@tonic-gate 15577c478bd9Sstevel@tonic-gate if (!first) { 15587c478bd9Sstevel@tonic-gate if (size > 1) { 15597c478bd9Sstevel@tonic-gate *buf = (bit & content) ? '+' : '-'; 15607c478bd9Sstevel@tonic-gate buf++; 15617c478bd9Sstevel@tonic-gate size--; 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate tot++; 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate index = popc(bit - 1); 15677c478bd9Sstevel@tonic-gate tot += (n = strlcpy(buf, content_str[index], size)); 15687c478bd9Sstevel@tonic-gate if (n > size) 15697c478bd9Sstevel@tonic-gate n = size; 15707c478bd9Sstevel@tonic-gate buf += n; 15717c478bd9Sstevel@tonic-gate size -= n; 15727c478bd9Sstevel@tonic-gate 15737c478bd9Sstevel@tonic-gate mask ^= bit; 15747c478bd9Sstevel@tonic-gate first = 0; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate 15777c478bd9Sstevel@tonic-gate return ((int)tot); 15787c478bd9Sstevel@tonic-gate } 1579