Wed Jun 17 21:04:25 2009 UTC ()
Make kobj_stat() return ENOSYS instead of panicking ("not modular")
on non-MODULAR kernels.  Make a few kobj_stat() callers check for
a non-zero return code and deal gracefully.


(dyoung)
diff -r1.48 -r1.49 src/sys/kern/kern_module.c
diff -r1.38 -r1.39 src/sys/kern/subr_kobj.c
diff -r1.11 -r1.12 src/sys/sys/kobj.h

cvs diff -r1.48 -r1.49 src/sys/kern/kern_module.c (switch to unified diff)

--- src/sys/kern/kern_module.c 2009/06/09 20:35:02 1.48
+++ src/sys/kern/kern_module.c 2009/06/17 21:04:25 1.49
@@ -1,1239 +1,1239 @@ @@ -1,1239 +1,1239 @@
1/* $NetBSD: kern_module.c,v 1.48 2009/06/09 20:35:02 jnemeth Exp $ */ 1/* $NetBSD: kern_module.c,v 1.49 2009/06/17 21:04:25 dyoung Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software developed for The NetBSD Foundation 7 * This code is derived from software developed for The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Kernel module support. 33 * Kernel module support.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.48 2009/06/09 20:35:02 jnemeth Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: kern_module.c,v 1.49 2009/06/17 21:04:25 dyoung Exp $");
38 38
39#ifdef _KERNEL_OPT 39#ifdef _KERNEL_OPT
40#include "opt_ddb.h" 40#include "opt_ddb.h"
41#include "opt_modular.h" 41#include "opt_modular.h"
42#endif 42#endif
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/systm.h> 45#include <sys/systm.h>
46#include <sys/kernel.h> 46#include <sys/kernel.h>
47#include <sys/fcntl.h> 47#include <sys/fcntl.h>
48#include <sys/proc.h> 48#include <sys/proc.h>
49#include <sys/kauth.h> 49#include <sys/kauth.h>
50#include <sys/kobj.h> 50#include <sys/kobj.h>
51#include <sys/kmem.h> 51#include <sys/kmem.h>
52#include <sys/module.h> 52#include <sys/module.h>
53#include <sys/kauth.h> 53#include <sys/kauth.h>
54#include <sys/kthread.h> 54#include <sys/kthread.h>
55#include <sys/sysctl.h> 55#include <sys/sysctl.h>
56#include <sys/namei.h> 56#include <sys/namei.h>
57#include <sys/lock.h> 57#include <sys/lock.h>
58#include <sys/vnode.h> 58#include <sys/vnode.h>
59#include <sys/stat.h> 59#include <sys/stat.h>
60 60
61#include <uvm/uvm_extern.h> 61#include <uvm/uvm_extern.h>
62 62
63#include <machine/stdarg.h> 63#include <machine/stdarg.h>
64 64
65struct vm_map *module_map; 65struct vm_map *module_map;
66 66
67struct modlist module_list = TAILQ_HEAD_INITIALIZER(module_list); 67struct modlist module_list = TAILQ_HEAD_INITIALIZER(module_list);
68struct modlist module_bootlist = TAILQ_HEAD_INITIALIZER(module_bootlist); 68struct modlist module_bootlist = TAILQ_HEAD_INITIALIZER(module_bootlist);
69static module_t *module_active; 69static module_t *module_active;
70static char module_base[64]; 70static char module_base[64];
71static int module_verbose_on; 71static int module_verbose_on;
72static int module_autoload_on = 1; 72static int module_autoload_on = 1;
73u_int module_count; 73u_int module_count;
74kmutex_t module_lock; 74kmutex_t module_lock;
75u_int module_autotime = 10; 75u_int module_autotime = 10;
76u_int module_gen = 1; 76u_int module_gen = 1;
77static kcondvar_t module_thread_cv; 77static kcondvar_t module_thread_cv;
78static kmutex_t module_thread_lock; 78static kmutex_t module_thread_lock;
79static int module_thread_ticks; 79static int module_thread_ticks;
80 80
81/* Ensure that the kernel's link set isn't empty. */ 81/* Ensure that the kernel's link set isn't empty. */
82static modinfo_t module_dummy; 82static modinfo_t module_dummy;
83__link_set_add_rodata(modules, module_dummy); 83__link_set_add_rodata(modules, module_dummy);
84 84
85static module_t *module_lookup(const char *); 85static module_t *module_lookup(const char *);
86static int module_do_load(const char *, bool, int, prop_dictionary_t, 86static int module_do_load(const char *, bool, int, prop_dictionary_t,
87 module_t **, modclass_t class, bool); 87 module_t **, modclass_t class, bool);
88static int module_do_unload(const char *); 88static int module_do_unload(const char *);
89static void module_error(const char *, ...) 89static void module_error(const char *, ...)
90 __attribute__((__format__(__printf__,1,2))); 90 __attribute__((__format__(__printf__,1,2)));
91static void module_print(const char *, ...) 91static void module_print(const char *, ...)
92 __attribute__((__format__(__printf__,1,2))); 92 __attribute__((__format__(__printf__,1,2)));
93static int module_do_builtin(const char *, module_t **); 93static int module_do_builtin(const char *, module_t **);
94static int module_fetch_info(module_t *); 94static int module_fetch_info(module_t *);
95static void module_thread(void *); 95static void module_thread(void *);
96static int module_load_plist_file(const char *, const bool, void **, 96static int module_load_plist_file(const char *, const bool, void **,
97 size_t *); 97 size_t *);
98static bool module_merge_dicts(prop_dictionary_t, const prop_dictionary_t); 98static bool module_merge_dicts(prop_dictionary_t, const prop_dictionary_t);
99 99
100/* 100/*
101 * module_error: 101 * module_error:
102 * 102 *
103 * Utility function: log an error. 103 * Utility function: log an error.
104 */ 104 */
105static void 105static void
106module_error(const char *fmt, ...) 106module_error(const char *fmt, ...)
107{ 107{
108 va_list ap; 108 va_list ap;
109 109
110 va_start(ap, fmt); 110 va_start(ap, fmt);
111 printf("WARNING: module error: "); 111 printf("WARNING: module error: ");
112 vprintf(fmt, ap); 112 vprintf(fmt, ap);
113 printf("\n"); 113 printf("\n");
114 va_end(ap); 114 va_end(ap);
115} 115}
116 116
117/* 117/*
118 * module_print: 118 * module_print:
119 * 119 *
120 * Utility function: log verbose output. 120 * Utility function: log verbose output.
121 */ 121 */
122static void 122static void
123module_print(const char *fmt, ...) 123module_print(const char *fmt, ...)
124{ 124{
125 va_list ap; 125 va_list ap;
126 126
127 if (module_verbose_on) { 127 if (module_verbose_on) {
128 va_start(ap, fmt); 128 va_start(ap, fmt);
129 printf("DEBUG: module: "); 129 printf("DEBUG: module: ");
130 vprintf(fmt, ap); 130 vprintf(fmt, ap);
131 printf("\n"); 131 printf("\n");
132 va_end(ap); 132 va_end(ap);
133 } 133 }
134} 134}
135 135
136/* 136/*
137 * module_init: 137 * module_init:
138 * 138 *
139 * Initialize the module subsystem. 139 * Initialize the module subsystem.
140 */ 140 */
141void 141void
142module_init(void) 142module_init(void)
143{ 143{
144 extern struct vm_map *module_map; 144 extern struct vm_map *module_map;
145 int error; 145 int error;
146 146
147 if (module_map == NULL) { 147 if (module_map == NULL) {
148 module_map = kernel_map; 148 module_map = kernel_map;
149 } 149 }
150 mutex_init(&module_lock, MUTEX_DEFAULT, IPL_NONE); 150 mutex_init(&module_lock, MUTEX_DEFAULT, IPL_NONE);
151 cv_init(&module_thread_cv, "modunload"); 151 cv_init(&module_thread_cv, "modunload");
152 mutex_init(&module_thread_lock, MUTEX_DEFAULT, IPL_NONE); 152 mutex_init(&module_thread_lock, MUTEX_DEFAULT, IPL_NONE);
153#ifdef MODULAR /* XXX */ 153#ifdef MODULAR /* XXX */
154 module_init_md(); 154 module_init_md();
155#endif 155#endif
156 156
157#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */ 157#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
158 snprintf(module_base, sizeof(module_base), "/stand/%s/%s/modules", 158 snprintf(module_base, sizeof(module_base), "/stand/%s/%s/modules",
159 machine, osrelease); 159 machine, osrelease);
160#else /* release */ 160#else /* release */
161 snprintf(module_base, sizeof(module_base), "/stand/%s/%d.%d/modules", 161 snprintf(module_base, sizeof(module_base), "/stand/%s/%d.%d/modules",
162 machine, __NetBSD_Version__ / 100000000, 162 machine, __NetBSD_Version__ / 100000000,
163 __NetBSD_Version__ / 1000000 % 100); 163 __NetBSD_Version__ / 1000000 % 100);
164#endif 164#endif
165 165
166 error = kthread_create(PRI_VM, KTHREAD_MPSAFE, NULL, module_thread, 166 error = kthread_create(PRI_VM, KTHREAD_MPSAFE, NULL, module_thread,
167 NULL, NULL, "modunload"); 167 NULL, NULL, "modunload");
168 if (error != 0) 168 if (error != 0)
169 panic("module_init: %d", error); 169 panic("module_init: %d", error);
170} 170}
171 171
172SYSCTL_SETUP(sysctl_module_setup, "sysctl module setup") 172SYSCTL_SETUP(sysctl_module_setup, "sysctl module setup")
173{ 173{
174 const struct sysctlnode *node = NULL; 174 const struct sysctlnode *node = NULL;
175 175
176 sysctl_createv(clog, 0, NULL, NULL, 176 sysctl_createv(clog, 0, NULL, NULL,
177 CTLFLAG_PERMANENT, 177 CTLFLAG_PERMANENT,
178 CTLTYPE_NODE, "kern", NULL, 178 CTLTYPE_NODE, "kern", NULL,
179 NULL, 0, NULL, 0, 179 NULL, 0, NULL, 0,
180 CTL_KERN, CTL_EOL); 180 CTL_KERN, CTL_EOL);
181 sysctl_createv(clog, 0, NULL, &node, 181 sysctl_createv(clog, 0, NULL, &node,
182 CTLFLAG_PERMANENT, 182 CTLFLAG_PERMANENT,
183 CTLTYPE_NODE, "module", 183 CTLTYPE_NODE, "module",
184 SYSCTL_DESCR("Module options"), 184 SYSCTL_DESCR("Module options"),
185 NULL, 0, NULL, 0, 185 NULL, 0, NULL, 0,
186 CTL_KERN, CTL_CREATE, CTL_EOL); 186 CTL_KERN, CTL_CREATE, CTL_EOL);
187 187
188 if (node == NULL) 188 if (node == NULL)
189 return; 189 return;
190 190
191 sysctl_createv(clog, 0, &node, NULL, 191 sysctl_createv(clog, 0, &node, NULL,
192 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 192 CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
193 CTLTYPE_INT, "autoload", 193 CTLTYPE_INT, "autoload",
194 SYSCTL_DESCR("Enable automatic load of modules"), 194 SYSCTL_DESCR("Enable automatic load of modules"),
195 NULL, 0, &module_autoload_on, 0, 195 NULL, 0, &module_autoload_on, 0,
196 CTL_CREATE, CTL_EOL); 196 CTL_CREATE, CTL_EOL);
197 sysctl_createv(clog, 0, &node, NULL, 197 sysctl_createv(clog, 0, &node, NULL,
198 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 198 CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
199 CTLTYPE_INT, "verbose", 199 CTLTYPE_INT, "verbose",
200 SYSCTL_DESCR("Enable verbose output"), 200 SYSCTL_DESCR("Enable verbose output"),
201 NULL, 0, &module_verbose_on, 0, 201 NULL, 0, &module_verbose_on, 0,
202 CTL_CREATE, CTL_EOL); 202 CTL_CREATE, CTL_EOL);
203} 203}
204 204
205/* 205/*
206 * module_init_class: 206 * module_init_class:
207 * 207 *
208 * Initialize all built-in and pre-loaded modules of the 208 * Initialize all built-in and pre-loaded modules of the
209 * specified class. 209 * specified class.
210 */ 210 */
211void 211void
212module_init_class(modclass_t class) 212module_init_class(modclass_t class)
213{ 213{
214 __link_set_decl(modules, modinfo_t); 214 __link_set_decl(modules, modinfo_t);
215 modinfo_t *const *mip, *mi; 215 modinfo_t *const *mip, *mi;
216 module_t *mod; 216 module_t *mod;
217 217
218 mutex_enter(&module_lock); 218 mutex_enter(&module_lock);
219 /* 219 /*
220 * Builtins first. These can't depend on pre-loaded modules. 220 * Builtins first. These can't depend on pre-loaded modules.
221 */ 221 */
222 __link_set_foreach(mip, modules) { 222 __link_set_foreach(mip, modules) {
223 mi = *mip; 223 mi = *mip;
224 if (mi == &module_dummy) { 224 if (mi == &module_dummy) {
225 continue; 225 continue;
226 } 226 }
227 if (class != MODULE_CLASS_ANY && class != mi->mi_class) { 227 if (class != MODULE_CLASS_ANY && class != mi->mi_class) {
228 continue; 228 continue;
229 } 229 }
230 (void)module_do_builtin(mi->mi_name, NULL); 230 (void)module_do_builtin(mi->mi_name, NULL);
231 } 231 }
232 /* 232 /*
233 * Now preloaded modules. These will be pulled off the 233 * Now preloaded modules. These will be pulled off the
234 * list as we call module_do_load(); 234 * list as we call module_do_load();
235 */ 235 */
236 do { 236 do {
237 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) { 237 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
238 mi = mod->mod_info; 238 mi = mod->mod_info;
239 if (class != MODULE_CLASS_ANY && 239 if (class != MODULE_CLASS_ANY &&
240 class != mi->mi_class) 240 class != mi->mi_class)
241 continue; 241 continue;
242 module_do_load(mi->mi_name, false, 0, NULL, NULL, 242 module_do_load(mi->mi_name, false, 0, NULL, NULL,
243 class, false); 243 class, false);
244 break; 244 break;
245 } 245 }
246 } while (mod != NULL); 246 } while (mod != NULL);
247 mutex_exit(&module_lock); 247 mutex_exit(&module_lock);
248} 248}
249 249
250/* 250/*
251 * module_compatible: 251 * module_compatible:
252 * 252 *
253 * Return true if the two supplied kernel versions are said to 253 * Return true if the two supplied kernel versions are said to
254 * have the same binary interface for kernel code. The entire 254 * have the same binary interface for kernel code. The entire
255 * version is signficant for the development tree (-current), 255 * version is signficant for the development tree (-current),
256 * major and minor versions are significant for official 256 * major and minor versions are significant for official
257 * releases of the system. 257 * releases of the system.
258 */ 258 */
259bool 259bool
260module_compatible(int v1, int v2) 260module_compatible(int v1, int v2)
261{ 261{
262 262
263#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */ 263#if __NetBSD_Version__ / 1000000 % 100 == 99 /* -current */
264 return v1 == v2; 264 return v1 == v2;
265#else /* release */ 265#else /* release */
266 return abs(v1 - v2) < 10000; 266 return abs(v1 - v2) < 10000;
267#endif 267#endif
268} 268}
269 269
270/* 270/*
271 * module_load: 271 * module_load:
272 * 272 *
273 * Load a single module from the file system. 273 * Load a single module from the file system.
274 */ 274 */
275int 275int
276module_load(const char *filename, int flags, prop_dictionary_t props, 276module_load(const char *filename, int flags, prop_dictionary_t props,
277 modclass_t class) 277 modclass_t class)
278{ 278{
279 int error; 279 int error;
280 280
281 /* Authorize. */ 281 /* Authorize. */
282 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 282 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
283 0, (void *)(uintptr_t)MODCTL_LOAD, NULL, NULL); 283 0, (void *)(uintptr_t)MODCTL_LOAD, NULL, NULL);
284 if (error != 0) { 284 if (error != 0) {
285 return error; 285 return error;
286 } 286 }
287 287
288 mutex_enter(&module_lock); 288 mutex_enter(&module_lock);
289 error = module_do_load(filename, false, flags, props, NULL, class, 289 error = module_do_load(filename, false, flags, props, NULL, class,
290 false); 290 false);
291 mutex_exit(&module_lock); 291 mutex_exit(&module_lock);
292 292
293 return error; 293 return error;
294} 294}
295 295
296/* 296/*
297 * module_autoload: 297 * module_autoload:
298 * 298 *
299 * Load a single module from the file system, system initiated. 299 * Load a single module from the file system, system initiated.
300 */ 300 */
301int 301int
302module_autoload(const char *filename, modclass_t class) 302module_autoload(const char *filename, modclass_t class)
303{ 303{
304 int error; 304 int error;
305 305
306 KASSERT(mutex_owned(&module_lock)); 306 KASSERT(mutex_owned(&module_lock));
307 307
308 /* Nothing if the user has disabled it. */ 308 /* Nothing if the user has disabled it. */
309 if (!module_autoload_on) { 309 if (!module_autoload_on) {
310 return EPERM; 310 return EPERM;
311 } 311 }
312 312
313 /* Disallow path seperators and magic symlinks. */ 313 /* Disallow path seperators and magic symlinks. */
314 if (strchr(filename, '/') != NULL || strchr(filename, '@') != NULL || 314 if (strchr(filename, '/') != NULL || strchr(filename, '@') != NULL ||
315 strchr(filename, '.') != NULL) { 315 strchr(filename, '.') != NULL) {
316 return EPERM; 316 return EPERM;
317 } 317 }
318 318
319 /* Authorize. */ 319 /* Authorize. */
320 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 320 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
321 0, (void *)(uintptr_t)MODCTL_LOAD, (void *)(uintptr_t)1, NULL); 321 0, (void *)(uintptr_t)MODCTL_LOAD, (void *)(uintptr_t)1, NULL);
322 if (error != 0) { 322 if (error != 0) {
323 return error; 323 return error;
324 } 324 }
325 325
326 return module_do_load(filename, false, 0, NULL, NULL, class, true); 326 return module_do_load(filename, false, 0, NULL, NULL, class, true);
327} 327}
328 328
329/* 329/*
330 * module_unload: 330 * module_unload:
331 * 331 *
332 * Find and unload a module by name. 332 * Find and unload a module by name.
333 */ 333 */
334int 334int
335module_unload(const char *name) 335module_unload(const char *name)
336{ 336{
337 int error; 337 int error;
338 338
339 /* Authorize. */ 339 /* Authorize. */
340 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE, 340 error = kauth_authorize_system(kauth_cred_get(), KAUTH_SYSTEM_MODULE,
341 0, (void *)(uintptr_t)MODCTL_UNLOAD, NULL, NULL); 341 0, (void *)(uintptr_t)MODCTL_UNLOAD, NULL, NULL);
342 if (error != 0) { 342 if (error != 0) {
343 return error; 343 return error;
344 } 344 }
345 345
346 mutex_enter(&module_lock); 346 mutex_enter(&module_lock);
347 error = module_do_unload(name); 347 error = module_do_unload(name);
348 mutex_exit(&module_lock); 348 mutex_exit(&module_lock);
349 349
350 return error; 350 return error;
351} 351}
352 352
353/* 353/*
354 * module_lookup: 354 * module_lookup:
355 * 355 *
356 * Look up a module by name. 356 * Look up a module by name.
357 */ 357 */
358module_t * 358module_t *
359module_lookup(const char *name) 359module_lookup(const char *name)
360{ 360{
361 module_t *mod; 361 module_t *mod;
362 362
363 KASSERT(mutex_owned(&module_lock)); 363 KASSERT(mutex_owned(&module_lock));
364 364
365 TAILQ_FOREACH(mod, &module_list, mod_chain) { 365 TAILQ_FOREACH(mod, &module_list, mod_chain) {
366 if (strcmp(mod->mod_info->mi_name, name) == 0) { 366 if (strcmp(mod->mod_info->mi_name, name) == 0) {
367 break; 367 break;
368 } 368 }
369 } 369 }
370 370
371 return mod; 371 return mod;
372} 372}
373 373
374/* 374/*
375 * module_hold: 375 * module_hold:
376 * 376 *
377 * Add a single reference to a module. It's the caller's 377 * Add a single reference to a module. It's the caller's
378 * responsibility to ensure that the reference is dropped 378 * responsibility to ensure that the reference is dropped
379 * later. 379 * later.
380 */ 380 */
381int 381int
382module_hold(const char *name) 382module_hold(const char *name)
383{ 383{
384 module_t *mod; 384 module_t *mod;
385 385
386 mutex_enter(&module_lock); 386 mutex_enter(&module_lock);
387 mod = module_lookup(name); 387 mod = module_lookup(name);
388 if (mod == NULL) { 388 if (mod == NULL) {
389 mutex_exit(&module_lock); 389 mutex_exit(&module_lock);
390 return ENOENT; 390 return ENOENT;
391 } 391 }
392 mod->mod_refcnt++; 392 mod->mod_refcnt++;
393 mutex_exit(&module_lock); 393 mutex_exit(&module_lock);
394 394
395 return 0; 395 return 0;
396} 396}
397 397
398/* 398/*
399 * module_rele: 399 * module_rele:
400 * 400 *
401 * Release a reference acquired with module_hold(). 401 * Release a reference acquired with module_hold().
402 */ 402 */
403void 403void
404module_rele(const char *name) 404module_rele(const char *name)
405{ 405{
406 module_t *mod; 406 module_t *mod;
407 407
408 mutex_enter(&module_lock); 408 mutex_enter(&module_lock);
409 mod = module_lookup(name); 409 mod = module_lookup(name);
410 if (mod == NULL) { 410 if (mod == NULL) {
411 mutex_exit(&module_lock); 411 mutex_exit(&module_lock);
412 panic("module_rele: gone"); 412 panic("module_rele: gone");
413 } 413 }
414 mod->mod_refcnt--; 414 mod->mod_refcnt--;
415 mutex_exit(&module_lock); 415 mutex_exit(&module_lock);
416} 416}
417 417
418/* 418/*
419 * module_enqueue: 419 * module_enqueue:
420 * 420 *
421 * Put a module onto the global list and update counters. 421 * Put a module onto the global list and update counters.
422 */ 422 */
423static void 423static void
424module_enqueue(module_t *mod) 424module_enqueue(module_t *mod)
425{ 425{
426 int i; 426 int i;
427 427
428 /* 428 /*
429 * If there are requisite modules, put at the head of the queue. 429 * If there are requisite modules, put at the head of the queue.
430 * This is so that autounload can unload requisite modules with 430 * This is so that autounload can unload requisite modules with
431 * only one pass through the queue. 431 * only one pass through the queue.
432 */ 432 */
433 if (mod->mod_nrequired) { 433 if (mod->mod_nrequired) {
434 TAILQ_INSERT_HEAD(&module_list, mod, mod_chain); 434 TAILQ_INSERT_HEAD(&module_list, mod, mod_chain);
435 435
436 /* Add references to the requisite modules. */ 436 /* Add references to the requisite modules. */
437 for (i = 0; i < mod->mod_nrequired; i++) { 437 for (i = 0; i < mod->mod_nrequired; i++) {
438 KASSERT(mod->mod_required[i] != NULL); 438 KASSERT(mod->mod_required[i] != NULL);
439 mod->mod_required[i]->mod_refcnt++; 439 mod->mod_required[i]->mod_refcnt++;
440 } 440 }
441 } else { 441 } else {
442 TAILQ_INSERT_TAIL(&module_list, mod, mod_chain); 442 TAILQ_INSERT_TAIL(&module_list, mod, mod_chain);
443 } 443 }
444 module_count++; 444 module_count++;
445 module_gen++; 445 module_gen++;
446} 446}
447 447
448/* 448/*
449 * module_do_builtin: 449 * module_do_builtin:
450 * 450 *
451 * Initialize a single module from the list of modules that are 451 * Initialize a single module from the list of modules that are
452 * built into the kernel (linked into the kernel image). 452 * built into the kernel (linked into the kernel image).
453 */ 453 */
454static int 454static int
455module_do_builtin(const char *name, module_t **modp) 455module_do_builtin(const char *name, module_t **modp)
456{ 456{
457 __link_set_decl(modules, modinfo_t); 457 __link_set_decl(modules, modinfo_t);
458 modinfo_t *const *mip; 458 modinfo_t *const *mip;
459 const char *p, *s; 459 const char *p, *s;
460 char buf[MAXMODNAME]; 460 char buf[MAXMODNAME];
461 modinfo_t *mi; 461 modinfo_t *mi;
462 module_t *mod, *mod2; 462 module_t *mod, *mod2;
463 size_t len; 463 size_t len;
464 int error; 464 int error;
465 465
466 KASSERT(mutex_owned(&module_lock)); 466 KASSERT(mutex_owned(&module_lock));
467 467
468 /* 468 /*
469 * Check to see if already loaded. 469 * Check to see if already loaded.
470 */ 470 */
471 if ((mod = module_lookup(name)) != NULL) { 471 if ((mod = module_lookup(name)) != NULL) {
472 if (modp != NULL) { 472 if (modp != NULL) {
473 *modp = mod; 473 *modp = mod;
474 } 474 }
475 return 0; 475 return 0;
476 } 476 }
477 477
478 /* 478 /*
479 * Search the list to see if we have a module by this name. 479 * Search the list to see if we have a module by this name.
480 */ 480 */
481 error = ENOENT; 481 error = ENOENT;
482 __link_set_foreach(mip, modules) { 482 __link_set_foreach(mip, modules) {
483 mi = *mip; 483 mi = *mip;
484 if (mi == &module_dummy) { 484 if (mi == &module_dummy) {
485 continue; 485 continue;
486 } 486 }
487 if (strcmp(mi->mi_name, name) == 0) { 487 if (strcmp(mi->mi_name, name) == 0) {
488 error = 0; 488 error = 0;
489 break; 489 break;
490 } 490 }
491 } 491 }
492 if (error != 0) { 492 if (error != 0) {
493 module_error("can't find `%s'", name); 493 module_error("can't find `%s'", name);
494 return error; 494 return error;
495 } 495 }
496 496
497 /* 497 /*
498 * Initialize pre-requisites. 498 * Initialize pre-requisites.
499 */ 499 */
500 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP); 500 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
501 if (mod == NULL) { 501 if (mod == NULL) {
502 module_error("out of memory for `%s'", name); 502 module_error("out of memory for `%s'", name);
503 return ENOMEM; 503 return ENOMEM;
504 } 504 }
505 if (modp != NULL) { 505 if (modp != NULL) {
506 *modp = mod; 506 *modp = mod;
507 } 507 }
508 if (mi->mi_required != NULL) { 508 if (mi->mi_required != NULL) {
509 for (s = mi->mi_required; *s != '\0'; s = p) { 509 for (s = mi->mi_required; *s != '\0'; s = p) {
510 if (*s == ',') 510 if (*s == ',')
511 s++; 511 s++;
512 p = s; 512 p = s;
513 while (*p != '\0' && *p != ',') 513 while (*p != '\0' && *p != ',')
514 p++; 514 p++;
515 len = min(p - s + 1, sizeof(buf)); 515 len = min(p - s + 1, sizeof(buf));
516 strlcpy(buf, s, len); 516 strlcpy(buf, s, len);
517 if (buf[0] == '\0') 517 if (buf[0] == '\0')
518 break; 518 break;
519 if (mod->mod_nrequired == MAXMODDEPS - 1) { 519 if (mod->mod_nrequired == MAXMODDEPS - 1) {
520 module_error("too many required modules"); 520 module_error("too many required modules");
521 kmem_free(mod, sizeof(*mod)); 521 kmem_free(mod, sizeof(*mod));
522 return EINVAL; 522 return EINVAL;
523 } 523 }
524 error = module_do_builtin(buf, &mod2); 524 error = module_do_builtin(buf, &mod2);
525 if (error != 0) { 525 if (error != 0) {
526 kmem_free(mod, sizeof(*mod)); 526 kmem_free(mod, sizeof(*mod));
527 return error; 527 return error;
528 } 528 }
529 mod->mod_required[mod->mod_nrequired++] = mod2; 529 mod->mod_required[mod->mod_nrequired++] = mod2;
530 } 530 }
531 } 531 }
532 532
533 /* 533 /*
534 * Try to initialize the module. 534 * Try to initialize the module.
535 */ 535 */
536 KASSERT(module_active == NULL); 536 KASSERT(module_active == NULL);
537 module_active = mod; 537 module_active = mod;
538 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, NULL); 538 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, NULL);
539 module_active = NULL; 539 module_active = NULL;
540 if (error != 0) { 540 if (error != 0) {
541 module_error("builtin module `%s' " 541 module_error("builtin module `%s' "
542 "failed to init", mi->mi_name); 542 "failed to init", mi->mi_name);
543 kmem_free(mod, sizeof(*mod)); 543 kmem_free(mod, sizeof(*mod));
544 return error; 544 return error;
545 } 545 }
546 mod->mod_info = mi; 546 mod->mod_info = mi;
547 mod->mod_source = MODULE_SOURCE_KERNEL; 547 mod->mod_source = MODULE_SOURCE_KERNEL;
548 module_enqueue(mod); 548 module_enqueue(mod);
549 return 0; 549 return 0;
550} 550}
551 551
552/* 552/*
553 * module_do_load: 553 * module_do_load:
554 * 554 *
555 * Helper routine: load a module from the file system, or one 555 * Helper routine: load a module from the file system, or one
556 * pushed by the boot loader. 556 * pushed by the boot loader.
557 */ 557 */
558static int 558static int
559module_do_load(const char *name, bool isdep, int flags, 559module_do_load(const char *name, bool isdep, int flags,
560 prop_dictionary_t props, module_t **modp, modclass_t class, 560 prop_dictionary_t props, module_t **modp, modclass_t class,
561 bool autoload) 561 bool autoload)
562{ 562{
563 static TAILQ_HEAD(,module) pending = TAILQ_HEAD_INITIALIZER(pending); 563 static TAILQ_HEAD(,module) pending = TAILQ_HEAD_INITIALIZER(pending);
564 static int depth; 564 static int depth;
565 const int maxdepth = 6; 565 const int maxdepth = 6;
566 modinfo_t *mi; 566 modinfo_t *mi;
567 module_t *mod, *mod2; 567 module_t *mod, *mod2;
568 prop_dictionary_t filedict; 568 prop_dictionary_t filedict;
569 void *plist; 569 void *plist;
570 char buf[MAXMODNAME], *path; 570 char buf[MAXMODNAME], *path;
571 const char *s, *p; 571 const char *s, *p;
572 int error; 572 int error;
573 size_t len, plistlen; 573 size_t len, plistlen;
574 bool nochroot; 574 bool nochroot;
575 575
576 KASSERT(mutex_owned(&module_lock)); 576 KASSERT(mutex_owned(&module_lock));
577 577
578 filedict = NULL; 578 filedict = NULL;
579 path = NULL; 579 path = NULL;
580 error = 0; 580 error = 0;
581 nochroot = false; 581 nochroot = false;
582 582
583 /* 583 /*
584 * Avoid recursing too far. 584 * Avoid recursing too far.
585 */ 585 */
586 if (++depth > maxdepth) { 586 if (++depth > maxdepth) {
587 module_error("too many required modules"); 587 module_error("too many required modules");
588 depth--; 588 depth--;
589 return EMLINK; 589 return EMLINK;
590 } 590 }
591 591
592 /* 592 /*
593 * Load the module and link. Before going to the file system, 593 * Load the module and link. Before going to the file system,
594 * scan the list of modules loaded by the boot loader. Just 594 * scan the list of modules loaded by the boot loader. Just
595 * before init is started the list of modules loaded at boot 595 * before init is started the list of modules loaded at boot
596 * will be purged. Before init is started we can assume that 596 * will be purged. Before init is started we can assume that
597 * `name' is a module name and not a path name. 597 * `name' is a module name and not a path name.
598 */ 598 */
599 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) { 599 TAILQ_FOREACH(mod, &module_bootlist, mod_chain) {
600 if (strcmp(mod->mod_info->mi_name, name) == 0) { 600 if (strcmp(mod->mod_info->mi_name, name) == 0) {
601 TAILQ_REMOVE(&module_bootlist, mod, mod_chain); 601 TAILQ_REMOVE(&module_bootlist, mod, mod_chain);
602 break; 602 break;
603 } 603 }
604 } 604 }
605 if (mod != NULL) { 605 if (mod != NULL) {
606 TAILQ_INSERT_TAIL(&pending, mod, mod_chain); 606 TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
607 } else { 607 } else {
608 /* 608 /*
609 * If a requisite module, check to see if it is 609 * If a requisite module, check to see if it is
610 * already present. 610 * already present.
611 */ 611 */
612 if (isdep) { 612 if (isdep) {
613 TAILQ_FOREACH(mod, &module_list, mod_chain) { 613 TAILQ_FOREACH(mod, &module_list, mod_chain) {
614 if (strcmp(mod->mod_info->mi_name, name) == 0) { 614 if (strcmp(mod->mod_info->mi_name, name) == 0) {
615 break; 615 break;
616 } 616 }
617 } 617 }
618 if (mod != NULL) { 618 if (mod != NULL) {
619 if (modp != NULL) { 619 if (modp != NULL) {
620 *modp = mod; 620 *modp = mod;
621 } 621 }
622 depth--; 622 depth--;
623 return 0; 623 return 0;
624 } 624 }
625 }  625 }
626 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP); 626 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
627 if (mod == NULL) { 627 if (mod == NULL) {
628 module_error("out of memory for `%s'", name); 628 module_error("out of memory for `%s'", name);
629 depth--; 629 depth--;
630 return ENOMEM; 630 return ENOMEM;
631 } 631 }
632 path = PNBUF_GET(); 632 path = PNBUF_GET();
633 if (!autoload) { 633 if (!autoload) {
634 nochroot = false; 634 nochroot = false;
635 snprintf(path, MAXPATHLEN, "%s", name); 635 snprintf(path, MAXPATHLEN, "%s", name);
636 error = kobj_load_file(&mod->mod_kobj, path, nochroot); 636 error = kobj_load_file(&mod->mod_kobj, path, nochroot);
637 } 637 }
638 if (autoload || (error == ENOENT)) { 638 if (autoload || (error == ENOENT)) {
639 nochroot = true; 639 nochroot = true;
640 snprintf(path, MAXPATHLEN, "%s/%s/%s.kmod", 640 snprintf(path, MAXPATHLEN, "%s/%s/%s.kmod",
641 module_base, name, name); 641 module_base, name, name);
642 error = kobj_load_file(&mod->mod_kobj, path, nochroot); 642 error = kobj_load_file(&mod->mod_kobj, path, nochroot);
643 } 643 }
644 if (error != 0) { 644 if (error != 0) {
645 kmem_free(mod, sizeof(*mod)); 645 kmem_free(mod, sizeof(*mod));
646 depth--; 646 depth--;
647 PNBUF_PUT(path); 647 PNBUF_PUT(path);
648 if (autoload) { 648 if (autoload) {
649 module_print("Cannot load kernel object `%s'" 649 module_print("Cannot load kernel object `%s'"
650 " error=%d", name, error); 650 " error=%d", name, error);
651 } else { 651 } else {
652 module_error("Cannot load kernel object `%s'" 652 module_error("Cannot load kernel object `%s'"
653 " error=%d", name, error); 653 " error=%d", name, error);
654 } 654 }
655 return error; 655 return error;
656 } 656 }
657 TAILQ_INSERT_TAIL(&pending, mod, mod_chain); 657 TAILQ_INSERT_TAIL(&pending, mod, mod_chain);
658 mod->mod_source = MODULE_SOURCE_FILESYS; 658 mod->mod_source = MODULE_SOURCE_FILESYS;
659 error = module_fetch_info(mod); 659 error = module_fetch_info(mod);
660 if (error != 0) { 660 if (error != 0) {
661 module_error("cannot fetch module info for `%s'", 661 module_error("cannot fetch module info for `%s'",
662 name); 662 name);
663 goto fail; 663 goto fail;
664 } 664 }
665 } 665 }
666 666
667 /* 667 /*
668 * Check compatibility. 668 * Check compatibility.
669 */ 669 */
670 mi = mod->mod_info; 670 mi = mod->mod_info;
671 if (strlen(mi->mi_name) >= MAXMODNAME) { 671 if (strlen(mi->mi_name) >= MAXMODNAME) {
672 error = EINVAL; 672 error = EINVAL;
673 module_error("module name `%s' too long", mi->mi_name); 673 module_error("module name `%s' too long", mi->mi_name);
674 goto fail; 674 goto fail;
675 } 675 }
676 if (!module_compatible(mi->mi_version, __NetBSD_Version__)) { 676 if (!module_compatible(mi->mi_version, __NetBSD_Version__)) {
677 module_error("module built for `%d', system `%d'", 677 module_error("module built for `%d', system `%d'",
678 mi->mi_version, __NetBSD_Version__); 678 mi->mi_version, __NetBSD_Version__);
679 if ((flags & MODCTL_LOAD_FORCE) != 0) { 679 if ((flags & MODCTL_LOAD_FORCE) != 0) {
680 module_error("forced load, system may be unstable"); 680 module_error("forced load, system may be unstable");
681 } else { 681 } else {
682 error = EPROGMISMATCH; 682 error = EPROGMISMATCH;
683 goto fail; 683 goto fail;
684 } 684 }
685 } 685 }
686 686
687 /* 687 /*
688 * If a specific kind of module was requested, ensure that we have 688 * If a specific kind of module was requested, ensure that we have
689 * a match. 689 * a match.
690 */ 690 */
691 if (class != MODULE_CLASS_ANY && class != mi->mi_class) { 691 if (class != MODULE_CLASS_ANY && class != mi->mi_class) {
692 module_print("incompatible module class for `%s' (%d != %d)", 692 module_print("incompatible module class for `%s' (%d != %d)",
693 name, class, mi->mi_class); 693 name, class, mi->mi_class);
694 error = ENOENT; 694 error = ENOENT;
695 goto fail; 695 goto fail;
696 } 696 }
697 697
698 /* 698 /*
699 * If loading a dependency, `name' is a plain module name. 699 * If loading a dependency, `name' is a plain module name.
700 * The name must match. 700 * The name must match.
701 */ 701 */
702 if (isdep && strcmp(mi->mi_name, name) != 0) { 702 if (isdep && strcmp(mi->mi_name, name) != 0) {
703 module_error("dependency name mismatch (`%s' != `%s')", 703 module_error("dependency name mismatch (`%s' != `%s')",
704 name, mi->mi_name); 704 name, mi->mi_name);
705 error = ENOENT; 705 error = ENOENT;
706 goto fail; 706 goto fail;
707 } 707 }
708 708
709 /* 709 /*
710 * Check to see if the module is already loaded. If so, we may 710 * Check to see if the module is already loaded. If so, we may
711 * have been recursively called to handle a dependency, so be sure 711 * have been recursively called to handle a dependency, so be sure
712 * to set modp. 712 * to set modp.
713 */ 713 */
714 if ((mod2 = module_lookup(mi->mi_name)) != NULL) { 714 if ((mod2 = module_lookup(mi->mi_name)) != NULL) {
715 if (modp != NULL) 715 if (modp != NULL)
716 *modp = mod2; 716 *modp = mod2;
717 module_print("module `%s' already loaded", mi->mi_name); 717 module_print("module `%s' already loaded", mi->mi_name);
718 error = EEXIST; 718 error = EEXIST;
719 goto fail; 719 goto fail;
720 } 720 }
721 721
722 /* 722 /*
723 * Block circular dependencies. 723 * Block circular dependencies.
724 */ 724 */
725 TAILQ_FOREACH(mod2, &pending, mod_chain) { 725 TAILQ_FOREACH(mod2, &pending, mod_chain) {
726 if (mod == mod2) { 726 if (mod == mod2) {
727 continue; 727 continue;
728 } 728 }
729 if (strcmp(mod2->mod_info->mi_name, mi->mi_name) == 0) { 729 if (strcmp(mod2->mod_info->mi_name, mi->mi_name) == 0) {
730 error = EDEADLK; 730 error = EDEADLK;
731 module_error("circular dependency detected for `%s'", 731 module_error("circular dependency detected for `%s'",
732 mi->mi_name); 732 mi->mi_name);
733 goto fail; 733 goto fail;
734 } 734 }
735 } 735 }
736 736
737 /* 737 /*
738 * Now try to load any requisite modules. 738 * Now try to load any requisite modules.
739 */ 739 */
740 if (mi->mi_required != NULL) { 740 if (mi->mi_required != NULL) {
741 for (s = mi->mi_required; *s != '\0'; s = p) { 741 for (s = mi->mi_required; *s != '\0'; s = p) {
742 if (*s == ',') 742 if (*s == ',')
743 s++; 743 s++;
744 p = s; 744 p = s;
745 while (*p != '\0' && *p != ',') 745 while (*p != '\0' && *p != ',')
746 p++; 746 p++;
747 len = p - s + 1; 747 len = p - s + 1;
748 if (len >= MAXMODNAME) { 748 if (len >= MAXMODNAME) {
749 error = EINVAL; 749 error = EINVAL;
750 module_error("required module name `%s'" 750 module_error("required module name `%s'"
751 " too long", mi->mi_required); 751 " too long", mi->mi_required);
752 goto fail; 752 goto fail;
753 } 753 }
754 strlcpy(buf, s, len); 754 strlcpy(buf, s, len);
755 if (buf[0] == '\0') 755 if (buf[0] == '\0')
756 break; 756 break;
757 if (mod->mod_nrequired == MAXMODDEPS - 1) { 757 if (mod->mod_nrequired == MAXMODDEPS - 1) {
758 error = EINVAL; 758 error = EINVAL;
759 module_error("too many required modules (%d)", 759 module_error("too many required modules (%d)",
760 mod->mod_nrequired); 760 mod->mod_nrequired);
761 goto fail; 761 goto fail;
762 } 762 }
763 if (strcmp(buf, mi->mi_name) == 0) { 763 if (strcmp(buf, mi->mi_name) == 0) {
764 error = EDEADLK; 764 error = EDEADLK;
765 module_error("self-dependency detected for " 765 module_error("self-dependency detected for "
766 "`%s'", mi->mi_name); 766 "`%s'", mi->mi_name);
767 goto fail; 767 goto fail;
768 } 768 }
769 error = module_do_load(buf, true, flags, NULL, 769 error = module_do_load(buf, true, flags, NULL,
770 &mod->mod_required[mod->mod_nrequired++], 770 &mod->mod_required[mod->mod_nrequired++],
771 MODULE_CLASS_ANY, true); 771 MODULE_CLASS_ANY, true);
772 if (error != 0) 772 if (error != 0)
773 goto fail; 773 goto fail;
774 } 774 }
775 } 775 }
776 776
777 /* 777 /*
778 * We loaded all needed modules successfully: perform global 778 * We loaded all needed modules successfully: perform global
779 * relocations and initialize. 779 * relocations and initialize.
780 */ 780 */
781 error = kobj_affix(mod->mod_kobj, mi->mi_name); 781 error = kobj_affix(mod->mod_kobj, mi->mi_name);
782 if (error != 0) { 782 if (error != 0) {
783 /* Cannot touch 'mi' as the module is now gone. */ 783 /* Cannot touch 'mi' as the module is now gone. */
784 module_error("unable to affix module `%s'", name); 784 module_error("unable to affix module `%s'", name);
785 goto fail2; 785 goto fail2;
786 } 786 }
787 787
788 /* 788 /*
789 * Load and process <module>.prop if it exists. 789 * Load and process <module>.prop if it exists.
790 */ 790 */
791 if (((flags & MODCTL_NO_PROP) == 0) && 791 if (((flags & MODCTL_NO_PROP) == 0) &&
792 (mod->mod_source == MODULE_SOURCE_FILESYS)) { 792 (mod->mod_source == MODULE_SOURCE_FILESYS)) {
793 error = module_load_plist_file(path, nochroot, &plist, 793 error = module_load_plist_file(path, nochroot, &plist,
794 &plistlen); 794 &plistlen);
795 if (error != 0) { 795 if (error != 0) {
796 module_print("plist load returned error %d for `%s'", 796 module_print("plist load returned error %d for `%s'",
797 error, path); 797 error, path);
798 } else { 798 } else {
799 filedict = prop_dictionary_internalize(plist); 799 filedict = prop_dictionary_internalize(plist);
800 if (filedict == NULL) { 800 if (filedict == NULL) {
801 error = EINVAL; 801 error = EINVAL;
802 } else if (!module_merge_dicts(filedict, props)) { 802 } else if (!module_merge_dicts(filedict, props)) {
803 error = EINVAL; 803 error = EINVAL;
804 prop_object_release(filedict); 804 prop_object_release(filedict);
805 filedict = NULL; 805 filedict = NULL;
806 } 806 }
807 } 807 }
808 if (plist != NULL) { 808 if (plist != NULL) {
809 kmem_free(plist, PAGE_SIZE); 809 kmem_free(plist, PAGE_SIZE);
810 } 810 }
811 if ((error != 0) && (error != ENOENT)) { 811 if ((error != 0) && (error != ENOENT)) {
812 goto fail; 812 goto fail;
813 } 813 }
814 } 814 }
815 815
816 KASSERT(module_active == NULL); 816 KASSERT(module_active == NULL);
817 module_active = mod; 817 module_active = mod;
818 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, (filedict != NULL) ? 818 error = (*mi->mi_modcmd)(MODULE_CMD_INIT, (filedict != NULL) ?
819 filedict : props); /* props will have been merged with filedict */ 819 filedict : props); /* props will have been merged with filedict */
820 module_active = NULL; 820 module_active = NULL;
821 if (filedict != NULL) { 821 if (filedict != NULL) {
822 prop_object_release(filedict); 822 prop_object_release(filedict);
823 } 823 }
824 if (error != 0) { 824 if (error != 0) {
825 module_error("modcmd function returned error %d for `%s'", 825 module_error("modcmd function returned error %d for `%s'",
826 error, mi->mi_name); 826 error, mi->mi_name);
827 goto fail; 827 goto fail;
828 } 828 }
829 829
830 /* 830 /*
831 * Good, the module loaded successfully. Put it onto the 831 * Good, the module loaded successfully. Put it onto the
832 * list and add references to its requisite modules. 832 * list and add references to its requisite modules.
833 */ 833 */
834 TAILQ_REMOVE(&pending, mod, mod_chain); 834 TAILQ_REMOVE(&pending, mod, mod_chain);
835 module_enqueue(mod); 835 module_enqueue(mod);
836 if (modp != NULL) { 836 if (modp != NULL) {
837 *modp = mod; 837 *modp = mod;
838 } 838 }
839 if (autoload) { 839 if (autoload) {
840 /* 840 /*
841 * Arrange to try unloading the module after 841 * Arrange to try unloading the module after
842 * a short delay. 842 * a short delay.
843 */ 843 */
844 mod->mod_autotime = time_second + module_autotime; 844 mod->mod_autotime = time_second + module_autotime;
845 module_thread_kick(); 845 module_thread_kick();
846 } 846 }
847 depth--; 847 depth--;
848 if (path != NULL) 848 if (path != NULL)
849 PNBUF_PUT(path); 849 PNBUF_PUT(path);
850 return 0; 850 return 0;
851 851
852 fail: 852 fail:
853 kobj_unload(mod->mod_kobj); 853 kobj_unload(mod->mod_kobj);
854 fail2: 854 fail2:
855 TAILQ_REMOVE(&pending, mod, mod_chain); 855 TAILQ_REMOVE(&pending, mod, mod_chain);
856 kmem_free(mod, sizeof(*mod)); 856 kmem_free(mod, sizeof(*mod));
857 depth--; 857 depth--;
858 if (path != NULL) 858 if (path != NULL)
859 PNBUF_PUT(path); 859 PNBUF_PUT(path);
860 return error; 860 return error;
861} 861}
862 862
863/* 863/*
864 * module_do_unload: 864 * module_do_unload:
865 * 865 *
866 * Helper routine: do the dirty work of unloading a module. 866 * Helper routine: do the dirty work of unloading a module.
867 */ 867 */
868static int 868static int
869module_do_unload(const char *name) 869module_do_unload(const char *name)
870{ 870{
871 module_t *mod; 871 module_t *mod;
872 int error; 872 int error;
873 u_int i; 873 u_int i;
874 874
875 KASSERT(mutex_owned(&module_lock)); 875 KASSERT(mutex_owned(&module_lock));
876 876
877 mod = module_lookup(name); 877 mod = module_lookup(name);
878 if (mod == NULL) { 878 if (mod == NULL) {
879 module_error("module `%s' not found", name); 879 module_error("module `%s' not found", name);
880 return ENOENT; 880 return ENOENT;
881 } 881 }
882 if (mod->mod_refcnt != 0 || mod->mod_source == MODULE_SOURCE_KERNEL) { 882 if (mod->mod_refcnt != 0 || mod->mod_source == MODULE_SOURCE_KERNEL) {
883 module_print("module `%s' busy", name); 883 module_print("module `%s' busy", name);
884 return EBUSY; 884 return EBUSY;
885 } 885 }
886 KASSERT(module_active == NULL); 886 KASSERT(module_active == NULL);
887 module_active = mod; 887 module_active = mod;
888 error = (*mod->mod_info->mi_modcmd)(MODULE_CMD_FINI, NULL); 888 error = (*mod->mod_info->mi_modcmd)(MODULE_CMD_FINI, NULL);
889 module_active = NULL; 889 module_active = NULL;
890 if (error != 0) { 890 if (error != 0) {
891 module_print("cannot unload module `%s' error=%d", name, 891 module_print("cannot unload module `%s' error=%d", name,
892 error); 892 error);
893 return error; 893 return error;
894 } 894 }
895 module_count--; 895 module_count--;
896 TAILQ_REMOVE(&module_list, mod, mod_chain); 896 TAILQ_REMOVE(&module_list, mod, mod_chain);
897 for (i = 0; i < mod->mod_nrequired; i++) { 897 for (i = 0; i < mod->mod_nrequired; i++) {
898 mod->mod_required[i]->mod_refcnt--; 898 mod->mod_required[i]->mod_refcnt--;
899 } 899 }
900 if (mod->mod_kobj != NULL) { 900 if (mod->mod_kobj != NULL) {
901 kobj_unload(mod->mod_kobj); 901 kobj_unload(mod->mod_kobj);
902 } 902 }
903 kmem_free(mod, sizeof(*mod)); 903 kmem_free(mod, sizeof(*mod));
904 module_gen++; 904 module_gen++;
905 905
906 return 0; 906 return 0;
907} 907}
908 908
909/* 909/*
910 * module_prime: 910 * module_prime:
911 * 911 *
912 * Push a module loaded by the bootloader onto our internal 912 * Push a module loaded by the bootloader onto our internal
913 * list. 913 * list.
914 */ 914 */
915int 915int
916module_prime(void *base, size_t size) 916module_prime(void *base, size_t size)
917{ 917{
918 module_t *mod; 918 module_t *mod;
919 int error; 919 int error;
920 920
921 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP); 921 mod = kmem_zalloc(sizeof(*mod), KM_SLEEP);
922 if (mod == NULL) { 922 if (mod == NULL) {
923 return ENOMEM; 923 return ENOMEM;
924 } 924 }
925 mod->mod_source = MODULE_SOURCE_BOOT; 925 mod->mod_source = MODULE_SOURCE_BOOT;
926 926
927 error = kobj_load_mem(&mod->mod_kobj, base, size); 927 error = kobj_load_mem(&mod->mod_kobj, base, size);
928 if (error != 0) { 928 if (error != 0) {
929 kmem_free(mod, sizeof(*mod)); 929 kmem_free(mod, sizeof(*mod));
930 module_error("unable to load object pushed by boot loader"); 930 module_error("unable to load object pushed by boot loader");
931 return error; 931 return error;
932 } 932 }
933 error = module_fetch_info(mod); 933 error = module_fetch_info(mod);
934 if (error != 0) { 934 if (error != 0) {
935 kobj_unload(mod->mod_kobj); 935 kobj_unload(mod->mod_kobj);
936 kmem_free(mod, sizeof(*mod)); 936 kmem_free(mod, sizeof(*mod));
937 module_error("unable to load object pushed by boot loader"); 937 module_error("unable to load object pushed by boot loader");
938 return error; 938 return error;
939 } 939 }
940 940
941 TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain); 941 TAILQ_INSERT_TAIL(&module_bootlist, mod, mod_chain);
942 942
943 return 0; 943 return 0;
944} 944}
945 945
946/* 946/*
947 * module_fetch_into: 947 * module_fetch_into:
948 * 948 *
949 * Fetch modinfo record from a loaded module. 949 * Fetch modinfo record from a loaded module.
950 */ 950 */
951static int 951static int
952module_fetch_info(module_t *mod) 952module_fetch_info(module_t *mod)
953{ 953{
954 int error; 954 int error;
955 void *addr; 955 void *addr;
956 size_t size; 956 size_t size;
957 957
958 /* 958 /*
959 * Find module info record and check compatibility. 959 * Find module info record and check compatibility.
960 */ 960 */
961 error = kobj_find_section(mod->mod_kobj, "link_set_modules", 961 error = kobj_find_section(mod->mod_kobj, "link_set_modules",
962 &addr, &size); 962 &addr, &size);
963 if (error != 0) { 963 if (error != 0) {
964 module_error("`link_set_modules' section not present"); 964 module_error("`link_set_modules' section not present");
965 return error; 965 return error;
966 } 966 }
967 if (size != sizeof(modinfo_t **)) { 967 if (size != sizeof(modinfo_t **)) {
968 module_error("`link_set_modules' section wrong size"); 968 module_error("`link_set_modules' section wrong size");
969 return error; 969 return error;
970 } 970 }
971 mod->mod_info = *(modinfo_t **)addr; 971 mod->mod_info = *(modinfo_t **)addr;
972 972
973 return 0; 973 return 0;
974} 974}
975 975
976/* 976/*
977 * module_find_section: 977 * module_find_section:
978 * 978 *
979 * Allows a module that is being initialized to look up a section 979 * Allows a module that is being initialized to look up a section
980 * within its ELF object. 980 * within its ELF object.
981 */ 981 */
982int 982int
983module_find_section(const char *name, void **addr, size_t *size) 983module_find_section(const char *name, void **addr, size_t *size)
984{ 984{
985 985
986 KASSERT(mutex_owned(&module_lock)); 986 KASSERT(mutex_owned(&module_lock));
987 KASSERT(module_active != NULL); 987 KASSERT(module_active != NULL);
988 988
989 return kobj_find_section(module_active->mod_kobj, name, addr, size); 989 return kobj_find_section(module_active->mod_kobj, name, addr, size);
990} 990}
991 991
992/* 992/*
993 * module_thread: 993 * module_thread:
994 * 994 *
995 * Automatically unload modules. We try once to unload autoloaded 995 * Automatically unload modules. We try once to unload autoloaded
996 * modules after module_autotime seconds. If the system is under 996 * modules after module_autotime seconds. If the system is under
997 * severe memory pressure, we'll try unloading all modules. 997 * severe memory pressure, we'll try unloading all modules.
998 */ 998 */
999static void 999static void
1000module_thread(void *cookie) 1000module_thread(void *cookie)
1001{ 1001{
1002 module_t *mod, *next; 1002 module_t *mod, *next;
1003 modinfo_t *mi; 1003 modinfo_t *mi;
1004 int error; 1004 int error;
1005 1005
1006 for (;;) { 1006 for (;;) {
1007 mutex_enter(&module_lock); 1007 mutex_enter(&module_lock);
1008 for (mod = TAILQ_FIRST(&module_list); mod != NULL; mod = next) { 1008 for (mod = TAILQ_FIRST(&module_list); mod != NULL; mod = next) {
1009 next = TAILQ_NEXT(mod, mod_chain); 1009 next = TAILQ_NEXT(mod, mod_chain);
1010 if (uvmexp.free < uvmexp.freemin) { 1010 if (uvmexp.free < uvmexp.freemin) {
1011 module_thread_ticks = hz; 1011 module_thread_ticks = hz;
1012 } else if (mod->mod_autotime == 0) { 1012 } else if (mod->mod_autotime == 0) {
1013 continue; 1013 continue;
1014 } else if (time_second < mod->mod_autotime) { 1014 } else if (time_second < mod->mod_autotime) {
1015 module_thread_ticks = hz; 1015 module_thread_ticks = hz;
1016 continue; 1016 continue;
1017 } else { 1017 } else {
1018 mod->mod_autotime = 0; 1018 mod->mod_autotime = 0;
1019 } 1019 }
1020 /* 1020 /*
1021 * If this module wants to avoid autounload then 1021 * If this module wants to avoid autounload then
1022 * skip it. Some modules can ping-pong in and out 1022 * skip it. Some modules can ping-pong in and out
1023 * because their use is transient but often.  1023 * because their use is transient but often.
1024 * Example: exec_script. 1024 * Example: exec_script.
1025 */ 1025 */
1026 mi = mod->mod_info; 1026 mi = mod->mod_info;
1027 error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL); 1027 error = (*mi->mi_modcmd)(MODULE_CMD_AUTOUNLOAD, NULL);
1028 if (error == 0 || error == ENOTTY) { 1028 if (error == 0 || error == ENOTTY) {
1029 (void)module_do_unload(mi->mi_name); 1029 (void)module_do_unload(mi->mi_name);
1030 } 1030 }
1031 } 1031 }
1032 mutex_exit(&module_lock); 1032 mutex_exit(&module_lock);
1033 1033
1034 mutex_enter(&module_thread_lock); 1034 mutex_enter(&module_thread_lock);
1035 (void)cv_timedwait(&module_thread_cv, &module_thread_lock, 1035 (void)cv_timedwait(&module_thread_cv, &module_thread_lock,
1036 module_thread_ticks); 1036 module_thread_ticks);
1037 module_thread_ticks = 0; 1037 module_thread_ticks = 0;
1038 mutex_exit(&module_thread_lock); 1038 mutex_exit(&module_thread_lock);
1039 } 1039 }
1040} 1040}
1041 1041
1042/* 1042/*
1043 * module_thread: 1043 * module_thread:
1044 * 1044 *
1045 * Kick the module thread into action, perhaps because the 1045 * Kick the module thread into action, perhaps because the
1046 * system is low on memory. 1046 * system is low on memory.
1047 */ 1047 */
1048void 1048void
1049module_thread_kick(void) 1049module_thread_kick(void)
1050{ 1050{
1051 1051
1052 mutex_enter(&module_thread_lock); 1052 mutex_enter(&module_thread_lock);
1053 module_thread_ticks = hz; 1053 module_thread_ticks = hz;
1054 cv_broadcast(&module_thread_cv); 1054 cv_broadcast(&module_thread_cv);
1055 mutex_exit(&module_thread_lock); 1055 mutex_exit(&module_thread_lock);
1056} 1056}
1057 1057
1058#ifdef DDB 1058#ifdef DDB
1059/* 1059/*
1060 * module_whatis: 1060 * module_whatis:
1061 * 1061 *
1062 * Helper routine for DDB. 1062 * Helper routine for DDB.
1063 */ 1063 */
1064void 1064void
1065module_whatis(uintptr_t addr, void (*pr)(const char *, ...)) 1065module_whatis(uintptr_t addr, void (*pr)(const char *, ...))
1066{ 1066{
1067 module_t *mod; 1067 module_t *mod;
1068 size_t msize; 1068 size_t msize;
1069 vaddr_t maddr; 1069 vaddr_t maddr;
1070 1070
1071 TAILQ_FOREACH(mod, &module_list, mod_chain) { 1071 TAILQ_FOREACH(mod, &module_list, mod_chain) {
1072 if (mod->mod_kobj == NULL) { 1072 if (mod->mod_kobj == NULL) {
1073 continue; 1073 continue;
1074 } 1074 }
1075 kobj_stat(mod->mod_kobj, &maddr, &msize); 1075 if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0)
 1076 continue;
1076 if (addr < maddr || addr >= maddr + msize) { 1077 if (addr < maddr || addr >= maddr + msize) {
1077 continue; 1078 continue;
1078 } 1079 }
1079 (*pr)("%p is %p+%zu, in kernel module `%s'\n", 1080 (*pr)("%p is %p+%zu, in kernel module `%s'\n",
1080 (void *)addr, (void *)maddr, 1081 (void *)addr, (void *)maddr,
1081 (size_t)(addr - maddr), mod->mod_info->mi_name); 1082 (size_t)(addr - maddr), mod->mod_info->mi_name);
1082 } 1083 }
1083} 1084}
1084 1085
1085/* 1086/*
1086 * module_print_list: 1087 * module_print_list:
1087 * 1088 *
1088 * Helper routine for DDB. 1089 * Helper routine for DDB.
1089 */ 1090 */
1090void 1091void
1091module_print_list(void (*pr)(const char *, ...)) 1092module_print_list(void (*pr)(const char *, ...))
1092{ 1093{
1093 const char *src; 1094 const char *src;
1094 module_t *mod; 1095 module_t *mod;
1095 size_t msize; 1096 size_t msize;
1096 vaddr_t maddr; 1097 vaddr_t maddr;
1097 1098
1098 (*pr)("%16s %16s %8s %8s\n", "NAME", "TEXT/DATA", "SIZE", "SOURCE"); 1099 (*pr)("%16s %16s %8s %8s\n", "NAME", "TEXT/DATA", "SIZE", "SOURCE");
1099 1100
1100 TAILQ_FOREACH(mod, &module_list, mod_chain) { 1101 TAILQ_FOREACH(mod, &module_list, mod_chain) {
1101 switch (mod->mod_source) { 1102 switch (mod->mod_source) {
1102 case MODULE_SOURCE_KERNEL: 1103 case MODULE_SOURCE_KERNEL:
1103 src = "builtin"; 1104 src = "builtin";
1104 break; 1105 break;
1105 case MODULE_SOURCE_FILESYS: 1106 case MODULE_SOURCE_FILESYS:
1106 src = "filesys"; 1107 src = "filesys";
1107 break; 1108 break;
1108 case MODULE_SOURCE_BOOT: 1109 case MODULE_SOURCE_BOOT:
1109 src = "boot"; 1110 src = "boot";
1110 break; 1111 break;
1111 default: 1112 default:
1112 src = "unknown"; 1113 src = "unknown";
1113 break; 1114 break;
1114 } 1115 }
1115 if (mod->mod_kobj != NULL) { 1116 if (mod->mod_kobj == NULL) {
1116 kobj_stat(mod->mod_kobj, &maddr, &msize); 
1117 } else { 
1118 maddr = 0; 1117 maddr = 0;
1119 msize = 0; 1118 msize = 0;
1120 } 1119 } else if (kobj_stat(mod->mod_kobj, &maddr, &msize) != 0)
 1120 continue;
1121 (*pr)("%16s %16lx %8ld %8s\n", mod->mod_info->mi_name, 1121 (*pr)("%16s %16lx %8ld %8s\n", mod->mod_info->mi_name,
1122 (long)maddr, (long)msize, src); 1122 (long)maddr, (long)msize, src);
1123 } 1123 }
1124} 1124}
1125#endif /* DDB */ 1125#endif /* DDB */
1126 1126
1127/* 1127/*
1128 * module_load_plist_file: 1128 * module_load_plist_file:
1129 * 1129 *
1130 * Load a plist located in the file system into memory. 1130 * Load a plist located in the file system into memory.
1131 */ 1131 */
1132static int 1132static int
1133module_load_plist_file(const char *modpath, const bool nochroot, 1133module_load_plist_file(const char *modpath, const bool nochroot,
1134 void **basep, size_t *length) 1134 void **basep, size_t *length)
1135{ 1135{
1136 struct nameidata nd; 1136 struct nameidata nd;
1137 struct stat sb; 1137 struct stat sb;
1138 void *base; 1138 void *base;
1139 char *proppath; 1139 char *proppath;
1140 size_t resid; 1140 size_t resid;
1141 int error, pathlen; 1141 int error, pathlen;
1142 1142
1143 base = NULL; 1143 base = NULL;
1144 *length = 0; 1144 *length = 0;
1145 1145
1146 proppath = PNBUF_GET(); 1146 proppath = PNBUF_GET();
1147 strcpy(proppath, modpath); 1147 strcpy(proppath, modpath);
1148 pathlen = strlen(proppath); 1148 pathlen = strlen(proppath);
1149 if ((pathlen >= 5) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) { 1149 if ((pathlen >= 5) && (strcmp(&proppath[pathlen - 5], ".kmod") == 0)) {
1150 strcpy(&proppath[pathlen - 5], ".prop"); 1150 strcpy(&proppath[pathlen - 5], ".prop");
1151 } else if (pathlen < MAXPATHLEN - 5) { 1151 } else if (pathlen < MAXPATHLEN - 5) {
1152 strcat(proppath, ".prop"); 1152 strcat(proppath, ".prop");
1153 } else { 1153 } else {
1154 error = ENOENT; 1154 error = ENOENT;
1155 goto out1; 1155 goto out1;
1156 } 1156 }
1157 1157
1158 NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), 1158 NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0),
1159 UIO_SYSSPACE, proppath); 1159 UIO_SYSSPACE, proppath);
1160 1160
1161 error = namei(&nd); 1161 error = namei(&nd);
1162 if (error != 0) { 1162 if (error != 0) {
1163 goto out1; 1163 goto out1;
1164 } 1164 }
1165 1165
1166 error = vn_stat(nd.ni_vp, &sb); 1166 error = vn_stat(nd.ni_vp, &sb);
1167 if (sb.st_size >= (PAGE_SIZE - 1)) { /* leave space for term \0 */ 1167 if (sb.st_size >= (PAGE_SIZE - 1)) { /* leave space for term \0 */
1168 error = EINVAL; 1168 error = EINVAL;
1169 } 1169 }
1170 if (error != 0) { 1170 if (error != 0) {
1171 goto out1; 1171 goto out1;
1172 } 1172 }
1173 1173
1174 error = vn_open(&nd, FREAD, 0); 1174 error = vn_open(&nd, FREAD, 0);
1175 if (error != 0) { 1175 if (error != 0) {
1176 goto out1; 1176 goto out1;
1177 } 1177 }
1178 1178
1179 base = kmem_alloc(PAGE_SIZE, KM_SLEEP); 1179 base = kmem_alloc(PAGE_SIZE, KM_SLEEP);
1180 if (base == NULL) { 1180 if (base == NULL) {
1181 error = ENOMEM; 1181 error = ENOMEM;
1182 goto out; 1182 goto out;
1183 } 1183 }
1184 1184
1185 error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0, 1185 error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0,
1186 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp); 1186 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
1187 *((uint8_t *)base + sb.st_size) = '\0'; 1187 *((uint8_t *)base + sb.st_size) = '\0';
1188 if (error == 0 && resid != 0) { 1188 if (error == 0 && resid != 0) {
1189 error = EINVAL; 1189 error = EINVAL;
1190 } 1190 }
1191 if (error != 0) { 1191 if (error != 0) {
1192 kmem_free(base, PAGE_SIZE); 1192 kmem_free(base, PAGE_SIZE);
1193 base = NULL; 1193 base = NULL;
1194 } 1194 }
1195 *length = sb.st_size; 1195 *length = sb.st_size;
1196 1196
1197out: 1197out:
1198 VOP_UNLOCK(nd.ni_vp, 0); 1198 VOP_UNLOCK(nd.ni_vp, 0);
1199 vn_close(nd.ni_vp, FREAD, kauth_cred_get()); 1199 vn_close(nd.ni_vp, FREAD, kauth_cred_get());
1200 1200
1201out1: 1201out1:
1202 PNBUF_PUT(proppath); 1202 PNBUF_PUT(proppath);
1203 *basep = base; 1203 *basep = base;
1204 return error; 1204 return error;
1205} 1205}
1206 1206
1207static bool 1207static bool
1208module_merge_dicts(prop_dictionary_t existing_dict, 1208module_merge_dicts(prop_dictionary_t existing_dict,
1209 const prop_dictionary_t new_dict) 1209 const prop_dictionary_t new_dict)
1210{ 1210{
1211 prop_dictionary_keysym_t props_keysym; 1211 prop_dictionary_keysym_t props_keysym;
1212 prop_object_iterator_t props_iter; 1212 prop_object_iterator_t props_iter;
1213 prop_object_t props_obj; 1213 prop_object_t props_obj;
1214 const char *props_key; 1214 const char *props_key;
1215 bool error; 1215 bool error;
1216 1216
1217 error = false; 1217 error = false;
1218 props_iter = prop_dictionary_iterator(new_dict); 1218 props_iter = prop_dictionary_iterator(new_dict);
1219 if (props_iter == NULL) { 1219 if (props_iter == NULL) {
1220 return false; 1220 return false;
1221 } 1221 }
1222 1222
1223 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) { 1223 while ((props_obj = prop_object_iterator_next(props_iter)) != NULL) {
1224 props_keysym = (prop_dictionary_keysym_t)props_obj; 1224 props_keysym = (prop_dictionary_keysym_t)props_obj;
1225 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym); 1225 props_key = prop_dictionary_keysym_cstring_nocopy(props_keysym);
1226 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym); 1226 props_obj = prop_dictionary_get_keysym(new_dict, props_keysym);
1227 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict, 1227 if ((props_obj == NULL) || !prop_dictionary_set(existing_dict,
1228 props_key, props_obj)) { 1228 props_key, props_obj)) {
1229 error = true; 1229 error = true;
1230 goto out; 1230 goto out;
1231 } 1231 }
1232 } 1232 }
1233 error = false; 1233 error = false;
1234 1234
1235out: 1235out:
1236 prop_object_iterator_release(props_iter); 1236 prop_object_iterator_release(props_iter);
1237 1237
1238 return !error; 1238 return !error;
1239} 1239}

