Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Apr 2013 08:10:47 +0000 (UTC)
From:      Mikolaj Golub <trociny@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r249681 - head/lib/libprocstat
Message-ID:  <201304200810.r3K8Alom014369@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/param.h>
+#include <sys/elf.h>
 #include <sys/time.h>
 #include <sys/resourcevar.h>
 #include <sys/proc.h>
@@ -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 <sys/elf.h>
+#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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201304200810.r3K8Alom014369>