Module Name: src Committed By: pooka Date: Fri Nov 27 17:54:11 UTC 2009
Modified Files: src/sys/conf: files src/sys/kern: subr_kobj.c src/sys/sys: kobj_impl.h Added Files: src/sys/kern: subr_kobj_vfs.c Log Message: Due to the schizophrenic nature of kobj (mem + vfs source), split the module in twain to subj_kobj.c (master + mem) and subr_kobj_vfs.c (vfs). To generate a diff of this commit: cvs rdiff -u -r1.965 -r1.966 src/sys/conf/files cvs rdiff -u -r1.39 -r1.40 src/sys/kern/subr_kobj.c cvs rdiff -u -r0 -r1.1 src/sys/kern/subr_kobj_vfs.c cvs rdiff -u -r1.1 -r1.2 src/sys/sys/kobj_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/conf/files diff -u src/sys/conf/files:1.965 src/sys/conf/files:1.966 --- src/sys/conf/files:1.965 Wed Nov 25 08:52:38 2009 +++ src/sys/conf/files Fri Nov 27 17:54:11 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.965 2009/11/25 08:52:38 kiyohara Exp $ +# $NetBSD: files,v 1.966 2009/11/27 17:54:11 pooka Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20090313 @@ -1490,6 +1490,7 @@ file kern/subr_iostat.c file kern/subr_kmem.c file kern/subr_kobj.c +file kern/subr_kobj_vfs.c file kern/subr_lockdebug.c file kern/subr_log.c file kern/subr_once.c Index: src/sys/kern/subr_kobj.c diff -u src/sys/kern/subr_kobj.c:1.39 src/sys/kern/subr_kobj.c:1.40 --- src/sys/kern/subr_kobj.c:1.39 Wed Jun 17 21:04:25 2009 +++ src/sys/kern/subr_kobj.c Fri Nov 27 17:54:11 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_kobj.c,v 1.39 2009/06/17 21:04:25 dyoung Exp $ */ +/* $NetBSD: subr_kobj.c,v 1.40 2009/11/27 17:54:11 pooka Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.39 2009/06/17 21:04:25 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.40 2009/11/27 17:54:11 pooka Exp $"); #include "opt_modular.h" @@ -75,9 +75,6 @@ #include <sys/kernel.h> #include <sys/kmem.h> #include <sys/proc.h> -#include <sys/namei.h> -#include <sys/vnode.h> -#include <sys/fcntl.h> #include <sys/ksyms.h> #include <sys/module.h> @@ -88,51 +85,15 @@ static int kobj_relocate(kobj_t, bool); static int kobj_checksyms(kobj_t, bool); static void kobj_error(const char *, ...); -static int kobj_read(kobj_t, void **, size_t, off_t); -static int kobj_read_bits(kobj_t, void *, size_t, off_t); static void kobj_jettison(kobj_t); static void kobj_free(kobj_t, void *, size_t); static void kobj_close(kobj_t); -static int kobj_load(kobj_t); +static int kobj_read_mem(kobj_t, void **, size_t, off_t, bool); +static void kobj_close_mem(kobj_t); extern struct vm_map *module_map; /* - * kobj_load_file: - * - * Load an object located in the file system. - */ -int -kobj_load_file(kobj_t *kop, const char *path, const bool nochroot) -{ - struct nameidata nd; - kauth_cred_t cred; - int error; - kobj_t ko; - - cred = kauth_cred_get(); - - ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); - if (ko == NULL) { - return ENOMEM; - } - - NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), - UIO_SYSSPACE, path); - error = vn_open(&nd, FREAD, 0); - - if (error != 0) { - kmem_free(ko, sizeof(*ko)); - return error; - } - - ko->ko_type = KT_VNODE; - ko->ko_source = nd.ni_vp; - *kop = ko; - return kobj_load(ko); -} - -/* * kobj_load_mem: * * Load an object already resident in memory. If size is not -1, @@ -151,6 +112,9 @@ ko->ko_type = KT_MEMORY; ko->ko_source = base; ko->ko_memsize = size; + ko->ko_read = kobj_read_mem; + ko->ko_close = kobj_close_mem; + *kop = ko; return kobj_load(ko); } @@ -168,29 +132,24 @@ return; } - switch (ko->ko_type) { - case KT_VNODE: - VOP_UNLOCK(ko->ko_source, 0); - vn_close(ko->ko_source, FREAD, kauth_cred_get()); - break; - case KT_MEMORY: - /* nothing */ - break; - default: - panic("kobj_close: unknown type"); - break; - } - + ko->ko_close(ko); ko->ko_source = NULL; } +static void +kobj_close_mem(kobj_t ko) +{ + + return; +} + /* * kobj_load: * * Load an ELF object and prepare to link into the running kernel * image. */ -static int +int kobj_load(kobj_t ko) { Elf_Ehdr *hdr; @@ -218,7 +177,7 @@ /* * Read the elf header from the file. */ - error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0); + error = ko->ko_read(ko, (void **)&hdr, sizeof(*hdr), 0, true); if (error != 0) goto out; if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) { @@ -264,7 +223,8 @@ error = ENOEXEC; goto out; } - error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff); + error = ko->ko_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff, + true); if (error != 0) { goto out; } @@ -355,9 +315,9 @@ kobj_error("no symbol table"); goto out; } - error = kobj_read(ko, (void **)&ko->ko_symtab, + error = ko->ko_read(ko, (void **)&ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym), - shdr[symtabindex].sh_offset); + shdr[symtabindex].sh_offset, true); if (error != 0) { goto out; } @@ -370,8 +330,8 @@ kobj_error("no symbol strings"); goto out; } - error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz, - shdr[symstrindex].sh_offset); + error = ko->ko_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz, + shdr[symstrindex].sh_offset, true); if (error != 0) { goto out; } @@ -382,9 +342,9 @@ if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 && shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size; - error = kobj_read(ko, (void **)&ko->ko_shstrtab, + error = ko->ko_read(ko, (void **)&ko->ko_shstrtab, shdr[hdr->e_shstrndx].sh_size, - shdr[hdr->e_shstrndx].sh_offset); + shdr[hdr->e_shstrndx].sh_offset, true); if (error != 0) { goto out; } @@ -461,8 +421,8 @@ ko->ko_progtab[pb].addr = addr; if (shdr[i].sh_type == SHT_PROGBITS) { ko->ko_progtab[pb].name = "<<PROGBITS>>"; - error = kobj_read_bits(ko, addr, - shdr[i].sh_size, shdr[i].sh_offset); + error = ko->ko_read(ko, &addr, + shdr[i].sh_size, shdr[i].sh_offset, false); if (error != 0) { goto out; } @@ -501,10 +461,10 @@ ko->ko_reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel); ko->ko_reltab[rl].sec = shdr[i].sh_info; - error = kobj_read(ko, + error = ko->ko_read(ko, (void **)&ko->ko_reltab[rl].rel, ko->ko_reltab[rl].size, - shdr[i].sh_offset); + shdr[i].sh_offset, true); if (error != 0) { goto out; } @@ -519,10 +479,10 @@ ko->ko_relatab[ra].nrela = shdr[i].sh_size / sizeof(Elf_Rela); ko->ko_relatab[ra].sec = shdr[i].sh_info; - error = kobj_read(ko, + error = ko->ko_read(ko, (void **)&ko->ko_relatab[ra].rela, shdr[i].sh_size, - shdr[i].sh_offset); + shdr[i].sh_offset, true); if (error != 0) { goto out; } @@ -995,98 +955,32 @@ va_end(ap); } -/* - * kobj_read: - * - * Utility function: read from the object. - */ static int -kobj_read(kobj_t ko, void **basep, size_t size, off_t off) +kobj_read_mem(kobj_t ko, void **basep, size_t size, off_t off, + bool allocate) { - size_t resid; - void *base; + void *base = *basep; int error; - KASSERT(ko->ko_source != NULL); - - switch (ko->ko_type) { - case KT_VNODE: - base = kmem_alloc(size, KM_SLEEP); - if (base == NULL) { - error = ENOMEM; - break; - } - error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, - UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, - curlwp); - if (error == 0 && resid != 0) { - error = EINVAL; - } - if (error != 0) { - kmem_free(base, size); - base = NULL; - } - break; - case KT_MEMORY: - if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { - kobj_error("kobj_read: preloaded object short"); - error = EINVAL; - base = NULL; - } else { - base = (uint8_t *)ko->ko_source + off; - error = 0; - } - break; - default: - panic("kobj_read: invalid type"); + if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { + kobj_error("kobj_read_mem: preloaded object short"); + error = EINVAL; + base = NULL; + } else if (allocate) { + base = (uint8_t *)ko->ko_source + off; + error = 0; + } else if ((uint8_t *)base != (uint8_t *)ko->ko_source + off) { + kobj_error("kobj_read_mem: object not aligned"); + kobj_error("source=%p base=%p off=%d size=%zd", + ko->ko_source, base, (int)off, size); + error = EINVAL; + } else { + /* Nothing to do. Loading in-situ. */ + error = 0; } - *basep = base; - return error; -} - -/* - * kobj_read_bits: - * - * Utility function: load a section from the object. - */ -static int -kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off) -{ - size_t resid; - int error; - - KASSERT(ko->ko_source != NULL); - - switch (ko->ko_type) { - case KT_VNODE: - KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address); - KASSERT((uintptr_t)base + size <= - (uintptr_t)ko->ko_address + ko->ko_size); - error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, - UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, - curlwp); - if (error == 0 && resid != 0) { - error = EINVAL; - } - break; - case KT_MEMORY: - if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { - kobj_error("kobj_read_bits: preloaded object short"); - error = EINVAL; - } else if ((uint8_t *)base != (uint8_t *)ko->ko_source + off) { - kobj_error("kobj_read_bits: object not aligned"); - kobj_error("source=%p base=%p off=%d size=%zd", - ko->ko_source, base, (int)off, size); - error = EINVAL; - } else { - /* Nothing to do. Loading in-situ. */ - error = 0; - } - break; - default: - panic("kobj_read: invalid type"); - } + if (allocate) + *basep = base; return error; } @@ -1107,13 +1001,6 @@ #else /* MODULAR */ int -kobj_load_file(kobj_t *kop, const char *name, const bool nochroot) -{ - - return ENOSYS; -} - -int kobj_load_mem(kobj_t *kop, void *base, ssize_t size) { Index: src/sys/sys/kobj_impl.h diff -u src/sys/sys/kobj_impl.h:1.1 src/sys/sys/kobj_impl.h:1.2 --- src/sys/sys/kobj_impl.h:1.1 Sun May 24 15:00:24 2009 +++ src/sys/sys/kobj_impl.h Fri Nov 27 17:54:11 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: kobj_impl.h,v 1.1 2009/05/24 15:00:24 ad Exp $ */ +/* $NetBSD: kobj_impl.h,v 1.2 2009/11/27 17:54:11 pooka Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -99,6 +99,9 @@ KT_MEMORY } kobjtype_t; +typedef int (*kobj_read_fn)(kobj_t, void **, size_t, off_t, bool); +typedef void (*kobj_close_fn)(kobj_t); + struct kobj { char ko_name[MAXMODNAME]; kobjtype_t ko_type; @@ -122,6 +125,12 @@ int ko_nprogtab; bool ko_ksyms; bool ko_loaded; + kobj_read_fn ko_read; + kobj_close_fn ko_close; }; +#ifdef _KERNEL +int kobj_load(kobj_t); +#endif + #endif /* _SYS_KOBJ_IMPL_H_ */ Added files: Index: src/sys/kern/subr_kobj_vfs.c diff -u /dev/null src/sys/kern/subr_kobj_vfs.c:1.1 --- /dev/null Fri Nov 27 17:54:12 2009 +++ src/sys/kern/subr_kobj_vfs.c Fri Nov 27 17:54:11 2009 @@ -0,0 +1,175 @@ +/* $NetBSD: subr_kobj_vfs.c,v 1.1 2009/11/27 17:54:11 pooka Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software developed for The NetBSD Foundation + * by Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1998-2000 Doug Rabson + * Copyright (c) 2004 Peter Wemm + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Kernel loader vfs routines. + */ + +#include <sys/kobj_impl.h> +#include "opt_modular.h" + +#ifdef MODULAR + +#include <sys/param.h> +#include <sys/fcntl.h> +#include <sys/module.h> +#include <sys/namei.h> +#include <sys/vnode.h> + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: subr_kobj_vfs.c,v 1.1 2009/11/27 17:54:11 pooka Exp $"); + +static void +kobj_close_file(kobj_t ko) +{ + + VOP_UNLOCK(ko->ko_source, 0); + vn_close(ko->ko_source, FREAD, kauth_cred_get()); +} + +/* + * kobj_read: + * + * Utility function: read from the object. + */ +static int +kobj_read_file(kobj_t ko, void **basep, size_t size, off_t off, + bool allocate) +{ + size_t resid; + void *base; + int error; + + KASSERT(ko->ko_source != NULL); + + if (allocate) { + base = kmem_alloc(size, KM_SLEEP); + } else { + base = *basep; + KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address); + KASSERT((uintptr_t)base + size <= + (uintptr_t)ko->ko_address + ko->ko_size); + } + + error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, + UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, + curlwp); + + if (error == 0 && resid != 0) { + error = EINVAL; + } + + if (allocate && error != 0) { + kmem_free(base, size); + base = NULL; + } + + if (allocate) + *basep = base; + + return error; +} + +/* + * kobj_load_file: + * + * Load an object located in the file system. + */ +int +kobj_load_file(kobj_t *kop, const char *path, const bool nochroot) +{ + struct nameidata nd; + kauth_cred_t cred; + int error; + kobj_t ko; + + cred = kauth_cred_get(); + + ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); + if (ko == NULL) { + return ENOMEM; + } + + NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), + UIO_SYSSPACE, path); + error = vn_open(&nd, FREAD, 0); + + if (error != 0) { + kmem_free(ko, sizeof(*ko)); + return error; + } + + ko->ko_type = KT_VNODE; + ko->ko_source = nd.ni_vp; + ko->ko_read = kobj_read_file; + ko->ko_close = kobj_close_file; + + *kop = ko; + return kobj_load(ko); +} + +#else /* MODULAR */ + +int +kobj_load_file(kobj_t *kop, const char *path, const bool nochroot) +{ + + return ENOSYS; +} + +#endif