cvs diff -r1.38 -r1.39 src/sys/kern/subr_kobj.c (switch to unified diff)

--- src/sys/kern/subr_kobj.c 2009/05/26 08:34:23 1.38
+++ src/sys/kern/subr_kobj.c 2009/06/17 21:04:25 1.39
@@ -1,1150 +1,1151 @@ @@ -1,1150 +1,1151 @@
1/* $NetBSD: subr_kobj.c,v 1.38 2009/05/26 08:34:23 jnemeth Exp $ */ 1/* $NetBSD: subr_kobj.c,v 1.39 2009/06/17 21:04:25 dyoung Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software developed for The NetBSD Foundation 7 * This code is derived from software developed for The NetBSD Foundation
8 * by Andrew Doran. 8 * by Andrew Doran.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/*- 32/*-
33 * Copyright (c) 1998-2000 Doug Rabson 33 * Copyright (c) 1998-2000 Doug Rabson
34 * Copyright (c) 2004 Peter Wemm 34 * Copyright (c) 2004 Peter Wemm
35 * All rights reserved. 35 * All rights reserved.
36 * 36 *
37 * Redistribution and use in source and binary forms, with or without 37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions 38 * modification, are permitted provided that the following conditions
39 * are met: 39 * are met:
40 * 1. Redistributions of source code must retain the above copyright 40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer. 41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright 42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the 43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution. 44 * documentation and/or other materials provided with the distribution.
45 * 45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE. 56 * SUCH DAMAGE.
57 */ 57 */
58 58
59/* 59/*
60 * Kernel loader for ELF objects. 60 * Kernel loader for ELF objects.
61 * 61 *
62 * TODO: adjust kmem_alloc() calls to avoid needless fragmentation. 62 * TODO: adjust kmem_alloc() calls to avoid needless fragmentation.
63 */ 63 */
64 64
65#include <sys/cdefs.h> 65#include <sys/cdefs.h>
66__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.38 2009/05/26 08:34:23 jnemeth Exp $"); 66__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.39 2009/06/17 21:04:25 dyoung Exp $");
67 67
68#include "opt_modular.h" 68#include "opt_modular.h"
69 69
70#include <sys/kobj_impl.h> 70#include <sys/kobj_impl.h>
71 71
72#ifdef MODULAR 72#ifdef MODULAR
73 73
74#include <sys/param.h> 74#include <sys/param.h>
75#include <sys/kernel.h> 75#include <sys/kernel.h>
76#include <sys/kmem.h> 76#include <sys/kmem.h>
77#include <sys/proc.h> 77#include <sys/proc.h>
78#include <sys/namei.h> 78#include <sys/namei.h>
79#include <sys/vnode.h> 79#include <sys/vnode.h>
80#include <sys/fcntl.h> 80#include <sys/fcntl.h>
81#include <sys/ksyms.h> 81#include <sys/ksyms.h>
82#include <sys/module.h> 82#include <sys/module.h>
83 83
84#include <machine/stdarg.h> 84#include <machine/stdarg.h>
85 85
86#include <uvm/uvm_extern.h> 86#include <uvm/uvm_extern.h>
87 87
88static int kobj_relocate(kobj_t, bool); 88static int kobj_relocate(kobj_t, bool);
89static int kobj_checksyms(kobj_t, bool); 89static int kobj_checksyms(kobj_t, bool);
90static void kobj_error(const char *, ...); 90static void kobj_error(const char *, ...);
91static int kobj_read(kobj_t, void **, size_t, off_t); 91static int kobj_read(kobj_t, void **, size_t, off_t);
92static int kobj_read_bits(kobj_t, void *, size_t, off_t); 92static int kobj_read_bits(kobj_t, void *, size_t, off_t);
93static void kobj_jettison(kobj_t); 93static void kobj_jettison(kobj_t);
94static void kobj_free(kobj_t, void *, size_t); 94static void kobj_free(kobj_t, void *, size_t);
95static void kobj_close(kobj_t); 95static void kobj_close(kobj_t);
96static int kobj_load(kobj_t); 96static int kobj_load(kobj_t);
97 97
98extern struct vm_map *module_map; 98extern struct vm_map *module_map;
99 99
100/* 100/*
101 * kobj_load_file: 101 * kobj_load_file:
102 * 102 *
103 * Load an object located in the file system. 103 * Load an object located in the file system.
104 */ 104 */
105int 105int
106kobj_load_file(kobj_t *kop, const char *path, const bool nochroot) 106kobj_load_file(kobj_t *kop, const char *path, const bool nochroot)
107{ 107{
108 struct nameidata nd; 108 struct nameidata nd;
109 kauth_cred_t cred; 109 kauth_cred_t cred;
110 int error; 110 int error;
111 kobj_t ko; 111 kobj_t ko;
112 112
113 cred = kauth_cred_get(); 113 cred = kauth_cred_get();
114 114
115 ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); 115 ko = kmem_zalloc(sizeof(*ko), KM_SLEEP);
116 if (ko == NULL) { 116 if (ko == NULL) {
117 return ENOMEM; 117 return ENOMEM;
118 } 118 }
119 119
120 NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), 120 NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0),
121 UIO_SYSSPACE, path); 121 UIO_SYSSPACE, path);
122 error = vn_open(&nd, FREAD, 0); 122 error = vn_open(&nd, FREAD, 0);
123 123
124 if (error != 0) { 124 if (error != 0) {
125 kmem_free(ko, sizeof(*ko)); 125 kmem_free(ko, sizeof(*ko));
126 return error; 126 return error;
127 } 127 }
128 128
129 ko->ko_type = KT_VNODE; 129 ko->ko_type = KT_VNODE;
130 ko->ko_source = nd.ni_vp; 130 ko->ko_source = nd.ni_vp;
131 *kop = ko; 131 *kop = ko;
132 return kobj_load(ko); 132 return kobj_load(ko);
133} 133}
134 134
135/* 135/*
136 * kobj_load_mem: 136 * kobj_load_mem:
137 * 137 *
138 * Load an object already resident in memory. If size is not -1, 138 * Load an object already resident in memory. If size is not -1,
139 * the complete size of the object is known. 139 * the complete size of the object is known.
140 */ 140 */
141int 141int
142kobj_load_mem(kobj_t *kop, void *base, ssize_t size) 142kobj_load_mem(kobj_t *kop, void *base, ssize_t size)
143{ 143{
144 kobj_t ko; 144 kobj_t ko;
145 145
146 ko = kmem_zalloc(sizeof(*ko), KM_SLEEP); 146 ko = kmem_zalloc(sizeof(*ko), KM_SLEEP);
147 if (ko == NULL) { 147 if (ko == NULL) {
148 return ENOMEM; 148 return ENOMEM;
149 } 149 }
150 150
151 ko->ko_type = KT_MEMORY; 151 ko->ko_type = KT_MEMORY;
152 ko->ko_source = base; 152 ko->ko_source = base;
153 ko->ko_memsize = size; 153 ko->ko_memsize = size;
154 *kop = ko; 154 *kop = ko;
155 return kobj_load(ko); 155 return kobj_load(ko);
156} 156}
157 157
158/* 158/*
159 * kobj_close: 159 * kobj_close:
160 * 160 *
161 * Close an open ELF object. 161 * Close an open ELF object.
162 */ 162 */
163static void 163static void
164kobj_close(kobj_t ko) 164kobj_close(kobj_t ko)
165{ 165{
166 166
167 if (ko->ko_source == NULL) { 167 if (ko->ko_source == NULL) {
168 return; 168 return;
169 } 169 }
170 170
171 switch (ko->ko_type) { 171 switch (ko->ko_type) {
172 case KT_VNODE: 172 case KT_VNODE:
173 VOP_UNLOCK(ko->ko_source, 0); 173 VOP_UNLOCK(ko->ko_source, 0);
174 vn_close(ko->ko_source, FREAD, kauth_cred_get()); 174 vn_close(ko->ko_source, FREAD, kauth_cred_get());
175 break; 175 break;
176 case KT_MEMORY: 176 case KT_MEMORY:
177 /* nothing */ 177 /* nothing */
178 break; 178 break;
179 default: 179 default:
180 panic("kobj_close: unknown type"); 180 panic("kobj_close: unknown type");
181 break; 181 break;
182 } 182 }
183 183
184 ko->ko_source = NULL; 184 ko->ko_source = NULL;
185} 185}
186 186
187/* 187/*
188 * kobj_load: 188 * kobj_load:
189 * 189 *
190 * Load an ELF object and prepare to link into the running kernel 190 * Load an ELF object and prepare to link into the running kernel
191 * image. 191 * image.
192 */ 192 */
193static int 193static int
194kobj_load(kobj_t ko) 194kobj_load(kobj_t ko)
195{ 195{
196 Elf_Ehdr *hdr; 196 Elf_Ehdr *hdr;
197 Elf_Shdr *shdr; 197 Elf_Shdr *shdr;
198 Elf_Sym *es; 198 Elf_Sym *es;
199 vaddr_t mapbase; 199 vaddr_t mapbase;
200 size_t mapsize; 200 size_t mapsize;
201 int error; 201 int error;
202 int symtabindex; 202 int symtabindex;
203 int symstrindex; 203 int symstrindex;
204 int nsym; 204 int nsym;
205 int pb, rl, ra; 205 int pb, rl, ra;
206 int alignmask; 206 int alignmask;
207 int i, j; 207 int i, j;
208 void *addr; 208 void *addr;
209 209
210 KASSERT(ko->ko_type != KT_UNSET); 210 KASSERT(ko->ko_type != KT_UNSET);
211 KASSERT(ko->ko_source != NULL); 211 KASSERT(ko->ko_source != NULL);
212 212
213 shdr = NULL; 213 shdr = NULL;
214 mapsize = 0; 214 mapsize = 0;
215 error = 0; 215 error = 0;
216 hdr = NULL; 216 hdr = NULL;
217 217
218 /* 218 /*
219 * Read the elf header from the file. 219 * Read the elf header from the file.
220 */ 220 */
221 error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0); 221 error = kobj_read(ko, (void **)&hdr, sizeof(*hdr), 0);
222 if (error != 0) 222 if (error != 0)
223 goto out; 223 goto out;
224 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) { 224 if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0) {
225 kobj_error("not an ELF object"); 225 kobj_error("not an ELF object");
226 error = ENOEXEC; 226 error = ENOEXEC;
227 goto out; 227 goto out;
228 } 228 }
229 229
230 if (hdr->e_ident[EI_VERSION] != EV_CURRENT || 230 if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
231 hdr->e_version != EV_CURRENT) { 231 hdr->e_version != EV_CURRENT) {
232 kobj_error("unsupported file version"); 232 kobj_error("unsupported file version");
233 error = ENOEXEC; 233 error = ENOEXEC;
234 goto out; 234 goto out;
235 } 235 }
236 if (hdr->e_type != ET_REL) { 236 if (hdr->e_type != ET_REL) {
237 kobj_error("unsupported file type"); 237 kobj_error("unsupported file type");
238 error = ENOEXEC; 238 error = ENOEXEC;
239 goto out; 239 goto out;
240 } 240 }
241 switch (hdr->e_machine) { 241 switch (hdr->e_machine) {
242#if ELFSIZE == 32 242#if ELFSIZE == 32
243 ELF32_MACHDEP_ID_CASES 243 ELF32_MACHDEP_ID_CASES
244#else 244#else
245 ELF64_MACHDEP_ID_CASES 245 ELF64_MACHDEP_ID_CASES
246#endif 246#endif
247 default: 247 default:
248 kobj_error("unsupported machine"); 248 kobj_error("unsupported machine");
249 error = ENOEXEC; 249 error = ENOEXEC;
250 goto out; 250 goto out;
251 } 251 }
252 252
253 ko->ko_nprogtab = 0; 253 ko->ko_nprogtab = 0;
254 ko->ko_shdr = 0; 254 ko->ko_shdr = 0;
255 ko->ko_nrel = 0; 255 ko->ko_nrel = 0;
256 ko->ko_nrela = 0; 256 ko->ko_nrela = 0;
257 257
258 /* 258 /*
259 * Allocate and read in the section header. 259 * Allocate and read in the section header.
260 */ 260 */
261 ko->ko_shdrsz = hdr->e_shnum * hdr->e_shentsize; 261 ko->ko_shdrsz = hdr->e_shnum * hdr->e_shentsize;
262 if (ko->ko_shdrsz == 0 || hdr->e_shoff == 0 || 262 if (ko->ko_shdrsz == 0 || hdr->e_shoff == 0 ||
263 hdr->e_shentsize != sizeof(Elf_Shdr)) { 263 hdr->e_shentsize != sizeof(Elf_Shdr)) {
264 error = ENOEXEC; 264 error = ENOEXEC;
265 goto out; 265 goto out;
266 } 266 }
267 error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff); 267 error = kobj_read(ko, (void **)&shdr, ko->ko_shdrsz, hdr->e_shoff);
268 if (error != 0) { 268 if (error != 0) {
269 goto out; 269 goto out;
270 } 270 }
271 ko->ko_shdr = shdr; 271 ko->ko_shdr = shdr;
272 272
273 /* 273 /*
274 * Scan the section header for information and table sizing. 274 * Scan the section header for information and table sizing.
275 */ 275 */
276 nsym = 0; 276 nsym = 0;
277 symtabindex = -1; 277 symtabindex = -1;
278 symstrindex = -1; 278 symstrindex = -1;
279 for (i = 0; i < hdr->e_shnum; i++) { 279 for (i = 0; i < hdr->e_shnum; i++) {
280 switch (shdr[i].sh_type) { 280 switch (shdr[i].sh_type) {
281 case SHT_PROGBITS: 281 case SHT_PROGBITS:
282 case SHT_NOBITS: 282 case SHT_NOBITS:
283 ko->ko_nprogtab++; 283 ko->ko_nprogtab++;
284 break; 284 break;
285 case SHT_SYMTAB: 285 case SHT_SYMTAB:
286 nsym++; 286 nsym++;
287 symtabindex = i; 287 symtabindex = i;
288 symstrindex = shdr[i].sh_link; 288 symstrindex = shdr[i].sh_link;
289 break; 289 break;
290 case SHT_REL: 290 case SHT_REL:
291 ko->ko_nrel++; 291 ko->ko_nrel++;
292 break; 292 break;
293 case SHT_RELA: 293 case SHT_RELA:
294 ko->ko_nrela++; 294 ko->ko_nrela++;
295 break; 295 break;
296 case SHT_STRTAB: 296 case SHT_STRTAB:
297 break; 297 break;
298 } 298 }
299 } 299 }
300 if (ko->ko_nprogtab == 0) { 300 if (ko->ko_nprogtab == 0) {
301 kobj_error("file has no contents"); 301 kobj_error("file has no contents");
302 error = ENOEXEC; 302 error = ENOEXEC;
303 goto out; 303 goto out;
304 } 304 }
305 if (nsym != 1) { 305 if (nsym != 1) {
306 /* Only allow one symbol table for now */ 306 /* Only allow one symbol table for now */
307 kobj_error("file has no valid symbol table"); 307 kobj_error("file has no valid symbol table");
308 error = ENOEXEC; 308 error = ENOEXEC;
309 goto out; 309 goto out;
310 } 310 }
311 if (symstrindex < 0 || symstrindex > hdr->e_shnum || 311 if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
312 shdr[symstrindex].sh_type != SHT_STRTAB) { 312 shdr[symstrindex].sh_type != SHT_STRTAB) {
313 kobj_error("file has invalid symbol strings"); 313 kobj_error("file has invalid symbol strings");
314 error = ENOEXEC; 314 error = ENOEXEC;
315 goto out; 315 goto out;
316 } 316 }
317 317
318 /* 318 /*
319 * Allocate space for tracking the load chunks. 319 * Allocate space for tracking the load chunks.
320 */ 320 */
321 if (ko->ko_nprogtab != 0) { 321 if (ko->ko_nprogtab != 0) {
322 ko->ko_progtab = kmem_zalloc(ko->ko_nprogtab * 322 ko->ko_progtab = kmem_zalloc(ko->ko_nprogtab *
323 sizeof(*ko->ko_progtab), KM_SLEEP); 323 sizeof(*ko->ko_progtab), KM_SLEEP);
324 if (ko->ko_progtab == NULL) { 324 if (ko->ko_progtab == NULL) {
325 error = ENOMEM; 325 error = ENOMEM;
326 goto out; 326 goto out;
327 } 327 }
328 } 328 }
329 if (ko->ko_nrel != 0) { 329 if (ko->ko_nrel != 0) {
330 ko->ko_reltab = kmem_zalloc(ko->ko_nrel * 330 ko->ko_reltab = kmem_zalloc(ko->ko_nrel *
331 sizeof(*ko->ko_reltab), KM_SLEEP); 331 sizeof(*ko->ko_reltab), KM_SLEEP);
332 if (ko->ko_reltab == NULL) { 332 if (ko->ko_reltab == NULL) {
333 error = ENOMEM; 333 error = ENOMEM;
334 goto out; 334 goto out;
335 } 335 }
336 } 336 }
337 if (ko->ko_nrela != 0) { 337 if (ko->ko_nrela != 0) {
338 ko->ko_relatab = kmem_zalloc(ko->ko_nrela * 338 ko->ko_relatab = kmem_zalloc(ko->ko_nrela *
339 sizeof(*ko->ko_relatab), KM_SLEEP); 339 sizeof(*ko->ko_relatab), KM_SLEEP);
340 if (ko->ko_relatab == NULL) { 340 if (ko->ko_relatab == NULL) {
341 error = ENOMEM; 341 error = ENOMEM;
342 goto out; 342 goto out;
343 } 343 }
344 } 344 }
345 if (symtabindex == -1) { 345 if (symtabindex == -1) {
346 kobj_error("lost symbol table index"); 346 kobj_error("lost symbol table index");
347 goto out; 347 goto out;
348 } 348 }
349 349
350 /* 350 /*
351 * Allocate space for and load the symbol table. 351 * Allocate space for and load the symbol table.
352 */ 352 */
353 ko->ko_symcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym); 353 ko->ko_symcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
354 if (ko->ko_symcnt == 0) { 354 if (ko->ko_symcnt == 0) {
355 kobj_error("no symbol table"); 355 kobj_error("no symbol table");
356 goto out; 356 goto out;
357 } 357 }
358 error = kobj_read(ko, (void **)&ko->ko_symtab, 358 error = kobj_read(ko, (void **)&ko->ko_symtab,
359 ko->ko_symcnt * sizeof(Elf_Sym), 359 ko->ko_symcnt * sizeof(Elf_Sym),
360 shdr[symtabindex].sh_offset); 360 shdr[symtabindex].sh_offset);
361 if (error != 0) { 361 if (error != 0) {
362 goto out; 362 goto out;
363 } 363 }
364 364
365 /* 365 /*
366 * Allocate space for and load the symbol strings. 366 * Allocate space for and load the symbol strings.
367 */ 367 */
368 ko->ko_strtabsz = shdr[symstrindex].sh_size; 368 ko->ko_strtabsz = shdr[symstrindex].sh_size;
369 if (ko->ko_strtabsz == 0) { 369 if (ko->ko_strtabsz == 0) {
370 kobj_error("no symbol strings"); 370 kobj_error("no symbol strings");
371 goto out; 371 goto out;
372 } 372 }
373 error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz, 373 error = kobj_read(ko, (void *)&ko->ko_strtab, ko->ko_strtabsz,
374 shdr[symstrindex].sh_offset); 374 shdr[symstrindex].sh_offset);
375 if (error != 0) { 375 if (error != 0) {
376 goto out; 376 goto out;
377 } 377 }
378 378
379 /* 379 /*
380 * Do we have a string table for the section names? 380 * Do we have a string table for the section names?
381 */ 381 */
382 if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 && 382 if (hdr->e_shstrndx != 0 && shdr[hdr->e_shstrndx].sh_size != 0 &&
383 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) { 383 shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
384 ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size; 384 ko->ko_shstrtabsz = shdr[hdr->e_shstrndx].sh_size;
385 error = kobj_read(ko, (void **)&ko->ko_shstrtab, 385 error = kobj_read(ko, (void **)&ko->ko_shstrtab,
386 shdr[hdr->e_shstrndx].sh_size, 386 shdr[hdr->e_shstrndx].sh_size,
387 shdr[hdr->e_shstrndx].sh_offset); 387 shdr[hdr->e_shstrndx].sh_offset);
388 if (error != 0) { 388 if (error != 0) {
389 goto out; 389 goto out;
390 } 390 }
391 } 391 }
392 392
393 /* 393 /*
394 * Size up code/data(progbits) and bss(nobits). 394 * Size up code/data(progbits) and bss(nobits).
395 */ 395 */
396 alignmask = 0; 396 alignmask = 0;
397 mapbase = 0; 397 mapbase = 0;
398 for (i = 0; i < hdr->e_shnum; i++) { 398 for (i = 0; i < hdr->e_shnum; i++) {
399 switch (shdr[i].sh_type) { 399 switch (shdr[i].sh_type) {
400 case SHT_PROGBITS: 400 case SHT_PROGBITS:
401 case SHT_NOBITS: 401 case SHT_NOBITS:
402 if (mapbase == 0) 402 if (mapbase == 0)
403 mapbase = shdr[i].sh_offset; 403 mapbase = shdr[i].sh_offset;
404 alignmask = shdr[i].sh_addralign - 1; 404 alignmask = shdr[i].sh_addralign - 1;
405 mapsize += alignmask; 405 mapsize += alignmask;
406 mapsize &= ~alignmask; 406 mapsize &= ~alignmask;
407 mapsize += shdr[i].sh_size; 407 mapsize += shdr[i].sh_size;
408 break; 408 break;
409 } 409 }
410 } 410 }
411 411
412 /* 412 /*
413 * We know how much space we need for the text/data/bss/etc. 413 * We know how much space we need for the text/data/bss/etc.
414 * This stuff needs to be in a single chunk so that profiling etc 414 * This stuff needs to be in a single chunk so that profiling etc
415 * can get the bounds and gdb can associate offsets with modules. 415 * can get the bounds and gdb can associate offsets with modules.
416 */ 416 */
417 if (mapsize == 0) { 417 if (mapsize == 0) {
418 kobj_error("no text/data/bss"); 418 kobj_error("no text/data/bss");
419 goto out; 419 goto out;
420 } 420 }
421 if (ko->ko_type == KT_MEMORY) { 421 if (ko->ko_type == KT_MEMORY) {
422 mapbase += (vaddr_t)ko->ko_source; 422 mapbase += (vaddr_t)ko->ko_source;
423 } else { 423 } else {
424 mapbase = uvm_km_alloc(module_map, round_page(mapsize), 424 mapbase = uvm_km_alloc(module_map, round_page(mapsize),
425 0, UVM_KMF_WIRED | UVM_KMF_EXEC); 425 0, UVM_KMF_WIRED | UVM_KMF_EXEC);
426 if (mapbase == 0) { 426 if (mapbase == 0) {
427 error = ENOMEM; 427 error = ENOMEM;
428 goto out; 428 goto out;
429 } 429 }
430 } 430 }
431 ko->ko_address = mapbase; 431 ko->ko_address = mapbase;
432 ko->ko_size = mapsize; 432 ko->ko_size = mapsize;
433 433
434 /* 434 /*
435 * Now load code/data(progbits), zero bss(nobits), allocate space 435 * Now load code/data(progbits), zero bss(nobits), allocate space
436 * for and load relocs 436 * for and load relocs
437 */ 437 */
438 pb = 0; 438 pb = 0;
439 rl = 0; 439 rl = 0;
440 ra = 0; 440 ra = 0;
441 alignmask = 0; 441 alignmask = 0;
442 for (i = 0; i < hdr->e_shnum; i++) { 442 for (i = 0; i < hdr->e_shnum; i++) {
443 switch (shdr[i].sh_type) { 443 switch (shdr[i].sh_type) {
444 case SHT_PROGBITS: 444 case SHT_PROGBITS:
445 case SHT_NOBITS: 445 case SHT_NOBITS:
446 alignmask = shdr[i].sh_addralign - 1; 446 alignmask = shdr[i].sh_addralign - 1;
447 if (ko->ko_type == KT_MEMORY) { 447 if (ko->ko_type == KT_MEMORY) {
448 addr = (void *)(shdr[i].sh_offset + 448 addr = (void *)(shdr[i].sh_offset +
449 (vaddr_t)ko->ko_source); 449 (vaddr_t)ko->ko_source);
450 if (((vaddr_t)addr & alignmask) != 0) { 450 if (((vaddr_t)addr & alignmask) != 0) {
451 kobj_error("section %d not aligned\n", 451 kobj_error("section %d not aligned\n",
452 i); 452 i);
453 goto out; 453 goto out;
454 } 454 }
455 } else { 455 } else {
456 mapbase += alignmask; 456 mapbase += alignmask;
457 mapbase &= ~alignmask; 457 mapbase &= ~alignmask;
458 addr = (void *)mapbase; 458 addr = (void *)mapbase;
459 mapbase += shdr[i].sh_size; 459 mapbase += shdr[i].sh_size;
460 } 460 }
461 ko->ko_progtab[pb].addr = addr; 461 ko->ko_progtab[pb].addr = addr;
462 if (shdr[i].sh_type == SHT_PROGBITS) { 462 if (shdr[i].sh_type == SHT_PROGBITS) {
463 ko->ko_progtab[pb].name = "<<PROGBITS>>"; 463 ko->ko_progtab[pb].name = "<<PROGBITS>>";
464 error = kobj_read_bits(ko, addr, 464 error = kobj_read_bits(ko, addr,
465 shdr[i].sh_size, shdr[i].sh_offset); 465 shdr[i].sh_size, shdr[i].sh_offset);
466 if (error != 0) { 466 if (error != 0) {
467 goto out; 467 goto out;
468 } 468 }
469 } else if (ko->ko_type == KT_MEMORY && 469 } else if (ko->ko_type == KT_MEMORY &&
470 shdr[i].sh_size != 0) { 470 shdr[i].sh_size != 0) {
471 kobj_error("non-loadable BSS section in " 471 kobj_error("non-loadable BSS section in "
472 "pre-loaded module"); 472 "pre-loaded module");
473 error = EINVAL; 473 error = EINVAL;
474 goto out; 474 goto out;
475 } else { 475 } else {
476 ko->ko_progtab[pb].name = "<<NOBITS>>"; 476 ko->ko_progtab[pb].name = "<<NOBITS>>";
477 memset(addr, 0, shdr[i].sh_size); 477 memset(addr, 0, shdr[i].sh_size);
478 } 478 }
479 ko->ko_progtab[pb].size = shdr[i].sh_size; 479 ko->ko_progtab[pb].size = shdr[i].sh_size;
480 ko->ko_progtab[pb].sec = i; 480 ko->ko_progtab[pb].sec = i;
481 if (ko->ko_shstrtab != NULL && shdr[i].sh_name != 0) { 481 if (ko->ko_shstrtab != NULL && shdr[i].sh_name != 0) {
482 ko->ko_progtab[pb].name = 482 ko->ko_progtab[pb].name =
483 ko->ko_shstrtab + shdr[i].sh_name; 483 ko->ko_shstrtab + shdr[i].sh_name;
484 } 484 }
485 485
486 /* Update all symbol values with the offset. */ 486 /* Update all symbol values with the offset. */
487 for (j = 0; j < ko->ko_symcnt; j++) { 487 for (j = 0; j < ko->ko_symcnt; j++) {
488 es = &ko->ko_symtab[j]; 488 es = &ko->ko_symtab[j];
489 if (es->st_shndx != i) { 489 if (es->st_shndx != i) {
490 continue; 490 continue;
491 } 491 }
492 es->st_value += (Elf_Addr)addr; 492 es->st_value += (Elf_Addr)addr;
493 } 493 }
494 pb++; 494 pb++;
495 break; 495 break;
496 case SHT_REL: 496 case SHT_REL:
497 ko->ko_reltab[rl].size = shdr[i].sh_size; 497 ko->ko_reltab[rl].size = shdr[i].sh_size;
498 ko->ko_reltab[rl].size -= 498 ko->ko_reltab[rl].size -=
499 shdr[i].sh_size % sizeof(Elf_Rel); 499 shdr[i].sh_size % sizeof(Elf_Rel);
500 if (ko->ko_reltab[rl].size != 0) { 500 if (ko->ko_reltab[rl].size != 0) {
501 ko->ko_reltab[rl].nrel = 501 ko->ko_reltab[rl].nrel =
502 shdr[i].sh_size / sizeof(Elf_Rel); 502 shdr[i].sh_size / sizeof(Elf_Rel);
503 ko->ko_reltab[rl].sec = shdr[i].sh_info; 503 ko->ko_reltab[rl].sec = shdr[i].sh_info;
504 error = kobj_read(ko, 504 error = kobj_read(ko,
505 (void **)&ko->ko_reltab[rl].rel, 505 (void **)&ko->ko_reltab[rl].rel,
506 ko->ko_reltab[rl].size, 506 ko->ko_reltab[rl].size,
507 shdr[i].sh_offset); 507 shdr[i].sh_offset);
508 if (error != 0) { 508 if (error != 0) {
509 goto out; 509 goto out;
510 } 510 }
511 } 511 }
512 rl++; 512 rl++;
513 break; 513 break;
514 case SHT_RELA: 514 case SHT_RELA:
515 ko->ko_relatab[ra].size = shdr[i].sh_size; 515 ko->ko_relatab[ra].size = shdr[i].sh_size;
516 ko->ko_relatab[ra].size -= 516 ko->ko_relatab[ra].size -=
517 shdr[i].sh_size % sizeof(Elf_Rela); 517 shdr[i].sh_size % sizeof(Elf_Rela);
518 if (ko->ko_relatab[ra].size != 0) { 518 if (ko->ko_relatab[ra].size != 0) {
519 ko->ko_relatab[ra].nrela = 519 ko->ko_relatab[ra].nrela =
520 shdr[i].sh_size / sizeof(Elf_Rela); 520 shdr[i].sh_size / sizeof(Elf_Rela);
521 ko->ko_relatab[ra].sec = shdr[i].sh_info; 521 ko->ko_relatab[ra].sec = shdr[i].sh_info;
522 error = kobj_read(ko, 522 error = kobj_read(ko,
523 (void **)&ko->ko_relatab[ra].rela, 523 (void **)&ko->ko_relatab[ra].rela,
524 shdr[i].sh_size, 524 shdr[i].sh_size,
525 shdr[i].sh_offset); 525 shdr[i].sh_offset);
526 if (error != 0) { 526 if (error != 0) {
527 goto out; 527 goto out;
528 } 528 }
529 } 529 }
530 ra++; 530 ra++;
531 break; 531 break;
532 default: 532 default:
533 break; 533 break;
534 } 534 }
535 } 535 }
536 if (pb != ko->ko_nprogtab) { 536 if (pb != ko->ko_nprogtab) {
537 panic("lost progbits"); 537 panic("lost progbits");
538 } 538 }
539 if (rl != ko->ko_nrel) { 539 if (rl != ko->ko_nrel) {
540 panic("lost rel"); 540 panic("lost rel");
541 } 541 }
542 if (ra != ko->ko_nrela) { 542 if (ra != ko->ko_nrela) {
543 panic("lost rela"); 543 panic("lost rela");
544 } 544 }
545 if (ko->ko_type != KT_MEMORY && mapbase != ko->ko_address + mapsize) { 545 if (ko->ko_type != KT_MEMORY && mapbase != ko->ko_address + mapsize) {
546 panic("mapbase 0x%lx != address %lx + mapsize %ld (0x%lx)\n", 546 panic("mapbase 0x%lx != address %lx + mapsize %ld (0x%lx)\n",
547 (long)mapbase, (long)ko->ko_address, (long)mapsize, 547 (long)mapbase, (long)ko->ko_address, (long)mapsize,
548 (long)ko->ko_address + mapsize); 548 (long)ko->ko_address + mapsize);
549 } 549 }
550 550
551 /* 551 /*
552 * Perform local relocations only. Relocations relating to global 552 * Perform local relocations only. Relocations relating to global
553 * symbols will be done by kobj_affix(). 553 * symbols will be done by kobj_affix().
554 */ 554 */
555 error = kobj_checksyms(ko, false); 555 error = kobj_checksyms(ko, false);
556 if (error == 0) { 556 if (error == 0) {
557 error = kobj_relocate(ko, true); 557 error = kobj_relocate(ko, true);
558 } 558 }
559 out: 559 out:
560 if (hdr != NULL) { 560 if (hdr != NULL) {
561 kobj_free(ko, hdr, sizeof(*hdr)); 561 kobj_free(ko, hdr, sizeof(*hdr));
562 } 562 }
563 kobj_close(ko); 563 kobj_close(ko);
564 if (error != 0) { 564 if (error != 0) {
565 kobj_unload(ko); 565 kobj_unload(ko);
566 } 566 }
567 567
568 return error; 568 return error;
569} 569}
570 570
571/* 571/*
572 * kobj_unload: 572 * kobj_unload:
573 * 573 *
574 * Unload an object previously loaded by kobj_load(). 574 * Unload an object previously loaded by kobj_load().
575 */ 575 */
576void 576void
577kobj_unload(kobj_t ko) 577kobj_unload(kobj_t ko)
578{ 578{
579 int error; 579 int error;
580 580
581 kobj_close(ko); 581 kobj_close(ko);
582 kobj_jettison(ko); 582 kobj_jettison(ko);
583 583
584 /* 584 /*
585 * Notify MD code that a module has been unloaded. 585 * Notify MD code that a module has been unloaded.
586 */ 586 */
587 if (ko->ko_loaded) { 587 if (ko->ko_loaded) {
588 error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, 588 error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size,
589 false); 589 false);
590 if (error != 0) { 590 if (error != 0) {
591 kobj_error("machine dependent deinit failed"); 591 kobj_error("machine dependent deinit failed");
592 } 592 }
593 } 593 }
594 if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) { 594 if (ko->ko_address != 0 && ko->ko_type != KT_MEMORY) {
595 uvm_km_free(module_map, ko->ko_address, round_page(ko->ko_size), 595 uvm_km_free(module_map, ko->ko_address, round_page(ko->ko_size),
596 UVM_KMF_WIRED); 596 UVM_KMF_WIRED);
597 } 597 }
598 if (ko->ko_ksyms == true) { 598 if (ko->ko_ksyms == true) {
599 ksyms_modunload(ko->ko_name); 599 ksyms_modunload(ko->ko_name);
600 } 600 }
601 if (ko->ko_symtab != NULL) { 601 if (ko->ko_symtab != NULL) {
602 kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym)); 602 kobj_free(ko, ko->ko_symtab, ko->ko_symcnt * sizeof(Elf_Sym));
603 } 603 }
604 if (ko->ko_strtab != NULL) { 604 if (ko->ko_strtab != NULL) {
605 kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz); 605 kobj_free(ko, ko->ko_strtab, ko->ko_strtabsz);
606 } 606 }
607 if (ko->ko_progtab != NULL) { 607 if (ko->ko_progtab != NULL) {
608 kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab * 608 kobj_free(ko, ko->ko_progtab, ko->ko_nprogtab *
609 sizeof(*ko->ko_progtab)); 609 sizeof(*ko->ko_progtab));
610 ko->ko_progtab = NULL; 610 ko->ko_progtab = NULL;
611 } 611 }
612 if (ko->ko_shstrtab) { 612 if (ko->ko_shstrtab) {
613 kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz); 613 kobj_free(ko, ko->ko_shstrtab, ko->ko_shstrtabsz);
614 ko->ko_shstrtab = NULL; 614 ko->ko_shstrtab = NULL;
615 } 615 }
616 616
617 kmem_free(ko, sizeof(*ko)); 617 kmem_free(ko, sizeof(*ko));
618} 618}
619 619
620/* 620/*
621 * kobj_stat: 621 * kobj_stat:
622 * 622 *
623 * Return size and load address of an object. 623 * Return size and load address of an object.
624 */ 624 */
625void 625int
626kobj_stat(kobj_t ko, vaddr_t *address, size_t *size) 626kobj_stat(kobj_t ko, vaddr_t *address, size_t *size)
627{ 627{
628 628
629 if (address != NULL) { 629 if (address != NULL) {
630 *address = ko->ko_address; 630 *address = ko->ko_address;
631 } 631 }
632 if (size != NULL) { 632 if (size != NULL) {
633 *size = ko->ko_size; 633 *size = ko->ko_size;
634 } 634 }
 635 return 0;
635} 636}
636 637
637/* 638/*
638 * kobj_affix: 639 * kobj_affix:
639 * 640 *
640 * Set an object's name and perform global relocs. May only be 641 * Set an object's name and perform global relocs. May only be
641 * called after the module and any requisite modules are loaded. 642 * called after the module and any requisite modules are loaded.
642 */ 643 */
643int 644int
644kobj_affix(kobj_t ko, const char *name) 645kobj_affix(kobj_t ko, const char *name)
645{ 646{
646 int error; 647 int error;
647 648
648 KASSERT(ko->ko_ksyms == false); 649 KASSERT(ko->ko_ksyms == false);
649 KASSERT(ko->ko_loaded == false); 650 KASSERT(ko->ko_loaded == false);
650 651
651 strlcpy(ko->ko_name, name, sizeof(ko->ko_name)); 652 strlcpy(ko->ko_name, name, sizeof(ko->ko_name));
652 653
653 /* Cache addresses of undefined symbols. */ 654 /* Cache addresses of undefined symbols. */
654 error = kobj_checksyms(ko, true); 655 error = kobj_checksyms(ko, true);
655 656
656 /* Now do global relocations. */ 657 /* Now do global relocations. */
657 if (error == 0) 658 if (error == 0)
658 error = kobj_relocate(ko, false); 659 error = kobj_relocate(ko, false);
659 660
660 /* 661 /*
661 * Now that we know the name, register the symbol table. 662 * Now that we know the name, register the symbol table.
662 * Do after global relocations because ksyms will pack 663 * Do after global relocations because ksyms will pack
663 * the table. 664 * the table.
664 */ 665 */
665 if (error == 0) { 666 if (error == 0) {
666 ksyms_modload(ko->ko_name, ko->ko_symtab, ko->ko_symcnt * 667 ksyms_modload(ko->ko_name, ko->ko_symtab, ko->ko_symcnt *
667 sizeof(Elf_Sym), ko->ko_strtab, ko->ko_strtabsz); 668 sizeof(Elf_Sym), ko->ko_strtab, ko->ko_strtabsz);
668 ko->ko_ksyms = true; 669 ko->ko_ksyms = true;
669 } 670 }
670 671
671 /* Jettison unneeded memory post-link. */ 672 /* Jettison unneeded memory post-link. */
672 kobj_jettison(ko); 673 kobj_jettison(ko);
673 674
674 /* 675 /*
675 * Notify MD code that a module has been loaded. 676 * Notify MD code that a module has been loaded.
676 * 677 *
677 * Most architectures use this opportunity to flush their caches. 678 * Most architectures use this opportunity to flush their caches.
678 */ 679 */
679 if (error == 0) { 680 if (error == 0) {
680 error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size, 681 error = kobj_machdep(ko, (void *)ko->ko_address, ko->ko_size,
681 true); 682 true);
682 if (error != 0) { 683 if (error != 0) {
683 kobj_error("machine dependent init failed"); 684 kobj_error("machine dependent init failed");
684 } 685 }
685 ko->ko_loaded = true; 686 ko->ko_loaded = true;
686 } 687 }
687 688
688 /* If there was an error, destroy the whole object. */ 689 /* If there was an error, destroy the whole object. */
689 if (error != 0) { 690 if (error != 0) {
690 kobj_unload(ko); 691 kobj_unload(ko);
691 } 692 }
692 693
693 return error; 694 return error;
694} 695}
695 696
696/* 697/*
697 * kobj_find_section: 698 * kobj_find_section:
698 * 699 *
699 * Given a section name, search the loaded object and return 700 * Given a section name, search the loaded object and return
700 * virtual address if present and loaded. 701 * virtual address if present and loaded.
701 */ 702 */
702int 703int
703kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size) 704kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size)
704{ 705{
705 int i; 706 int i;
706 707
707 KASSERT(ko->ko_progtab != NULL); 708 KASSERT(ko->ko_progtab != NULL);
708 709
709 for (i = 0; i < ko->ko_nprogtab; i++) { 710 for (i = 0; i < ko->ko_nprogtab; i++) {
710 if (strcmp(ko->ko_progtab[i].name, name) == 0) {  711 if (strcmp(ko->ko_progtab[i].name, name) == 0) {
711 if (addr != NULL) { 712 if (addr != NULL) {
712 *addr = ko->ko_progtab[i].addr; 713 *addr = ko->ko_progtab[i].addr;
713 } 714 }
714 if (size != NULL) { 715 if (size != NULL) {
715 *size = ko->ko_progtab[i].size; 716 *size = ko->ko_progtab[i].size;
716 } 717 }
717 return 0; 718 return 0;
718 } 719 }
719 } 720 }
720 721
721 return ENOENT; 722 return ENOENT;
722} 723}
723 724
724/* 725/*
725 * kobj_jettison:  726 * kobj_jettison:
726 * 727 *
727 * Release object data not needed after performing relocations. 728 * Release object data not needed after performing relocations.
728 */ 729 */
729static void 730static void
730kobj_jettison(kobj_t ko) 731kobj_jettison(kobj_t ko)
731{ 732{
732 int i; 733 int i;
733 734
734 if (ko->ko_reltab != NULL) { 735 if (ko->ko_reltab != NULL) {
735 for (i = 0; i < ko->ko_nrel; i++) { 736 for (i = 0; i < ko->ko_nrel; i++) {
736 if (ko->ko_reltab[i].rel) { 737 if (ko->ko_reltab[i].rel) {
737 kobj_free(ko, ko->ko_reltab[i].rel, 738 kobj_free(ko, ko->ko_reltab[i].rel,
738 ko->ko_reltab[i].size); 739 ko->ko_reltab[i].size);
739 } 740 }
740 } 741 }
741 kobj_free(ko, ko->ko_reltab, ko->ko_nrel * 742 kobj_free(ko, ko->ko_reltab, ko->ko_nrel *
742 sizeof(*ko->ko_reltab)); 743 sizeof(*ko->ko_reltab));
743 ko->ko_reltab = NULL; 744 ko->ko_reltab = NULL;
744 ko->ko_nrel = 0; 745 ko->ko_nrel = 0;
745 } 746 }
746 if (ko->ko_relatab != NULL) { 747 if (ko->ko_relatab != NULL) {
747 for (i = 0; i < ko->ko_nrela; i++) { 748 for (i = 0; i < ko->ko_nrela; i++) {
748 if (ko->ko_relatab[i].rela) { 749 if (ko->ko_relatab[i].rela) {
749 kobj_free(ko, ko->ko_relatab[i].rela, 750 kobj_free(ko, ko->ko_relatab[i].rela,
750 ko->ko_relatab[i].size); 751 ko->ko_relatab[i].size);
751 } 752 }
752 } 753 }
753 kobj_free(ko, ko->ko_relatab, ko->ko_nrela * 754 kobj_free(ko, ko->ko_relatab, ko->ko_nrela *
754 sizeof(*ko->ko_relatab)); 755 sizeof(*ko->ko_relatab));
755 ko->ko_relatab = NULL; 756 ko->ko_relatab = NULL;
756 ko->ko_nrela = 0; 757 ko->ko_nrela = 0;
757 } 758 }
758 if (ko->ko_shdr != NULL) { 759 if (ko->ko_shdr != NULL) {
759 kobj_free(ko, ko->ko_shdr, ko->ko_shdrsz); 760 kobj_free(ko, ko->ko_shdr, ko->ko_shdrsz);
760 ko->ko_shdr = NULL; 761 ko->ko_shdr = NULL;
761 } 762 }
762} 763}
763 764
764/* 765/*
765 * kobj_sym_lookup: 766 * kobj_sym_lookup:
766 * 767 *
767 * Symbol lookup function to be used when the symbol index 768 * Symbol lookup function to be used when the symbol index
768 * is known (ie during relocation). 769 * is known (ie during relocation).
769 */ 770 */
770uintptr_t 771uintptr_t
771kobj_sym_lookup(kobj_t ko, uintptr_t symidx) 772kobj_sym_lookup(kobj_t ko, uintptr_t symidx)
772{ 773{
773 const Elf_Sym *sym; 774 const Elf_Sym *sym;
774 const char *symbol; 775 const char *symbol;
775 776
776 /* Don't even try to lookup the symbol if the index is bogus. */ 777 /* Don't even try to lookup the symbol if the index is bogus. */
777 if (symidx >= ko->ko_symcnt) 778 if (symidx >= ko->ko_symcnt)
778 return 0; 779 return 0;
779 780
780 sym = ko->ko_symtab + symidx; 781 sym = ko->ko_symtab + symidx;
781 782
782 /* Quick answer if there is a definition included. */ 783 /* Quick answer if there is a definition included. */
783 if (sym->st_shndx != SHN_UNDEF) { 784 if (sym->st_shndx != SHN_UNDEF) {
784 return (uintptr_t)sym->st_value; 785 return (uintptr_t)sym->st_value;
785 } 786 }
786 787
787 /* If we get here, then it is undefined and needs a lookup. */ 788 /* If we get here, then it is undefined and needs a lookup. */
788 switch (ELF_ST_BIND(sym->st_info)) { 789 switch (ELF_ST_BIND(sym->st_info)) {
789 case STB_LOCAL: 790 case STB_LOCAL:
790 /* Local, but undefined? huh? */ 791 /* Local, but undefined? huh? */
791 kobj_error("local symbol undefined"); 792 kobj_error("local symbol undefined");
792 return 0; 793 return 0;
793 794
794 case STB_GLOBAL: 795 case STB_GLOBAL:
795 /* Relative to Data or Function name */ 796 /* Relative to Data or Function name */
796 symbol = ko->ko_strtab + sym->st_name; 797 symbol = ko->ko_strtab + sym->st_name;
797 798
798 /* Force a lookup failure if the symbol name is bogus. */ 799 /* Force a lookup failure if the symbol name is bogus. */
799 if (*symbol == 0) { 800 if (*symbol == 0) {
800 kobj_error("bad symbol name"); 801 kobj_error("bad symbol name");
801 return 0; 802 return 0;
802 } 803 }
803 804
804 return (uintptr_t)sym->st_value; 805 return (uintptr_t)sym->st_value;
805 806
806 case STB_WEAK: 807 case STB_WEAK:
807 kobj_error("weak symbols not supported\n"); 808 kobj_error("weak symbols not supported\n");
808 return 0; 809 return 0;
809 810
810 default: 811 default:
811 return 0; 812 return 0;
812 } 813 }
813} 814}
814 815
815/* 816/*
816 * kobj_findbase: 817 * kobj_findbase:
817 * 818 *
818 * Return base address of the given section. 819 * Return base address of the given section.
819 */ 820 */
820static uintptr_t 821static uintptr_t
821kobj_findbase(kobj_t ko, int sec) 822kobj_findbase(kobj_t ko, int sec)
822{ 823{
823 int i; 824 int i;
824 825
825 for (i = 0; i < ko->ko_nprogtab; i++) { 826 for (i = 0; i < ko->ko_nprogtab; i++) {
826 if (sec == ko->ko_progtab[i].sec) { 827 if (sec == ko->ko_progtab[i].sec) {
827 return (uintptr_t)ko->ko_progtab[i].addr; 828 return (uintptr_t)ko->ko_progtab[i].addr;
828 } 829 }
829 } 830 }
830 return 0; 831 return 0;
831} 832}
832 833
833/* 834/*
834 * kobj_checksyms: 835 * kobj_checksyms:
835 * 836 *
836 * Scan symbol table for duplicates or resolve references to 837 * Scan symbol table for duplicates or resolve references to
837 * exernal symbols. 838 * exernal symbols.
838 */ 839 */
839static int 840static int
840kobj_checksyms(kobj_t ko, bool undefined) 841kobj_checksyms(kobj_t ko, bool undefined)
841{ 842{
842 unsigned long rval; 843 unsigned long rval;
843 Elf_Sym *sym, *ms; 844 Elf_Sym *sym, *ms;
844 const char *name; 845 const char *name;
845 int error; 846 int error;
846 847
847 error = 0; 848 error = 0;
848 849
849 for (ms = (sym = ko->ko_symtab) + ko->ko_symcnt; sym < ms; sym++) { 850 for (ms = (sym = ko->ko_symtab) + ko->ko_symcnt; sym < ms; sym++) {
850 /* Check validity of the symbol. */ 851 /* Check validity of the symbol. */
851 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL || 852 if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL ||
852 sym->st_name == 0) 853 sym->st_name == 0)
853 continue; 854 continue;
854 if (undefined != (sym->st_shndx == SHN_UNDEF)) { 855 if (undefined != (sym->st_shndx == SHN_UNDEF)) {
855 continue; 856 continue;
856 } 857 }
857 858
858 /* 859 /*
859 * Look it up. Don't need to lock, as it is known that 860 * Look it up. Don't need to lock, as it is known that
860 * the symbol tables aren't going to change (we hold 861 * the symbol tables aren't going to change (we hold
861 * module_lock). 862 * module_lock).
862 */ 863 */
863 name = ko->ko_strtab + sym->st_name; 864 name = ko->ko_strtab + sym->st_name;
864 if (ksyms_getval_unlocked(NULL, name, &rval, 865 if (ksyms_getval_unlocked(NULL, name, &rval,
865 KSYMS_EXTERN) != 0) { 866 KSYMS_EXTERN) != 0) {
866 if (undefined) { 867 if (undefined) {
867 kobj_error("symbol `%s' not found", name); 868 kobj_error("symbol `%s' not found", name);
868 error = ENOEXEC; 869 error = ENOEXEC;
869 } 870 }
870 continue; 871 continue;
871 } 872 }
872 873
873 /* Save values of undefined globals. */ 874 /* Save values of undefined globals. */
874 if (undefined) { 875 if (undefined) {
875 sym->st_value = (Elf_Addr)rval; 876 sym->st_value = (Elf_Addr)rval;
876 continue; 877 continue;
877 } 878 }
878 879
879 /* Check (and complain) about differing values. */ 880 /* Check (and complain) about differing values. */
880 if (sym->st_value == rval) { 881 if (sym->st_value == rval) {
881 continue; 882 continue;
882 } 883 }
883 if (strcmp(name, "_bss_start") == 0 || 884 if (strcmp(name, "_bss_start") == 0 ||
884 strcmp(name, "__bss_start") == 0 || 885 strcmp(name, "__bss_start") == 0 ||
885 strcmp(name, "_bss_end__") == 0 || 886 strcmp(name, "_bss_end__") == 0 ||
886 strcmp(name, "__bss_end__") == 0 || 887 strcmp(name, "__bss_end__") == 0 ||
887 strcmp(name, "_edata") == 0 || 888 strcmp(name, "_edata") == 0 ||
888 strcmp(name, "_end") == 0 || 889 strcmp(name, "_end") == 0 ||
889 strcmp(name, "__end") == 0 || 890 strcmp(name, "__end") == 0 ||
890 strcmp(name, "__end__") == 0 || 891 strcmp(name, "__end__") == 0 ||
891 strncmp(name, "__start_link_set_", 17) == 0 || 892 strncmp(name, "__start_link_set_", 17) == 0 ||
892 strncmp(name, "__stop_link_set_", 16)) { 893 strncmp(name, "__stop_link_set_", 16)) {
893 continue; 894 continue;
894 } 895 }
895 kobj_error("global symbol `%s' redefined\n", name); 896 kobj_error("global symbol `%s' redefined\n", name);
896 error = ENOEXEC; 897 error = ENOEXEC;
897 } 898 }
898 899
899 return error; 900 return error;
900} 901}
901 902
902/* 903/*
903 * kobj_relocate: 904 * kobj_relocate:
904 * 905 *
905 * Resolve relocations for the loaded object. 906 * Resolve relocations for the loaded object.
906 */ 907 */
907static int 908static int
908kobj_relocate(kobj_t ko, bool local) 909kobj_relocate(kobj_t ko, bool local)
909{ 910{
910 const Elf_Rel *rellim; 911 const Elf_Rel *rellim;
911 const Elf_Rel *rel; 912 const Elf_Rel *rel;
912 const Elf_Rela *relalim; 913 const Elf_Rela *relalim;
913 const Elf_Rela *rela; 914 const Elf_Rela *rela;
914 const Elf_Sym *sym; 915 const Elf_Sym *sym;
915 uintptr_t base; 916 uintptr_t base;
916 int i, error; 917 int i, error;
917 uintptr_t symidx; 918 uintptr_t symidx;
918 919
919 /* 920 /*
920 * Perform relocations without addend if there are any. 921 * Perform relocations without addend if there are any.
921 */ 922 */
922 for (i = 0; i < ko->ko_nrel; i++) { 923 for (i = 0; i < ko->ko_nrel; i++) {
923 rel = ko->ko_reltab[i].rel; 924 rel = ko->ko_reltab[i].rel;
924 if (rel == NULL) { 925 if (rel == NULL) {
925 continue; 926 continue;
926 } 927 }
927 rellim = rel + ko->ko_reltab[i].nrel; 928 rellim = rel + ko->ko_reltab[i].nrel;
928 base = kobj_findbase(ko, ko->ko_reltab[i].sec); 929 base = kobj_findbase(ko, ko->ko_reltab[i].sec);
929 if (base == 0) { 930 if (base == 0) {
930 panic("lost base for e_reltab"); 931 panic("lost base for e_reltab");
931 } 932 }
932 for (; rel < rellim; rel++) { 933 for (; rel < rellim; rel++) {
933 symidx = ELF_R_SYM(rel->r_info); 934 symidx = ELF_R_SYM(rel->r_info);
934 if (symidx >= ko->ko_symcnt) { 935 if (symidx >= ko->ko_symcnt) {
935 continue; 936 continue;
936 } 937 }
937 sym = ko->ko_symtab + symidx; 938 sym = ko->ko_symtab + symidx;
938 if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { 939 if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) {
939 continue; 940 continue;
940 } 941 }
941 error = kobj_reloc(ko, base, rel, false, local); 942 error = kobj_reloc(ko, base, rel, false, local);
942 if (error != 0) { 943 if (error != 0) {
943 return ENOENT; 944 return ENOENT;
944 } 945 }
945 } 946 }
946 } 947 }
947 948
948 /* 949 /*
949 * Perform relocations with addend if there are any. 950 * Perform relocations with addend if there are any.
950 */ 951 */
951 for (i = 0; i < ko->ko_nrela; i++) { 952 for (i = 0; i < ko->ko_nrela; i++) {
952 rela = ko->ko_relatab[i].rela; 953 rela = ko->ko_relatab[i].rela;
953 if (rela == NULL) { 954 if (rela == NULL) {
954 continue; 955 continue;
955 } 956 }
956 relalim = rela + ko->ko_relatab[i].nrela; 957 relalim = rela + ko->ko_relatab[i].nrela;
957 base = kobj_findbase(ko, ko->ko_relatab[i].sec); 958 base = kobj_findbase(ko, ko->ko_relatab[i].sec);
958 if (base == 0) { 959 if (base == 0) {
959 panic("lost base for e_relatab"); 960 panic("lost base for e_relatab");
960 } 961 }
961 for (; rela < relalim; rela++) { 962 for (; rela < relalim; rela++) {
962 symidx = ELF_R_SYM(rela->r_info); 963 symidx = ELF_R_SYM(rela->r_info);
963 if (symidx >= ko->ko_symcnt) { 964 if (symidx >= ko->ko_symcnt) {
964 continue; 965 continue;
965 } 966 }
966 sym = ko->ko_symtab + symidx; 967 sym = ko->ko_symtab + symidx;
967 if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) { 968 if (local != (ELF_ST_BIND(sym->st_info) == STB_LOCAL)) {
968 continue; 969 continue;
969 } 970 }
970 error = kobj_reloc(ko, base, rela, true, local); 971 error = kobj_reloc(ko, base, rela, true, local);
971 if (error != 0) { 972 if (error != 0) {
972 return ENOENT; 973 return ENOENT;
973 } 974 }
974 } 975 }
975 } 976 }
976 977
977 return 0; 978 return 0;
978} 979}
979 980
980/* 981/*
981 * kobj_error: 982 * kobj_error:
982 * 983 *
983 * Utility function: log an error. 984 * Utility function: log an error.
984 */ 985 */
985static void 986static void
986kobj_error(const char *fmt, ...) 987kobj_error(const char *fmt, ...)
987{ 988{
988 va_list ap; 989 va_list ap;
989 990
990 va_start(ap, fmt); 991 va_start(ap, fmt);
991 printf("WARNING: linker error: "); 992 printf("WARNING: linker error: ");
992 vprintf(fmt, ap); 993 vprintf(fmt, ap);
993 printf("\n"); 994 printf("\n");
994 va_end(ap); 995 va_end(ap);
995} 996}
996 997
997/* 998/*
998 * kobj_read: 999 * kobj_read:
999 * 1000 *
1000 * Utility function: read from the object. 1001 * Utility function: read from the object.
1001 */ 1002 */
1002static int 1003static int
1003kobj_read(kobj_t ko, void **basep, size_t size, off_t off) 1004kobj_read(kobj_t ko, void **basep, size_t size, off_t off)
1004{ 1005{
1005 size_t resid; 1006 size_t resid;
1006 void *base; 1007 void *base;
1007 int error; 1008 int error;
1008 1009
1009 KASSERT(ko->ko_source != NULL); 1010 KASSERT(ko->ko_source != NULL);
1010 1011
1011 switch (ko->ko_type) { 1012 switch (ko->ko_type) {
1012 case KT_VNODE: 1013 case KT_VNODE:
1013 base = kmem_alloc(size, KM_SLEEP); 1014 base = kmem_alloc(size, KM_SLEEP);
1014 if (base == NULL) { 1015 if (base == NULL) {
1015 error = ENOMEM; 1016 error = ENOMEM;
1016 break; 1017 break;
1017 } 1018 }
1018 error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, 1019 error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off,
1019 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, 1020 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid,
1020 curlwp); 1021 curlwp);
1021 if (error == 0 && resid != 0) { 1022 if (error == 0 && resid != 0) {
1022 error = EINVAL; 1023 error = EINVAL;
1023 } 1024 }
1024 if (error != 0) { 1025 if (error != 0) {
1025 kmem_free(base, size); 1026 kmem_free(base, size);
1026 base = NULL; 1027 base = NULL;
1027 } 1028 }
1028 break; 1029 break;
1029 case KT_MEMORY: 1030 case KT_MEMORY:
1030 if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { 1031 if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) {
1031 kobj_error("kobj_read: preloaded object short"); 1032 kobj_error("kobj_read: preloaded object short");
1032 error = EINVAL; 1033 error = EINVAL;
1033 base = NULL; 1034 base = NULL;
1034 } else { 1035 } else {
1035 base = (uint8_t *)ko->ko_source + off; 1036 base = (uint8_t *)ko->ko_source + off;
1036 error = 0; 1037 error = 0;
1037 } 1038 }
1038 break; 1039 break;
1039 default: 1040 default:
1040 panic("kobj_read: invalid type"); 1041 panic("kobj_read: invalid type");
1041 } 1042 }
1042 1043
1043 *basep = base; 1044 *basep = base;
1044 return error; 1045 return error;
1045} 1046}
1046 1047
1047/* 1048/*
1048 * kobj_read_bits: 1049 * kobj_read_bits:
1049 * 1050 *
1050 * Utility function: load a section from the object. 1051 * Utility function: load a section from the object.
1051 */ 1052 */
1052static int 1053static int
1053kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off) 1054kobj_read_bits(kobj_t ko, void *base, size_t size, off_t off)
1054{ 1055{
1055 size_t resid; 1056 size_t resid;
1056 int error; 1057 int error;
1057 1058
1058 KASSERT(ko->ko_source != NULL); 1059 KASSERT(ko->ko_source != NULL);
1059 1060
1060 switch (ko->ko_type) { 1061 switch (ko->ko_type) {
1061 case KT_VNODE: 1062 case KT_VNODE:
1062 KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address); 1063 KASSERT((uintptr_t)base >= (uintptr_t)ko->ko_address);
1063 KASSERT((uintptr_t)base + size <= 1064 KASSERT((uintptr_t)base + size <=
1064 (uintptr_t)ko->ko_address + ko->ko_size); 1065 (uintptr_t)ko->ko_address + ko->ko_size);
1065 error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off, 1066 error = vn_rdwr(UIO_READ, ko->ko_source, base, size, off,
1066 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, 1067 UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid,
1067 curlwp); 1068 curlwp);
1068 if (error == 0 && resid != 0) { 1069 if (error == 0 && resid != 0) {
1069 error = EINVAL; 1070 error = EINVAL;
1070 } 1071 }
1071 break; 1072 break;
1072 case KT_MEMORY: 1073 case KT_MEMORY:
1073 if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) { 1074 if (ko->ko_memsize != -1 && off + size > ko->ko_memsize) {
1074 kobj_error("kobj_read_bits: preloaded object short"); 1075 kobj_error("kobj_read_bits: preloaded object short");
1075 error = EINVAL; 1076 error = EINVAL;
1076 } else if ((uint8_t *)base != (uint8_t *)ko->ko_source + off) { 1077 } else if ((uint8_t *)base != (uint8_t *)ko->ko_source + off) {
1077 kobj_error("kobj_read_bits: object not aligned"); 1078 kobj_error("kobj_read_bits: object not aligned");
1078 kobj_error("source=%p base=%p off=%d size=%zd", 1079 kobj_error("source=%p base=%p off=%d size=%zd",
1079 ko->ko_source, base, (int)off, size); 1080 ko->ko_source, base, (int)off, size);
1080 error = EINVAL; 1081 error = EINVAL;
1081 } else { 1082 } else {
1082 /* Nothing to do. Loading in-situ. */ 1083 /* Nothing to do. Loading in-situ. */
1083 error = 0; 1084 error = 0;
1084 } 1085 }
1085 break; 1086 break;
1086 default: 1087 default:
1087 panic("kobj_read: invalid type"); 1088 panic("kobj_read: invalid type");
1088 } 1089 }
1089 1090
1090 return error; 1091 return error;
1091} 1092}
1092 1093
1093/* 1094/*
1094 * kobj_free: 1095 * kobj_free:
1095 * 1096 *
1096 * Utility function: free memory if it was allocated from the heap. 1097 * Utility function: free memory if it was allocated from the heap.
1097 */ 1098 */
1098static void 1099static void
1099kobj_free(kobj_t ko, void *base, size_t size) 1100kobj_free(kobj_t ko, void *base, size_t size)
1100{ 1101{
1101 1102
1102 if (ko->ko_type != KT_MEMORY) 1103 if (ko->ko_type != KT_MEMORY)
1103 kmem_free(base, size); 1104 kmem_free(base, size);
1104} 1105}
1105 1106
1106#else /* MODULAR */ 1107#else /* MODULAR */
1107 1108
1108int 1109int
1109kobj_load_file(kobj_t *kop, const char *name, const bool nochroot) 1110kobj_load_file(kobj_t *kop, const char *name, const bool nochroot)
1110{ 1111{
1111 1112
1112 return ENOSYS; 1113 return ENOSYS;
1113} 1114}
1114 1115
1115int 1116int
1116kobj_load_mem(kobj_t *kop, void *base, ssize_t size) 1117kobj_load_mem(kobj_t *kop, void *base, ssize_t size)
1117{ 1118{
1118 1119
1119 return ENOSYS; 1120 return ENOSYS;
1120} 1121}
1121 1122
1122void 1123void
1123kobj_unload(kobj_t ko) 1124kobj_unload(kobj_t ko)
1124{ 1125{
1125 1126
1126 panic("not modular"); 1127 panic("not modular");
1127} 1128}
1128 1129
1129void 1130int
1130kobj_stat(kobj_t ko, vaddr_t *base, size_t *size) 1131kobj_stat(kobj_t ko, vaddr_t *base, size_t *size)
1131{ 1132{
1132 1133
1133 panic("not modular"); 1134 return ENOSYS;
1134} 1135}
1135 1136
1136int 1137int
1137kobj_affix(kobj_t ko, const char *name) 1138kobj_affix(kobj_t ko, const char *name)
1138{ 1139{
1139 1140
1140 panic("not modular"); 1141 panic("not modular");
1141} 1142}
1142 1143
1143int 1144int
1144kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size) 1145kobj_find_section(kobj_t ko, const char *name, void **addr, size_t *size)
1145{ 1146{
1146 1147
1147 panic("not modular"); 1148 panic("not modular");
1148} 1149}
1149 1150
1150#endif /* MODULAR */ 1151#endif /* MODULAR */

