1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <unistd.h> 32*7c478bd9Sstevel@tonic-gate #include <ctype.h> 33*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 34*7c478bd9Sstevel@tonic-gate #include <string.h> 35*7c478bd9Sstevel@tonic-gate #include <dirent.h> 36*7c478bd9Sstevel@tonic-gate #include <limits.h> 37*7c478bd9Sstevel@tonic-gate #include <link.h> 38*7c478bd9Sstevel@tonic-gate #include <libelf.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 42*7c478bd9Sstevel@tonic-gate #include <libproc.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate struct totals { 45*7c478bd9Sstevel@tonic-gate ulong_t total_size; 46*7c478bd9Sstevel@tonic-gate ulong_t total_swap; 47*7c478bd9Sstevel@tonic-gate ulong_t total_rss; 48*7c478bd9Sstevel@tonic-gate ulong_t total_anon; 49*7c478bd9Sstevel@tonic-gate ulong_t total_locked; 50*7c478bd9Sstevel@tonic-gate }; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate typedef int proc_xmap_f(void *, const prxmap_t *, const char *, int, int); 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static int xmapping_iter(struct ps_prochandle *, proc_xmap_f *, void *, 55*7c478bd9Sstevel@tonic-gate int); 56*7c478bd9Sstevel@tonic-gate static int rmapping_iter(struct ps_prochandle *, proc_map_f *, void *); 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate static int look_map(void *, const prmap_t *, const char *); 59*7c478bd9Sstevel@tonic-gate static int look_smap(void *, const prxmap_t *, const char *, int, int); 60*7c478bd9Sstevel@tonic-gate static int look_xmap(void *, const prxmap_t *, const char *, int, int); 61*7c478bd9Sstevel@tonic-gate static int look_xmap_nopgsz(void *, const prxmap_t *, const char *, 62*7c478bd9Sstevel@tonic-gate int, int); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static int gather_map(void *, const prmap_t *, const char *); 65*7c478bd9Sstevel@tonic-gate static int gather_xmap(void *, const prxmap_t *, const char *, int, int); 66*7c478bd9Sstevel@tonic-gate static int iter_map(proc_map_f *, void *); 67*7c478bd9Sstevel@tonic-gate static int iter_xmap(proc_xmap_f *, void *); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate static int perr(char *); 70*7c478bd9Sstevel@tonic-gate static void printK(long, int); 71*7c478bd9Sstevel@tonic-gate static char *mflags(uint_t); 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate static int lflag = 0; 74*7c478bd9Sstevel@tonic-gate static int aflag = 0; 75*7c478bd9Sstevel@tonic-gate static int addr_width, size_width; 76*7c478bd9Sstevel@tonic-gate static char *command; 77*7c478bd9Sstevel@tonic-gate static char *procname; 78*7c478bd9Sstevel@tonic-gate static struct ps_prochandle *Pr; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate typedef struct lwpstack { 81*7c478bd9Sstevel@tonic-gate lwpid_t lwps_lwpid; 82*7c478bd9Sstevel@tonic-gate stack_t lwps_stack; 83*7c478bd9Sstevel@tonic-gate } lwpstack_t; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate typedef struct { 86*7c478bd9Sstevel@tonic-gate prxmap_t md_xmap; 87*7c478bd9Sstevel@tonic-gate prmap_t md_map; 88*7c478bd9Sstevel@tonic-gate char *md_objname; 89*7c478bd9Sstevel@tonic-gate int md_last; 90*7c478bd9Sstevel@tonic-gate int md_doswap; 91*7c478bd9Sstevel@tonic-gate } mapdata_t; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate static mapdata_t *maps; 94*7c478bd9Sstevel@tonic-gate static int map_count; 95*7c478bd9Sstevel@tonic-gate static int map_alloc; 96*7c478bd9Sstevel@tonic-gate 97*7c478bd9Sstevel@tonic-gate static lwpstack_t *stacks = NULL; 98*7c478bd9Sstevel@tonic-gate static uint_t nstacks = 0; 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate #define MAX_TRIES 5 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate static int 103*7c478bd9Sstevel@tonic-gate getstack(void *data, const lwpstatus_t *lsp) 104*7c478bd9Sstevel@tonic-gate { 105*7c478bd9Sstevel@tonic-gate int *np = (int *)data; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if (Plwp_alt_stack(Pr, lsp->pr_lwpid, &stacks[*np].lwps_stack) == 0) { 108*7c478bd9Sstevel@tonic-gate stacks[*np].lwps_stack.ss_flags |= SS_ONSTACK; 109*7c478bd9Sstevel@tonic-gate stacks[*np].lwps_lwpid = lsp->pr_lwpid; 110*7c478bd9Sstevel@tonic-gate (*np)++; 111*7c478bd9Sstevel@tonic-gate } 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (Plwp_main_stack(Pr, lsp->pr_lwpid, &stacks[*np].lwps_stack) == 0) { 114*7c478bd9Sstevel@tonic-gate stacks[*np].lwps_lwpid = lsp->pr_lwpid; 115*7c478bd9Sstevel@tonic-gate (*np)++; 116*7c478bd9Sstevel@tonic-gate } 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate return (0); 119*7c478bd9Sstevel@tonic-gate } 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * We compare the high memory addresses since stacks are faulted in from 123*7c478bd9Sstevel@tonic-gate * high memory addresses to low memory addresses, and our prmap_t 124*7c478bd9Sstevel@tonic-gate * structures identify only the range of addresses that have been faulted 125*7c478bd9Sstevel@tonic-gate * in so far. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate static int 128*7c478bd9Sstevel@tonic-gate cmpstacks(const void *ap, const void *bp) 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate const lwpstack_t *as = ap; 131*7c478bd9Sstevel@tonic-gate const lwpstack_t *bs = bp; 132*7c478bd9Sstevel@tonic-gate uintptr_t a = (uintptr_t)as->lwps_stack.ss_sp + as->lwps_stack.ss_size; 133*7c478bd9Sstevel@tonic-gate uintptr_t b = (uintptr_t)bs->lwps_stack.ss_sp + bs->lwps_stack.ss_size; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate if (a < b) 136*7c478bd9Sstevel@tonic-gate return (1); 137*7c478bd9Sstevel@tonic-gate if (a > b) 138*7c478bd9Sstevel@tonic-gate return (-1); 139*7c478bd9Sstevel@tonic-gate return (0); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate int 144*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 145*7c478bd9Sstevel@tonic-gate { 146*7c478bd9Sstevel@tonic-gate int rflag = 0, sflag = 0, xflag = 0; 147*7c478bd9Sstevel@tonic-gate int errflg = 0, Sflag = 0; 148*7c478bd9Sstevel@tonic-gate int rc = 0; 149*7c478bd9Sstevel@tonic-gate int opt; 150*7c478bd9Sstevel@tonic-gate const char *bar8 = "-------"; 151*7c478bd9Sstevel@tonic-gate const char *bar16 = "----------"; 152*7c478bd9Sstevel@tonic-gate const char *bar; 153*7c478bd9Sstevel@tonic-gate struct rlimit rlim; 154*7c478bd9Sstevel@tonic-gate struct stat64 statbuf; 155*7c478bd9Sstevel@tonic-gate char buf[128]; 156*7c478bd9Sstevel@tonic-gate int mapfd; 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate if ((command = strrchr(argv[0], '/')) != NULL) 159*7c478bd9Sstevel@tonic-gate command++; 160*7c478bd9Sstevel@tonic-gate else 161*7c478bd9Sstevel@tonic-gate command = argv[0]; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate while ((opt = getopt(argc, argv, "arsxSlF")) != EOF) { 164*7c478bd9Sstevel@tonic-gate switch (opt) { 165*7c478bd9Sstevel@tonic-gate case 'a': /* include shared mappings in -[xS] */ 166*7c478bd9Sstevel@tonic-gate aflag = 1; 167*7c478bd9Sstevel@tonic-gate break; 168*7c478bd9Sstevel@tonic-gate case 'r': /* show reserved mappings */ 169*7c478bd9Sstevel@tonic-gate rflag = 1; 170*7c478bd9Sstevel@tonic-gate break; 171*7c478bd9Sstevel@tonic-gate case 's': /* show hardware page sizes */ 172*7c478bd9Sstevel@tonic-gate sflag = 1; 173*7c478bd9Sstevel@tonic-gate break; 174*7c478bd9Sstevel@tonic-gate case 'S': /* show swap reservations */ 175*7c478bd9Sstevel@tonic-gate Sflag = 1; 176*7c478bd9Sstevel@tonic-gate break; 177*7c478bd9Sstevel@tonic-gate case 'x': /* show extended mappings */ 178*7c478bd9Sstevel@tonic-gate xflag = 1; 179*7c478bd9Sstevel@tonic-gate break; 180*7c478bd9Sstevel@tonic-gate case 'l': /* show unresolved link map names */ 181*7c478bd9Sstevel@tonic-gate lflag = 1; 182*7c478bd9Sstevel@tonic-gate break; 183*7c478bd9Sstevel@tonic-gate case 'F': 184*7c478bd9Sstevel@tonic-gate /* 185*7c478bd9Sstevel@tonic-gate * Since we grab the process readonly now, the -F flag 186*7c478bd9Sstevel@tonic-gate * is meaningless. Consume it anyway it for backwards 187*7c478bd9Sstevel@tonic-gate * compatbility. 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate default: 191*7c478bd9Sstevel@tonic-gate errflg = 1; 192*7c478bd9Sstevel@tonic-gate break; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate argc -= optind; 197*7c478bd9Sstevel@tonic-gate argv += optind; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate if ((Sflag && (xflag || rflag || sflag)) || (xflag && rflag) || 200*7c478bd9Sstevel@tonic-gate (aflag && (!xflag && !Sflag))) { 201*7c478bd9Sstevel@tonic-gate errflg = 1; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate if (errflg || argc <= 0) { 205*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 206*7c478bd9Sstevel@tonic-gate "usage:\t%s [-rslF] { pid | core } ...\n", command); 207*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 208*7c478bd9Sstevel@tonic-gate "\t\t(report process address maps)\n"); 209*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 210*7c478bd9Sstevel@tonic-gate "\t%s -x [-aslF] pid ...\n", command); 211*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 212*7c478bd9Sstevel@tonic-gate "\t\t(show resident/anon/locked mapping details)\n"); 213*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 214*7c478bd9Sstevel@tonic-gate "\t%s -S [-alF] { pid | core } ...\n", command); 215*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 216*7c478bd9Sstevel@tonic-gate "\t\t(show swap reservations)\n\n"); 217*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 218*7c478bd9Sstevel@tonic-gate "\t-a: include shared mappings in -[xS] summary\n"); 219*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 220*7c478bd9Sstevel@tonic-gate "\t-r: show reserved address maps\n"); 221*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 222*7c478bd9Sstevel@tonic-gate "\t-s: show hardware page sizes\n"); 223*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 224*7c478bd9Sstevel@tonic-gate "\t-l: show unresolved dynamic linker map names\n"); 225*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 226*7c478bd9Sstevel@tonic-gate "\t-F: force grabbing of the target process\n"); 227*7c478bd9Sstevel@tonic-gate return (2); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * Make sure we'll have enough file descriptors to handle a target 232*7c478bd9Sstevel@tonic-gate * that has many many mappings. 233*7c478bd9Sstevel@tonic-gate */ 234*7c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { 235*7c478bd9Sstevel@tonic-gate rlim.rlim_cur = rlim.rlim_max; 236*7c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_NOFILE, &rlim); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate while (argc-- > 0) { 240*7c478bd9Sstevel@tonic-gate char *arg; 241*7c478bd9Sstevel@tonic-gate int gcode; 242*7c478bd9Sstevel@tonic-gate psinfo_t psinfo; 243*7c478bd9Sstevel@tonic-gate int tries = 0; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY, 246*7c478bd9Sstevel@tonic-gate PGRAB_RDONLY, &gcode)) == NULL) { 247*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot examine %s: %s\n", 248*7c478bd9Sstevel@tonic-gate command, arg, Pgrab_error(gcode)); 249*7c478bd9Sstevel@tonic-gate rc++; 250*7c478bd9Sstevel@tonic-gate continue; 251*7c478bd9Sstevel@tonic-gate } 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate procname = arg; /* for perr() */ 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate addr_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 16 : 8; 256*7c478bd9Sstevel@tonic-gate size_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 11 : 8; 257*7c478bd9Sstevel@tonic-gate bar = addr_width == 8 ? bar8 : bar16; 258*7c478bd9Sstevel@tonic-gate (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t)); 259*7c478bd9Sstevel@tonic-gate proc_unctrl_psinfo(&psinfo); 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate if (Pstate(Pr) != PS_DEAD) { 262*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 263*7c478bd9Sstevel@tonic-gate "/proc/%d/map", (int)psinfo.pr_pid); 264*7c478bd9Sstevel@tonic-gate if ((mapfd = open(buf, O_RDONLY)) < 0) { 265*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot " 266*7c478bd9Sstevel@tonic-gate "examine %s: lost control of " 267*7c478bd9Sstevel@tonic-gate "process\n", command, arg); 268*7c478bd9Sstevel@tonic-gate rc++; 269*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 270*7c478bd9Sstevel@tonic-gate continue; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate } else { 273*7c478bd9Sstevel@tonic-gate mapfd = -1; 274*7c478bd9Sstevel@tonic-gate } 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate again: 277*7c478bd9Sstevel@tonic-gate map_count = 0; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate if (Pstate(Pr) == PS_DEAD) { 280*7c478bd9Sstevel@tonic-gate (void) printf("core '%s' of %d:\t%.70s\n", 281*7c478bd9Sstevel@tonic-gate arg, (int)psinfo.pr_pid, psinfo.pr_psargs); 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate if (rflag || sflag || xflag || Sflag) { 284*7c478bd9Sstevel@tonic-gate (void) printf(" -%c option is not compatible " 285*7c478bd9Sstevel@tonic-gate "with core files\n", xflag ? 'x' : 286*7c478bd9Sstevel@tonic-gate sflag ? 's' : rflag ? 'r' : 'S'); 287*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 288*7c478bd9Sstevel@tonic-gate rc++; 289*7c478bd9Sstevel@tonic-gate continue; 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate } else { 293*7c478bd9Sstevel@tonic-gate (void) printf("%d:\t%.70s\n", 294*7c478bd9Sstevel@tonic-gate (int)psinfo.pr_pid, psinfo.pr_psargs); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate if (!(Pstatus(Pr)->pr_flags & PR_ISSYS)) { 298*7c478bd9Sstevel@tonic-gate struct totals t; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * Since we're grabbing the process readonly, we need 302*7c478bd9Sstevel@tonic-gate * to make sure the address space doesn't change during 303*7c478bd9Sstevel@tonic-gate * execution. 304*7c478bd9Sstevel@tonic-gate */ 305*7c478bd9Sstevel@tonic-gate if (Pstate(Pr) != PS_DEAD) { 306*7c478bd9Sstevel@tonic-gate if (tries++ == MAX_TRIES) { 307*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 308*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 309*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot " 310*7c478bd9Sstevel@tonic-gate "examine %s: address space is " 311*7c478bd9Sstevel@tonic-gate "changing\n", command, arg); 312*7c478bd9Sstevel@tonic-gate continue; 313*7c478bd9Sstevel@tonic-gate } 314*7c478bd9Sstevel@tonic-gate 315*7c478bd9Sstevel@tonic-gate if (fstat64(mapfd, &statbuf) != 0) { 316*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 317*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 318*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot " 319*7c478bd9Sstevel@tonic-gate "examine %s: lost control of " 320*7c478bd9Sstevel@tonic-gate "process\n", command, arg); 321*7c478bd9Sstevel@tonic-gate continue; 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate } 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate nstacks = psinfo.pr_nlwp * 2; 326*7c478bd9Sstevel@tonic-gate stacks = calloc(nstacks, sizeof (stacks[0])); 327*7c478bd9Sstevel@tonic-gate if (stacks != NULL) { 328*7c478bd9Sstevel@tonic-gate int n = 0; 329*7c478bd9Sstevel@tonic-gate (void) Plwp_iter(Pr, getstack, &n); 330*7c478bd9Sstevel@tonic-gate qsort(stacks, nstacks, sizeof (stacks[0]), 331*7c478bd9Sstevel@tonic-gate cmpstacks); 332*7c478bd9Sstevel@tonic-gate } 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate (void) memset(&t, 0, sizeof (t)); 335*7c478bd9Sstevel@tonic-gate 336*7c478bd9Sstevel@tonic-gate if (Pgetauxval(Pr, AT_BASE) != -1L && 337*7c478bd9Sstevel@tonic-gate Prd_agent(Pr) == NULL) { 338*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: warning: " 339*7c478bd9Sstevel@tonic-gate "librtld_db failed to initialize; " 340*7c478bd9Sstevel@tonic-gate "shared library information will not be " 341*7c478bd9Sstevel@tonic-gate "available\n", command); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Gather data 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate if (xflag) 348*7c478bd9Sstevel@tonic-gate rc += xmapping_iter(Pr, gather_xmap, NULL, 0); 349*7c478bd9Sstevel@tonic-gate else if (Sflag) 350*7c478bd9Sstevel@tonic-gate rc += xmapping_iter(Pr, gather_xmap, NULL, 1); 351*7c478bd9Sstevel@tonic-gate else { 352*7c478bd9Sstevel@tonic-gate if (rflag) 353*7c478bd9Sstevel@tonic-gate rc += rmapping_iter(Pr, gather_map, 354*7c478bd9Sstevel@tonic-gate NULL); 355*7c478bd9Sstevel@tonic-gate else if (sflag) 356*7c478bd9Sstevel@tonic-gate rc += xmapping_iter(Pr, gather_xmap, 357*7c478bd9Sstevel@tonic-gate NULL, 0); 358*7c478bd9Sstevel@tonic-gate else 359*7c478bd9Sstevel@tonic-gate rc += Pmapping_iter(Pr, gather_map, 360*7c478bd9Sstevel@tonic-gate NULL); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /* 364*7c478bd9Sstevel@tonic-gate * Ensure mappings are consistent. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate if (Pstate(Pr) != PS_DEAD) { 367*7c478bd9Sstevel@tonic-gate struct stat64 newbuf; 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (fstat64(mapfd, &newbuf) != 0 || 370*7c478bd9Sstevel@tonic-gate memcmp(&newbuf.st_mtim, &statbuf.st_mtim, 371*7c478bd9Sstevel@tonic-gate sizeof (newbuf.st_mtim)) != 0) { 372*7c478bd9Sstevel@tonic-gate if (stacks != NULL) { 373*7c478bd9Sstevel@tonic-gate free(stacks); 374*7c478bd9Sstevel@tonic-gate stacks = NULL; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate goto again; 377*7c478bd9Sstevel@tonic-gate } 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Display data. 382*7c478bd9Sstevel@tonic-gate */ 383*7c478bd9Sstevel@tonic-gate if (xflag) { 384*7c478bd9Sstevel@tonic-gate (void) printf("%*s%*s%*s%*s%*s " 385*7c478bd9Sstevel@tonic-gate "%sMode Mapped File\n", 386*7c478bd9Sstevel@tonic-gate addr_width, "Address", 387*7c478bd9Sstevel@tonic-gate size_width, "Kbytes", 388*7c478bd9Sstevel@tonic-gate size_width, "RSS", 389*7c478bd9Sstevel@tonic-gate size_width, "Anon", 390*7c478bd9Sstevel@tonic-gate size_width, "Locked", 391*7c478bd9Sstevel@tonic-gate sflag ? "Pgsz " : ""); 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate rc += iter_xmap(sflag ? look_xmap : 394*7c478bd9Sstevel@tonic-gate look_xmap_nopgsz, &t); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate (void) printf("%s%s %s %s %s %s\n", 397*7c478bd9Sstevel@tonic-gate addr_width == 8 ? "-" : "------", 398*7c478bd9Sstevel@tonic-gate bar, bar, bar, bar, bar); 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate (void) printf("%stotal Kb", addr_width == 16 ? 401*7c478bd9Sstevel@tonic-gate " " : ""); 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate printK(t.total_size, size_width); 404*7c478bd9Sstevel@tonic-gate printK(t.total_rss, size_width); 405*7c478bd9Sstevel@tonic-gate printK(t.total_anon, size_width); 406*7c478bd9Sstevel@tonic-gate printK(t.total_locked, size_width); 407*7c478bd9Sstevel@tonic-gate 408*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate } else if (Sflag) { 411*7c478bd9Sstevel@tonic-gate (void) printf("%*s%*s%*s Mode Mapped File\n", 412*7c478bd9Sstevel@tonic-gate addr_width, "Address", 413*7c478bd9Sstevel@tonic-gate size_width, "Kbytes", 414*7c478bd9Sstevel@tonic-gate size_width, "Swap"); 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate rc += iter_xmap(look_xmap_nopgsz, &t); 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate (void) printf("%s%s %s %s\n", 419*7c478bd9Sstevel@tonic-gate addr_width == 8 ? "-" : "------", 420*7c478bd9Sstevel@tonic-gate bar, bar, bar); 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate (void) printf("%stotal Kb", addr_width == 16 ? 423*7c478bd9Sstevel@tonic-gate " " : ""); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate printK(t.total_size, size_width); 426*7c478bd9Sstevel@tonic-gate printK(t.total_swap, size_width); 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate } else { 431*7c478bd9Sstevel@tonic-gate 432*7c478bd9Sstevel@tonic-gate if (rflag) { 433*7c478bd9Sstevel@tonic-gate rc += iter_map(look_map, &t); 434*7c478bd9Sstevel@tonic-gate } else if (sflag) { 435*7c478bd9Sstevel@tonic-gate (void) printf("%*s %*s %4s %-6s %s\n", 436*7c478bd9Sstevel@tonic-gate addr_width, "Address", size_width, 437*7c478bd9Sstevel@tonic-gate "Bytes", "Pgsz", "Mode ", 438*7c478bd9Sstevel@tonic-gate "Mapped File"); 439*7c478bd9Sstevel@tonic-gate rc += iter_xmap(look_smap, &t); 440*7c478bd9Sstevel@tonic-gate } else { 441*7c478bd9Sstevel@tonic-gate rc += iter_map(look_map, &t); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate (void) printf(" %stotal %*luK\n", 445*7c478bd9Sstevel@tonic-gate addr_width == 16 ? 446*7c478bd9Sstevel@tonic-gate " " : "", 447*7c478bd9Sstevel@tonic-gate size_width, t.total_size); 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate if (stacks != NULL) { 451*7c478bd9Sstevel@tonic-gate free(stacks); 452*7c478bd9Sstevel@tonic-gate stacks = NULL; 453*7c478bd9Sstevel@tonic-gate } 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate Prelease(Pr, 0); 458*7c478bd9Sstevel@tonic-gate if (mapfd != -1) 459*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate 462*7c478bd9Sstevel@tonic-gate return (rc); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate static char * 466*7c478bd9Sstevel@tonic-gate make_name(struct ps_prochandle *Pr, uintptr_t addr, const char *mapname, 467*7c478bd9Sstevel@tonic-gate char *buf, size_t bufsz) 468*7c478bd9Sstevel@tonic-gate { 469*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Pr); 470*7c478bd9Sstevel@tonic-gate char fname[100]; 471*7c478bd9Sstevel@tonic-gate struct stat statb; 472*7c478bd9Sstevel@tonic-gate int len; 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate if (!lflag && strcmp(mapname, "a.out") == 0 && 475*7c478bd9Sstevel@tonic-gate Pexecname(Pr, buf, bufsz) != NULL) 476*7c478bd9Sstevel@tonic-gate return (buf); 477*7c478bd9Sstevel@tonic-gate 478*7c478bd9Sstevel@tonic-gate if (Pobjname(Pr, addr, buf, bufsz) != NULL) { 479*7c478bd9Sstevel@tonic-gate if (lflag) 480*7c478bd9Sstevel@tonic-gate return (buf); 481*7c478bd9Sstevel@tonic-gate if ((len = resolvepath(buf, buf, bufsz)) > 0) { 482*7c478bd9Sstevel@tonic-gate buf[len] = '\0'; 483*7c478bd9Sstevel@tonic-gate return (buf); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate } 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (Pstate(Pr) != PS_DEAD && *mapname != '\0') { 488*7c478bd9Sstevel@tonic-gate (void) snprintf(fname, sizeof (fname), "/proc/%d/object/%s", 489*7c478bd9Sstevel@tonic-gate (int)Psp->pr_pid, mapname); 490*7c478bd9Sstevel@tonic-gate if (stat(fname, &statb) == 0) { 491*7c478bd9Sstevel@tonic-gate dev_t dev = statb.st_dev; 492*7c478bd9Sstevel@tonic-gate ino_t ino = statb.st_ino; 493*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, bufsz, "dev:%lu,%lu ino:%lu", 494*7c478bd9Sstevel@tonic-gate (ulong_t)major(dev), (ulong_t)minor(dev), ino); 495*7c478bd9Sstevel@tonic-gate return (buf); 496*7c478bd9Sstevel@tonic-gate } 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate return (NULL); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate static char * 503*7c478bd9Sstevel@tonic-gate anon_name(char *name, const pstatus_t *Psp, 504*7c478bd9Sstevel@tonic-gate uintptr_t vaddr, size_t size, int mflags, int shmid) 505*7c478bd9Sstevel@tonic-gate { 506*7c478bd9Sstevel@tonic-gate if (mflags & MA_ISM) { 507*7c478bd9Sstevel@tonic-gate if (shmid == -1) 508*7c478bd9Sstevel@tonic-gate (void) snprintf(name, PATH_MAX, " [ %s shmid=null ]", 509*7c478bd9Sstevel@tonic-gate (mflags & MA_NORESERVE) ? "ism" : "dism"); 510*7c478bd9Sstevel@tonic-gate else 511*7c478bd9Sstevel@tonic-gate (void) snprintf(name, PATH_MAX, " [ %s shmid=0x%x ]", 512*7c478bd9Sstevel@tonic-gate (mflags & MA_NORESERVE) ? "ism" : "dism", shmid); 513*7c478bd9Sstevel@tonic-gate } else if (mflags & MA_SHM) { 514*7c478bd9Sstevel@tonic-gate if (shmid == -1) 515*7c478bd9Sstevel@tonic-gate (void) sprintf(name, " [ shmid=null ]"); 516*7c478bd9Sstevel@tonic-gate else 517*7c478bd9Sstevel@tonic-gate (void) sprintf(name, " [ shmid=0x%x ]", shmid); 518*7c478bd9Sstevel@tonic-gate } else if (vaddr + size > Psp->pr_stkbase && 519*7c478bd9Sstevel@tonic-gate vaddr < Psp->pr_stkbase + Psp->pr_stksize) { 520*7c478bd9Sstevel@tonic-gate (void) strcpy(name, " [ stack ]"); 521*7c478bd9Sstevel@tonic-gate } else if ((mflags & MA_ANON) && 522*7c478bd9Sstevel@tonic-gate vaddr + size > Psp->pr_brkbase && 523*7c478bd9Sstevel@tonic-gate vaddr < Psp->pr_brkbase + Psp->pr_brksize) { 524*7c478bd9Sstevel@tonic-gate (void) strcpy(name, " [ heap ]"); 525*7c478bd9Sstevel@tonic-gate } else { 526*7c478bd9Sstevel@tonic-gate lwpstack_t key, *stk; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate key.lwps_stack.ss_sp = (void *)vaddr; 529*7c478bd9Sstevel@tonic-gate key.lwps_stack.ss_size = size; 530*7c478bd9Sstevel@tonic-gate if (nstacks > 0 && 531*7c478bd9Sstevel@tonic-gate (stk = bsearch(&key, stacks, nstacks, sizeof (stacks[0]), 532*7c478bd9Sstevel@tonic-gate cmpstacks)) != NULL) { 533*7c478bd9Sstevel@tonic-gate (void) snprintf(name, PATH_MAX, " [ %s tid=%d ]", 534*7c478bd9Sstevel@tonic-gate (stk->lwps_stack.ss_flags & SS_ONSTACK) ? 535*7c478bd9Sstevel@tonic-gate "altstack" : "stack", 536*7c478bd9Sstevel@tonic-gate stk->lwps_lwpid); 537*7c478bd9Sstevel@tonic-gate } else if (Pstate(Pr) != PS_DEAD) { 538*7c478bd9Sstevel@tonic-gate (void) strcpy(name, " [ anon ]"); 539*7c478bd9Sstevel@tonic-gate } else { 540*7c478bd9Sstevel@tonic-gate return (NULL); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate } 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate return (name); 545*7c478bd9Sstevel@tonic-gate } 546*7c478bd9Sstevel@tonic-gate 547*7c478bd9Sstevel@tonic-gate static int 548*7c478bd9Sstevel@tonic-gate rmapping_iter(struct ps_prochandle *Pr, proc_map_f *func, void *cd) 549*7c478bd9Sstevel@tonic-gate { 550*7c478bd9Sstevel@tonic-gate char mapname[PATH_MAX]; 551*7c478bd9Sstevel@tonic-gate int mapfd, nmap, i, rc; 552*7c478bd9Sstevel@tonic-gate struct stat st; 553*7c478bd9Sstevel@tonic-gate prmap_t *prmapp, *pmp; 554*7c478bd9Sstevel@tonic-gate ssize_t n; 555*7c478bd9Sstevel@tonic-gate 556*7c478bd9Sstevel@tonic-gate (void) snprintf(mapname, sizeof (mapname), 557*7c478bd9Sstevel@tonic-gate "/proc/%d/rmap", (int)Pstatus(Pr)->pr_pid); 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if ((mapfd = open(mapname, O_RDONLY)) < 0 || fstat(mapfd, &st) != 0) { 560*7c478bd9Sstevel@tonic-gate if (mapfd >= 0) 561*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 562*7c478bd9Sstevel@tonic-gate return (perr(mapname)); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate nmap = st.st_size / sizeof (prmap_t); 566*7c478bd9Sstevel@tonic-gate prmapp = malloc((nmap + 1) * sizeof (prmap_t)); 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate if ((n = pread(mapfd, prmapp, (nmap + 1) * sizeof (prmap_t), 0L)) < 0) { 569*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 570*7c478bd9Sstevel@tonic-gate free(prmapp); 571*7c478bd9Sstevel@tonic-gate return (perr("read rmap")); 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 575*7c478bd9Sstevel@tonic-gate nmap = n / sizeof (prmap_t); 576*7c478bd9Sstevel@tonic-gate 577*7c478bd9Sstevel@tonic-gate for (i = 0, pmp = prmapp; i < nmap; i++, pmp++) { 578*7c478bd9Sstevel@tonic-gate if ((rc = func(cd, pmp, NULL)) != 0) { 579*7c478bd9Sstevel@tonic-gate free(prmapp); 580*7c478bd9Sstevel@tonic-gate return (rc); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate } 583*7c478bd9Sstevel@tonic-gate 584*7c478bd9Sstevel@tonic-gate free(prmapp); 585*7c478bd9Sstevel@tonic-gate return (0); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate static int 589*7c478bd9Sstevel@tonic-gate xmapping_iter(struct ps_prochandle *Pr, proc_xmap_f *func, void *cd, int doswap) 590*7c478bd9Sstevel@tonic-gate { 591*7c478bd9Sstevel@tonic-gate char mapname[PATH_MAX]; 592*7c478bd9Sstevel@tonic-gate int mapfd, nmap, i, rc; 593*7c478bd9Sstevel@tonic-gate struct stat st; 594*7c478bd9Sstevel@tonic-gate prxmap_t *prmapp, *pmp; 595*7c478bd9Sstevel@tonic-gate ssize_t n; 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate (void) snprintf(mapname, sizeof (mapname), 598*7c478bd9Sstevel@tonic-gate "/proc/%d/xmap", (int)Pstatus(Pr)->pr_pid); 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate if ((mapfd = open(mapname, O_RDONLY)) < 0 || fstat(mapfd, &st) != 0) { 601*7c478bd9Sstevel@tonic-gate if (mapfd >= 0) 602*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 603*7c478bd9Sstevel@tonic-gate return (perr(mapname)); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate nmap = st.st_size / sizeof (prxmap_t); 607*7c478bd9Sstevel@tonic-gate nmap *= 2; 608*7c478bd9Sstevel@tonic-gate again: 609*7c478bd9Sstevel@tonic-gate prmapp = malloc((nmap + 1) * sizeof (prxmap_t)); 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate if ((n = pread(mapfd, prmapp, (nmap + 1) * sizeof (prxmap_t), 0)) < 0) { 612*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 613*7c478bd9Sstevel@tonic-gate free(prmapp); 614*7c478bd9Sstevel@tonic-gate return (perr("read xmap")); 615*7c478bd9Sstevel@tonic-gate } 616*7c478bd9Sstevel@tonic-gate 617*7c478bd9Sstevel@tonic-gate if (nmap < n / sizeof (prxmap_t)) { 618*7c478bd9Sstevel@tonic-gate free(prmapp); 619*7c478bd9Sstevel@tonic-gate nmap *= 2; 620*7c478bd9Sstevel@tonic-gate goto again; 621*7c478bd9Sstevel@tonic-gate } 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate (void) close(mapfd); 624*7c478bd9Sstevel@tonic-gate nmap = n / sizeof (prxmap_t); 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate for (i = 0, pmp = prmapp; i < nmap; i++, pmp++) { 627*7c478bd9Sstevel@tonic-gate if ((rc = func(cd, pmp, NULL, i == nmap - 1, doswap)) != 0) { 628*7c478bd9Sstevel@tonic-gate free(prmapp); 629*7c478bd9Sstevel@tonic-gate return (rc); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate free(prmapp); 634*7c478bd9Sstevel@tonic-gate return (0); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 638*7c478bd9Sstevel@tonic-gate static int 639*7c478bd9Sstevel@tonic-gate look_map(void *data, const prmap_t *pmp, const char *object_name) 640*7c478bd9Sstevel@tonic-gate { 641*7c478bd9Sstevel@tonic-gate struct totals *t = data; 642*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Pr); 643*7c478bd9Sstevel@tonic-gate size_t size = (pmp->pr_size + 1023) / 1024; 644*7c478bd9Sstevel@tonic-gate char mname[PATH_MAX]; 645*7c478bd9Sstevel@tonic-gate char *lname = NULL; 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate /* 648*7c478bd9Sstevel@tonic-gate * If the mapping is not anon or not part of the heap, make a name 649*7c478bd9Sstevel@tonic-gate * for it. We don't want to report the heap as a.out's data. 650*7c478bd9Sstevel@tonic-gate */ 651*7c478bd9Sstevel@tonic-gate if (!(pmp->pr_mflags & MA_ANON) || 652*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr + pmp->pr_size <= Psp->pr_brkbase || 653*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr >= Psp->pr_brkbase + Psp->pr_brksize) { 654*7c478bd9Sstevel@tonic-gate lname = make_name(Pr, pmp->pr_vaddr, pmp->pr_mapname, 655*7c478bd9Sstevel@tonic-gate mname, sizeof (mname)); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if (lname == NULL && 659*7c478bd9Sstevel@tonic-gate ((pmp->pr_mflags & MA_ANON) || Pstate(Pr) == PS_DEAD)) { 660*7c478bd9Sstevel@tonic-gate lname = anon_name(mname, Psp, pmp->pr_vaddr, 661*7c478bd9Sstevel@tonic-gate pmp->pr_size, pmp->pr_mflags, pmp->pr_shmid); 662*7c478bd9Sstevel@tonic-gate } 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate (void) printf(lname ? "%.*lX %*luK %-6s %s\n" : "%.*lX %*luK %s\n", 665*7c478bd9Sstevel@tonic-gate addr_width, (uintptr_t)pmp->pr_vaddr, 666*7c478bd9Sstevel@tonic-gate size_width - 1, size, mflags(pmp->pr_mflags), lname); 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate t->total_size += size; 669*7c478bd9Sstevel@tonic-gate return (0); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate static void 673*7c478bd9Sstevel@tonic-gate printK(long value, int width) 674*7c478bd9Sstevel@tonic-gate { 675*7c478bd9Sstevel@tonic-gate if (value == 0) 676*7c478bd9Sstevel@tonic-gate (void) printf(width == 8 ? " -" : " -"); 677*7c478bd9Sstevel@tonic-gate else 678*7c478bd9Sstevel@tonic-gate (void) printf(" %*lu", width - 1, value); 679*7c478bd9Sstevel@tonic-gate } 680*7c478bd9Sstevel@tonic-gate 681*7c478bd9Sstevel@tonic-gate static const char * 682*7c478bd9Sstevel@tonic-gate pagesize(const prxmap_t *pmp) 683*7c478bd9Sstevel@tonic-gate { 684*7c478bd9Sstevel@tonic-gate int pagesize = pmp->pr_hatpagesize; 685*7c478bd9Sstevel@tonic-gate static char buf[32]; 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate if (pagesize == 0) { 688*7c478bd9Sstevel@tonic-gate return ("-"); /* no underlying HAT mapping */ 689*7c478bd9Sstevel@tonic-gate } 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if (pagesize >= 1024 && (pagesize % 1024) == 0) { 692*7c478bd9Sstevel@tonic-gate if ((pagesize % (1024 * 1024 * 1024)) == 0) 693*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%dG", 694*7c478bd9Sstevel@tonic-gate pagesize / (1024 * 1024 * 1024)); 695*7c478bd9Sstevel@tonic-gate else if ((pagesize % (1024 * 1024)) == 0) 696*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%dM", 697*7c478bd9Sstevel@tonic-gate pagesize / (1024 * 1024)); 698*7c478bd9Sstevel@tonic-gate else 699*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%dK", 700*7c478bd9Sstevel@tonic-gate pagesize / 1024); 701*7c478bd9Sstevel@tonic-gate } else 702*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%db", pagesize); 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate return (buf); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 708*7c478bd9Sstevel@tonic-gate static int 709*7c478bd9Sstevel@tonic-gate look_smap(void *data, 710*7c478bd9Sstevel@tonic-gate const prxmap_t *pmp, 711*7c478bd9Sstevel@tonic-gate const char *object_name, 712*7c478bd9Sstevel@tonic-gate int last, int doswap) 713*7c478bd9Sstevel@tonic-gate { 714*7c478bd9Sstevel@tonic-gate struct totals *t = data; 715*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Pr); 716*7c478bd9Sstevel@tonic-gate size_t size = (pmp->pr_size + 1023) / 1024; 717*7c478bd9Sstevel@tonic-gate char mname[PATH_MAX]; 718*7c478bd9Sstevel@tonic-gate char *lname = NULL; 719*7c478bd9Sstevel@tonic-gate const char *format; 720*7c478bd9Sstevel@tonic-gate 721*7c478bd9Sstevel@tonic-gate /* 722*7c478bd9Sstevel@tonic-gate * If the mapping is not anon or not part of the heap, make a name 723*7c478bd9Sstevel@tonic-gate * for it. We don't want to report the heap as a.out's data. 724*7c478bd9Sstevel@tonic-gate */ 725*7c478bd9Sstevel@tonic-gate if (!(pmp->pr_mflags & MA_ANON) || 726*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr + pmp->pr_size <= Psp->pr_brkbase || 727*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr >= Psp->pr_brkbase + Psp->pr_brksize) { 728*7c478bd9Sstevel@tonic-gate lname = make_name(Pr, pmp->pr_vaddr, pmp->pr_mapname, 729*7c478bd9Sstevel@tonic-gate mname, sizeof (mname)); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate if (lname == NULL && 733*7c478bd9Sstevel@tonic-gate ((pmp->pr_mflags & MA_ANON) || Pstate(Pr) == PS_DEAD)) { 734*7c478bd9Sstevel@tonic-gate lname = anon_name(mname, Psp, pmp->pr_vaddr, 735*7c478bd9Sstevel@tonic-gate pmp->pr_size, pmp->pr_mflags, pmp->pr_shmid); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate 738*7c478bd9Sstevel@tonic-gate if (lname != NULL) 739*7c478bd9Sstevel@tonic-gate format = "%.*lX %*luK %4s %-6s %s\n"; 740*7c478bd9Sstevel@tonic-gate else 741*7c478bd9Sstevel@tonic-gate format = "%.*lX %*luK %4s %s\n"; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate (void) printf(format, addr_width, (uintptr_t)pmp->pr_vaddr, 744*7c478bd9Sstevel@tonic-gate size_width - 1, size, 745*7c478bd9Sstevel@tonic-gate pagesize(pmp), mflags(pmp->pr_mflags), lname); 746*7c478bd9Sstevel@tonic-gate 747*7c478bd9Sstevel@tonic-gate t->total_size += size; 748*7c478bd9Sstevel@tonic-gate return (0); 749*7c478bd9Sstevel@tonic-gate } 750*7c478bd9Sstevel@tonic-gate 751*7c478bd9Sstevel@tonic-gate #define ANON(x) ((aflag || (((x)->pr_mflags & MA_SHARED) == 0)) ? \ 752*7c478bd9Sstevel@tonic-gate ((x)->pr_anon) : 0) 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 755*7c478bd9Sstevel@tonic-gate static int 756*7c478bd9Sstevel@tonic-gate look_xmap(void *data, 757*7c478bd9Sstevel@tonic-gate const prxmap_t *pmp, 758*7c478bd9Sstevel@tonic-gate const char *object_name, 759*7c478bd9Sstevel@tonic-gate int last, int doswap) 760*7c478bd9Sstevel@tonic-gate { 761*7c478bd9Sstevel@tonic-gate struct totals *t = data; 762*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Pr); 763*7c478bd9Sstevel@tonic-gate char mname[PATH_MAX]; 764*7c478bd9Sstevel@tonic-gate char *lname = NULL; 765*7c478bd9Sstevel@tonic-gate char *ln; 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate /* 768*7c478bd9Sstevel@tonic-gate * If the mapping is not anon or not part of the heap, make a name 769*7c478bd9Sstevel@tonic-gate * for it. We don't want to report the heap as a.out's data. 770*7c478bd9Sstevel@tonic-gate */ 771*7c478bd9Sstevel@tonic-gate if (!(pmp->pr_mflags & MA_ANON) || 772*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr + pmp->pr_size <= Psp->pr_brkbase || 773*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr >= Psp->pr_brkbase + Psp->pr_brksize) { 774*7c478bd9Sstevel@tonic-gate lname = make_name(Pr, pmp->pr_vaddr, pmp->pr_mapname, 775*7c478bd9Sstevel@tonic-gate mname, sizeof (mname)); 776*7c478bd9Sstevel@tonic-gate } 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate if (lname != NULL) { 779*7c478bd9Sstevel@tonic-gate if ((ln = strrchr(lname, '/')) != NULL) 780*7c478bd9Sstevel@tonic-gate lname = ln + 1; 781*7c478bd9Sstevel@tonic-gate } else if ((pmp->pr_mflags & MA_ANON) || Pstate(Pr) == PS_DEAD) { 782*7c478bd9Sstevel@tonic-gate lname = anon_name(mname, Psp, pmp->pr_vaddr, 783*7c478bd9Sstevel@tonic-gate pmp->pr_size, pmp->pr_mflags, pmp->pr_shmid); 784*7c478bd9Sstevel@tonic-gate } 785*7c478bd9Sstevel@tonic-gate 786*7c478bd9Sstevel@tonic-gate (void) printf("%.*lX", addr_width, (ulong_t)pmp->pr_vaddr); 787*7c478bd9Sstevel@tonic-gate 788*7c478bd9Sstevel@tonic-gate printK((pmp->pr_size + 1023) / 1024, size_width); 789*7c478bd9Sstevel@tonic-gate printK(pmp->pr_rss * (pmp->pr_pagesize / 1024), size_width); 790*7c478bd9Sstevel@tonic-gate printK(ANON(pmp) * (pmp->pr_pagesize / 1024), size_width); 791*7c478bd9Sstevel@tonic-gate printK(pmp->pr_locked * (pmp->pr_pagesize / 1024), size_width); 792*7c478bd9Sstevel@tonic-gate (void) printf(lname ? " %4s %-6s %s\n" : " %4s %s\n", 793*7c478bd9Sstevel@tonic-gate pagesize(pmp), mflags(pmp->pr_mflags), lname); 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate t->total_size += (pmp->pr_size + 1023) / 1024; 796*7c478bd9Sstevel@tonic-gate t->total_rss += pmp->pr_rss * (pmp->pr_pagesize / 1024); 797*7c478bd9Sstevel@tonic-gate t->total_anon += ANON(pmp) * (pmp->pr_pagesize / 1024); 798*7c478bd9Sstevel@tonic-gate t->total_locked += (pmp->pr_locked * (pmp->pr_pagesize / 1024)); 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate return (0); 801*7c478bd9Sstevel@tonic-gate } 802*7c478bd9Sstevel@tonic-gate 803*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 804*7c478bd9Sstevel@tonic-gate static int 805*7c478bd9Sstevel@tonic-gate look_xmap_nopgsz(void *data, 806*7c478bd9Sstevel@tonic-gate const prxmap_t *pmp, 807*7c478bd9Sstevel@tonic-gate const char *object_name, 808*7c478bd9Sstevel@tonic-gate int last, int doswap) 809*7c478bd9Sstevel@tonic-gate { 810*7c478bd9Sstevel@tonic-gate struct totals *t = data; 811*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Pr); 812*7c478bd9Sstevel@tonic-gate char mname[PATH_MAX]; 813*7c478bd9Sstevel@tonic-gate char *lname = NULL; 814*7c478bd9Sstevel@tonic-gate char *ln; 815*7c478bd9Sstevel@tonic-gate static uintptr_t prev_vaddr; 816*7c478bd9Sstevel@tonic-gate static size_t prev_size; 817*7c478bd9Sstevel@tonic-gate static offset_t prev_offset; 818*7c478bd9Sstevel@tonic-gate static int prev_mflags; 819*7c478bd9Sstevel@tonic-gate static char *prev_lname; 820*7c478bd9Sstevel@tonic-gate static char prev_mname[PATH_MAX]; 821*7c478bd9Sstevel@tonic-gate static ulong_t prev_rss; 822*7c478bd9Sstevel@tonic-gate static ulong_t prev_anon; 823*7c478bd9Sstevel@tonic-gate static ulong_t prev_locked; 824*7c478bd9Sstevel@tonic-gate static ulong_t prev_swap; 825*7c478bd9Sstevel@tonic-gate int merged = 0; 826*7c478bd9Sstevel@tonic-gate static int first = 1; 827*7c478bd9Sstevel@tonic-gate ulong_t swap = 0; 828*7c478bd9Sstevel@tonic-gate int kperpage; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate /* 831*7c478bd9Sstevel@tonic-gate * Calculate swap reservations 832*7c478bd9Sstevel@tonic-gate */ 833*7c478bd9Sstevel@tonic-gate if (pmp->pr_mflags & MA_SHARED) { 834*7c478bd9Sstevel@tonic-gate if (aflag && (pmp->pr_mflags & MA_NORESERVE) == 0) { 835*7c478bd9Sstevel@tonic-gate /* Swap reserved for entire non-ism SHM */ 836*7c478bd9Sstevel@tonic-gate swap = pmp->pr_size / pmp->pr_pagesize; 837*7c478bd9Sstevel@tonic-gate } 838*7c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_NORESERVE) { 839*7c478bd9Sstevel@tonic-gate /* Swap reserved on fault for each anon page */ 840*7c478bd9Sstevel@tonic-gate swap = pmp->pr_anon; 841*7c478bd9Sstevel@tonic-gate } else if (pmp->pr_mflags & MA_WRITE) { 842*7c478bd9Sstevel@tonic-gate /* Swap reserve for entire writable segment */ 843*7c478bd9Sstevel@tonic-gate swap = pmp->pr_size / pmp->pr_pagesize; 844*7c478bd9Sstevel@tonic-gate } 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate /* 847*7c478bd9Sstevel@tonic-gate * If the mapping is not anon or not part of the heap, make a name 848*7c478bd9Sstevel@tonic-gate * for it. We don't want to report the heap as a.out's data. 849*7c478bd9Sstevel@tonic-gate */ 850*7c478bd9Sstevel@tonic-gate if (!(pmp->pr_mflags & MA_ANON) || 851*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr + pmp->pr_size <= Psp->pr_brkbase || 852*7c478bd9Sstevel@tonic-gate pmp->pr_vaddr >= Psp->pr_brkbase + Psp->pr_brksize) { 853*7c478bd9Sstevel@tonic-gate lname = make_name(Pr, pmp->pr_vaddr, pmp->pr_mapname, 854*7c478bd9Sstevel@tonic-gate mname, sizeof (mname)); 855*7c478bd9Sstevel@tonic-gate } 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate if (lname != NULL) { 858*7c478bd9Sstevel@tonic-gate if ((ln = strrchr(lname, '/')) != NULL) 859*7c478bd9Sstevel@tonic-gate lname = ln + 1; 860*7c478bd9Sstevel@tonic-gate } else if ((pmp->pr_mflags & MA_ANON) || Pstate(Pr) == PS_DEAD) { 861*7c478bd9Sstevel@tonic-gate lname = anon_name(mname, Psp, pmp->pr_vaddr, 862*7c478bd9Sstevel@tonic-gate pmp->pr_size, pmp->pr_mflags, pmp->pr_shmid); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate 865*7c478bd9Sstevel@tonic-gate kperpage = pmp->pr_pagesize / 1024; 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate t->total_size += (pmp->pr_size + 1023) / 1024; 868*7c478bd9Sstevel@tonic-gate t->total_rss += pmp->pr_rss * kperpage; 869*7c478bd9Sstevel@tonic-gate t->total_anon += ANON(pmp) * kperpage; 870*7c478bd9Sstevel@tonic-gate t->total_locked += pmp->pr_locked * kperpage; 871*7c478bd9Sstevel@tonic-gate t->total_swap += swap * kperpage; 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate if (first == 1) { 874*7c478bd9Sstevel@tonic-gate first = 0; 875*7c478bd9Sstevel@tonic-gate prev_vaddr = pmp->pr_vaddr; 876*7c478bd9Sstevel@tonic-gate prev_size = pmp->pr_size; 877*7c478bd9Sstevel@tonic-gate prev_offset = pmp->pr_offset; 878*7c478bd9Sstevel@tonic-gate prev_mflags = pmp->pr_mflags; 879*7c478bd9Sstevel@tonic-gate if (lname == NULL) { 880*7c478bd9Sstevel@tonic-gate prev_lname = NULL; 881*7c478bd9Sstevel@tonic-gate } else { 882*7c478bd9Sstevel@tonic-gate (void) strcpy(prev_mname, lname); 883*7c478bd9Sstevel@tonic-gate prev_lname = prev_mname; 884*7c478bd9Sstevel@tonic-gate } 885*7c478bd9Sstevel@tonic-gate prev_rss = pmp->pr_rss * kperpage; 886*7c478bd9Sstevel@tonic-gate prev_anon = ANON(pmp) * kperpage; 887*7c478bd9Sstevel@tonic-gate prev_locked = pmp->pr_locked * kperpage; 888*7c478bd9Sstevel@tonic-gate prev_swap = swap * kperpage; 889*7c478bd9Sstevel@tonic-gate if (last == 0) { 890*7c478bd9Sstevel@tonic-gate return (0); 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate merged = 1; 893*7c478bd9Sstevel@tonic-gate } else if (prev_vaddr + prev_size == pmp->pr_vaddr && 894*7c478bd9Sstevel@tonic-gate prev_mflags == pmp->pr_mflags && 895*7c478bd9Sstevel@tonic-gate ((prev_mflags & MA_ISM) || 896*7c478bd9Sstevel@tonic-gate prev_offset + prev_size == pmp->pr_offset) && 897*7c478bd9Sstevel@tonic-gate ((lname == NULL && prev_lname == NULL) || 898*7c478bd9Sstevel@tonic-gate (lname != NULL && prev_lname != NULL && 899*7c478bd9Sstevel@tonic-gate strcmp(lname, prev_lname) == 0))) { 900*7c478bd9Sstevel@tonic-gate prev_size += pmp->pr_size; 901*7c478bd9Sstevel@tonic-gate prev_rss += pmp->pr_rss * kperpage; 902*7c478bd9Sstevel@tonic-gate prev_anon += ANON(pmp) * kperpage; 903*7c478bd9Sstevel@tonic-gate prev_locked += pmp->pr_locked * kperpage; 904*7c478bd9Sstevel@tonic-gate prev_swap += swap * kperpage; 905*7c478bd9Sstevel@tonic-gate if (last == 0) { 906*7c478bd9Sstevel@tonic-gate return (0); 907*7c478bd9Sstevel@tonic-gate } 908*7c478bd9Sstevel@tonic-gate merged = 1; 909*7c478bd9Sstevel@tonic-gate } 910*7c478bd9Sstevel@tonic-gate 911*7c478bd9Sstevel@tonic-gate (void) printf("%.*lX", addr_width, (ulong_t)prev_vaddr); 912*7c478bd9Sstevel@tonic-gate printK((prev_size + 1023) / 1024, size_width); 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate if (doswap) 915*7c478bd9Sstevel@tonic-gate printK(prev_swap, size_width); 916*7c478bd9Sstevel@tonic-gate else { 917*7c478bd9Sstevel@tonic-gate printK(prev_rss, size_width); 918*7c478bd9Sstevel@tonic-gate printK(prev_anon, size_width); 919*7c478bd9Sstevel@tonic-gate printK(prev_locked, size_width); 920*7c478bd9Sstevel@tonic-gate } 921*7c478bd9Sstevel@tonic-gate (void) printf(prev_lname ? " %-6s %s\n" : " %s\n", 922*7c478bd9Sstevel@tonic-gate mflags(prev_mflags), prev_lname); 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate if (last == 0) { 925*7c478bd9Sstevel@tonic-gate prev_vaddr = pmp->pr_vaddr; 926*7c478bd9Sstevel@tonic-gate prev_size = pmp->pr_size; 927*7c478bd9Sstevel@tonic-gate prev_offset = pmp->pr_offset; 928*7c478bd9Sstevel@tonic-gate prev_mflags = pmp->pr_mflags; 929*7c478bd9Sstevel@tonic-gate if (lname == NULL) { 930*7c478bd9Sstevel@tonic-gate prev_lname = NULL; 931*7c478bd9Sstevel@tonic-gate } else { 932*7c478bd9Sstevel@tonic-gate (void) strcpy(prev_mname, lname); 933*7c478bd9Sstevel@tonic-gate prev_lname = prev_mname; 934*7c478bd9Sstevel@tonic-gate } 935*7c478bd9Sstevel@tonic-gate prev_rss = pmp->pr_rss * kperpage; 936*7c478bd9Sstevel@tonic-gate prev_anon = ANON(pmp) * kperpage; 937*7c478bd9Sstevel@tonic-gate prev_locked = pmp->pr_locked * kperpage; 938*7c478bd9Sstevel@tonic-gate prev_swap = swap * kperpage; 939*7c478bd9Sstevel@tonic-gate } else if (merged == 0) { 940*7c478bd9Sstevel@tonic-gate (void) printf("%.*lX", addr_width, (ulong_t)pmp->pr_vaddr); 941*7c478bd9Sstevel@tonic-gate printK((pmp->pr_size + 1023) / 1024, size_width); 942*7c478bd9Sstevel@tonic-gate if (doswap) 943*7c478bd9Sstevel@tonic-gate printK(swap * kperpage, size_width); 944*7c478bd9Sstevel@tonic-gate else { 945*7c478bd9Sstevel@tonic-gate printK(pmp->pr_rss * kperpage, size_width); 946*7c478bd9Sstevel@tonic-gate printK(ANON(pmp) * kperpage, size_width); 947*7c478bd9Sstevel@tonic-gate printK(pmp->pr_locked * kperpage, size_width); 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate (void) printf(lname ? " %-6s %s\n" : " %s\n", 950*7c478bd9Sstevel@tonic-gate mflags(pmp->pr_mflags), lname); 951*7c478bd9Sstevel@tonic-gate } 952*7c478bd9Sstevel@tonic-gate 953*7c478bd9Sstevel@tonic-gate if (last != 0) 954*7c478bd9Sstevel@tonic-gate first = 1; 955*7c478bd9Sstevel@tonic-gate 956*7c478bd9Sstevel@tonic-gate return (0); 957*7c478bd9Sstevel@tonic-gate } 958*7c478bd9Sstevel@tonic-gate 959*7c478bd9Sstevel@tonic-gate static int 960*7c478bd9Sstevel@tonic-gate perr(char *s) 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate if (s) 963*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", procname); 964*7c478bd9Sstevel@tonic-gate else 965*7c478bd9Sstevel@tonic-gate s = procname; 966*7c478bd9Sstevel@tonic-gate perror(s); 967*7c478bd9Sstevel@tonic-gate return (1); 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate static char * 971*7c478bd9Sstevel@tonic-gate mflags(uint_t arg) 972*7c478bd9Sstevel@tonic-gate { 973*7c478bd9Sstevel@tonic-gate static char code_buf[80]; 974*7c478bd9Sstevel@tonic-gate char *str = code_buf; 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate /* 977*7c478bd9Sstevel@tonic-gate * rwxsR 978*7c478bd9Sstevel@tonic-gate * 979*7c478bd9Sstevel@tonic-gate * r - segment is readable 980*7c478bd9Sstevel@tonic-gate * w - segment is writable 981*7c478bd9Sstevel@tonic-gate * x - segment is executable 982*7c478bd9Sstevel@tonic-gate * s - segment is shared 983*7c478bd9Sstevel@tonic-gate * R - segment is mapped MAP_NORESERVE 984*7c478bd9Sstevel@tonic-gate * 985*7c478bd9Sstevel@tonic-gate */ 986*7c478bd9Sstevel@tonic-gate (void) sprintf(str, "%c%c%c%c%c%c", 987*7c478bd9Sstevel@tonic-gate arg & MA_READ ? 'r' : '-', 988*7c478bd9Sstevel@tonic-gate arg & MA_WRITE ? 'w' : '-', 989*7c478bd9Sstevel@tonic-gate arg & MA_EXEC ? 'x' : '-', 990*7c478bd9Sstevel@tonic-gate arg & MA_SHARED ? 's' : '-', 991*7c478bd9Sstevel@tonic-gate arg & MA_NORESERVE ? 'R' : '-', 992*7c478bd9Sstevel@tonic-gate arg & MA_RESERVED1 ? '*' : ' '); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate return (str); 995*7c478bd9Sstevel@tonic-gate } 996*7c478bd9Sstevel@tonic-gate 997*7c478bd9Sstevel@tonic-gate static mapdata_t * 998*7c478bd9Sstevel@tonic-gate nextmap(void) 999*7c478bd9Sstevel@tonic-gate { 1000*7c478bd9Sstevel@tonic-gate mapdata_t *newmaps; 1001*7c478bd9Sstevel@tonic-gate int next; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate if (map_count == map_alloc) { 1004*7c478bd9Sstevel@tonic-gate if (map_alloc == 0) 1005*7c478bd9Sstevel@tonic-gate next = 16; 1006*7c478bd9Sstevel@tonic-gate else 1007*7c478bd9Sstevel@tonic-gate next = map_alloc * 2; 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate newmaps = realloc(maps, next * sizeof (mapdata_t)); 1010*7c478bd9Sstevel@tonic-gate if (newmaps == NULL) { 1011*7c478bd9Sstevel@tonic-gate (void) perr("failed to allocate maps"); 1012*7c478bd9Sstevel@tonic-gate exit(1); 1013*7c478bd9Sstevel@tonic-gate } 1014*7c478bd9Sstevel@tonic-gate (void) memset(newmaps + map_alloc, '\0', 1015*7c478bd9Sstevel@tonic-gate (next - map_alloc) * sizeof (mapdata_t)); 1016*7c478bd9Sstevel@tonic-gate 1017*7c478bd9Sstevel@tonic-gate map_alloc = next; 1018*7c478bd9Sstevel@tonic-gate maps = newmaps; 1019*7c478bd9Sstevel@tonic-gate } 1020*7c478bd9Sstevel@tonic-gate 1021*7c478bd9Sstevel@tonic-gate return (&maps[map_count++]); 1022*7c478bd9Sstevel@tonic-gate } 1023*7c478bd9Sstevel@tonic-gate 1024*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1025*7c478bd9Sstevel@tonic-gate static int 1026*7c478bd9Sstevel@tonic-gate gather_map(void *ignored, const prmap_t *map, const char *objname) 1027*7c478bd9Sstevel@tonic-gate { 1028*7c478bd9Sstevel@tonic-gate mapdata_t *data = nextmap(); 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate data->md_map = *map; 1031*7c478bd9Sstevel@tonic-gate if (data->md_objname != NULL) 1032*7c478bd9Sstevel@tonic-gate free(data->md_objname); 1033*7c478bd9Sstevel@tonic-gate data->md_objname = objname ? strdup(objname) : NULL; 1034*7c478bd9Sstevel@tonic-gate 1035*7c478bd9Sstevel@tonic-gate return (0); 1036*7c478bd9Sstevel@tonic-gate } 1037*7c478bd9Sstevel@tonic-gate 1038*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1039*7c478bd9Sstevel@tonic-gate static int 1040*7c478bd9Sstevel@tonic-gate gather_xmap(void *ignored, const prxmap_t *xmap, const char *objname, 1041*7c478bd9Sstevel@tonic-gate int last, int doswap) 1042*7c478bd9Sstevel@tonic-gate { 1043*7c478bd9Sstevel@tonic-gate mapdata_t *data = nextmap(); 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate data->md_xmap = *xmap; 1046*7c478bd9Sstevel@tonic-gate if (data->md_objname != NULL) 1047*7c478bd9Sstevel@tonic-gate free(data->md_objname); 1048*7c478bd9Sstevel@tonic-gate data->md_objname = objname ? strdup(objname) : NULL; 1049*7c478bd9Sstevel@tonic-gate data->md_last = last; 1050*7c478bd9Sstevel@tonic-gate data->md_doswap = doswap; 1051*7c478bd9Sstevel@tonic-gate 1052*7c478bd9Sstevel@tonic-gate return (0); 1053*7c478bd9Sstevel@tonic-gate } 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate static int 1056*7c478bd9Sstevel@tonic-gate iter_map(proc_map_f *func, void *data) 1057*7c478bd9Sstevel@tonic-gate { 1058*7c478bd9Sstevel@tonic-gate int i; 1059*7c478bd9Sstevel@tonic-gate int ret; 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate for (i = 0; i < map_count; i++) { 1062*7c478bd9Sstevel@tonic-gate if ((ret = func(data, &maps[i].md_map, 1063*7c478bd9Sstevel@tonic-gate maps[i].md_objname)) != 0) 1064*7c478bd9Sstevel@tonic-gate return (ret); 1065*7c478bd9Sstevel@tonic-gate } 1066*7c478bd9Sstevel@tonic-gate 1067*7c478bd9Sstevel@tonic-gate return (0); 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate 1070*7c478bd9Sstevel@tonic-gate static int 1071*7c478bd9Sstevel@tonic-gate iter_xmap(proc_xmap_f *func, void *data) 1072*7c478bd9Sstevel@tonic-gate { 1073*7c478bd9Sstevel@tonic-gate int i; 1074*7c478bd9Sstevel@tonic-gate int ret; 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate for (i = 0; i < map_count; i++) { 1077*7c478bd9Sstevel@tonic-gate if ((ret = func(data, &maps[i].md_xmap, maps[i].md_objname, 1078*7c478bd9Sstevel@tonic-gate maps[i].md_last, maps[i].md_doswap)) != 0) 1079*7c478bd9Sstevel@tonic-gate return (ret); 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate 1082*7c478bd9Sstevel@tonic-gate return (0); 1083*7c478bd9Sstevel@tonic-gate } 1084