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 (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)