Module Name:    src
Committed By:   matt
Date:           Wed May 20 02:45:20 UTC 2015

Modified Files:
        src/lib/libc/gen: nlist_elf32.c
        src/sys/compat/netbsd32: netbsd32_ioctl.c netbsd32_ioctl.h
        src/sys/kern: kern_ksyms.c
        src/sys/sys: ksyms.h

Log Message:
Change the ksyms ioctls to more compat_netbsd32 friendly.  Use _IOWR ioctls
to avoid extra copyouts.  With these changes, netstat and vmstat work on
mips64eb with the normal N32 userland and a N64 kernel.


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/lib/libc/gen/nlist_elf32.c
cvs rdiff -u -r1.70 -r1.71 src/sys/compat/netbsd32/netbsd32_ioctl.c
cvs rdiff -u -r1.45 -r1.46 src/sys/compat/netbsd32/netbsd32_ioctl.h
cvs rdiff -u -r1.75 -r1.76 src/sys/kern/kern_ksyms.c
cvs rdiff -u -r1.30 -r1.31 src/sys/sys/ksyms.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/gen/nlist_elf32.c
diff -u src/lib/libc/gen/nlist_elf32.c:1.36 src/lib/libc/gen/nlist_elf32.c:1.37
--- src/lib/libc/gen/nlist_elf32.c:1.36	Tue May 19 06:09:15 2015
+++ src/lib/libc/gen/nlist_elf32.c	Wed May 20 02:45:20 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: nlist_elf32.c,v 1.36 2015/05/19 06:09:15 matt Exp $ */
+/* $NetBSD: nlist_elf32.c,v 1.37 2015/05/20 02:45:20 matt Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou
@@ -36,7 +36,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: nlist_elf32.c,v 1.36 2015/05/19 06:09:15 matt Exp $");
+__RCSID("$NetBSD: nlist_elf32.c,v 1.37 2015/05/20 02:45:20 matt Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 /* If not included by nlist_elf64.c, ELFSIZE won't be defined. */
@@ -77,14 +77,14 @@ ELFNAMEEND(__fdnlist)(int fd, struct nli
 {
 	struct stat st;
 	Elf_Ehdr ehdr;
-#if defined(_LP64) || ELFSIZE == 32 || defined(__mips_n32)
+#if defined(_LP64) || ELFSIZE == 32 || defined(ELF64_MACHDEP_ID)
 #if (ELFSIZE == 32)
 	Elf32_Half nshdr;
 #elif (ELFSIZE == 64)
 	Elf64_Word nshdr;
 #endif
-	/* Only support 64+32 mode on LP64 and MIPS N32 */
-	/* No support for 64 mode on ILP32 */
+	/* Only support 64+32 mode on LP64 and those that have defined */
+	/* ELF64_MACHDEP_ID, otherwise no support for 64 mode on ILP32 */
 	Elf_Ehdr *ehdrp;
 	Elf_Shdr *shdrp, *symshdrp, *symstrshdrp;
 	Elf_Sym *symp;
@@ -138,14 +138,13 @@ ELFNAMEEND(__fdnlist)(int fd, struct nli
 	default:
 		BAD;
 	}
-#if defined(_LP64) || ELFSIZE == 32 || defined(__mips_n32)
+#if defined(_LP64) || ELFSIZE == 32 || defined(ELF64_MACHDEP_ID)
 	symshdrp = symstrshdrp = NULL;
 
-	/* Only support 64+32 mode on LP64 and MIPS N32 */
-	/* No support for 64 mode on ILP32 */
+	/* Only support 64+32 mode on LP64 and those that have defined */
+	/* ELF64_MACHDEP_ID, otherwise no support for 64 mode on ILP32 */
 	if (S_ISCHR(st.st_mode)) {
 		const char *nlistname;
-		struct ksyms_gsymbol kg;
 		Elf_Sym sym;
 
 		/*
@@ -153,6 +152,8 @@ ELFNAMEEND(__fdnlist)(int fd, struct nli
 		 */
 		nent = 0;
 		for (p = list; !ISLAST(p); ++p) {
+			struct ksyms_gsymbol kg;
+			int error;
 
 			p->n_other = 0;
 			p->n_desc = 0;
@@ -160,9 +161,32 @@ ELFNAMEEND(__fdnlist)(int fd, struct nli
 			if (*nlistname == '_')
 				nlistname++;
 
+			memset(&kg, 0, sizeof(kg));
 			kg.kg_name = nlistname;
+#ifdef OKIOCGSYMBOL
+			struct ksyms_ogsymbol okg;
+			error = ioctl(fd, KIOCGSYMBOL, &kg);
+			if (error == 0) {
+				sym = kg.kg_sym;
+			} else if (error && errno == ENOTTY) {
+				memset(&okg, 0, sizeof(okg));
+				okg.kg_name = nlistname;
+				okg.kg_sym = &sym;
+				error = ioctl(fd, OKIOCGSYMBOL, &okg);
+			}
+#else
 			kg.kg_sym = &sym;
-			if (ioctl(fd, KIOCGSYMBOL, &kg) == 0) {
+			error = ioctl(fd, KIOCGSYMBOL, &kg);
+#endif
+			if (error == 0
+#if !defined(_LP64) && ELFSIZE == 64
+#if __mips__
+			    && (intptr_t)sym.st_value == (intmax_t)sym.st_value
+#else
+			    && (uintptr_t)sym.st_value == sym.st_value
+#endif
+#endif
+			    && 1) {
 				p->n_value = (uintptr_t)sym.st_value;
 				switch (ELF_ST_TYPE(sym.st_info)) {
 				case STT_NOTYPE:
@@ -310,7 +334,7 @@ done:
 	rv = nent;
 unmap:
 	munmap(mappedfile, mappedsize);
-#endif /* _LP64 || ELFSIZE == 32 || __mips_n32 */
+#endif /* _LP64 || ELFSIZE == 32 || ELF64_MACHDEP_ID */
 out:
 	return (rv);
 }

Index: src/sys/compat/netbsd32/netbsd32_ioctl.c
diff -u src/sys/compat/netbsd32/netbsd32_ioctl.c:1.70 src/sys/compat/netbsd32/netbsd32_ioctl.c:1.71
--- src/sys/compat/netbsd32/netbsd32_ioctl.c:1.70	Mon May 18 06:38:59 2015
+++ src/sys/compat/netbsd32/netbsd32_ioctl.c	Wed May 20 02:45:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_ioctl.c,v 1.70 2015/05/18 06:38:59 martin Exp $	*/
+/*	$NetBSD: netbsd32_ioctl.c,v 1.71 2015/05/20 02:45:20 matt Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.70 2015/05/18 06:38:59 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_ioctl.c,v 1.71 2015/05/20 02:45:20 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_ioc
 #include <sys/envsys.h>
 #include <sys/wdog.h>
 #include <sys/clockctl.h>
+#include <sys/ksyms.h>
 
 #ifdef __sparc__
 #include <dev/sun/fbio.h>
@@ -390,6 +391,26 @@ netbsd32_to_clockctl_ntp_adjtime(
 	p->retval = s32p->retval;
 }
 
+static inline void
+netbsd32_to_ksyms_gsymbol(
+    const struct netbsd32_ksyms_gsymbol *s32p,
+    struct ksyms_gsymbol *p,
+    u_long cmd)
+{
+
+	p->kg_name = NETBSD32PTR64(s32p->kg_name);
+}
+
+static inline void
+netbsd32_to_ksyms_gvalue(
+    const struct netbsd32_ksyms_gvalue *s32p,
+    struct ksyms_gvalue *p,
+    u_long cmd)
+{
+
+	p->kv_name = NETBSD32PTR64(s32p->kv_name);
+}
+
 /*
  * handle ioctl conversions from 64-bit kernel -> netbsd32
  */
@@ -711,6 +732,28 @@ netbsd32_from_clockctl_ntp_adjtime(
 	s32p->retval = p->retval;
 }
 
+static inline void
+netbsd32_from_ksyms_gsymbol(
+    const struct ksyms_gsymbol *p,
+    struct netbsd32_ksyms_gsymbol *s32p,
+    u_long cmd)
+{
+
+	NETBSD32PTR32(s32p->kg_name, p->kg_name);
+	s32p->kg_sym = p->kg_sym;
+}
+
+static inline void
+netbsd32_from_ksyms_gvalue(
+    const struct ksyms_gvalue *p,
+    struct netbsd32_ksyms_gvalue *s32p,
+    u_long cmd)
+{
+
+	NETBSD32PTR32(s32p->kv_name, p->kv_name);
+	s32p->kv_value = p->kv_value;
+}
+
 /*
  * main ioctl syscall.
  *
@@ -1075,6 +1118,11 @@ netbsd32_ioctl(struct lwp *l, const stru
 		IOCTL_STRUCT_CONV_TO(CLOCKCTL_NTP_ADJTIME,
 		    clockctl_ntp_adjtime);
 
+	case KIOCGSYMBOL32:
+		IOCTL_STRUCT_CONV_TO(KIOCGSYMBOL, ksyms_gsymbol);
+	case KIOCGVALUE32:
+		IOCTL_STRUCT_CONV_TO(KIOCGVALUE, ksyms_gvalue);
+
 	default:
 #ifdef NETBSD32_MD_IOCTL
 		error = netbsd32_md_ioctl(fp, com, data32, l);

Index: src/sys/compat/netbsd32/netbsd32_ioctl.h
diff -u src/sys/compat/netbsd32/netbsd32_ioctl.h:1.45 src/sys/compat/netbsd32/netbsd32_ioctl.h:1.46
--- src/sys/compat/netbsd32/netbsd32_ioctl.h:1.45	Mon May 18 06:38:59 2015
+++ src/sys/compat/netbsd32/netbsd32_ioctl.h	Wed May 20 02:45:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: netbsd32_ioctl.h,v 1.45 2015/05/18 06:38:59 martin Exp $	*/
+/*	$NetBSD: netbsd32_ioctl.h,v 1.46 2015/05/20 02:45:20 matt Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -533,3 +533,17 @@ struct netbsd32_clockctl_ntp_adjtime {
 #define CLOCKCTL_NTP_ADJTIME32 _IOWR('C', 0x8, \
     struct netbsd32_clockctl_ntp_adjtime)
 
+struct netbsd32_ksyms_gsymbol {
+	netbsd32_charp kg_name;
+	union {
+		Elf64_Sym ku_sym;
+	} _un;
+};
+
+struct netbsd32_ksyms_gvalue {
+	netbsd32_charp kv_name;
+	uint64_t kv_value;
+};
+
+#define	KIOCGVALUE32	_IOWR('l', 4, struct netbsd32_ksyms_gvalue)
+#define	KIOCGSYMBOL32	_IOWR('l', 5, struct netbsd32_ksyms_gsymbol)

Index: src/sys/kern/kern_ksyms.c
diff -u src/sys/kern/kern_ksyms.c:1.75 src/sys/kern/kern_ksyms.c:1.76
--- src/sys/kern/kern_ksyms.c:1.75	Mon Dec 15 13:50:10 2014
+++ src/sys/kern/kern_ksyms.c	Wed May 20 02:45:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_ksyms.c,v 1.75 2014/12/15 13:50:10 christos Exp $	*/
+/*	$NetBSD: kern_ksyms.c,v 1.76 2015/05/20 02:45:20 matt Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.75 2014/12/15 13:50:10 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.76 2015/05/20 02:45:20 matt Exp $");
 
 #if defined(_KERNEL) && defined(_KERNEL_OPT)
 #include "opt_ddb.h"
@@ -1065,10 +1065,15 @@ ksymswrite(dev_t dev, struct uio *uio, i
 	return EROFS;
 }
 
+__CTASSERT(offsetof(struct ksyms_ogsymbol, kg_name) == offsetof(struct ksyms_gsymbol, kg_name));
+__CTASSERT(offsetof(struct ksyms_gvalue, kv_name) == offsetof(struct ksyms_gsymbol, kg_name));
+
 static int
 ksymsioctl(dev_t dev, u_long cmd, void *data, int fflag, struct lwp *l)
 {
+	struct ksyms_ogsymbol *okg = (struct ksyms_ogsymbol *)data;
 	struct ksyms_gsymbol *kg = (struct ksyms_gsymbol *)data;
+	struct ksyms_gvalue *kv = (struct ksyms_gvalue *)data;
 	struct ksyms_symtab *st;
 	Elf_Sym *sym = NULL, copy;
 	unsigned long val;
@@ -1079,7 +1084,8 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 	/* Read ksyms_maxlen only once while not holding the lock. */
 	len = ksyms_maxlen;
 
-	if (cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) {
+	if (cmd == OKIOCGVALUE || cmd == OKIOCGSYMBOL
+	    || cmd == KIOCGVALUE || cmd == KIOCGSYMBOL) {
 		str = kmem_alloc(len, KM_SLEEP);
 		if ((error = copyinstr(kg->kg_name, str, len, NULL)) != 0) {
 			kmem_free(str, len);
@@ -1088,18 +1094,18 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 	}
 
 	switch (cmd) {
-	case KIOCGVALUE:
+	case OKIOCGVALUE:
 		/*
 		 * Use the in-kernel symbol lookup code for fast
 		 * retreival of a value.
 		 */
 		error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN);
 		if (error == 0)
-			error = copyout(&val, kg->kg_value, sizeof(long));
+			error = copyout(&val, okg->kg_value, sizeof(long));
 		kmem_free(str, len);
 		break;
 
-	case KIOCGSYMBOL:
+	case OKIOCGSYMBOL:
 		/*
 		 * Use the in-kernel symbol lookup code for fast
 		 * retreival of a symbol.
@@ -1122,7 +1128,7 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		if (sym != NULL) {
 			memcpy(&copy, sym, sizeof(copy));
 			mutex_exit(&ksyms_lock);
-			error = copyout(&copy, kg->kg_sym, sizeof(Elf_Sym));
+			error = copyout(&copy, okg->kg_sym, sizeof(Elf_Sym));
 		} else {
 			mutex_exit(&ksyms_lock);
 			error = ENOENT;
@@ -1130,6 +1136,46 @@ ksymsioctl(dev_t dev, u_long cmd, void *
 		kmem_free(str, len);
 		break;
 
+	case KIOCGVALUE:
+		/*
+		 * Use the in-kernel symbol lookup code for fast
+		 * retreival of a value.
+		 */
+		error = ksyms_getval(NULL, str, &val, KSYMS_EXTERN);
+		if (error == 0)
+			kv->kv_value = val;
+		kmem_free(str, len);
+		break;
+
+	case KIOCGSYMBOL:
+		/*
+		 * Use the in-kernel symbol lookup code for fast
+		 * retreival of a symbol.
+		 */
+		mutex_enter(&ksyms_lock);
+		TAILQ_FOREACH(st, &ksyms_symtabs, sd_queue) {
+			if (st->sd_gone)
+				continue;
+			if ((sym = findsym(str, st, KSYMS_ANY)) == NULL)
+				continue;
+#ifdef notdef
+			/* Skip if bad binding */
+			if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) {
+				sym = NULL;
+				continue;
+			}
+#endif
+			break;
+		}
+		if (sym != NULL) {
+			kg->kg_sym = *sym;
+		} else {
+			error = ENOENT;
+		}
+		mutex_exit(&ksyms_lock);
+		kmem_free(str, len);
+		break;
+
 	case KIOCGSIZE:
 		/*
 		 * Get total size of symbol table.

Index: src/sys/sys/ksyms.h
diff -u src/sys/sys/ksyms.h:1.30 src/sys/sys/ksyms.h:1.31
--- src/sys/sys/ksyms.h:1.30	Sun Dec 14 18:14:15 2014
+++ src/sys/sys/ksyms.h	Wed May 20 02:45:20 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: ksyms.h,v 1.30 2014/12/14 18:14:15 christos Exp $	*/
+/*	$NetBSD: ksyms.h,v 1.31 2015/05/20 02:45:20 matt Exp $	*/
 
 /*
  * Copyright (c) 2001, 2003 Anders Magnusson (ra...@ludd.luth.se).
@@ -30,10 +30,10 @@
 #ifndef _SYS_KSYMS_H_
 #define _SYS_KSYMS_H_
 
+#include <sys/exec_elf.h>
+
 #ifdef _KSYMS_PRIVATE
 
-#define	ELFSIZE	ARCH_ELFSIZE
-#include <sys/exec_elf.h>
 #include <sys/queue.h>
 
 struct ksyms_symtab {
@@ -82,7 +82,7 @@ struct ksyms_hdr {
 /*
  * Do a lookup of a symbol using the in-kernel lookup algorithm.
  */
-struct ksyms_gsymbol {
+struct ksyms_ogsymbol {
 	const char *kg_name;
 	union {
 		void *ku_sym;		 /* Normally Elf_Sym */
@@ -92,9 +92,23 @@ struct ksyms_gsymbol {
 #define	kg_value _un.ku_value
 };
 
-#define	KIOCGSYMBOL	_IOW('l', 1, struct ksyms_gsymbol)
-#define	KIOCGVALUE	_IOW('l', 2, struct ksyms_gsymbol)
+struct ksyms_gsymbol {
+	const char *kg_name;
+	union {
+		Elf_Sym ku_sym;
+	} _un;
+};
+
+struct ksyms_gvalue {
+	const char *kv_name;
+	uint64_t kv_value;
+};
+
+#define	OKIOCGSYMBOL	_IOW('l', 1, struct ksyms_ogsymbol)
+#define	OKIOCGVALUE	_IOW('l', 2, struct ksyms_ogsymbol)
 #define	KIOCGSIZE	_IOR('l', 3, int)
+#define	KIOCGVALUE	_IOWR('l', 4, struct ksyms_gvalue)
+#define	KIOCGSYMBOL	_IOWR('l', 5, struct ksyms_gsymbol)
 
 
 #if defined(_KERNEL) || defined(_KMEMUSER)

Reply via email to