Tue May 26 08:34:23 2009 UTC ()
Move all namei flags handling into kobj_load_file().

When I originally wrote this, I was going for maximum flexibility.
However, after a private discussion with dholland@, I see how this
will cause problems with the future world order of namei whenever
that might be.  At the moment, I don't need the extra flexibility,
but if something comes up this may have to be revisited.


(jnemeth)
diff -r1.44 -r1.45 src/sys/kern/kern_module.c
diff -r1.37 -r1.38 src/sys/kern/subr_kobj.c
diff -r1.10 -r1.11 src/sys/sys/kobj.h

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

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

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

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

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

--- src/sys/sys/kobj.h 2009/05/25 22:33:00 1.10
+++ src/sys/sys/kobj.h 2009/05/26 08:34:22 1.11
@@ -1,47 +1,47 @@ @@ -1,47 +1,47 @@
1/* $NetBSD: kobj.h,v 1.10 2009/05/25 22:33:00 jnemeth Exp $ */ 1/* $NetBSD: kobj.h,v 1.11 2009/05/26 08:34:22 jnemeth 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 uint32_t); 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 *); 39void 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_ */