diff options
author | trociny <trociny@FreeBSD.org> | 2011-12-12 22:01:33 +0000 |
---|---|---|
committer | trociny <trociny@FreeBSD.org> | 2011-12-12 22:01:33 +0000 |
commit | 276f79818d29293335512d8f834804c2bc8e45c8 (patch) | |
tree | 0389b1052df50c5837ac831671fa4443102d2b8d | |
parent | 34b16620f04505bad9708a6117d9cbfeca409fbc (diff) | |
download | FreeBSD-src-276f79818d29293335512d8f834804c2bc8e45c8.zip FreeBSD-src-276f79818d29293335512d8f834804c2bc8e45c8.tar.gz |
Make 64-bit procstat output ELF auxiliary vectors for 32-bit processes.
Reviewed by: kib
MFC after: 1 week
-rw-r--r-- | usr.bin/procstat/procstat_auxv.c | 103 |
1 files changed, 87 insertions, 16 deletions
diff --git a/usr.bin/procstat/procstat_auxv.c b/usr.bin/procstat/procstat_auxv.c index 543738c..73a85cd 100644 --- a/usr.bin/procstat/procstat_auxv.c +++ b/usr.bin/procstat/procstat_auxv.c @@ -43,39 +43,110 @@ #include "procstat.h" -static Elf_Auxinfo auxv[256]; +#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 error, 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); + error = sysctl(name, 4, auxv32, &len, NULL, 0); + if (error < 0 && 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)) -void -procstat_auxv(struct kinfo_proc *kipp) +static size_t +retrieve_auxv(pid_t pid) { int error, name[4]; - size_t len, i; - - if (!hflag) - printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE"); + 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] = kipp->ki_pid; - len = sizeof(auxv) * sizeof(*auxv); + name[3] = pid; + len = sizeof(auxv); error = sysctl(name, 4, auxv, &len, NULL, 0); if (error < 0 && errno != ESRCH && errno != EPERM) { - warn("sysctl: kern.proc.auxv: %d: %d", kipp->ki_pid, errno); - return; + warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); + return (0); } - if (error < 0 || len == 0) - return; - if (len == 0) { - printf(" -\n"); + return (len); +} + +void +procstat_auxv(struct kinfo_proc *kipp) +{ + size_t len, i; + + if (!hflag) + printf("%5s %-16s %-16s %-16s\n", "PID", "COMM", "AUXV", "VALUE"); + len = retrieve_auxv(kipp->ki_pid); + if (len == 0) return; - } snprintf(prefix, sizeof(prefix), "%5d %-16s", kipp->ki_pid, kipp->ki_comm); for (i = 0; i < len; i++) { |