cvs diff -r1.11 -r1.12 src/sys/sys/kobj.h (switch to unified diff)

--- src/sys/sys/kobj.h 2009/05/26 08:34:22 1.11
+++ src/sys/sys/kobj.h 2009/06/17 21:04:25 1.12
@@ -1,47 +1,47 @@ @@ -1,47 +1,47 @@
1/* $NetBSD: kobj.h,v 1.11 2009/05/26 08:34:22 jnemeth Exp $ */ 1/* $NetBSD: kobj.h,v 1.12 2009/06/17 21:04:25 dyoung Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#ifndef _SYS_KOBJ_H_ 29#ifndef _SYS_KOBJ_H_
30#define _SYS_KOBJ_H_ 30#define _SYS_KOBJ_H_
31 31
32typedef struct kobj *kobj_t; 32typedef struct kobj *kobj_t;
33 33
34/* External interface. */ 34/* External interface. */
35int kobj_load_file(kobj_t *, const char *, const bool); 35int kobj_load_file(kobj_t *, const char *, const bool);
36int kobj_load_mem(kobj_t *, void *, ssize_t); 36int kobj_load_mem(kobj_t *, void *, ssize_t);
37int kobj_affix(kobj_t, const char *); 37int kobj_affix(kobj_t, const char *);
38void kobj_unload(kobj_t); 38void kobj_unload(kobj_t);
39void kobj_stat(kobj_t, vaddr_t *, size_t *); 39int kobj_stat(kobj_t, vaddr_t *, size_t *);
40int kobj_find_section(kobj_t, const char *, void **, size_t *); 40int kobj_find_section(kobj_t, const char *, void **, size_t *);
41 41
42/* MI-MD interface. */ 42/* MI-MD interface. */
43uintptr_t kobj_sym_lookup(kobj_t, uintptr_t); 43uintptr_t kobj_sym_lookup(kobj_t, uintptr_t);
44int kobj_reloc(kobj_t, uintptr_t, const void *, bool, bool); 44int kobj_reloc(kobj_t, uintptr_t, const void *, bool, bool);
45int kobj_machdep(kobj_t, void *, size_t, bool); 45int kobj_machdep(kobj_t, void *, size_t, bool);
46 46
47#endif /* !_SYS_KOBJ_H_ */ 47#endif /* !_SYS_KOBJ_H_ */