Index: head/usr.bin/procstat/procstat.c =================================================================== --- head/usr.bin/procstat/procstat.c (revision 249682) +++ head/usr.bin/procstat/procstat.c (revision 249683) @@ -1,279 +1,279 @@ /*- * Copyright (c) 2007, 2011 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include "procstat.h" static int aflag, bflag, cflag, eflag, fflag, iflag, jflag, kflag, lflag, sflag; static int tflag, vflag, xflag; int hflag, nflag, Cflag; static void usage(void) { fprintf(stderr, "usage: procstat [-h] [-C] [-M core] [-N system] " "[-w interval] \n"); fprintf(stderr, " [-b | -c | -e | -f | -i | -j | -k | " "-l | -s | -t | -v | -x] [-a | pid ...]\n"); exit(EX_USAGE); } static void procstat(struct procstat *prstat, struct kinfo_proc *kipp) { if (bflag) procstat_bin(prstat, kipp); else if (cflag) procstat_args(prstat, kipp); else if (eflag) procstat_env(prstat, kipp); else if (fflag) procstat_files(prstat, kipp); else if (iflag) procstat_sigs(prstat, kipp); else if (jflag) procstat_threads_sigs(prstat, kipp); else if (kflag) procstat_kstack(kipp, kflag); else if (lflag) procstat_rlimit(prstat, kipp); else if (sflag) procstat_cred(prstat, kipp); else if (tflag) procstat_threads(prstat, kipp); else if (vflag) procstat_vm(prstat, kipp); else if (xflag) - procstat_auxv(kipp); + procstat_auxv(prstat, kipp); else procstat_basic(kipp); } /* * Sort processes first by pid and then tid. */ static int kinfo_proc_compare(const void *a, const void *b) { int i; i = ((const struct kinfo_proc *)a)->ki_pid - ((const struct kinfo_proc *)b)->ki_pid; if (i != 0) return (i); i = ((const struct kinfo_proc *)a)->ki_tid - ((const struct kinfo_proc *)b)->ki_tid; return (i); } void kinfo_proc_sort(struct kinfo_proc *kipp, int count) { qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); } int main(int argc, char *argv[]) { int ch, interval, tmp; int i; struct kinfo_proc *p; struct procstat *prstat; long l; pid_t pid; char *dummy; char *nlistf, *memf; int cnt; interval = 0; memf = nlistf = NULL; while ((ch = getopt(argc, argv, "CN:M:abcefijklhstvw:x")) != -1) { switch (ch) { case 'C': Cflag++; break; case 'M': memf = optarg; break; case 'N': nlistf = optarg; 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 '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 = bflag + cflag + eflag + fflag + iflag + jflag + (kflag ? 1 : 0) + lflag + 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(); 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') usage(); 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); /* Suppress header after first process. */ hflag = 1; } if (interval) sleep(interval); } while (interval); procstat_close(prstat); exit(0); } Index: head/usr.bin/procstat/procstat.h =================================================================== --- head/usr.bin/procstat/procstat.h (revision 249682) +++ head/usr.bin/procstat/procstat.h (revision 249683) @@ -1,51 +1,51 @@ /*- * Copyright (c) 2007 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef PROCSTAT_H #define PROCSTAT_H extern int hflag, nflag, Cflag; struct kinfo_proc; void kinfo_proc_sort(struct kinfo_proc *kipp, int count); void procstat_args(struct procstat *prstat, struct kinfo_proc *kipp); -void procstat_auxv(struct kinfo_proc *kipp); +void procstat_auxv(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_basic(struct kinfo_proc *kipp); void procstat_bin(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_cred(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_env(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_files(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_kstack(struct kinfo_proc *kipp, int kflag); void procstat_rlimit(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_sigs(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_threads(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_threads_sigs(struct procstat *prstat, struct kinfo_proc *kipp); void procstat_vm(struct procstat *prstat, struct kinfo_proc *kipp); #endif /* !PROCSTAT_H */ Index: head/usr.bin/procstat/procstat_auxv.c =================================================================== --- head/usr.bin/procstat/procstat_auxv.c (revision 249682) +++ head/usr.bin/procstat/procstat_auxv.c (revision 249683) @@ -1,246 +1,160 @@ /*- * Copyright (c) 2011 Mikolaj Golub * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include "procstat.h" -#define PROC_AUXV_MAX 256 - -static Elf_Auxinfo auxv[PROC_AUXV_MAX]; -static char prefix[256]; - -#if __ELF_WORD_SIZE == 64 -static Elf32_Auxinfo auxv32[PROC_AUXV_MAX]; - -static const char *elf32_sv_names[] = { - "Linux ELF32", - "FreeBSD ELF32", -}; - -static int -is_elf32(pid_t pid) -{ - int error, name[4]; - size_t len, i; - static char sv_name[256]; - - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_SV_NAME; - name[3] = pid; - len = sizeof(sv_name); - error = sysctl(name, 4, sv_name, &len, NULL, 0); - if (error != 0 || len == 0) - return (0); - for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) { - if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0) - return (1); - } - return (0); -} - -static size_t -retrieve_auxv32(pid_t pid) -{ - int name[4]; - size_t len, i; - void *ptr; - - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_AUXV; - name[3] = pid; - len = sizeof(auxv32); - if (sysctl(name, 4, auxv32, &len, NULL, 0) == -1) { - if (errno != ESRCH && errno != EPERM) - warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); - return (0); - } - for (i = 0; i < len; i++) { - /* - * XXX: We expect that values for a_type on a 32-bit platform - * are directly mapped to those on 64-bit one, which is not - * necessarily true. - */ - auxv[i].a_type = auxv32[i].a_type; - ptr = &auxv32[i].a_un; - auxv[i].a_un.a_val = *((uint32_t *)ptr); - } - return (len); -} -#endif /* __ELF_WORD_SIZE == 64 */ - #define PRINT(name, spec, val) \ printf("%s %-16s " #spec "\n", prefix, #name, (val)) #define PRINT_UNKNOWN(type, val) \ printf("%s %16ld %#lx\n", prefix, (long)type, (u_long)(val)) -static size_t -retrieve_auxv(pid_t pid) -{ - int name[4]; - size_t len; - -#if __ELF_WORD_SIZE == 64 - if (is_elf32(pid)) - return (retrieve_auxv32(pid)); -#endif - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_AUXV; - name[3] = pid; - len = sizeof(auxv); - if (sysctl(name, 4, auxv, &len, NULL, 0) == -1) { - if (errno != ESRCH && errno != EPERM) - warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); - return (0); - } - return (len); -} - void -procstat_auxv(struct kinfo_proc *kipp) +procstat_auxv(struct procstat *procstat, struct kinfo_proc *kipp) { - size_t len, i; + Elf_Auxinfo *auxv; + u_int count, i; + static char prefix[256]; if (!hflag) printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE"); - len = retrieve_auxv(kipp->ki_pid); - if (len == 0) + auxv = procstat_getauxv(procstat, kipp, &count); + if (auxv == NULL) return; snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid, kipp->ki_comm); - for (i = 0; i < len; i++) { + for (i = 0; i < count; i++) { switch(auxv[i].a_type) { case AT_NULL: return; case AT_IGNORE: break; case AT_EXECFD: PRINT(AT_EXECFD, %ld, (long)auxv[i].a_un.a_val); break; case AT_PHDR: PRINT(AT_PHDR, %p, auxv[i].a_un.a_ptr); break; case AT_PHENT: PRINT(AT_PHENT, %ld, (long)auxv[i].a_un.a_val); break; case AT_PHNUM: PRINT(AT_PHNUM, %ld, (long)auxv[i].a_un.a_val); break; case AT_PAGESZ: PRINT(AT_PAGESZ, %ld, (long)auxv[i].a_un.a_val); break; case AT_BASE: PRINT(AT_BASE, %p, auxv[i].a_un.a_ptr); break; case AT_FLAGS: PRINT(AT_FLAGS, %#lx, (u_long)auxv[i].a_un.a_val); break; case AT_ENTRY: PRINT(AT_ENTRY, %p, auxv[i].a_un.a_ptr); break; #ifdef AT_NOTELF case AT_NOTELF: PRINT(AT_NOTELF, %ld, (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_UID case AT_UID: PRINT(AT_UID, %ld, (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_EUID case AT_EUID: PRINT(AT_EUID, %ld, (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_GID case AT_GID: PRINT(AT_GID, %ld, (long)auxv[i].a_un.a_val); break; #endif #ifdef AT_EGID case AT_EGID: PRINT(AT_EGID, %ld, (long)auxv[i].a_un.a_val); break; #endif case AT_EXECPATH: PRINT(AT_EXECPATH, %p, auxv[i].a_un.a_ptr); break; case AT_CANARY: PRINT(AT_CANARY, %p, auxv[i].a_un.a_ptr); break; case AT_CANARYLEN: PRINT(AT_CANARYLEN, %ld, (long)auxv[i].a_un.a_val); break; case AT_OSRELDATE: PRINT(AT_OSRELDATE, %ld, (long)auxv[i].a_un.a_val); break; case AT_NCPUS: PRINT(AT_NCPUS, %ld, (long)auxv[i].a_un.a_val); break; case AT_PAGESIZES: PRINT(AT_PAGESIZES, %p, auxv[i].a_un.a_ptr); break; case AT_PAGESIZESLEN: PRINT(AT_PAGESIZESLEN, %ld, (long)auxv[i].a_un.a_val); break; case AT_STACKPROT: if ((auxv[i].a_un.a_val & VM_PROT_EXECUTE) != 0) PRINT(AT_STACKPROT, %s, "NONEXECUTABLE"); else PRINT(AT_STACKPROT, %s, "EXECUTABLE"); break; #ifdef AT_TIMEKEEP case AT_TIMEKEEP: PRINT(AT_TIMEKEEP, %p, auxv[i].a_un.a_ptr); break; #endif default: PRINT_UNKNOWN(auxv[i].a_type, auxv[i].a_un.a_val); break; } } printf("\n"); + procstat_freeauxv(procstat, auxv); }