int getdtablecount(void) { struct procstat *procstat; struct kinfo_proc *kipp; struct filestat_list *head; struct filestat *fst; unsigned int fd_count = 0; pid_t pid; unsigned int cnt; procstat = procstat_open_sysctl(); if (procstat == NULL) return 0; pid = getpid(); kipp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt); if (kipp == NULL) return 0; if (cnt != 0) { head = procstat_getfiles(procstat, kipp, 0); if (head == NULL) return 0; fst = STAILQ_LAST(head, filestat, next); fd_count = fst->fs_fd; } procstat_freeprocs(procstat, kipp); return fd_count; }
void procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; unsigned int count, i; if (!hflag) { printf("%5s ", "PID"); if (Hflag) printf("%6s ", "TID"); printf("%-16s %-32s %14s\n", "COMM", "RESOURCE", "VALUE "); } if (!Hflag) { print_rusage(kipp); return; } kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); if (kip == NULL) return; kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) print_rusage(&kip[i]); procstat_freeprocs(procstat, kip); }
void procstat_rusage(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; unsigned int count, i; if (!hflag) { xo_emit("{d:ta/%5s} ", "PID"); if (Hflag) xo_emit("{d:tb/%6s} ", "TID"); xo_emit("{d:tc/%-16s %-32s %14s}\n", "COMM", "RESOURCE", "VALUE "); } if (!Hflag) { print_rusage(kipp); return; } xo_emit("{e:process_id/%d}", kipp->ki_pid); xo_emit("{e:command/%s}", kipp->ki_comm); xo_open_container("threads"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); if (kip == NULL) return; kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) { print_rusage(&kip[i]); } xo_close_container("threads"); procstat_freeprocs(procstat, kip); }
int get_terminal_state(struct steal_pty_state *steal, pid_t target) { struct procstat *procstat; struct kinfo_proc *kp; unsigned int cnt; int err = 0; procstat = procstat_open_sysctl(); kp = procstat_getprocs(procstat, KERN_PROC_PID, target, &cnt); if (kp == NULL || cnt < 1) goto done; if (kp->ki_tdev == NODEV) { error("Child is not connected to a pseudo-TTY. Unable to steal TTY."); err = EINVAL; goto done; } if ((err = find_terminal_emulator(steal))) return err; done: procstat_freeprocs(procstat, kp); procstat_close(procstat); return err; }
int test_procstat(struct tf_test *thiz) { struct procstat *ps; struct kinfo_vmentry *kv; struct kinfo_proc *kp; unsigned cnt, i; ps = procstat_open_sysctl(); thiz->t_assert(ps != NULL); cnt = 0; kp = procstat_getprocs(ps, KERN_PROC_PID, getpid(), &cnt); thiz->t_assert(kp != NULL); thiz->t_pf("getprocs retrieved %u procs\n", cnt); kv = procstat_getvmmap(ps, kp, &cnt); thiz->t_assert(kv != NULL); for (i = 0; i < cnt; i++) { thiz->t_pf("[%u] type: %d, " "start: 0x%"PRIx64", end: 0x%"PRIx64" " "(sz: %"PRIu64"%c), prot: 0x%x\n", i, kv[i].kve_type, kv[i].kve_start, kv[i].kve_end, SZFORMAT(kv[i].kve_end - kv[i].kve_start), kv[i].kve_protection); } procstat_freevmmap(ps, kv); procstat_freeprocs(ps, kp); procstat_close(ps); return (TF_SUCC); }
void procstatCleanup(struct procstat* pstat, struct kinfo_proc* procs) { if (procs != nullptr) { procstat_freeprocs(pstat, procs); } if (pstat != nullptr) { procstat_close(pstat); } }
// Find the PID of the terminal emulator for `target's terminal. // // We assume that the terminal emulator is the parent of the session // leader. This is true in most cases, although in principle you can // construct situations where it is false. We should fail safe later // on if this turns out to be wrong, however. int find_terminal_emulator(struct steal_pty_state *steal) { struct procstat *procstat; struct kinfo_proc *kp; unsigned int cnt; procstat = procstat_open_sysctl(); kp = procstat_getprocs(procstat, KERN_PROC_PID, steal->target_stat.sid, &cnt); if (kp && cnt > 0) steal->emulator_pid = kp->ki_ppid; procstat_freeprocs(procstat, kp); procstat_close(procstat); return 0; }
void move_process_group(struct ptrace_child *child, pid_t from, pid_t to) { struct procstat *procstat; struct kinfo_proc *kp; unsigned int cnt; int i; int err; procstat = procstat_open_sysctl(); kp = procstat_getprocs(procstat, KERN_PROC_PGRP, from, &cnt); for (i = 0; i < cnt; i++) { debug("Change pgid for pid %d to %d", kp[i].ki_pid, to); err = do_syscall(child, setpgid, kp[i].ki_pid, to, 0, 0, 0, 0); if (err < 0) error(" failed: %s", strerror(-err)); } procstat_freeprocs(procstat, kp); procstat_close(procstat); }
int check_pgroup(pid_t target) { struct procstat *procstat; struct kinfo_proc *kp; pid_t pg; unsigned int cnt; pg = getpgid(target); procstat = procstat_open_sysctl(); kp = procstat_getprocs(procstat, KERN_PROC_PGRP, pg, &cnt); procstat_freeprocs(procstat, kp); procstat_close(procstat); if (cnt > 1) { error("Process %d shares a process group with %d other processes. Unable to attach.\n", target, cnt - 1); return EINVAL; } return 0; }
int gc_vm_tbl_update(_gc_cap struct gc_vm_tbl *vt) { #ifdef GC_USE_LIBPROCSTAT struct procstat *ps; struct kinfo_vmentry *kv; struct kinfo_proc *kp; unsigned cnt, i; ps = procstat_open_sysctl(); if (ps == NULL) return (GC_ERROR); cnt = 0; kp = procstat_getprocs(ps, KERN_PROC_PID, getpid(), &cnt); if (kp == NULL) return (GC_ERROR); gc_debug("getprocs retrieved %u procs", cnt); kv = procstat_getvmmap(ps, kp, &cnt); if (kv == NULL) return (GC_ERROR); gc_debug("getvmmap retrieved %u entries", cnt); if (vt->vt_sz < cnt) return (GC_TOO_SMALL); vt->vt_nent = cnt; for (i = 0; i < vt->vt_nent; i++) { vt->vt_ent[i].ve_start = kv[i].kve_start; vt->vt_ent[i].ve_end = kv[i].kve_end; vt->vt_ent[i].ve_prot = kv[i].kve_protection; vt->vt_ent[i].ve_type = kv[i].kve_type; vt->vt_ent[i].ve_gctype = 0; gc_vm_tbl_track(vt, &vt->vt_ent[i]); } procstat_freevmmap(ps, kv); procstat_freeprocs(ps, kp); procstat_close(ps); return (GC_SUCC); #else /* !GC_USE_LIBPROCSTAT */ return (GC_ERROR); #endif /* GC_USE_LIBPROCSTAT */ }
int *get_child_tty_fds(struct ptrace_child *child, int statfd, int *count) { struct filestat *fst; struct filestat_list *head; struct procstat *procstat; struct kinfo_proc *kp; unsigned int cnt; struct fd_array fds = {}; struct vnstat vn; int er; char errbuf[_POSIX2_LINE_MAX]; head = get_procfiles(child->pid, &kp, &procstat, &cnt); STAILQ_FOREACH(fst, head, next) { if (fst->fs_type == PS_FST_TYPE_VNODE) { er = procstat_get_vnode_info(procstat, fst, &vn, errbuf); if (er != 0) { error("%s", errbuf); goto out; } if (vn.vn_dev == kp->ki_tdev) { if (fd_array_push(&fds, fst->fs_fd) != 0) { error("Unable to allocate memory for fd array."); goto out; } } } } out: procstat_freefiles(procstat, head); procstat_freeprocs(procstat, kp); procstat_close(procstat); *count = fds.n; debug("Found %d tty fds in child %d.", fds.n, child->pid); return fds.fds; }
int check_proc_stopped(pid_t pid, int fd) { struct procstat *procstat; struct kinfo_proc *kp; int state; unsigned int cnt; procstat = procstat_open_sysctl(); kp = procstat_getprocs(procstat, KERN_PROC_PID, pid, &cnt); if (cnt > 0) state = kp->ki_stat; procstat_freeprocs(procstat, kp); procstat_close(procstat); if (cnt < 1) return 1; if (state == SSTOP) return 1; return 0; }
int get_process_tty_termios(pid_t pid, struct termios *tio) { int err = EINVAL; struct kinfo_proc *kp; unsigned int cnt; struct filestat_list *head; struct filestat *fst; struct procstat *procstat; int fd = -1; head = get_procfiles(pid, &kp, &procstat, &cnt); STAILQ_FOREACH(fst, head, next) { if (fst->fs_type == PS_FST_TYPE_VNODE) { if (fst->fs_path) { fd = open(fst->fs_path, O_RDONLY); if (fd >= 0 && isatty(fd)) { if (tcgetattr(fd, tio) < 0) { err = -assert_nonzero(errno); } else { close(fd); err = 0; goto done; } } close(fd); } } } done: procstat_freefiles(procstat, head); procstat_freeprocs(procstat, kp); procstat_close(procstat); return err; }
int main(int argc, char *argv[]) { int ch, interval, tmp; int i; struct kinfo_proc *p; struct procstat *prstat, *cprstat; long l; pid_t pid; char *dummy; char *nlistf, *memf; int cnt; interval = 0; memf = nlistf = NULL; while ((ch = getopt(argc, argv, "CHLM:N:ORSXabcefijklhrstvw:x")) != -1) { switch (ch) { case 'C': Cflag++; break; case 'L': Lflag++; break; case 'H': Hflag++; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'O': Oflag++; break; case 'R': Rflag++; break; case 'S': Sflag++; break; case 'X': Xflag++; break; case 'a': aflag++; break; case 'b': bflag++; break; case 'c': cflag++; break; case 'e': eflag++; break; case 'f': fflag++; break; case 'i': iflag++; break; case 'j': jflag++; break; case 'k': kflag++; break; case 'l': lflag++; break; case 'n': nflag++; break; case 'h': hflag++; break; case 'r': rflag++; break; case 's': sflag++; break; case 't': tflag++; break; case 'v': vflag++; break; case 'w': l = strtol(optarg, &dummy, 10); if (*dummy != '\0') usage(); if (l < 1 || l > INT_MAX) usage(); interval = l; break; case 'x': xflag++; break; case '?': default: usage(); } } argc -= optind; argv += optind; /* We require that either 0 or 1 mode flags be set. */ tmp = Lflag + Oflag + Rflag + Sflag + bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + lflag + rflag + sflag + tflag + vflag + xflag; if (!(tmp == 0 || tmp == 1)) usage(); /* We allow -k to be specified up to twice, but not more. */ if (kflag > 2) usage(); /* Must specify either the -a flag or a list of pids. */ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(); /* Only allow -C with -f. */ if (Cflag && !fflag) usage(); /* Only allow -X with -S and -R. */ if (Xflag && !(Sflag || Rflag)) usage(); if (memf != NULL) prstat = procstat_open_kvm(nlistf, memf); else prstat = procstat_open_sysctl(); if (prstat == NULL) errx(1, "procstat_open()"); do { if (aflag) { p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); kinfo_proc_sort(p, cnt); for (i = 0; i < cnt; i++) { procstat(prstat, &p[i]); /* Suppress header after first process. */ hflag = 1; } procstat_freeprocs(prstat, p); } for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy == '\0') { if (l < 0) usage(); pid = l; p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(prstat, p); procstat_freeprocs(prstat, p); } else { cprstat = procstat_open_core(argv[i]); if (cprstat == NULL) { warnx("procstat_open()"); continue; } p = procstat_getprocs(cprstat, KERN_PROC_PID, -1, &cnt); if (p == NULL) errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(cprstat, p); procstat_freeprocs(cprstat, p); procstat_close(cprstat); } /* Suppress header after first process. */ hflag = 1; } if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); }
void procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; unsigned int count, i; const char *str; char *threadid; if (!hflag) xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s %-9s}\n", "PID", "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN"); xo_emit("{ek:process_id/%d}", kipp->ki_pid); xo_emit("{e:command/%s}", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); xo_open_container("threads"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); if (kip == NULL) return; kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) { kipp = &kip[i]; asprintf(&threadid, "%d", kipp->ki_tid); if (threadid == NULL) xo_errc(1, ENOMEM, "Failed to allocate memory in " "procstat_threads()"); xo_open_container(threadid); xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid); xo_emit("{d:command/%-19s/%s} ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); xo_emit("{:thread_name/%-19s/%s} ", kinfo_proc_thread_name(kipp)); if (kipp->ki_oncpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu); else xo_emit("{:cpu/%3s/%s} ", "-"); xo_emit("{:priority/%4d/%d} ", kipp->ki_pri.pri_level); switch (kipp->ki_stat) { case SRUN: str = "run"; break; case SSTOP: str = "stop"; break; case SSLEEP: str = "sleep"; break; case SLOCK: str = "lock"; break; case SWAIT: str = "wait"; break; case SZOMB: str = "zomb"; break; case SIDL: str = "idle"; break; default: str = "??"; break; } xo_emit("{:run_state/%-7s/%s} ", str); if (kipp->ki_kiflag & KI_LOCKBLOCK) { xo_emit("{:lock_name/*%-8s/%s} ", strlen(kipp->ki_lockname) ? kipp->ki_lockname : "-"); } else { xo_emit("{:wait_channel/%-9s/%s} ", strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-"); } xo_close_container(threadid); free(threadid); xo_emit("\n"); } xo_close_container("threads"); procstat_freeprocs(procstat, kip); }
void procstat_threads(struct procstat *procstat, struct kinfo_proc *kipp) { struct kinfo_proc *kip; unsigned int count, i; const char *str; if (!hflag) printf("%5s %6s %-16s %-16s %2s %4s %-7s %-9s\n", "PID", "TID", "COMM", "TDNAME", "CPU", "PRI", "STATE", "WCHAN"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); if (kip == NULL) return; kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) { kipp = &kip[i]; printf("%5d ", kipp->ki_pid); printf("%6d ", kipp->ki_tid); printf("%-16s ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); printf("%-16s ", (strlen(kipp->ki_tdname) && (strcmp(kipp->ki_comm, kipp->ki_tdname) != 0)) ? kipp->ki_tdname : "-"); if (kipp->ki_oncpu != 255) printf("%3d ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255) printf("%3d ", kipp->ki_lastcpu); else printf("%3s ", "-"); printf("%4d ", kipp->ki_pri.pri_level); switch (kipp->ki_stat) { case SRUN: str = "run"; break; case SSTOP: str = "stop"; break; case SSLEEP: str = "sleep"; break; case SLOCK: str = "lock"; break; case SWAIT: str = "wait"; break; case SZOMB: str = "zomb"; break; case SIDL: str = "idle"; break; default: str = "??"; break; } printf("%-7s ", str); if (kipp->ki_kiflag & KI_LOCKBLOCK) { printf("*%-8s ", strlen(kipp->ki_lockname) ? kipp->ki_lockname : "-"); } else { printf("%-9s ", strlen(kipp->ki_wmesg) ? kipp->ki_wmesg : "-"); } printf("\n"); } procstat_freeprocs(procstat, kip); }
/** * \todo This function contains many cases that do not allow for a * recovery. Currently, xbt_abort() is called but we should * much rather die with the specific reason so that it's easier * to find out what's going on. */ XBT_PRIVATE std::vector<VmMap> get_memory_map(pid_t pid) { std::vector<VmMap> ret; #ifdef __linux__ /* Open the actual process's proc maps file and create the memory_map_t */ /* to be returned. */ char* path = bprintf("/proc/%i/maps", (int) pid); FILE *fp = std::fopen(path, "r"); if (fp == nullptr) { std::perror("fopen failed"); xbt_die("Cannot open %s to investigate the memory map of the process.", path); } free(path); setbuf(fp, nullptr); /* Read one line at the time, parse it and add it to the memory map to be returned */ ssize_t read; /* Number of bytes readed */ char* line = nullptr; std::size_t n = 0; /* Amount of bytes to read by xbt_getline */ while ((read = xbt_getline(&line, &n, fp)) != -1) { /** * The lines that we read have this format: (This is just an example) * 00602000-00603000 rw-p 00002000 00:28 1837264 <complete-path-to-file> */ //fprintf(stderr,"%s", line); /* Wipeout the new line character */ line[read - 1] = '\0'; /* Tokenize the line using spaces as delimiters and store each token in lfields array. We expect 5 tokens for 6 fields */ char* lfields[6]; lfields[0] = strtok(line, " "); int i; for (i = 1; i < 6 && lfields[i - 1] != nullptr; i++) { lfields[i] = std::strtok(nullptr, " "); } /* Check to see if we got the expected amount of columns */ if (i < 6) xbt_die("The memory map apparently only supplied less than 6 columns. Recovery impossible."); /* Ok we are good enough to try to get the info we need */ /* First get the start and the end address of the map */ char *tok = std::strtok(lfields[0], "-"); if (tok == nullptr) xbt_die("Start and end address of the map are not concatenated by a hyphen (-). Recovery impossible."); VmMap memreg; char *endptr; memreg.start_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(nullptr, "-"); if (tok == nullptr) xbt_abort(); memreg.end_addr = std::strtoull(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the permissions flags */ if (std::strlen(lfields[1]) < 4) xbt_abort(); memreg.prot = 0; for (i = 0; i < 3; i++){ switch(lfields[1][i]){ case 'r': memreg.prot |= PROT_READ; break; case 'w': memreg.prot |= PROT_WRITE; break; case 'x': memreg.prot |= PROT_EXEC; break; default: break; } } if (memreg.prot == 0) memreg.prot |= PROT_NONE; if (lfields[1][3] == 'p') { memreg.flags |= MAP_PRIVATE; } else { memreg.flags |= MAP_SHARED; if (lfields[1][3] != 's') XBT_WARN("The protection is neither 'p' (private) nor 's' (shared) but '%s'. Let's assume shared, as on b0rken win-ubuntu systems.\nFull line: %s\n", lfields[1], line); } /* Get the offset value */ memreg.offset = std::strtoull(lfields[2], &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the device major:minor bytes */ tok = std::strtok(lfields[3], ":"); if (tok == nullptr) xbt_abort(); memreg.dev_major = (char) strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); tok = std::strtok(nullptr, ":"); if (tok == nullptr) xbt_abort(); memreg.dev_minor = (char) std::strtoul(tok, &endptr, 16); /* Make sure that the entire string was an hex number */ if (*endptr != '\0') xbt_abort(); /* Get the inode number and make sure that the entire string was a long int */ memreg.inode = strtoul(lfields[4], &endptr, 10); if (*endptr != '\0') xbt_abort(); /* And finally get the pathname */ if (lfields[5]) memreg.pathname = lfields[5]; /* Create space for a new map region in the region's array and copy the */ /* parsed stuff from the temporal memreg variable */ XBT_DEBUG("Found region for %s", !memreg.pathname.empty() ? memreg.pathname.c_str() : "(null)"); ret.push_back(std::move(memreg)); } std::free(line); std::fclose(fp); #elif defined __FreeBSD__ struct procstat *prstat; struct kinfo_proc *proc; struct kinfo_vmentry *vmentries; unsigned int cnt; if ((prstat = procstat_open_sysctl()) == NULL) { std::perror("procstat_open_sysctl failed"); xbt_die("Cannot access kernel state information"); } if ((proc = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt)) == NULL) { std::perror("procstat_open_sysctl failed"); xbt_die("Cannot access process information"); } if ((vmentries = procstat_getvmmap(prstat, proc, &cnt)) == NULL) { std::perror("procstat_getvmmap failed"); xbt_die("Cannot access process memory mappings"); } for (unsigned int i = 0; i < cnt; i++) { VmMap memreg; /* Addresses */ memreg.start_addr = vmentries[i].kve_start; memreg.end_addr = vmentries[i].kve_end; /* Permissions */ memreg.prot = PROT_NONE; if (vmentries[i].kve_protection & KVME_PROT_READ) memreg.prot |= PROT_READ; if (vmentries[i].kve_protection & KVME_PROT_WRITE) memreg.prot |= PROT_WRITE; if (vmentries[i].kve_protection & KVME_PROT_EXEC) memreg.prot |= PROT_EXEC; /* Private (copy-on-write) or shared? */ if (vmentries[i].kve_flags & KVME_FLAG_COW) memreg.flags |= MAP_PRIVATE; else memreg.flags |= MAP_SHARED; /* Offset */ memreg.offset = vmentries[i].kve_offset; /* Device : not sure this can be mapped to something outside of Linux? */ memreg.dev_major = 0; memreg.dev_minor = 0; /* Inode */ memreg.inode = vmentries[i].kve_vn_fileid; /* * Path. Linuxize result by giving an anonymous mapping a path from * the previous mapping, provided previous is vnode and has a path, * and mark the stack. */ if (vmentries[i].kve_path[0] != '\0') memreg.pathname = vmentries[i].kve_path; else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT && vmentries[i-1].kve_type == KVME_TYPE_VNODE && vmentries[i-1].kve_path[0] != '\0') memreg.pathname = vmentries[i-1].kve_path; else if (vmentries[i].kve_type == KVME_TYPE_DEFAULT && vmentries[i].kve_flags & KVME_FLAG_GROWS_DOWN) memreg.pathname = "[stack]"; /* * One last dirty modification: remove write permission from shared * libraries private clean pages. This is necessary because simgrid * later identifies mappings based on the permissions that are expected * when running the Linux kernel. */ if (vmentries[i].kve_type == KVME_TYPE_VNODE && ! (vmentries[i].kve_flags & KVME_FLAG_NEEDS_COPY)) memreg.prot &= ~PROT_WRITE; ret.push_back(std::move(memreg)); } procstat_freevmmap(prstat, vmentries); procstat_freeprocs(prstat, proc); procstat_close(prstat); #else xbt_die("Could not get memory map from process %lli", (long long int) pid); #endif return ret; }
int main(int argc, char *argv[]) { int ch, interval, tmp; int i; struct kinfo_proc *p; struct procstat *prstat, *cprstat; long l; pid_t pid; char *dummy; char *nlistf, *memf; const char *xocontainer; int cnt; interval = 0; memf = nlistf = NULL; argc = xo_parse_args(argc, argv); xocontainer = "basic"; while ((ch = getopt(argc, argv, "CHN:M:abcefijklhrsStvw:x")) != -1) { switch (ch) { case 'C': Cflag++; break; case 'H': Hflag++; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; break; case 'S': Sflag++; xocontainer = "cs"; break; case 'a': aflag++; break; case 'b': bflag++; xocontainer = "binary"; break; case 'c': cflag++; xocontainer = "arguments"; break; case 'e': eflag++; xocontainer = "environment"; break; case 'f': fflag++; xocontainer = "files"; break; case 'i': iflag++; xocontainer = "signals"; break; case 'j': jflag++; xocontainer = "thread_signals"; break; case 'k': kflag++; xocontainer = "kstack"; break; case 'l': lflag++; xocontainer = "rlimit"; break; case 'n': nflag++; break; case 'h': hflag++; break; case 'r': rflag++; xocontainer = "rusage"; break; case 's': sflag++; xocontainer = "credentials"; break; case 't': tflag++; xocontainer = "threads"; break; case 'v': vflag++; xocontainer = "vm"; break; case 'w': l = strtol(optarg, &dummy, 10); if (*dummy != '\0') usage(); if (l < 1 || l > INT_MAX) usage(); interval = l; break; case 'x': xflag++; xocontainer = "auxv"; break; case '?': default: usage(); } } argc -= optind; argv += optind; /* We require that either 0 or 1 mode flags be set. */ tmp = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + lflag + rflag + sflag + tflag + vflag + xflag + Sflag; if (!(tmp == 0 || tmp == 1)) usage(); /* We allow -k to be specified up to twice, but not more. */ if (kflag > 2) usage(); /* Must specify either the -a flag or a list of pids. */ if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0)) usage(); /* Only allow -C with -f. */ if (Cflag && !fflag) usage(); if (memf != NULL) prstat = procstat_open_kvm(nlistf, memf); else prstat = procstat_open_sysctl(); if (prstat == NULL) xo_errx(1, "procstat_open()"); do { xo_set_version(PROCSTAT_XO_VERSION); xo_open_container("procstat"); xo_open_container(xocontainer); if (aflag) { p = procstat_getprocs(prstat, KERN_PROC_PROC, 0, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); kinfo_proc_sort(p, cnt); for (i = 0; i < cnt; i++) { procstat(prstat, &p[i]); /* Suppress header after first process. */ hflag = 1; xo_flush(); } procstat_freeprocs(prstat, p); } for (i = 0; i < argc; i++) { l = strtol(argv[i], &dummy, 10); if (*dummy == '\0') { if (l < 0) usage(); pid = l; p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(prstat, p); procstat_freeprocs(prstat, p); } else { cprstat = procstat_open_core(argv[i]); if (cprstat == NULL) { warnx("procstat_open()"); continue; } p = procstat_getprocs(cprstat, KERN_PROC_PID, -1, &cnt); if (p == NULL) xo_errx(1, "procstat_getprocs()"); if (cnt != 0) procstat(cprstat, p); procstat_freeprocs(cprstat, p); procstat_close(cprstat); } /* Suppress header after first process. */ hflag = 1; } xo_close_container(xocontainer); xo_close_container("procstat"); xo_finish(); if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); }
void procstat_cs(struct procstat *procstat, struct kinfo_proc *kipp) { cpusetid_t cs; cpuset_t mask; struct kinfo_proc *kip; struct sbuf *cpusetbuf; unsigned int count, i; int once, twice, lastcpu, cpu; if ((procstat_opts & PS_OPT_NOHEADER) == 0) xo_emit("{T:/%5s %6s %-19s %-19s %2s %4s %-7s}\n", "PID", "TID", "COMM", "TDNAME", "CPU", "CSID", "CPU MASK"); kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD, kipp->ki_pid, &count); if (kip == NULL) return; kinfo_proc_sort(kip, count); for (i = 0; i < count; i++) { kipp = &kip[i]; xo_emit("{k:process_id/%5d/%d} ", kipp->ki_pid); xo_emit("{:thread_id/%6d/%d} ", kipp->ki_tid); xo_emit("{:command/%-19s/%s} ", strlen(kipp->ki_comm) ? kipp->ki_comm : "-"); xo_emit("{:thread_name/%-19s/%s} ", kinfo_proc_thread_name(kipp)); if (kipp->ki_oncpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_oncpu); else if (kipp->ki_lastcpu != 255) xo_emit("{:cpu/%3d/%d} ", kipp->ki_lastcpu); else xo_emit("{:cpu/%3s/%s} ", "-"); if (cpuset_getid(CPU_LEVEL_CPUSET, CPU_WHICH_TID, kipp->ki_tid, &cs) != 0) { cs = CPUSET_INVALID; } xo_emit("{:cpu_set_id/%4d/%d} ", cs); if ((cs != CPUSET_INVALID) && (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, kipp->ki_tid, sizeof(mask), &mask) == 0)) { lastcpu = -1; once = 0; twice = 0; cpusetbuf = sbuf_new_auto(); for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { if (CPU_ISSET(cpu, &mask)) { if (once == 0) { sbuf_printf(cpusetbuf, "%d", cpu); once = 1; } else if (cpu == lastcpu + 1) { twice = 1; } else if (twice == 1) { sbuf_printf(cpusetbuf, "-%d,%d", lastcpu, cpu); twice = 0; } else sbuf_printf(cpusetbuf, ",%d", cpu); lastcpu = cpu; } } if (once && twice) sbuf_printf(cpusetbuf, "-%d", lastcpu); if (sbuf_finish(cpusetbuf) != 0) xo_err(1, "Could not generate output"); xo_emit("{:cpu_set/%s}", sbuf_data(cpusetbuf)); sbuf_delete(cpusetbuf); } xo_emit("\n"); } procstat_freeprocs(procstat, kip); }