static int look(char *arg) { int gcode; int gcode2; pstatus_t pstatus; psinfo_t psinfo; int flags; sigset_t sigmask; fltset_t fltmask; sysset_t entryset; sysset_t exitset; uint32_t sigtrace, sigtrace1, sigtrace2, fltbits; uint32_t sigpend, sigpend1, sigpend2; uint32_t *bits; char buf[PRSIGBUFSZ]; look_arg_t lookarg; if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_ANY, PGRAB_RETAIN | PGRAB_FORCE | PGRAB_RDONLY | PGRAB_NOSTOP, &gcode, &lookarg.lwps)) == NULL) { if (gcode == G_NOPROC && proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gcode2) > 0 && psinfo.pr_nlwp == 0) { (void) printf("%d:\t<defunct>\n\n", (int)psinfo.pr_pid); return (0); } (void) fprintf(stderr, "%s: cannot examine %s: %s\n", command, arg, Pgrab_error(gcode)); return (1); } (void) memcpy(&pstatus, Pstatus(Pr), sizeof (pstatus_t)); (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t)); proc_unctrl_psinfo(&psinfo); if (psinfo.pr_nlwp == 0) { (void) printf("%d:\t<defunct>\n\n", (int)psinfo.pr_pid); Prelease(Pr, PRELEASE_RETAIN); return (0); } is64 = (pstatus.pr_dmodel == PR_MODEL_LP64); sigmask = pstatus.pr_sigtrace; fltmask = pstatus.pr_flttrace; entryset = pstatus.pr_sysentry; exitset = pstatus.pr_sysexit; if (Pstate(Pr) == PS_DEAD) { (void) printf("core '%s' of %d:\t%.70s\n", arg, (int)psinfo.pr_pid, psinfo.pr_psargs); } else { (void) printf("%d:\t%.70s\n", (int)psinfo.pr_pid, psinfo.pr_psargs); } (void) printf("\tdata model = %s", is64? "_LP64" : "_ILP32"); if ((flags = (pstatus.pr_flags & PROCFLAGS)) != 0) (void) printf(" flags = %s", prflags(flags)); (void) printf("\n"); fltbits = *((uint32_t *)&fltmask); if (fltbits) (void) printf("\tflttrace = 0x%.8x\n", fltbits); #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */ sigtrace = *((uint32_t *)&sigmask); sigtrace1 = *((uint32_t *)&sigmask + 1); sigtrace2 = *((uint32_t *)&sigmask + 2); #else #error "fix me: MAXSIG out of bounds" #endif if (sigtrace | sigtrace1 | sigtrace2) (void) printf("\tsigtrace = 0x%.8x 0x%.8x 0x%.8x\n\t %s\n", sigtrace, sigtrace1, sigtrace2, proc_sigset2str(&sigmask, "|", 1, buf, sizeof (buf))); bits = ((uint32_t *)&entryset); if (bits[0] | bits[1] | bits[2] | bits[3] | bits[4] | bits[5] | bits[6] | bits[7]) (void) printf( "\tentryset = " "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" "\t " "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); bits = ((uint32_t *)&exitset); if (bits[0] | bits[1] | bits[2] | bits[3] | bits[4] | bits[5] | bits[6] | bits[7]) (void) printf( "\texitset = " "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" "\t " "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n", bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); #if (MAXSIG > 2 * 32) && (MAXSIG <= 3 * 32) /* assumption */ sigpend = *((uint32_t *)&pstatus.pr_sigpend); sigpend1 = *((uint32_t *)&pstatus.pr_sigpend + 1); sigpend2 = *((uint32_t *)&pstatus.pr_sigpend + 2); #else #error "fix me: MAXSIG out of bounds" #endif if (sigpend | sigpend1 | sigpend2) (void) printf("\tsigpend = 0x%.8x,0x%.8x,0x%.8x\n", sigpend, sigpend1, sigpend2); lookarg.pflags = pstatus.pr_flags; lookarg.count = 0; (void) Plwp_iter_all(Pr, (proc_lwp_all_f *)lwplook, &lookarg); if (lookarg.count == 0) (void) printf("No matching lwps found"); (void) printf("\n"); Prelease(Pr, PRELEASE_RETAIN); return (0); }
int main(int argc, char **argv) { int rflag = 0, sflag = 0, xflag = 0, Fflag = 0; int errflg = 0, Sflag = 0; int rc = 0; int opt; const char *bar8 = "-------"; const char *bar16 = "----------"; const char *bar; struct rlimit rlim; struct stat64 statbuf; char buf[128]; int mapfd; int prg_gflags = PGRAB_RDONLY; int prr_flags = 0; boolean_t use_agent_lwp = B_FALSE; if ((command = strrchr(argv[0], '/')) != NULL) command++; else command = argv[0]; while ((opt = getopt(argc, argv, "arsxSlLFA:")) != EOF) { switch (opt) { case 'a': /* include shared mappings in -[xS] */ aflag = 1; break; case 'r': /* show reserved mappings */ rflag = 1; break; case 's': /* show hardware page sizes */ sflag = 1; break; case 'S': /* show swap reservations */ Sflag = 1; break; case 'x': /* show extended mappings */ xflag = 1; break; case 'l': /* show unresolved link map names */ lflag = 1; break; case 'L': /* show lgroup information */ Lflag = 1; use_agent_lwp = B_TRUE; break; case 'F': /* force grabbing (no O_EXCL) */ Fflag = PGRAB_FORCE; break; case 'A': if (parse_addr_range(optarg, &start_addr, &end_addr) != 0) errflg++; break; default: errflg = 1; break; } } argc -= optind; argv += optind; if ((Sflag && (xflag || rflag || sflag)) || (xflag && rflag) || (aflag && (!xflag && !Sflag)) || (Lflag && (xflag || Sflag))) { errflg = 1; } if (errflg || argc <= 0) { (void) fprintf(stderr, "usage:\t%s [-rslF] [-A start[,end]] { pid | core } ...\n", command); (void) fprintf(stderr, "\t\t(report process address maps)\n"); (void) fprintf(stderr, "\t%s -L [-rslF] [-A start[,end]] pid ...\n", command); (void) fprintf(stderr, "\t\t(report process address maps lgroups mappings)\n"); (void) fprintf(stderr, "\t%s -x [-aslF] [-A start[,end]] pid ...\n", command); (void) fprintf(stderr, "\t\t(show resident/anon/locked mapping details)\n"); (void) fprintf(stderr, "\t%s -S [-alF] [-A start[,end]] { pid | core } ...\n", command); (void) fprintf(stderr, "\t\t(show swap reservations)\n\n"); (void) fprintf(stderr, "\t-a: include shared mappings in -[xS] summary\n"); (void) fprintf(stderr, "\t-r: show reserved address maps\n"); (void) fprintf(stderr, "\t-s: show hardware page sizes\n"); (void) fprintf(stderr, "\t-l: show unresolved dynamic linker map names\n"); (void) fprintf(stderr, "\t-F: force grabbing of the target process\n"); (void) fprintf(stderr, "\t-L: show lgroup mappings\n"); (void) fprintf(stderr, "\t-A start,end: limit output to the specified range\n"); return (2); } /* * Make sure we'll have enough file descriptors to handle a target * that has many many mappings. */ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { rlim.rlim_cur = rlim.rlim_max; (void) setrlimit(RLIMIT_NOFILE, &rlim); (void) enable_extended_FILE_stdio(-1, -1); } /* * The implementation of -L option creates an agent LWP in the target * process address space. The agent LWP issues meminfo(2) system calls * on behalf of the target process. If we are interrupted prematurely, * the target process remains in the stopped state with the agent still * attached to it. To prevent such situation we catch signals from * terminal and terminate gracefully. */ if (use_agent_lwp) { /* * Buffer output to stdout, stderr while process is grabbed. * Prevents infamous deadlocks due to pmap `pgrep xterm` and * other variants. */ (void) proc_initstdio(); prg_gflags = PGRAB_RETAIN | Fflag; prr_flags = PRELEASE_RETAIN; if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) (void) sigset(SIGHUP, intr); if (sigset(SIGINT, SIG_IGN) == SIG_DFL) (void) sigset(SIGINT, intr); if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) (void) sigset(SIGQUIT, intr); (void) sigset(SIGPIPE, intr); (void) sigset(SIGTERM, intr); } while (argc-- > 0) { char *arg; int gcode; psinfo_t psinfo; int tries = 0; if (use_agent_lwp) (void) proc_flushstdio(); if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY, prg_gflags, &gcode)) == NULL) { (void) fprintf(stderr, "%s: cannot examine %s: %s\n", command, arg, Pgrab_error(gcode)); rc++; continue; } procname = arg; /* for perr() */ addr_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 16 : 8; size_width = (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) ? 11 : 8; bar = addr_width == 8 ? bar8 : bar16; (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t)); proc_unctrl_psinfo(&psinfo); if (Pstate(Pr) != PS_DEAD) { (void) snprintf(buf, sizeof (buf), "/proc/%d/map", (int)psinfo.pr_pid); if ((mapfd = open(buf, O_RDONLY)) < 0) { (void) fprintf(stderr, "%s: cannot " "examine %s: lost control of " "process\n", command, arg); rc++; Prelease(Pr, prr_flags); continue; } } else { mapfd = -1; } again: map_count = 0; if (Pstate(Pr) == PS_DEAD) { (void) printf("core '%s' of %d:\t%.70s\n", arg, (int)psinfo.pr_pid, psinfo.pr_psargs); if (rflag || sflag || xflag || Sflag || Lflag) { (void) printf(" -%c option is not compatible " "with core files\n", xflag ? 'x' : sflag ? 's' : rflag ? 'r' : Lflag ? 'L' : 'S'); Prelease(Pr, prr_flags); rc++; continue; } } else { (void) printf("%d:\t%.70s\n", (int)psinfo.pr_pid, psinfo.pr_psargs); } if (!(Pstatus(Pr)->pr_flags & PR_ISSYS)) { struct totals t; /* * Since we're grabbing the process readonly, we need * to make sure the address space doesn't change during * execution. */ if (Pstate(Pr) != PS_DEAD) { if (tries++ == MAX_TRIES) { Prelease(Pr, prr_flags); (void) close(mapfd); (void) fprintf(stderr, "%s: cannot " "examine %s: address space is " "changing\n", command, arg); continue; } if (fstat64(mapfd, &statbuf) != 0) { Prelease(Pr, prr_flags); (void) close(mapfd); (void) fprintf(stderr, "%s: cannot " "examine %s: lost control of " "process\n", command, arg); continue; } } nstacks = psinfo.pr_nlwp * 2; stacks = calloc(nstacks, sizeof (stacks[0])); if (stacks != NULL) { int n = 0; (void) Plwp_iter(Pr, getstack, &n); qsort(stacks, nstacks, sizeof (stacks[0]), cmpstacks); } (void) memset(&t, 0, sizeof (t)); if (Pgetauxval(Pr, AT_BASE) != -1L && Prd_agent(Pr) == NULL) { (void) fprintf(stderr, "%s: warning: " "librtld_db failed to initialize; " "shared library information will not be " "available\n", command); } /* * Gather data */ if (xflag) rc += xmapping_iter(Pr, gather_xmap, NULL, 0); else if (Sflag) rc += xmapping_iter(Pr, gather_xmap, NULL, 1); else { if (rflag) rc += rmapping_iter(Pr, gather_map, NULL); else if (sflag) rc += xmapping_iter(Pr, gather_xmap, NULL, 0); else if (lflag) rc += Pmapping_iter(Pr, gather_map, NULL); else rc += Pmapping_iter_resolved(Pr, gather_map, NULL); } /* * Ensure mappings are consistent. */ if (Pstate(Pr) != PS_DEAD) { struct stat64 newbuf; if (fstat64(mapfd, &newbuf) != 0 || memcmp(&newbuf.st_mtim, &statbuf.st_mtim, sizeof (newbuf.st_mtim)) != 0) { if (stacks != NULL) { free(stacks); stacks = NULL; } goto again; } } /* * Display data. */ if (xflag) { (void) printf("%*s%*s%*s%*s%*s " "%sMode Mapped File\n", addr_width, "Address", size_width, "Kbytes", size_width, "RSS", size_width, "Anon", size_width, "Locked", sflag ? "Pgsz " : ""); rc += iter_xmap(sflag ? look_xmap : look_xmap_nopgsz, &t); (void) printf("%s%s %s %s %s %s\n", addr_width == 8 ? "-" : "------", bar, bar, bar, bar, bar); (void) printf("%stotal Kb", addr_width == 16 ? " " : ""); printK(t.total_size, size_width); printK(t.total_rss, size_width); printK(t.total_anon, size_width); printK(t.total_locked, size_width); (void) printf("\n"); } else if (Sflag) { (void) printf("%*s%*s%*s Mode" " Mapped File\n", addr_width, "Address", size_width, "Kbytes", size_width, "Swap"); rc += iter_xmap(look_xmap_nopgsz, &t); (void) printf("%s%s %s %s\n", addr_width == 8 ? "-" : "------", bar, bar, bar); (void) printf("%stotal Kb", addr_width == 16 ? " " : ""); printK(t.total_size, size_width); printK(t.total_swap, size_width); (void) printf("\n"); } else { if (rflag) { rc += iter_map(look_map, &t); } else if (sflag) { if (Lflag) { (void) printf("%*s %*s %4s" " %-6s %s %s\n", addr_width, "Address", size_width, "Bytes", "Pgsz", "Mode ", "Lgrp", "Mapped File"); rc += iter_xmap(look_smap, &t); } else { (void) printf("%*s %*s %4s" " %-6s %s\n", addr_width, "Address", size_width, "Bytes", "Pgsz", "Mode ", "Mapped File"); rc += iter_xmap(look_smap, &t); } } else { rc += iter_map(look_map, &t); } (void) printf(" %stotal %*luK\n", addr_width == 16 ? " " : "", size_width, t.total_size); } if (stacks != NULL) { free(stacks); stacks = NULL; } } Prelease(Pr, prr_flags); if (mapfd != -1) (void) close(mapfd); } if (use_agent_lwp) (void) proc_finistdio(); return (rc); }
int main(int argc, char **argv) { secflagdelta_t act; psecflagwhich_t which = PSF_INHERIT; int ret = 0; int pgrab_flags = PGRAB_RDONLY; int opt; char *idtypename = NULL; idtype_t idtype = P_PID; boolean_t usage = B_FALSE; boolean_t e_flag = B_FALSE; boolean_t l_flag = B_FALSE; boolean_t s_flag = B_FALSE; int errc = 0; while ((opt = getopt(argc, argv, "eFi:ls:")) != -1) { switch (opt) { case 'e': e_flag = B_TRUE; break; case 'F': pgrab_flags |= PGRAB_FORCE; break; case 'i': idtypename = optarg; break; case 's': s_flag = B_TRUE; if ((strlen(optarg) >= 2) && ((optarg[1] == '='))) { switch (optarg[0]) { case 'L': which = PSF_LOWER; break; case 'U': which = PSF_UPPER; break; case 'I': which = PSF_INHERIT; break; case 'E': errx(1, "the effective flags cannot " "be changed", optarg[0]); default: errx(1, "unknown security flag " "set: '%c'", optarg[0]); } optarg += 2; } if (secflags_parse(NULL, optarg, &act) == -1) errx(1, "couldn't parse security flags: %s", optarg); break; case 'l': l_flag = B_TRUE; break; default: usage = B_TRUE; break; } } argc -= optind; argv += optind; if (l_flag && ((idtypename != NULL) || s_flag || (argc != 0))) usage = B_TRUE; if ((idtypename != NULL) && !s_flag) usage = B_TRUE; if (e_flag && !s_flag) usage = B_TRUE; if (!l_flag && argc <= 0) usage = B_TRUE; if (usage) { (void) fprintf(stderr, gettext("usage:\t%s [-F] { pid | core } ...\n"), __progname); (void) fprintf(stderr, gettext("\t%s -s spec [-i idtype] id ...\n"), __progname); (void) fprintf(stderr, gettext("\t%s -s spec -e command [arg]...\n"), __progname); (void) fprintf(stderr, gettext("\t%s -l\n"), __progname); return (2); } if (l_flag) { secflag_t i; const char *name; for (i = 0; (name = secflag_to_str(i)) != NULL; i++) (void) printf("%s\n", name); return (0); } else if (s_flag && e_flag) { /* * Don't use the strerror() message for EPERM, "Not Owner" * which is misleading. */ errc = psecflags(P_PID, P_MYID, which, &act); switch (errc) { case 0: break; case EPERM: errx(1, gettext("failed setting " "security-flags: Permission denied")); break; default: err(1, gettext("failed setting security-flags")); } (void) execvp(argv[0], &argv[0]); err(1, "%s", argv[0]); } else if (s_flag) { int i; id_t id; if (idtypename != NULL) if (str2idtype(idtypename, &idtype) == -1) errx(1, gettext("No such id type: '%s'"), idtypename); for (i = 0; i < argc; i++) { if ((id = getid(idtype, argv[i])) == (id_t)-1) { errx(1, gettext("invalid or non-existent " "identifier: '%s'"), argv[i]); } /* * Don't use the strerror() message for EPERM, "Not * Owner" which is misleading. */ if (psecflags(idtype, id, which, &act) != 0) { switch (errno) { case EPERM: errx(1, gettext("failed setting " "security-flags: " "Permission denied")); break; default: err(1, gettext("failed setting " "security-flags")); } } } return (0); } /* Display the flags for the given pids */ while (argc-- > 0) { struct ps_prochandle *Pr; const char *arg; psinfo_t psinfo; prsecflags_t *psf; int gcode; if ((Pr = proc_arg_grab(arg = *argv++, PR_ARG_ANY, pgrab_flags, &gcode)) == NULL) { warnx(gettext("cannot examine %s: %s"), arg, Pgrab_error(gcode)); ret = 1; continue; } (void) memcpy(&psinfo, Ppsinfo(Pr), sizeof (psinfo_t)); proc_unctrl_psinfo(&psinfo); if (Pstate(Pr) == PS_DEAD) { (void) printf(gettext("core '%s' of %d:\t%.70s\n"), arg, (int)psinfo.pr_pid, psinfo.pr_psargs); } else { (void) printf("%d:\t%.70s\n", (int)psinfo.pr_pid, psinfo.pr_psargs); } if (Psecflags(Pr, &psf) != 0) err(1, gettext("cannot read secflags of %s"), arg); print_flags("E", psf->pr_effective); print_flags("I", psf->pr_inherit); print_flags("L", psf->pr_lower); print_flags("U", psf->pr_upper); Psecflags_free(psf); Prelease(Pr, 0); } return (ret); }