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(©, sym, sizeof(copy));
mutex_exit(&ksyms_lock);
- error = copyout(©, kg->kg_sym, sizeof(Elf_Sym));
+ error = copyout(©, 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 ([email protected]).
@@ -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)