Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Change the ksyms ioctls to more compat_netbsd32 friendly. U...



details:   https://anonhg.NetBSD.org/src/rev/d26aa126be60
branches:  trunk
changeset: 338359:d26aa126be60
user:      matt <matt%NetBSD.org@localhost>
date:      Wed May 20 02:45:20 2015 +0000

description:
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.

diffstat:

 lib/libc/gen/nlist_elf32.c           |  46 ++++++++++++++++++++------
 sys/compat/netbsd32/netbsd32_ioctl.c |  52 +++++++++++++++++++++++++++++-
 sys/compat/netbsd32/netbsd32_ioctl.h |  16 ++++++++-
 sys/kern/kern_ksyms.c                |  62 +++++++++++++++++++++++++++++++----
 sys/sys/ksyms.h                      |  26 +++++++++++---
 5 files changed, 174 insertions(+), 28 deletions(-)

diffs (truncated from 402 to 300 lines):

diff -r 2b5e1af39cb3 -r d26aa126be60 lib/libc/gen/nlist_elf32.c
--- a/lib/libc/gen/nlist_elf32.c        Wed May 20 01:30:42 2015 +0000
+++ b/lib/libc/gen/nlist_elf32.c        Wed May 20 02:45:20 2015 +0000
@@ -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 @@
 {
        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 @@
        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 @@
                 */
                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 @@
                        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 @@
        rv = nent;
 unmap:
        munmap(mappedfile, mappedsize);
-#endif /* _LP64 || ELFSIZE == 32 || __mips_n32 */
+#endif /* _LP64 || ELFSIZE == 32 || ELF64_MACHDEP_ID */
 out:
        return (rv);
 }
diff -r 2b5e1af39cb3 -r d26aa126be60 sys/compat/netbsd32/netbsd32_ioctl.c
--- a/sys/compat/netbsd32/netbsd32_ioctl.c      Wed May 20 01:30:42 2015 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.c      Wed May 20 02:45:20 2015 +0000
@@ -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 @@
 #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 @@
        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 @@
        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 @@
                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);
diff -r 2b5e1af39cb3 -r d26aa126be60 sys/compat/netbsd32/netbsd32_ioctl.h
--- a/sys/compat/netbsd32/netbsd32_ioctl.h      Wed May 20 01:30:42 2015 +0000
+++ b/sys/compat/netbsd32/netbsd32_ioctl.h      Wed May 20 02:45:20 2015 +0000
@@ -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 @@
 #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)
diff -r 2b5e1af39cb3 -r d26aa126be60 sys/kern/kern_ksyms.c
--- a/sys/kern/kern_ksyms.c     Wed May 20 01:30:42 2015 +0000
+++ b/sys/kern/kern_ksyms.c     Wed May 20 02:45:20 2015 +0000
@@ -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 @@
        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 @@
        /* 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,6 +1094,48 @@
        }
 
        switch (cmd) {
+       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, okg->kg_value, sizeof(long));
+               kmem_free(str, len);
+               break;
+
+       case OKIOCGSYMBOL:
+               /*
+                * 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) {



Home | Main Index | Thread Index | Old Index