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