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 2021 Oxide Computer Company
  32  */
  33 
  34 #define _STRUCTURED_PROC        1
  35 
  36 #include <assert.h>
  37 #include <stdlib.h>
  38 #include <ctype.h>
  39 #include <string.h>
  40 #include <strings.h>
  41 #include <errno.h>
  42 #include <procfs.h>
  43 #include <priv.h>
  44 #include <sys/elf.h>
  45 #include <sys/machelf.h>
  46 #include <sys/sysmacros.h>
  47 #include <sys/systeminfo.h>
  48 #include <sys/proc.h>
  49 #include <sys/utsname.h>
  50 #include <core_shstrtab.h>
  51 
  52 #include <sys/old_procfs.h>
  53 
  54 #include "Pcontrol.h"
  55 #include "P32ton.h"
  56 #include "proc_fd.h"
  57 
  58 typedef struct {
  59         struct ps_prochandle *P;
  60         int             pgc_fd;
  61         off64_t         *pgc_poff;
  62         off64_t         *pgc_soff;
  63         off64_t         *pgc_doff;
  64         core_content_t  pgc_content;
  65         void            *pgc_chunk;
  66         size_t          pgc_chunksz;
  67 
  68         shstrtab_t      pgc_shstrtab;
  69 } pgcore_t;
  70 
  71 typedef struct {
  72         int             fd_fd;
  73         off64_t         *fd_doff;
  74 } fditer_t;
  75 
  76 static int
  77 gc_pwrite64(int fd, const void *buf, size_t len, off64_t off)
  78 {
  79         int err;
  80 
  81         err = pwrite64(fd, buf, len, off);
  82 
  83         if (err < 0)
  84                 return (err);
  85 
  86         /*
  87          * We will take a page from ZFS's book here and use the otherwise
  88          * unused EBADE to mean a short write.  Typically this will actually
  89          * result from ENOSPC or EDQUOT, but we can't be sure.
  90          */
  91         if (err < len) {
  92                 errno = EBADE;
  93                 return (-1);
  94         }
  95 
  96         return (0);
  97 }
  98 
  99 int
 100 Pgcore(struct ps_prochandle *P, const char *fname, core_content_t content)
 101 {
 102         int fd;
 103         int err;
 104         int saved_errno;
 105 
 106         if ((fd = creat64(fname, 0666)) < 0)
 107                 return (-1);
 108 
 109         if ((err = Pfgcore(P, fd, content)) != 0) {
 110                 saved_errno = errno;
 111                 (void) close(fd);
 112                 (void) unlink(fname);
 113                 errno = saved_errno;
 114                 return (err);
 115         }
 116 
 117         return (close(fd));
 118 }
 119 
 120 /*
 121  * Since we don't want to use the old-school procfs interfaces, we use the
 122  * new-style data structures we already have to construct the old-style
 123  * data structures. We include these data structures in core files for
 124  * backward compatability.
 125  */
 126 
 127 static void
 128 mkprstatus(struct ps_prochandle *P, const lwpstatus_t *lsp,
 129     const lwpsinfo_t *lip, prstatus_t *psp)
 130 {
 131         bzero(psp, sizeof (*psp));
 132 
 133         if (lsp->pr_flags & PR_STOPPED)
 134                 psp->pr_flags = 0x0001;
 135         if (lsp->pr_flags & PR_ISTOP)
 136                 psp->pr_flags = 0x0002;
 137         if (lsp->pr_flags & PR_DSTOP)
 138                 psp->pr_flags = 0x0004;
 139         if (lsp->pr_flags & PR_ASLEEP)
 140                 psp->pr_flags = 0x0008;
 141         if (lsp->pr_flags & PR_FORK)
 142                 psp->pr_flags = 0x0010;
 143         if (lsp->pr_flags & PR_RLC)
 144                 psp->pr_flags = 0x0020;
 145         /*
 146          * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
 147          * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>.
 148          */
 149         if (lsp->pr_flags & PR_PCINVAL)
 150                 psp->pr_flags = 0x0080;
 151         if (lsp->pr_flags & PR_ISSYS)
 152                 psp->pr_flags = 0x0100;
 153         if (lsp->pr_flags & PR_STEP)
 154                 psp->pr_flags = 0x0200;
 155         if (lsp->pr_flags & PR_KLC)
 156                 psp->pr_flags = 0x0400;
 157         if (lsp->pr_flags & PR_ASYNC)
 158                 psp->pr_flags = 0x0800;
 159         if (lsp->pr_flags & PR_PTRACE)
 160                 psp->pr_flags = 0x1000;
 161         if (lsp->pr_flags & PR_MSACCT)
 162                 psp->pr_flags = 0x2000;
 163         if (lsp->pr_flags & PR_BPTADJ)
 164                 psp->pr_flags = 0x4000;
 165         if (lsp->pr_flags & PR_ASLWP)
 166                 psp->pr_flags = 0x8000;
 167 
 168         psp->pr_why = lsp->pr_why;
 169         psp->pr_what = lsp->pr_what;
 170         psp->pr_info = lsp->pr_info;
 171         psp->pr_cursig = lsp->pr_cursig;
 172         psp->pr_nlwp = P->status.pr_nlwp;
 173         psp->pr_sigpend = P->status.pr_sigpend;
 174         psp->pr_sighold = lsp->pr_lwphold;
 175         psp->pr_altstack = lsp->pr_altstack;
 176         psp->pr_action = lsp->pr_action;
 177         psp->pr_pid = P->status.pr_pid;
 178         psp->pr_ppid = P->status.pr_ppid;
 179         psp->pr_pgrp = P->status.pr_pgid;
 180         psp->pr_sid = P->status.pr_sid;
 181         psp->pr_utime = P->status.pr_utime;
 182         psp->pr_stime = P->status.pr_stime;
 183         psp->pr_cutime = P->status.pr_cutime;
 184         psp->pr_cstime = P->status.pr_cstime;
 185         (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname));
 186         psp->pr_syscall = lsp->pr_syscall;
 187         psp->pr_nsysarg = lsp->pr_nsysarg;
 188         bcopy(lsp->pr_sysarg, psp->pr_sysarg, sizeof (psp->pr_sysarg));
 189         psp->pr_who = lsp->pr_lwpid;
 190         psp->pr_lwppend = lsp->pr_lwppend;
 191         psp->pr_oldcontext = (ucontext_t *)lsp->pr_oldcontext;
 192         psp->pr_brkbase = (caddr_t)P->status.pr_brkbase;
 193         psp->pr_brksize = P->status.pr_brksize;
 194         psp->pr_stkbase = (caddr_t)P->status.pr_stkbase;
 195         psp->pr_stksize = P->status.pr_stksize;
 196         psp->pr_processor = (short)lip->pr_onpro;
 197         psp->pr_bind = (short)lip->pr_bindpro;
 198         psp->pr_instr = lsp->pr_instr;
 199         bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg));
 200 }
 201 
 202 static void
 203 mkprpsinfo(struct ps_prochandle *P, prpsinfo_t *psp)
 204 {
 205         bzero(psp, sizeof (*psp));
 206         psp->pr_state = P->psinfo.pr_lwp.pr_state;
 207         psp->pr_sname = P->psinfo.pr_lwp.pr_sname;
 208         psp->pr_zomb = (psp->pr_state == SZOMB);
 209         psp->pr_nice = P->psinfo.pr_lwp.pr_nice;
 210         psp->pr_flag = P->psinfo.pr_lwp.pr_flag;
 211         psp->pr_uid = P->psinfo.pr_uid;
 212         psp->pr_gid = P->psinfo.pr_gid;
 213         psp->pr_pid = P->psinfo.pr_pid;
 214         psp->pr_ppid = P->psinfo.pr_ppid;
 215         psp->pr_pgrp = P->psinfo.pr_pgid;
 216         psp->pr_sid = P->psinfo.pr_sid;
 217         psp->pr_addr = (caddr_t)P->psinfo.pr_addr;
 218         psp->pr_size = P->psinfo.pr_size;
 219         psp->pr_rssize = P->psinfo.pr_rssize;
 220         psp->pr_wchan = (caddr_t)P->psinfo.pr_lwp.pr_wchan;
 221         psp->pr_start = P->psinfo.pr_start;
 222         psp->pr_time = P->psinfo.pr_time;
 223         psp->pr_pri = P->psinfo.pr_lwp.pr_pri;
 224         psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri;
 225         psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu;
 226         psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev);
 227         psp->pr_lttydev = P->psinfo.pr_ttydev;
 228         (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname,
 229             sizeof (psp->pr_clname));
 230         (void) strncpy(psp->pr_fname, P->psinfo.pr_fname,
 231             sizeof (psp->pr_fname));
 232         bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs,
 233             sizeof (psp->pr_psargs));
 234         psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall;
 235         psp->pr_ctime = P->psinfo.pr_ctime;
 236         psp->pr_bysize = psp->pr_size * PAGESIZE;
 237         psp->pr_byrssize = psp->pr_rssize * PAGESIZE;
 238         psp->pr_argc = P->psinfo.pr_argc;
 239         psp->pr_argv = (char **)P->psinfo.pr_argv;
 240         psp->pr_envp = (char **)P->psinfo.pr_envp;
 241         psp->pr_wstat = P->psinfo.pr_wstat;
 242         psp->pr_pctcpu = P->psinfo.pr_pctcpu;
 243         psp->pr_pctmem = P->psinfo.pr_pctmem;
 244         psp->pr_euid = P->psinfo.pr_euid;
 245         psp->pr_egid = P->psinfo.pr_egid;
 246         psp->pr_aslwpid = 0;
 247         psp->pr_dmodel = P->psinfo.pr_dmodel;
 248 }
 249 
 250 #ifdef _LP64
 251 
 252 static void
 253 mkprstatus32(struct ps_prochandle *P, const lwpstatus_t *lsp,
 254     const lwpsinfo_t *lip, prstatus32_t *psp)
 255 {
 256         bzero(psp, sizeof (*psp));
 257 
 258         if (lsp->pr_flags & PR_STOPPED)
 259                 psp->pr_flags = 0x0001;
 260         if (lsp->pr_flags & PR_ISTOP)
 261                 psp->pr_flags = 0x0002;
 262         if (lsp->pr_flags & PR_DSTOP)
 263                 psp->pr_flags = 0x0004;
 264         if (lsp->pr_flags & PR_ASLEEP)
 265                 psp->pr_flags = 0x0008;
 266         if (lsp->pr_flags & PR_FORK)
 267                 psp->pr_flags = 0x0010;
 268         if (lsp->pr_flags & PR_RLC)
 269                 psp->pr_flags = 0x0020;
 270         /*
 271          * Note that PR_PTRACE (0x0040) from <sys/old_procfs.h> is never set;
 272          * PR_PCOMPAT corresponds to PR_PTRACE in the newer <sys/procfs.h>.
 273          */
 274         if (lsp->pr_flags & PR_PCINVAL)
 275                 psp->pr_flags = 0x0080;
 276         if (lsp->pr_flags & PR_ISSYS)
 277                 psp->pr_flags = 0x0100;
 278         if (lsp->pr_flags & PR_STEP)
 279                 psp->pr_flags = 0x0200;
 280         if (lsp->pr_flags & PR_KLC)
 281                 psp->pr_flags = 0x0400;
 282         if (lsp->pr_flags & PR_ASYNC)
 283                 psp->pr_flags = 0x0800;
 284         if (lsp->pr_flags & PR_PTRACE)
 285                 psp->pr_flags = 0x1000;
 286         if (lsp->pr_flags & PR_MSACCT)
 287                 psp->pr_flags = 0x2000;
 288         if (lsp->pr_flags & PR_BPTADJ)
 289                 psp->pr_flags = 0x4000;
 290         if (lsp->pr_flags & PR_ASLWP)
 291                 psp->pr_flags = 0x8000;
 292 
 293         psp->pr_why = lsp->pr_why;
 294         psp->pr_what = lsp->pr_what;
 295         siginfo_n_to_32(&lsp->pr_info, &psp->pr_info);
 296         psp->pr_cursig = lsp->pr_cursig;
 297         psp->pr_nlwp = P->status.pr_nlwp;
 298         psp->pr_sigpend = P->status.pr_sigpend;
 299         psp->pr_sighold = lsp->pr_lwphold;
 300         stack_n_to_32(&lsp->pr_altstack, &psp->pr_altstack);
 301         sigaction_n_to_32(&lsp->pr_action, &psp->pr_action);
 302         psp->pr_pid = P->status.pr_pid;
 303         psp->pr_ppid = P->status.pr_ppid;
 304         psp->pr_pgrp = P->status.pr_pgid;
 305         psp->pr_sid = P->status.pr_sid;
 306         timestruc_n_to_32(&P->status.pr_utime, &psp->pr_utime);
 307         timestruc_n_to_32(&P->status.pr_stime, &psp->pr_stime);
 308         timestruc_n_to_32(&P->status.pr_cutime, &psp->pr_cutime);
 309         timestruc_n_to_32(&P->status.pr_cstime, &psp->pr_cstime);
 310         (void) strncpy(psp->pr_clname, lsp->pr_clname, sizeof (psp->pr_clname));
 311         psp->pr_syscall = lsp->pr_syscall;
 312         psp->pr_nsysarg = lsp->pr_nsysarg;
 313         bcopy(lsp->pr_sysarg, psp->pr_sysarg, sizeof (psp->pr_sysarg));
 314         psp->pr_who = lsp->pr_lwpid;
 315         psp->pr_lwppend = lsp->pr_lwppend;
 316         psp->pr_oldcontext = (caddr32_t)lsp->pr_oldcontext;
 317         psp->pr_brkbase = (caddr32_t)P->status.pr_brkbase;
 318         psp->pr_brksize = P->status.pr_brksize;
 319         psp->pr_stkbase = (caddr32_t)P->status.pr_stkbase;
 320         psp->pr_stksize = P->status.pr_stksize;
 321         psp->pr_processor = (short)lip->pr_onpro;
 322         psp->pr_bind = (short)lip->pr_bindpro;
 323         psp->pr_instr = lsp->pr_instr;
 324         bcopy(lsp->pr_reg, psp->pr_reg, sizeof (psp->pr_sysarg));
 325 }
 326 
 327 static void
 328 mkprpsinfo32(struct ps_prochandle *P, prpsinfo32_t *psp)
 329 {
 330         bzero(psp, sizeof (*psp));
 331         psp->pr_state = P->psinfo.pr_lwp.pr_state;
 332         psp->pr_sname = P->psinfo.pr_lwp.pr_sname;
 333         psp->pr_zomb = (psp->pr_state == SZOMB);
 334         psp->pr_nice = P->psinfo.pr_lwp.pr_nice;
 335         psp->pr_flag = P->psinfo.pr_lwp.pr_flag;
 336         psp->pr_uid = P->psinfo.pr_uid;
 337         psp->pr_gid = P->psinfo.pr_gid;
 338         psp->pr_pid = P->psinfo.pr_pid;
 339         psp->pr_ppid = P->psinfo.pr_ppid;
 340         psp->pr_pgrp = P->psinfo.pr_pgid;
 341         psp->pr_sid = P->psinfo.pr_sid;
 342         psp->pr_addr = (caddr32_t)P->psinfo.pr_addr;
 343         psp->pr_size = P->psinfo.pr_size;
 344         psp->pr_rssize = P->psinfo.pr_rssize;
 345         psp->pr_wchan = (caddr32_t)P->psinfo.pr_lwp.pr_wchan;
 346         timestruc_n_to_32(&P->psinfo.pr_start, &psp->pr_start);
 347         timestruc_n_to_32(&P->psinfo.pr_time, &psp->pr_time);
 348         psp->pr_pri = P->psinfo.pr_lwp.pr_pri;
 349         psp->pr_oldpri = P->psinfo.pr_lwp.pr_oldpri;
 350         psp->pr_cpu = P->psinfo.pr_lwp.pr_cpu;
 351         psp->pr_ottydev = cmpdev(P->psinfo.pr_ttydev);
 352         psp->pr_lttydev = prcmpldev(P->psinfo.pr_ttydev);
 353         (void) strncpy(psp->pr_clname, P->psinfo.pr_lwp.pr_clname,
 354             sizeof (psp->pr_clname));
 355         (void) strncpy(psp->pr_fname, P->psinfo.pr_fname,
 356             sizeof (psp->pr_fname));
 357         bcopy(&P->psinfo.pr_psargs, &psp->pr_psargs,
 358             sizeof (psp->pr_psargs));
 359         psp->pr_syscall = P->psinfo.pr_lwp.pr_syscall;
 360         timestruc_n_to_32(&P->psinfo.pr_ctime, &psp->pr_ctime);
 361         psp->pr_bysize = psp->pr_size * PAGESIZE;
 362         psp->pr_byrssize = psp->pr_rssize * PAGESIZE;
 363         psp->pr_argc = P->psinfo.pr_argc;
 364         psp->pr_argv = (caddr32_t)P->psinfo.pr_argv;
 365         psp->pr_envp = (caddr32_t)P->psinfo.pr_envp;
 366         psp->pr_wstat = P->psinfo.pr_wstat;
 367         psp->pr_pctcpu = P->psinfo.pr_pctcpu;
 368         psp->pr_pctmem = P->psinfo.pr_pctmem;
 369         psp->pr_euid = P->psinfo.pr_euid;
 370         psp->pr_egid = P->psinfo.pr_egid;
 371         psp->pr_aslwpid = 0;
 372         psp->pr_dmodel = P->psinfo.pr_dmodel;
 373 }
 374 
 375 #endif  /* _LP64 */
 376 
 377 static int
 378 write_note(int fd, uint_t type, const void *desc, size_t descsz, off64_t *offp)
 379 {
 380         /*
 381          * Note headers are the same regardless of the data model of the
 382          * ELF file; we arbitrarily use Elf64_Nhdr here.
 383          */
 384         struct {
 385                 Elf64_Nhdr nhdr;
 386                 char name[8];
 387         } n;
 388 
 389         bzero(&n, sizeof (n));
 390         bcopy("CORE", n.name, 4);
 391         n.nhdr.n_type = type;
 392         n.nhdr.n_namesz = 5;
 393         n.nhdr.n_descsz = roundup(descsz, 4);
 394 
 395         if (gc_pwrite64(fd, &n, sizeof (n), *offp) != 0)
 396                 return (-1);
 397 
 398         *offp += sizeof (n);
 399 
 400         if (gc_pwrite64(fd, desc, n.nhdr.n_descsz, *offp) != 0)
 401                 return (-1);
 402 
 403         *offp += n.nhdr.n_descsz;
 404 
 405         return (0);
 406 }
 407 
 408 static int
 409 old_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
 410 {
 411         pgcore_t *pgc = data;
 412         struct ps_prochandle *P = pgc->P;
 413 
 414         /*
 415          * Legacy core files don't contain information about zombie LWPs.
 416          * We use Plwp_iter_all() so that we get the lwpsinfo_t structure
 417          * more cheaply.
 418          */
 419         if (lsp == NULL)
 420                 return (0);
 421 
 422         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
 423                 prstatus_t prstatus;
 424                 mkprstatus(P, lsp, lip, &prstatus);
 425                 if (write_note(pgc->pgc_fd, NT_PRSTATUS, &prstatus,
 426                     sizeof (prstatus_t), pgc->pgc_doff) != 0)
 427                         return (0);
 428                 if (write_note(pgc->pgc_fd, NT_PRFPREG, &lsp->pr_fpreg,
 429                     sizeof (prfpregset_t), pgc->pgc_doff) != 0)
 430                         return (1);
 431 #ifdef _LP64
 432         } else {
 433                 prstatus32_t pr32;
 434                 prfpregset32_t pf32;
 435                 mkprstatus32(P, lsp, lip, &pr32);
 436                 if (write_note(pgc->pgc_fd, NT_PRSTATUS, &pr32,
 437                     sizeof (prstatus32_t), pgc->pgc_doff) != 0)
 438                         return (1);
 439                 prfpregset_n_to_32(&lsp->pr_fpreg, &pf32);
 440                 if (write_note(pgc->pgc_fd, NT_PRFPREG, &pf32,
 441                     sizeof (prfpregset32_t), pgc->pgc_doff) != 0)
 442                         return (1);
 443 #endif  /* _LP64 */
 444         }
 445 
 446 #ifdef sparc
 447         {
 448                 prxregset_t xregs;
 449                 if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0 &&
 450                     write_note(pgc->pgc_fd, NT_PRXREG, &xregs,
 451                     sizeof (prxregset_t), pgc->pgc_doff) != 0)
 452                         return (1);
 453         }
 454 #endif  /* sparc */
 455 
 456         return (0);
 457 }
 458 
 459 static int
 460 new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip)
 461 {
 462         pgcore_t *pgc = data;
 463         struct ps_prochandle *P = pgc->P;
 464         prlwpname_t name = { 0, "" };
 465         psinfo_t ps;
 466 
 467         /*
 468          * If lsp is NULL this indicates that this is a zombie LWP in
 469          * which case we dump only the lwpsinfo_t structure and none of
 470          * the other ancillary LWP state data.
 471          */
 472         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
 473                 if (write_note(pgc->pgc_fd, NT_LWPSINFO, lip,
 474                     sizeof (lwpsinfo_t), pgc->pgc_doff) != 0)
 475                         return (1);
 476                 if (lsp == NULL)
 477                         return (0);
 478                 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, lsp,
 479                     sizeof (lwpstatus_t), pgc->pgc_doff) != 0)
 480                         return (1);
 481 #ifdef _LP64
 482         } else {
 483                 lwpsinfo32_t li32;
 484                 lwpstatus32_t ls32;
 485                 lwpsinfo_n_to_32(lip, &li32);
 486                 if (write_note(pgc->pgc_fd, NT_LWPSINFO, &li32,
 487                     sizeof (lwpsinfo32_t), pgc->pgc_doff) != 0)
 488                         return (1);
 489                 if (lsp == NULL)
 490                         return (0);
 491                 lwpstatus_n_to_32(lsp, &ls32);
 492                 if (write_note(pgc->pgc_fd, NT_LWPSTATUS, &ls32,
 493                     sizeof (lwpstatus32_t), pgc->pgc_doff) != 0)
 494                         return (1);
 495 #endif  /* _LP64 */
 496         }
 497 
 498 #ifdef sparc
 499         {
 500                 prxregset_t xregs;
 501                 gwindows_t gwins;
 502                 size_t size;
 503 
 504                 if (Plwp_getxregs(P, lsp->pr_lwpid, &xregs) == 0) {
 505                         if (write_note(pgc->pgc_fd, NT_PRXREG, &xregs,
 506                             sizeof (prxregset_t), pgc->pgc_doff) != 0)
 507                                 return (1);
 508                 }
 509 
 510                 if (Plwp_getgwindows(P, lsp->pr_lwpid, &gwins) == 0 &&
 511                     gwins.wbcnt > 0) {
 512                         size = sizeof (gwins) - sizeof (gwins.wbuf) +
 513                             gwins.wbcnt * sizeof (gwins.wbuf[0]);
 514 
 515                         if (write_note(pgc->pgc_fd, NT_GWINDOWS, &gwins, size,
 516                             pgc->pgc_doff) != 0)
 517                                 return (1);
 518                 }
 519 
 520         }
 521 #ifdef __sparcv9
 522         if (P->status.pr_dmodel == PR_MODEL_LP64) {
 523                 asrset_t asrs;
 524                 if (Plwp_getasrs(P, lsp->pr_lwpid, asrs) == 0) {
 525                         if (write_note(pgc->pgc_fd, NT_ASRS, &asrs,
 526                             sizeof (asrset_t), pgc->pgc_doff) != 0)
 527                                 return (1);
 528                 }
 529         }
 530 #endif  /* __sparcv9 */
 531 #endif  /* sparc */
 532 
 533         if (Plwp_getname(P, lsp->pr_lwpid, name.pr_lwpname,
 534             sizeof (name.pr_lwpname)) == 0) {
 535                 name.pr_lwpid = lsp->pr_lwpid;
 536                 if (write_note(pgc->pgc_fd, NT_LWPNAME, &name,
 537                     sizeof (name), pgc->pgc_doff) != 0)
 538                         return (1);
 539         }
 540 
 541         if (!(lsp->pr_flags & PR_AGENT))
 542                 return (0);
 543 
 544         if (Plwp_getspymaster(P, lsp->pr_lwpid, &ps) != 0)
 545                 return (0);
 546 
 547         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
 548                 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps,
 549                     sizeof (psinfo_t), pgc->pgc_doff) != 0)
 550                         return (1);
 551 #ifdef _LP64
 552         } else {
 553                 psinfo32_t ps32;
 554                 psinfo_n_to_32(&ps, &ps32);
 555                 if (write_note(pgc->pgc_fd, NT_SPYMASTER, &ps32,
 556                     sizeof (psinfo32_t), pgc->pgc_doff) != 0)
 557                         return (1);
 558 #endif  /* _LP64 */
 559         }
 560 
 561 
 562         return (0);
 563 }
 564 
 565 static int
 566 iter_fd(void *data, const prfdinfo_t *fdinfo)
 567 {
 568         fditer_t *iter = data;
 569         prfdinfo_core_t core;
 570         int ret = 0;
 571 
 572         if (proc_fdinfo_to_core(fdinfo, &core) != 0)
 573                 return (1);
 574 
 575         ret = write_note(iter->fd_fd, NT_FDINFO, &core,
 576             sizeof (core), iter->fd_doff);
 577 
 578         if (ret != 0)
 579                 return (1);
 580         return (0);
 581 }
 582 
 583 /*
 584  * Look for sections that begin with the string '.debug_'. In particular, this
 585  * will catch all DWARF related sections and it will catch those that different
 586  * folks use that are not related to DWARF, but still begin with this prefix
 587  * (e.g. .debug_gdb_scripts). Notably though, this does not catch something like
 588  * stabs (though it could). This really is filtering based on the section name,
 589  * less so intent.
 590  */
 591 static boolean_t
 592 is_debug_section(file_info_t *fptr, GElf_Shdr *shdr)
 593 {
 594         if (shdr->sh_name == 0 || shdr->sh_name > fptr->file_shstrsz)
 595                 return (B_FALSE);
 596 
 597         if (strncmp(fptr->file_shstrs + shdr->sh_name, ".debug_",
 598             strlen(".debug_")) != 0) {
 599                 return (B_FALSE);
 600         }
 601 
 602         return (B_TRUE);
 603 }
 604 
 605 static uint_t
 606 count_debug(file_info_t *fptr)
 607 {
 608         uint_t count = 0;
 609         Elf_Scn *scn = NULL;
 610 
 611         if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) {
 612                 return (0);
 613         }
 614 
 615         while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) {
 616                 GElf_Shdr shdr;
 617 
 618                 if (gelf_getshdr(scn, &shdr) == NULL)
 619                         continue;
 620 
 621                 if (is_debug_section(fptr, &shdr))
 622                         count++;
 623         }
 624 
 625         return (count);
 626 }
 627 
 628 static uint_t
 629 count_sections(pgcore_t *pgc)
 630 {
 631         struct ps_prochandle *P = pgc->P;
 632         file_info_t *fptr;
 633         uint_t nshdrs = 0;
 634 
 635         if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB |
 636             CC_CONTENT_DEBUG))) {
 637                 return (0);
 638         }
 639 
 640         for (fptr = list_head(&P->file_head); fptr != NULL;
 641             fptr = list_next(&P->file_head, fptr)) {
 642                 int hit_symtab = 0;
 643 
 644                 Pbuild_file_symtab(P, fptr);
 645 
 646                 if ((pgc->pgc_content & CC_CONTENT_CTF) &&
 647                     Pbuild_file_ctf(P, fptr) != NULL) {
 648                         sym_tbl_t *sym;
 649 
 650                         nshdrs++;
 651 
 652                         if (fptr->file_ctf_dyn) {
 653                                 sym = &fptr->file_dynsym;
 654                         } else {
 655                                 sym = &fptr->file_symtab;
 656                                 hit_symtab = 1;
 657                         }
 658 
 659                         if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
 660                             sym->sym_strs != NULL)
 661                                 nshdrs += 2;
 662                 }
 663 
 664                 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
 665                     fptr->file_symtab.sym_data_pri != NULL &&
 666                     fptr->file_symtab.sym_symn != 0 &&
 667                     fptr->file_symtab.sym_strs != NULL) {
 668                         nshdrs += 2;
 669                 }
 670 
 671                 if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0)
 672                         nshdrs += count_debug(fptr);
 673         }
 674 
 675         return (nshdrs == 0 ? 0 : nshdrs + 2);
 676 }
 677 
 678 static int
 679 write_shdr(pgcore_t *pgc, const char *name, uint_t type, ulong_t flags,
 680     uintptr_t addr, ulong_t offset, size_t size, uint_t link, uint_t info,
 681     uintptr_t addralign, uintptr_t entsize)
 682 {
 683         if (pgc->P->status.pr_dmodel == PR_MODEL_ILP32) {
 684                 Elf32_Shdr shdr;
 685 
 686                 bzero(&shdr, sizeof (shdr));
 687                 if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) {
 688                         return (-1);
 689                 }
 690                 shdr.sh_type = type;
 691                 shdr.sh_flags = flags;
 692                 shdr.sh_addr = (Elf32_Addr)addr;
 693                 shdr.sh_offset = offset;
 694                 shdr.sh_size = size;
 695                 shdr.sh_link = link;
 696                 shdr.sh_info = info;
 697                 shdr.sh_addralign = addralign;
 698                 shdr.sh_entsize = entsize;
 699 
 700                 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
 701                     *pgc->pgc_soff) != 0)
 702                         return (-1);
 703 
 704                 *pgc->pgc_soff += sizeof (shdr);
 705 #ifdef _LP64
 706         } else {
 707                 Elf64_Shdr shdr;
 708 
 709                 bzero(&shdr, sizeof (shdr));
 710                 if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) {
 711                         return (-1);
 712                 }
 713                 shdr.sh_type = type;
 714                 shdr.sh_flags = flags;
 715                 shdr.sh_addr = addr;
 716                 shdr.sh_offset = offset;
 717                 shdr.sh_size = size;
 718                 shdr.sh_link = link;
 719                 shdr.sh_info = info;
 720                 shdr.sh_addralign = addralign;
 721                 shdr.sh_entsize = entsize;
 722 
 723                 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
 724                     *pgc->pgc_soff) != 0)
 725                         return (-1);
 726 
 727                 *pgc->pgc_soff += sizeof (shdr);
 728 #endif  /* _LP64 */
 729         }
 730 
 731         return (0);
 732 }
 733 
 734 static int
 735 dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
 736 {
 737         sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab;
 738         shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB;
 739         shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB;
 740         uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB;
 741         size_t size;
 742         uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr;
 743 
 744         if (sym->sym_data_pri == NULL || sym->sym_symn == 0 ||
 745             sym->sym_strs == NULL)
 746                 return (0);
 747 
 748         size = sym->sym_hdr_pri.sh_size;
 749         if (gc_pwrite64(pgc->pgc_fd, sym->sym_data_pri->d_buf, size,
 750             *pgc->pgc_doff) != 0)
 751                 return (-1);
 752 
 753         if (write_shdr(pgc, shstrtab_data[symname], symtype, 0, addr,
 754             *pgc->pgc_doff, size, index + 1, sym->sym_hdr_pri.sh_info,
 755             sym->sym_hdr_pri.sh_addralign, sym->sym_hdr_pri.sh_entsize) != 0)
 756                 return (-1);
 757 
 758         *pgc->pgc_doff += roundup(size, 8);
 759 
 760         size = sym->sym_strhdr.sh_size;
 761         if (gc_pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != 0)
 762                 return (-1);
 763 
 764         if (write_shdr(pgc, shstrtab_data[strname], SHT_STRTAB, SHF_STRINGS,
 765             addr, *pgc->pgc_doff, size, 0, 0, 1, 0) != 0)
 766                 return (-1);
 767 
 768         *pgc->pgc_doff += roundup(size, 8);
 769 
 770         return (0);
 771 }
 772 
 773 static int
 774 dump_debug(pgcore_t *pgc, file_info_t *fptr, uint_t *indexp)
 775 {
 776         Elf_Scn *scn = NULL;
 777 
 778         if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) {
 779                 return (0);
 780         }
 781 
 782         while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) {
 783                 GElf_Shdr shdr;
 784                 Elf_Data *data;
 785 
 786                 if (gelf_getshdr(scn, &shdr) == NULL)
 787                         continue;
 788 
 789                 if (!is_debug_section(fptr, &shdr))
 790                         continue;
 791 
 792                 if ((data = elf_getdata(scn, NULL)) == NULL) {
 793                         return (-1);
 794                 }
 795 
 796                 if (gc_pwrite64(pgc->pgc_fd, data->d_buf, data->d_size,
 797                     *pgc->pgc_doff) != 0)
 798                         return (-1);
 799 
 800                 if (write_shdr(pgc, fptr->file_shstrs + shdr.sh_name,
 801                     shdr.sh_type, shdr.sh_flags,
 802                     fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff,
 803                     data->d_size, 0, shdr.sh_info, shdr.sh_addralign,
 804                     shdr.sh_entsize) != 0) {
 805                         return (-1);
 806                 }
 807 
 808                 *indexp = *indexp + 1;
 809                 *pgc->pgc_doff += roundup(data->d_size, 8);
 810         }
 811 
 812         return (0);
 813 }
 814 
 815 static int
 816 dump_sections(pgcore_t *pgc)
 817 {
 818         struct ps_prochandle *P = pgc->P;
 819         file_info_t *fptr;
 820         uint_t index = 1;
 821 
 822         if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB |
 823             CC_CONTENT_DEBUG))) {
 824                 return (0);
 825         }
 826 
 827         for (fptr = list_head(&P->file_head); fptr != NULL;
 828             fptr = list_next(&P->file_head, fptr)) {
 829                 int hit_symtab = 0;
 830 
 831                 Pbuild_file_symtab(P, fptr);
 832 
 833                 if ((pgc->pgc_content & CC_CONTENT_CTF) &&
 834                     Pbuild_file_ctf(P, fptr) != NULL) {
 835                         sym_tbl_t *sym;
 836                         uint_t dynsym;
 837                         uint_t symindex = 0;
 838 
 839                         /*
 840                          * Write the symtab out first so we can correctly
 841                          * set the sh_link field in the CTF section header.
 842                          * symindex will be 0 if there is no corresponding
 843                          * symbol table section.
 844                          */
 845                         if (fptr->file_ctf_dyn) {
 846                                 sym = &fptr->file_dynsym;
 847                                 dynsym = 1;
 848                         } else {
 849                                 sym = &fptr->file_symtab;
 850                                 dynsym = 0;
 851                                 hit_symtab = 1;
 852                         }
 853 
 854                         if (sym->sym_data_pri != NULL && sym->sym_symn != 0 &&
 855                             sym->sym_strs != NULL) {
 856                                 symindex = index;
 857                                 if (dump_symtab(pgc, fptr, index, dynsym) != 0)
 858                                         return (-1);
 859                                 index += 2;
 860                         }
 861 
 862                         /*
 863                          * Write the CTF data that we've read out of the
 864                          * file itself into the core file.
 865                          */
 866                         if (gc_pwrite64(pgc->pgc_fd, fptr->file_ctf_buf,
 867                             fptr->file_ctf_size, *pgc->pgc_doff) != 0)
 868                                 return (-1);
 869 
 870                         if (write_shdr(pgc, shstrtab_data[STR_CTF],
 871                             SHT_PROGBITS, 0, fptr->file_map->map_pmap.pr_vaddr,
 872                             *pgc->pgc_doff, fptr->file_ctf_size, symindex, 0,
 873                             4, 0) != 0)
 874                                 return (-1);
 875 
 876                         index++;
 877                         *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8);
 878                 }
 879 
 880                 if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab &&
 881                     fptr->file_symtab.sym_data_pri != NULL &&
 882                     fptr->file_symtab.sym_symn != 0 &&
 883                     fptr->file_symtab.sym_strs != NULL) {
 884                         if (dump_symtab(pgc, fptr, index, 0) != 0)
 885                                 return (-1);
 886                         index += 2;
 887                 }
 888 
 889                 if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0 &&
 890                     dump_debug(pgc, fptr, &index) != 0) {
 891                         return (-1);
 892                 }
 893         }
 894 
 895         return (0);
 896 }
 897 
 898 /*ARGSUSED*/
 899 static int
 900 dump_map(void *data, const prmap_t *pmp, const char *name)
 901 {
 902         pgcore_t *pgc = data;
 903         struct ps_prochandle *P = pgc->P;
 904 #ifdef _LP64
 905         Elf64_Phdr phdr;
 906 #else
 907         Elf32_Phdr phdr;
 908 #endif
 909         size_t n;
 910 
 911         bzero(&phdr, sizeof (phdr));
 912         phdr.p_type = PT_LOAD;
 913         phdr.p_vaddr = pmp->pr_vaddr;
 914         phdr.p_memsz = pmp->pr_size;
 915         if (pmp->pr_mflags & MA_READ)
 916                 phdr.p_flags |= PF_R;
 917         if (pmp->pr_mflags & MA_WRITE)
 918                 phdr.p_flags |= PF_W;
 919         if (pmp->pr_mflags & MA_EXEC)
 920                 phdr.p_flags |= PF_X;
 921 
 922         if (pmp->pr_vaddr + pmp->pr_size > P->status.pr_stkbase &&
 923             pmp->pr_vaddr < P->status.pr_stkbase + P->status.pr_stksize) {
 924                 if (!(pgc->pgc_content & CC_CONTENT_STACK))
 925                         goto exclude;
 926 
 927         } else if ((pmp->pr_mflags & MA_ANON) &&
 928             pmp->pr_vaddr + pmp->pr_size > P->status.pr_brkbase &&
 929             pmp->pr_vaddr < P->status.pr_brkbase + P->status.pr_brksize) {
 930                 if (!(pgc->pgc_content & CC_CONTENT_HEAP))
 931                         goto exclude;
 932 
 933         } else if (pmp->pr_mflags & MA_ISM) {
 934                 if (pmp->pr_mflags & MA_NORESERVE) {
 935                         if (!(pgc->pgc_content & CC_CONTENT_DISM))
 936                                 goto exclude;
 937                 } else {
 938                         if (!(pgc->pgc_content & CC_CONTENT_ISM))
 939                                 goto exclude;
 940                 }
 941 
 942         } else if (pmp->pr_mflags & MA_SHM) {
 943                 if (!(pgc->pgc_content & CC_CONTENT_SHM))
 944                         goto exclude;
 945 
 946         } else if (pmp->pr_mflags & MA_SHARED) {
 947                 if (pmp->pr_mflags & MA_ANON) {
 948                         if (!(pgc->pgc_content & CC_CONTENT_SHANON))
 949                                 goto exclude;
 950                 } else {
 951                         if (!(pgc->pgc_content & CC_CONTENT_SHFILE))
 952                                 goto exclude;
 953                 }
 954 
 955         } else if (pmp->pr_mflags & MA_ANON) {
 956                 if (!(pgc->pgc_content & CC_CONTENT_ANON))
 957                         goto exclude;
 958 
 959         } else if (phdr.p_flags == (PF_R | PF_X)) {
 960                 if (!(pgc->pgc_content & CC_CONTENT_TEXT))
 961                         goto exclude;
 962 
 963         } else if (phdr.p_flags == PF_R) {
 964                 if (!(pgc->pgc_content & CC_CONTENT_RODATA))
 965                         goto exclude;
 966 
 967         } else {
 968                 if (!(pgc->pgc_content & CC_CONTENT_DATA))
 969                         goto exclude;
 970         }
 971 
 972         n = 0;
 973         while (n < pmp->pr_size) {
 974                 size_t csz = MIN(pmp->pr_size - n, pgc->pgc_chunksz);
 975                 ssize_t ret;
 976 
 977                 /*
 978                  * If we happen to have a PROT_NONE mapping, don't try to read
 979                  * from the address space.
 980                  */
 981                 if ((pmp->pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) == 0) {
 982                         bzero(pgc->pgc_chunk, csz);
 983                         ret = csz;
 984                 } else {
 985                         ret = Pread(P, pgc->pgc_chunk, csz, pmp->pr_vaddr + n);
 986                 }
 987 
 988                 /*
 989                  * If we can't read out part of the victim's address
 990                  * space for some reason ignore that failure and try to
 991                  * emit a partial core file without that mapping's data.
 992                  * As in the kernel, we mark these failures with the
 993                  * PF_SUNW_FAILURE flag and store the errno where the
 994                  * mapping would have been.
 995                  */
 996                 if (ret != csz || gc_pwrite64(pgc->pgc_fd, pgc->pgc_chunk, csz,
 997                     *pgc->pgc_doff + n) != 0) {
 998                         int err = errno;
 999                         (void) gc_pwrite64(pgc->pgc_fd, &err, sizeof (err),
1000                             *pgc->pgc_doff);
1001                         *pgc->pgc_doff += roundup(sizeof (err), 8);
1002 
1003                         phdr.p_flags |= PF_SUNW_FAILURE;
1004                         (void) ftruncate64(pgc->pgc_fd, *pgc->pgc_doff);
1005                         goto exclude;
1006                 }
1007 
1008                 n += csz;
1009         }
1010 
1011         phdr.p_offset = *pgc->pgc_doff;
1012         phdr.p_filesz = pmp->pr_size;
1013         *pgc->pgc_doff += roundup(phdr.p_filesz, 8);
1014 
1015 exclude:
1016         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
1017                 if (gc_pwrite64(pgc->pgc_fd, &phdr, sizeof (phdr),
1018                     *pgc->pgc_poff) != 0)
1019                         return (1);
1020 
1021                 *pgc->pgc_poff += sizeof (phdr);
1022 #ifdef _LP64
1023         } else {
1024                 Elf32_Phdr phdr32;
1025 
1026                 bzero(&phdr32, sizeof (phdr32));
1027                 phdr32.p_type = phdr.p_type;
1028                 phdr32.p_vaddr = (Elf32_Addr)phdr.p_vaddr;
1029                 phdr32.p_memsz = (Elf32_Word)phdr.p_memsz;
1030                 phdr32.p_flags = phdr.p_flags;
1031                 phdr32.p_offset = (Elf32_Off)phdr.p_offset;
1032                 phdr32.p_filesz = (Elf32_Word)phdr.p_filesz;
1033 
1034                 if (gc_pwrite64(pgc->pgc_fd, &phdr32, sizeof (phdr32),
1035                     *pgc->pgc_poff) != 0)
1036                         return (1);
1037 
1038                 *pgc->pgc_poff += sizeof (phdr32);
1039 #endif  /* _LP64 */
1040         }
1041 
1042         return (0);
1043 }
1044 
1045 int
1046 write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc)
1047 {
1048         off64_t off = *pgc->pgc_doff;
1049         size_t size = 0;
1050         shstrtab_t *s = &pgc->pgc_shstrtab;
1051 
1052         if (shstrtab_size(s) == 1)
1053                 return (0);
1054 
1055         /*
1056          * Preemptively stick the name of the shstrtab in the string table.
1057          */
1058         if (!shstrtab_ndx(&pgc->pgc_shstrtab,
1059             shstrtab_data[STR_SHSTRTAB], NULL)) {
1060                 return (1);
1061         }
1062         size = shstrtab_size(s);
1063 
1064         /*
1065          * Dump all the strings that we used being sure we include the
1066          * terminating null character.
1067          */
1068         for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL;
1069             ent = list_next(&s->sst_names, ent)) {
1070                 if (gc_pwrite64(pgc->pgc_fd, ent->sste_name, ent->sste_len,
1071                     off + ent->sste_offset) != 0) {
1072                         return (1);
1073                 }
1074         }
1075 
1076         if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1077                 Elf32_Shdr shdr;
1078 
1079                 bzero(&shdr, sizeof (shdr));
1080                 if (!shstrtab_ndx(&pgc->pgc_shstrtab,
1081                     shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) {
1082                         return (1);
1083                 }
1084                 shdr.sh_size = size;
1085                 shdr.sh_offset = *pgc->pgc_doff;
1086                 shdr.sh_addralign = 1;
1087                 shdr.sh_flags = SHF_STRINGS;
1088                 shdr.sh_type = SHT_STRTAB;
1089 
1090                 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
1091                     *pgc->pgc_soff) != 0)
1092                         return (1);
1093 
1094                 *pgc->pgc_soff += sizeof (shdr);
1095 #ifdef _LP64
1096         } else {
1097                 Elf64_Shdr shdr;
1098 
1099                 bzero(&shdr, sizeof (shdr));
1100                 if (!shstrtab_ndx(&pgc->pgc_shstrtab,
1101                     shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) {
1102                         return (1);
1103                 }
1104                 shdr.sh_size = size;
1105                 shdr.sh_offset = *pgc->pgc_doff;
1106                 shdr.sh_addralign = 1;
1107                 shdr.sh_flags = SHF_STRINGS;
1108                 shdr.sh_type = SHT_STRTAB;
1109 
1110                 if (gc_pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr),
1111                     *pgc->pgc_soff) != 0)
1112                         return (1);
1113 
1114                 *pgc->pgc_soff += sizeof (shdr);
1115 #endif  /* _LP64 */
1116         }
1117 
1118         *pgc->pgc_doff += roundup(size, 8);
1119 
1120         return (0);
1121 }
1122 
1123 /*
1124  * Don't explicity stop the process; that's up to the consumer.
1125  */
1126 int
1127 Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
1128 {
1129         char plat[SYS_NMLN];
1130         char zonename[ZONENAME_MAX];
1131         int platlen = -1;
1132         pgcore_t pgc;
1133         off64_t poff, soff, doff, boff;
1134         struct utsname uts;
1135         uint_t nphdrs, nshdrs;
1136 
1137         if (ftruncate64(fd, 0) != 0)
1138                 return (-1);
1139 
1140         if (content == CC_CONTENT_INVALID) {
1141                 errno = EINVAL;
1142                 return (-1);
1143         }
1144 
1145         /*
1146          * Cache the mappings and other useful data.
1147          */
1148         (void) Prd_agent(P);
1149         (void) Ppsinfo(P);
1150 
1151         (void) memset(&pgc, 0, sizeof (pgc));
1152         pgc.P = P;
1153         pgc.pgc_fd = fd;
1154         pgc.pgc_poff = &poff;
1155         pgc.pgc_soff = &soff;
1156         pgc.pgc_doff = &doff;
1157         pgc.pgc_content = content;
1158         pgc.pgc_chunksz = PAGESIZE;
1159         if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL)
1160                 return (-1);
1161 
1162         if (!shstrtab_init(&pgc.pgc_shstrtab)) {
1163                 goto err;
1164         }
1165 
1166         /*
1167          * There are two PT_NOTE program headers for ancillary data, and
1168          * one for each mapping.
1169          */
1170         nphdrs = 2 + P->map_count;
1171         nshdrs = count_sections(&pgc);
1172 
1173         (void) Pplatform(P, plat, sizeof (plat));
1174         platlen = strlen(plat) + 1;
1175         Preadauxvec(P);
1176         (void) Puname(P, &uts);
1177         if (Pzonename(P, zonename, sizeof (zonename)) == NULL)
1178                 zonename[0] = '\0';
1179 
1180         /*
1181          * The core file contents may required zero section headers, but if we
1182          * overflow the 16 bits allotted to the program header count in the ELF
1183          * header, we'll need that program header at index zero.
1184          */
1185         if (nshdrs == 0 && nphdrs >= PN_XNUM)
1186                 nshdrs = 1;
1187 
1188         /*
1189          * Set up the ELF header.
1190          */
1191         if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1192                 Elf32_Ehdr ehdr;
1193 
1194                 bzero(&ehdr, sizeof (ehdr));
1195                 ehdr.e_ident[EI_MAG0] = ELFMAG0;
1196                 ehdr.e_ident[EI_MAG1] = ELFMAG1;
1197                 ehdr.e_ident[EI_MAG2] = ELFMAG2;
1198                 ehdr.e_ident[EI_MAG3] = ELFMAG3;
1199                 ehdr.e_type = ET_CORE;
1200 
1201                 ehdr.e_ident[EI_CLASS] = ELFCLASS32;
1202 #if defined(__sparc)
1203                 ehdr.e_machine = EM_SPARC;
1204                 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
1205 #elif defined(__i386) || defined(__amd64)
1206                 ehdr.e_machine = EM_386;
1207                 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1208 #else
1209 #error "unknown machine type"
1210 #endif
1211                 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1212 
1213                 ehdr.e_version = EV_CURRENT;
1214                 ehdr.e_ehsize = sizeof (ehdr);
1215 
1216                 if (nphdrs >= PN_XNUM)
1217                         ehdr.e_phnum = PN_XNUM;
1218                 else
1219                         ehdr.e_phnum = (unsigned short)nphdrs;
1220 
1221                 ehdr.e_phentsize = sizeof (Elf32_Phdr);
1222                 ehdr.e_phoff = ehdr.e_ehsize;
1223 
1224                 if (nshdrs > 0) {
1225                         if (nshdrs >= SHN_LORESERVE)
1226                                 ehdr.e_shnum = 0;
1227                         else
1228                                 ehdr.e_shnum = (unsigned short)nshdrs;
1229 
1230                         if (nshdrs - 1 >= SHN_LORESERVE)
1231                                 ehdr.e_shstrndx = SHN_XINDEX;
1232                         else
1233                                 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1);
1234 
1235                         ehdr.e_shentsize = sizeof (Elf32_Shdr);
1236                         ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs;
1237                 }
1238 
1239                 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0)
1240                         goto err;
1241 
1242                 poff = ehdr.e_phoff;
1243                 soff = ehdr.e_shoff;
1244                 doff = boff = ehdr.e_ehsize +
1245                     ehdr.e_phentsize * nphdrs +
1246                     ehdr.e_shentsize * nshdrs;
1247 
1248 #ifdef _LP64
1249         } else {
1250                 Elf64_Ehdr ehdr;
1251 
1252                 bzero(&ehdr, sizeof (ehdr));
1253                 ehdr.e_ident[EI_MAG0] = ELFMAG0;
1254                 ehdr.e_ident[EI_MAG1] = ELFMAG1;
1255                 ehdr.e_ident[EI_MAG2] = ELFMAG2;
1256                 ehdr.e_ident[EI_MAG3] = ELFMAG3;
1257                 ehdr.e_type = ET_CORE;
1258 
1259                 ehdr.e_ident[EI_CLASS] = ELFCLASS64;
1260 #if defined(__sparc)
1261                 ehdr.e_machine = EM_SPARCV9;
1262                 ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
1263 #elif defined(__i386) || defined(__amd64)
1264                 ehdr.e_machine = EM_AMD64;
1265                 ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
1266 #else
1267 #error "unknown machine type"
1268 #endif
1269                 ehdr.e_ident[EI_VERSION] = EV_CURRENT;
1270 
1271                 ehdr.e_version = EV_CURRENT;
1272                 ehdr.e_ehsize = sizeof (ehdr);
1273 
1274                 if (nphdrs >= PN_XNUM)
1275                         ehdr.e_phnum = PN_XNUM;
1276                 else
1277                         ehdr.e_phnum = (unsigned short)nphdrs;
1278 
1279                 ehdr.e_phentsize = sizeof (Elf64_Phdr);
1280                 ehdr.e_phoff = ehdr.e_ehsize;
1281 
1282                 if (nshdrs > 0) {
1283                         if (nshdrs >= SHN_LORESERVE)
1284                                 ehdr.e_shnum = 0;
1285                         else
1286                                 ehdr.e_shnum = (unsigned short)nshdrs;
1287 
1288                         if (nshdrs - 1 >= SHN_LORESERVE)
1289                                 ehdr.e_shstrndx = SHN_XINDEX;
1290                         else
1291                                 ehdr.e_shstrndx = (unsigned short)(nshdrs - 1);
1292 
1293                         ehdr.e_shentsize = sizeof (Elf64_Shdr);
1294                         ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phentsize * nphdrs;
1295                 }
1296 
1297                 if (gc_pwrite64(fd, &ehdr, sizeof (ehdr), 0) != 0)
1298                         goto err;
1299 
1300                 poff = ehdr.e_phoff;
1301                 soff = ehdr.e_shoff;
1302                 doff = boff = ehdr.e_ehsize +
1303                     ehdr.e_phentsize * nphdrs +
1304                     ehdr.e_shentsize * nshdrs;
1305 
1306 #endif  /* _LP64 */
1307         }
1308 
1309         /*
1310          * Write the zero indexed section if it exists.
1311          */
1312         if (nshdrs > 0 && write_shdr(&pgc, shstrtab_data[STR_NONE], 0, 0, 0, 0,
1313             nshdrs >= SHN_LORESERVE ? nshdrs : 0,
1314             nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0,
1315             nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0)
1316                 goto err;
1317 
1318         /*
1319          * Construct the old-style note header and section.
1320          */
1321 
1322         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
1323                 prpsinfo_t prpsinfo;
1324 
1325                 mkprpsinfo(P, &prpsinfo);
1326                 if (write_note(fd, NT_PRPSINFO, &prpsinfo, sizeof (prpsinfo_t),
1327                     &doff) != 0) {
1328                         goto err;
1329                 }
1330                 if (write_note(fd, NT_AUXV, P->auxv,
1331                     P->nauxv * sizeof (P->auxv[0]), &doff) != 0) {
1332                         goto err;
1333                 }
1334 #ifdef _LP64
1335         } else {
1336                 prpsinfo32_t pi32;
1337                 auxv32_t *av32;
1338                 size_t size = sizeof (auxv32_t) * P->nauxv;
1339                 int i;
1340 
1341                 mkprpsinfo32(P, &pi32);
1342                 if (write_note(fd, NT_PRPSINFO, &pi32, sizeof (prpsinfo32_t),
1343                     &doff) != 0) {
1344                         goto err;
1345                 }
1346 
1347                 if ((av32 = malloc(size)) == NULL)
1348                         goto err;
1349 
1350                 for (i = 0; i < P->nauxv; i++) {
1351                         auxv_n_to_32(&P->auxv[i], &av32[i]);
1352                 }
1353 
1354                 if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) {
1355                         free(av32);
1356                         goto err;
1357                 }
1358 
1359                 free(av32);
1360 #endif  /* _LP64 */
1361         }
1362 
1363         if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0)
1364                 goto err;
1365 
1366         if (Plwp_iter_all(P, old_per_lwp, &pgc) != 0)
1367                 goto err;
1368 
1369         if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1370                 Elf32_Phdr phdr;
1371 
1372                 bzero(&phdr, sizeof (phdr));
1373                 phdr.p_type = PT_NOTE;
1374                 phdr.p_flags = PF_R;
1375                 phdr.p_offset = (Elf32_Off)boff;
1376                 phdr.p_filesz = doff - boff;
1377                 boff = doff;
1378 
1379                 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1380                         goto err;
1381                 poff += sizeof (phdr);
1382 #ifdef _LP64
1383         } else {
1384                 Elf64_Phdr phdr;
1385 
1386                 bzero(&phdr, sizeof (phdr));
1387                 phdr.p_type = PT_NOTE;
1388                 phdr.p_flags = PF_R;
1389                 phdr.p_offset = boff;
1390                 phdr.p_filesz = doff - boff;
1391                 boff = doff;
1392 
1393                 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1394                         goto err;
1395                 poff += sizeof (phdr);
1396 #endif  /* _LP64 */
1397         }
1398 
1399         /*
1400          * Construct the new-style note header and section.
1401          */
1402 
1403         if (P->status.pr_dmodel == PR_MODEL_NATIVE) {
1404                 if (write_note(fd, NT_PSINFO, &P->psinfo, sizeof (psinfo_t),
1405                     &doff) != 0) {
1406                         goto err;
1407                 }
1408                 if (write_note(fd, NT_PSTATUS, &P->status, sizeof (pstatus_t),
1409                     &doff) != 0) {
1410                         goto err;
1411                 }
1412                 if (write_note(fd, NT_AUXV, P->auxv,
1413                     P->nauxv * sizeof (P->auxv[0]), &doff) != 0) {
1414                         goto err;
1415                 }
1416 #ifdef _LP64
1417         } else {
1418                 psinfo32_t pi32;
1419                 pstatus32_t ps32;
1420                 auxv32_t *av32;
1421                 size_t size = sizeof (auxv32_t) * P->nauxv;
1422                 int i;
1423 
1424                 psinfo_n_to_32(&P->psinfo, &pi32);
1425                 if (write_note(fd, NT_PSINFO, &pi32, sizeof (psinfo32_t),
1426                     &doff) != 0) {
1427                         goto err;
1428                 }
1429                 pstatus_n_to_32(&P->status, &ps32);
1430                 if (write_note(fd, NT_PSTATUS, &ps32, sizeof (pstatus32_t),
1431                     &doff) != 0) {
1432                         goto err;
1433                 }
1434                 if ((av32 = malloc(size)) == NULL)
1435                         goto err;
1436 
1437                 for (i = 0; i < P->nauxv; i++) {
1438                         auxv_n_to_32(&P->auxv[i], &av32[i]);
1439                 }
1440 
1441                 if (write_note(fd, NT_AUXV, av32, size, &doff) != 0) {
1442                         free(av32);
1443                         goto err;
1444                 }
1445 
1446                 free(av32);
1447 #endif  /* _LP64 */
1448         }
1449 
1450         if (write_note(fd, NT_PLATFORM, plat, platlen, &doff) != 0 ||
1451             write_note(fd, NT_UTSNAME, &uts, sizeof (uts), &doff) != 0 ||
1452             write_note(fd, NT_CONTENT, &content, sizeof (content), &doff) != 0)
1453                 goto err;
1454 
1455         {
1456                 prcred_t cred, *cp;
1457                 size_t size = sizeof (prcred_t);
1458 
1459                 if (Pcred(P, &cred, 0) != 0)
1460                         goto err;
1461 
1462                 if (cred.pr_ngroups > 0)
1463                         size += sizeof (gid_t) * (cred.pr_ngroups - 1);
1464                 if ((cp = malloc(size)) == NULL)
1465                         goto err;
1466 
1467                 if (Pcred(P, cp, cred.pr_ngroups) != 0 ||
1468                     write_note(fd, NT_PRCRED, cp, size, &doff) != 0) {
1469                         free(cp);
1470                         goto err;
1471                 }
1472 
1473                 free(cp);
1474         }
1475 
1476         {
1477                 prpriv_t *ppriv = NULL;
1478                 const priv_impl_info_t *pinfo;
1479                 size_t pprivsz, pinfosz;
1480 
1481                 if (Ppriv(P, &ppriv) == -1)
1482                         goto err;
1483                 pprivsz = PRIV_PRPRIV_SIZE(ppriv);
1484 
1485                 if (write_note(fd, NT_PRPRIV, ppriv, pprivsz, &doff) != 0) {
1486                         Ppriv_free(P, ppriv);
1487                         goto err;
1488                 }
1489                 Ppriv_free(P, ppriv);
1490 
1491                 if ((pinfo = getprivimplinfo()) == NULL)
1492                         goto err;
1493                 pinfosz = PRIV_IMPL_INFO_SIZE(pinfo);
1494 
1495                 if (write_note(fd, NT_PRPRIVINFO, pinfo, pinfosz, &doff) != 0)
1496                         goto err;
1497         }
1498 
1499         if (write_note(fd, NT_ZONENAME, zonename, strlen(zonename) + 1,
1500             &doff) != 0)
1501                 goto err;
1502 
1503         {
1504                 fditer_t iter;
1505                 iter.fd_fd = fd;
1506                 iter.fd_doff = &doff;
1507 
1508                 if (Pfdinfo_iter(P, iter_fd, &iter) != 0)
1509                         goto err;
1510         }
1511 
1512 
1513         {
1514                 prsecflags_t *psf = NULL;
1515 
1516                 if (Psecflags(P, &psf) != 0)
1517                         goto err;
1518 
1519                 if (write_note(fd, NT_SECFLAGS, psf,
1520                     sizeof (prsecflags_t), &doff) != 0) {
1521                         Psecflags_free(psf);
1522                         goto err;
1523                 }
1524 
1525                 Psecflags_free(psf);
1526         }
1527 
1528 #if defined(__i386) || defined(__amd64)
1529         /* CSTYLED */
1530         {
1531                 struct ssd *ldtp;
1532                 size_t size;
1533                 int nldt;
1534 
1535                 /*
1536                  * Only dump out non-zero sized LDT notes.
1537                  */
1538                 if ((nldt = Pldt(P, NULL, 0)) != 0) {
1539                         size = sizeof (struct ssd) * nldt;
1540                         if ((ldtp = malloc(size)) == NULL)
1541                                 goto err;
1542 
1543                         if (Pldt(P, ldtp, nldt) == -1 ||
1544                             write_note(fd, NT_LDT, ldtp, size, &doff) != 0) {
1545                                 free(ldtp);
1546                                 goto err;
1547                         }
1548 
1549                         free(ldtp);
1550                 }
1551         }
1552 #endif  /* __i386 || __amd64 */
1553 
1554         if (Plwp_iter_all(P, new_per_lwp, &pgc) != 0)
1555                 goto err;
1556 
1557         if (P->status.pr_dmodel == PR_MODEL_ILP32) {
1558                 Elf32_Phdr phdr;
1559 
1560                 bzero(&phdr, sizeof (phdr));
1561                 phdr.p_type = PT_NOTE;
1562                 phdr.p_flags = PF_R;
1563                 phdr.p_offset = (Elf32_Off)boff;
1564                 phdr.p_filesz = doff - boff;
1565                 boff = doff;
1566 
1567                 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1568                         goto err;
1569                 poff += sizeof (phdr);
1570 #ifdef _LP64
1571         } else {
1572                 Elf64_Phdr phdr;
1573 
1574                 bzero(&phdr, sizeof (phdr));
1575                 phdr.p_type = PT_NOTE;
1576                 phdr.p_flags = PF_R;
1577                 phdr.p_offset = boff;
1578                 phdr.p_filesz = doff - boff;
1579                 boff = doff;
1580 
1581                 if (gc_pwrite64(fd, &phdr, sizeof (phdr), poff) != 0)
1582                         goto err;
1583                 poff += sizeof (phdr);
1584 #endif  /* _LP64 */
1585         }
1586 
1587         /*
1588          * Construct the headers for each mapping and write out its data
1589          * if the content parameter indicates that it should be present
1590          * in the core file.
1591          */
1592         if (Pmapping_iter(P, dump_map, &pgc) != 0)
1593                 goto err;
1594 
1595         if (dump_sections(&pgc) != 0)
1596                 goto err;
1597 
1598         if (write_shstrtab(P, &pgc) != 0)
1599                 goto err;
1600 
1601         free(pgc.pgc_chunk);
1602         shstrtab_fini(&pgc.pgc_shstrtab);
1603 
1604         return (0);
1605 
1606 err:
1607         /*
1608          * Wipe out anything we may have written if there was an error.
1609          */
1610         (void) ftruncate64(fd, 0);
1611         free(pgc.pgc_chunk);
1612         shstrtab_fini(&pgc.pgc_shstrtab);
1613 
1614         return (-1);
1615 }
1616 
1617 static const char *content_str[] = {
1618         "stack",        /* CC_CONTENT_STACK */
1619         "heap",         /* CC_CONTENT_HEAP */
1620         "shfile",       /* CC_CONTENT_SHFILE */
1621         "shanon",       /* CC_CONTENT_SHANON */
1622         "text",         /* CC_CONTENT_TEXT */
1623         "data",         /* CC_CONTENT_DATA */
1624         "rodata",       /* CC_CONTENT_RODATA */
1625         "anon",         /* CC_CONTENT_ANON */
1626         "shm",          /* CC_CONTENT_SHM */
1627         "ism",          /* CC_CONTENT_ISM */
1628         "dism",         /* CC_CONTENT_DISM */
1629         "ctf",          /* CC_CONTENT_CTF */
1630         "symtab",       /* CC_CONTENT_SYMTAB */
1631         "debug"         /* CC_CONTENT_DEBUG */
1632 };
1633 
1634 static uint_t ncontent_str = sizeof (content_str) / sizeof (content_str[0]);
1635 
1636 #define STREQ(a, b, n)  (strlen(b) == (n) && strncmp(a, b, n) == 0)
1637 
1638 int
1639 proc_str2content(const char *str, core_content_t *cp)
1640 {
1641         const char *cur = str;
1642         int add = 1;
1643         core_content_t mask, content = 0;
1644 
1645         for (;;) {
1646                 for (cur = str; isalpha(*cur); cur++)
1647                         continue;
1648 
1649                 if (STREQ(str, "default", cur - str)) {
1650                         mask = CC_CONTENT_DEFAULT;
1651                 } else if (STREQ(str, "all", cur - str)) {
1652                         mask = CC_CONTENT_ALL;
1653                 } else if (STREQ(str, "none", cur - str)) {
1654                         mask = 0;
1655                 } else {
1656                         int i = 0;
1657 
1658                         while (!STREQ(str, content_str[i], cur - str)) {
1659                                 i++;
1660 
1661                                 if (i >= ncontent_str)
1662                                         return (-1);
1663                         }
1664 
1665                         mask = (core_content_t)1 << i;
1666                 }
1667 
1668                 if (add)
1669                         content |= mask;
1670                 else
1671                         content &= ~mask;
1672 
1673                 switch (*cur) {
1674                 case '\0':
1675                         *cp = content;
1676                         return (0);
1677                 case '+':
1678                         add = 1;
1679                         break;
1680                 case '-':
1681                         add = 0;
1682                         break;
1683                 default:
1684                         return (-1);
1685                 }
1686 
1687                 str = cur + 1;
1688         }
1689 }
1690 
1691 static int
1692 popc(core_content_t x)
1693 {
1694         int i;
1695 
1696         for (i = 0; x != 0; i++)
1697                 x &= x - 1;
1698 
1699         return (i);
1700 }
1701 
1702 int
1703 proc_content2str(core_content_t content, char *buf, size_t size)
1704 {
1705         int nonecnt, defcnt, allcnt;
1706         core_content_t mask, bit;
1707         int first;
1708         uint_t index;
1709         size_t n, tot = 0;
1710 
1711         if (content == 0)
1712                 return ((int)strlcpy(buf, "none", size));
1713 
1714         if (content & ~CC_CONTENT_ALL)
1715                 return ((int)strlcpy(buf, "<invalid>", size));
1716 
1717         nonecnt = popc(content);
1718         defcnt = 1 + popc(content ^ CC_CONTENT_DEFAULT);
1719         allcnt = 1 + popc(content ^ CC_CONTENT_ALL);
1720 
1721         if (defcnt <= nonecnt && defcnt <= allcnt) {
1722                 mask = content ^ CC_CONTENT_DEFAULT;
1723                 first = 0;
1724                 tot += (n = strlcpy(buf, "default", size));
1725                 if (n > size)
1726                         n = size;
1727                 buf += n;
1728                 size -= n;
1729         } else if (allcnt < nonecnt) {
1730                 mask = content ^ CC_CONTENT_ALL;
1731                 first = 0;
1732                 tot += (n = strlcpy(buf, "all", size));
1733                 if (n > size)
1734                         n = size;
1735                 buf += n;
1736                 size -= n;
1737         } else {
1738                 mask = content;
1739                 first = 1;
1740         }
1741 
1742         while (mask != 0) {
1743                 bit = mask ^ (mask & (mask - 1));
1744 
1745                 if (!first) {
1746                         if (size > 1) {
1747                                 *buf = (bit & content) ? '+' : '-';
1748                                 buf++;
1749                                 size--;
1750                         }
1751 
1752                         tot++;
1753                 }
1754                 index = popc(bit - 1);
1755                 tot += (n = strlcpy(buf, content_str[index], size));
1756                 if (n > size)
1757                         n = size;
1758                 buf += n;
1759                 size -= n;
1760 
1761                 mask ^= bit;
1762                 first = 0;
1763         }
1764 
1765         return ((int)tot);
1766 }