From owner-svn-src-all@FreeBSD.ORG Sat Apr 20 08:10:48 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id A8D0F33C; Sat, 20 Apr 2013 08:10:48 +0000 (UTC) (envelope-from trociny@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 9B9931259; Sat, 20 Apr 2013 08:10:48 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.6/8.14.6) with ESMTP id r3K8Am3L014394; Sat, 20 Apr 2013 08:10:48 GMT (envelope-from trociny@svn.freebsd.org) Received: (from trociny@localhost) by svn.freebsd.org (8.14.6/8.14.5/Submit) id r3K8Alom014369; Sat, 20 Apr 2013 08:10:47 GMT (envelope-from trociny@svn.freebsd.org) Message-Id: <201304200810.r3K8Alom014369@svn.freebsd.org> From: Mikolaj Golub Date: Sat, 20 Apr 2013 08:10:47 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r249681 - head/lib/libprocstat X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Apr 2013 08:10:48 -0000 Author: trociny Date: Sat Apr 20 08:10:47 2013 New Revision: 249681 URL: http://svnweb.freebsd.org/changeset/base/249681 Log: Add procstat_getauxv function to retrieve a process auxiliary vector. MFC after: 1 month Modified: head/lib/libprocstat/Symbol.map head/lib/libprocstat/core.c head/lib/libprocstat/core.h head/lib/libprocstat/libprocstat.3 head/lib/libprocstat/libprocstat.c head/lib/libprocstat/libprocstat.h Modified: head/lib/libprocstat/Symbol.map ============================================================================== --- head/lib/libprocstat/Symbol.map Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/Symbol.map Sat Apr 20 08:10:47 2013 (r249681) @@ -17,11 +17,13 @@ FBSD_1.2 { FBSD_1.3 { procstat_freeargv; + procstat_freeauxv; procstat_freeenvv; procstat_freegroups; procstat_freevmmap; procstat_get_shm_info; procstat_getargv; + procstat_getauxv; procstat_getenvv; procstat_getgroups; procstat_getosrel; Modified: head/lib/libprocstat/core.c ============================================================================== --- head/lib/libprocstat/core.c Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/core.c Sat Apr 20 08:10:47 2013 (r249681) @@ -195,6 +195,10 @@ procstat_core_get(struct procstat_core * n_type = NT_PROCSTAT_PSSTRINGS; structsize = sizeof(vm_offset_t); break; + case PSC_TYPE_AUXV: + n_type = NT_PROCSTAT_AUXV; + structsize = sizeof(Elf_Auxinfo); + break; default: warnx("unknown core stat type: %d", type); return (NULL); Modified: head/lib/libprocstat/core.h ============================================================================== --- head/lib/libprocstat/core.h Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/core.h Sat Apr 20 08:10:47 2013 (r249681) @@ -40,6 +40,7 @@ enum psc_type { PSC_TYPE_PSSTRINGS, PSC_TYPE_ARGV, PSC_TYPE_ENVV, + PSC_TYPE_AUXV, }; struct procstat_core; Modified: head/lib/libprocstat/libprocstat.3 ============================================================================== --- head/lib/libprocstat/libprocstat.3 Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/libprocstat.3 Sat Apr 20 08:10:47 2013 (r249681) @@ -33,6 +33,7 @@ .Nm procstat_open_sysctl , .Nm procstat_close , .Nm procstat_getargv , +.Nm procstat_getauxv , .Nm procstat_getenvv , .Nm procstat_getfiles , .Nm procstat_getgroups , @@ -42,6 +43,7 @@ .Nm procstat_getumask , .Nm procstat_getvmmap , .Nm procstat_freeargv , +.Nm procstat_freeauxv , .Nm procstat_freeenvv , .Nm procstat_freefiles , .Nm procstat_freegroups , @@ -67,6 +69,11 @@ .Fa "struct procstat *procstat" .Fc .Ft void +.Fo procstat_freeauxv +.Fa "struct procstat *procstat" +.Fa "Elf_Auxinfo *auxv" +.Fc +.Ft void .Fo procstat_freeenvv .Fa "struct procstat *procstat" .Fc @@ -129,6 +136,12 @@ .Fa "size_t nchr" .Fa "char *errbuf" .Fc +.Ft "Elf_Auxinfo *" +.Fo procstat_getauxv +.Fa "struct procstat *procstat" +.Fa "struct kinfo_proc *kp" +.Fa "unsigned int *count" +.Fc .Ft "char **" .Fo procstat_getenvv .Fa "struct procstat *procstat" @@ -321,6 +334,19 @@ The caller may free the allocated memory function call. .Pp The +.Fn procstat_getauxv +function gets a pointer to the +.Vt procstat +structure, a pointer to +.Vt kinfo_proc +structure, and returns the auxiliary vector as a dynamically allocated array of +.Vt Elf_Auxinfo +elements. +The caller is responsible to free the allocated memory with a subsequent +.Fn procstat_freeauxv +function call. +.Pp +The .Fn procstat_getfiles function gets a pointer to the .Vt procstat Modified: head/lib/libprocstat/libprocstat.c ============================================================================== --- head/lib/libprocstat/libprocstat.c Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/libprocstat.c Sat Apr 20 08:10:47 2013 (r249681) @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -110,6 +111,9 @@ static char **getargv(struct procstat *p static char *getmnton(kvm_t *kd, struct mount *m); static struct kinfo_vmentry * kinfo_getvmmap_core(struct procstat_core *core, int *cntp); +static Elf_Auxinfo *procstat_getauxv_core(struct procstat_core *core, + unsigned int *cntp); +static Elf_Auxinfo *procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp); static struct filestat_list *procstat_getfiles_kvm( struct procstat *procstat, struct kinfo_proc *kp, int mmapped); static struct filestat_list *procstat_getfiles_sysctl( @@ -2075,3 +2079,151 @@ procstat_getosrel(struct procstat *procs return (-1); } } + +#define PROC_AUXV_MAX 256 + +#if __ELF_WORD_SIZE == 64 +static const char *elf32_sv_names[] = { + "Linux ELF32", + "FreeBSD ELF32", +}; + +static int +is_elf32_sysctl(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 Elf_Auxinfo * +procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp) +{ + Elf_Auxinfo *auxv; + Elf32_Auxinfo *auxv32; + void *ptr; + size_t len; + unsigned int i, count; + int name[4]; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_AUXV; + name[3] = pid; + len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo); + auxv = NULL; + auxv32 = malloc(len); + if (auxv32 == NULL) { + warn("malloc(%zu)", len); + goto out; + } + if (sysctl(name, 4, auxv32, &len, NULL, 0) == -1) { + if (errno != ESRCH && errno != EPERM) + warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); + goto out; + } + count = len / sizeof(Elf_Auxinfo); + auxv = malloc(count * sizeof(Elf_Auxinfo)); + if (auxv == NULL) { + warn("malloc(%zu)", count * sizeof(Elf_Auxinfo)); + goto out; + } + for (i = 0; i < count; i++) { + /* + * XXX: We expect that values for a_type on a 32-bit platform + * are directly mapped to values 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); + } + *cntp = count; +out: + free(auxv32); + return (auxv); +} +#endif /* __ELF_WORD_SIZE == 64 */ + +static Elf_Auxinfo * +procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp) +{ + Elf_Auxinfo *auxv; + int name[4]; + size_t len; + +#if __ELF_WORD_SIZE == 64 + if (is_elf32_sysctl(pid)) + return (procstat_getauxv32_sysctl(pid, cntp)); +#endif + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_AUXV; + name[3] = pid; + len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo); + auxv = malloc(len); + if (auxv == NULL) { + warn("malloc(%zu)", len); + return (NULL); + } + if (sysctl(name, 4, auxv, &len, NULL, 0) == -1) { + if (errno != ESRCH && errno != EPERM) + warn("sysctl: kern.proc.auxv: %d: %d", pid, errno); + free(auxv); + return (NULL); + } + *cntp = len / sizeof(Elf_Auxinfo); + return (auxv); +} + +static Elf_Auxinfo * +procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp) +{ + Elf_Auxinfo *auxv; + size_t len; + + auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len); + if (auxv == NULL) + return (NULL); + *cntp = len / sizeof(Elf_Auxinfo); + return (auxv); +} + +Elf_Auxinfo * +procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp, + unsigned int *cntp) +{ + switch(procstat->type) { + case PROCSTAT_KVM: + warnx("kvm method is not supported"); + return (NULL); + case PROCSTAT_SYSCTL: + return (procstat_getauxv_sysctl(kp->ki_pid, cntp)); + case PROCSTAT_CORE: + return (procstat_getauxv_core(procstat->core, cntp)); + default: + warnx("unknown access method: %d", procstat->type); + return (NULL); + } +} + +void +procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv) +{ + + free(auxv); +} Modified: head/lib/libprocstat/libprocstat.h ============================================================================== --- head/lib/libprocstat/libprocstat.h Sat Apr 20 08:08:29 2013 (r249680) +++ head/lib/libprocstat/libprocstat.h Sat Apr 20 08:10:47 2013 (r249681) @@ -30,6 +30,14 @@ #define _LIBPROCSTAT_H_ /* + * XXX: sys/elf.h conflicts with zfs_context.h. Workaround this by not + * including conflicting parts when building zfs code. + */ +#ifndef ZFS +#include +#endif + +/* * Vnode types. */ #define PS_FST_VTYPE_VNON 1 @@ -148,6 +156,9 @@ STAILQ_HEAD(filestat_list, filestat); __BEGIN_DECLS void procstat_close(struct procstat *procstat); void procstat_freeargv(struct procstat *procstat); +#ifndef ZFS +void procstat_freeauxv(struct procstat *procstat, Elf_Auxinfo *auxv); +#endif void procstat_freeenvv(struct procstat *procstat); void procstat_freegroups(struct procstat *procstat, gid_t *groups); void procstat_freeprocs(struct procstat *procstat, struct kinfo_proc *p); @@ -171,6 +182,10 @@ int procstat_get_vnode_info(struct procs struct vnstat *vn, char *errbuf); char **procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr); +#ifndef ZFS +Elf_Auxinfo *procstat_getauxv(struct procstat *procstat, + struct kinfo_proc *kp, unsigned int *cntp); +#endif char **procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr); gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,