xref: /haiku/src/system/kernel/module.cpp (revision f09ba8ea46ba2f4e482d7cd03e8eb77f37a60663)
1 /*
2  * Copyright 2002-2007, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Copyright 2001, Thomas Kurschel. All rights reserved.
6  * Distributed under the terms of the NewOS License.
7  */
8 
9 /** Manages kernel add-ons and their exported modules. */
10 
11 
12 #include <boot_device.h>
13 #include <elf.h>
14 #include <kmodule.h>
15 #include <lock.h>
16 #include <vfs.h>
17 
18 #include <boot/elf.h>
19 #include <fs/KPath.h>
20 #include <util/khash.h>
21 
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 
27 
28 //#define TRACE_MODULE
29 #ifdef TRACE_MODULE
30 #	define TRACE(x) dprintf x
31 #else
32 #	define TRACE(x) ;
33 #endif
34 #define FATAL(x) dprintf x
35 
36 
37 #define MODULE_HASH_SIZE 16
38 
39 /** The modules referenced by this structure are built-in
40  *	modules that can't be loaded from disk.
41  */
42 
43 extern module_info gDeviceManagerModule;
44 extern module_info gDeviceRootModule;
45 extern module_info gDeviceForDriversModule;
46 extern module_info gFrameBufferConsoleModule;
47 
48 // file systems
49 extern module_info gRootFileSystem;
50 extern module_info gDeviceFileSystem;
51 extern module_info gPipeFileSystem;
52 
53 static module_info *sBuiltInModules[] = {
54 	&gDeviceManagerModule,
55 	&gDeviceRootModule,
56 	&gDeviceForDriversModule,
57 	&gFrameBufferConsoleModule,
58 
59 	&gRootFileSystem,
60 	&gDeviceFileSystem,
61 	&gPipeFileSystem,
62 	NULL
63 };
64 
65 enum module_state {
66 	MODULE_QUERIED = 0,
67 	MODULE_LOADED,
68 	MODULE_INIT,
69 	MODULE_READY,
70 	MODULE_UNINIT,
71 	MODULE_ERROR
72 };
73 
74 
75 /* Each loaded module image (which can export several modules) is put
76  * in a hash (gModuleImagesHash) to be easily found when you search
77  * for a specific file name.
78  * ToDo: Could use only the inode number for hashing. Would probably be
79  * a little bit slower, but would lower the memory foot print quite a lot.
80  */
81 
82 struct module_image {
83 	struct module_image	*next;
84 	module_info			**info;		/* the module_info we use */
85 	module_dependency	*dependencies;
86 	char				*path;		/* the full path for the module */
87 	image_id			image;
88 	int32				ref_count;	/* how many ref's to this file */
89 	bool				keep_loaded;
90 };
91 
92 /* Each known module will have this structure which is put in the
93  * gModulesHash, and looked up by name.
94  */
95 
96 struct module {
97 	struct module		*next;
98 	::module_image		*module_image;
99 	char				*name;
100 	char				*file;
101 	int32				ref_count;
102 	module_info			*info;		/* will only be valid if ref_count > 0 */
103 	int32				offset;		/* this is the offset in the headers */
104 	module_state		state;		/* state of module */
105 	uint32				flags;
106 };
107 
108 #define B_BUILT_IN_MODULE	2
109 
110 typedef struct module_path {
111 	const char			*name;
112 	uint32				base_length;
113 } module_path;
114 
115 typedef struct module_iterator {
116 	module_path			*stack;
117 	int32				stack_size;
118 	int32				stack_current;
119 
120 	char				*prefix;
121 	size_t				prefix_length;
122 	DIR					*current_dir;
123 	status_t			status;
124 	int32				module_offset;
125 		/* This is used to keep track of which module_info
126 		 * within a module we're addressing. */
127 	::module_image		*module_image;
128 	module_info			**current_header;
129 	const char			*current_path;
130 	uint32				path_base_length;
131 	const char			*current_module_path;
132 	bool				builtin_modules;
133 	bool				loaded_modules;
134 } module_iterator;
135 
136 
137 static bool sDisableUserAddOns = false;
138 
139 /* locking scheme: there is a global lock only; having several locks
140  * makes trouble if dependent modules get loaded concurrently ->
141  * they have to wait for each other, i.e. we need one lock per module;
142  * also we must detect circular references during init and not dead-lock
143  */
144 static recursive_lock sModulesLock;
145 
146 /* These are the standard base paths where we start to look for modules
147  * to load. Order is important, the last entry here will be searched
148  * first.
149  * ToDo: these should probably be retrieved by using find_directory().
150  */
151 static const char * const sModulePaths[] = {
152 	"/boot/beos/system/add-ons/kernel",
153 	"/boot/home/config/add-ons/kernel",
154 };
155 
156 #define NUM_MODULE_PATHS (sizeof(sModulePaths) / sizeof(sModulePaths[0]))
157 #define FIRST_USER_MODULE_PATH (NUM_MODULE_PATHS - 1)	/* first user path */
158 
159 /* we store the loaded modules by directory path, and all known modules by module name
160  * in a hash table for quick access
161  */
162 static hash_table *sModuleImagesHash;
163 static hash_table *sModulesHash;
164 
165 
166 /** calculates hash for a module using its name */
167 
168 static uint32
169 module_hash(void *_module, const void *_key, uint32 range)
170 {
171 	module *module = (struct module *)_module;
172 	const char *name = (const char *)_key;
173 
174 	if (module != NULL)
175 		return hash_hash_string(module->name) % range;
176 
177 	if (name != NULL)
178 		return hash_hash_string(name) % range;
179 
180 	return 0;
181 }
182 
183 
184 /** compares a module to a given name */
185 
186 static int
187 module_compare(void *_module, const void *_key)
188 {
189 	module *module = (struct module *)_module;
190 	const char *name = (const char *)_key;
191 	if (name == NULL)
192 		return -1;
193 
194 	return strcmp(module->name, name);
195 }
196 
197 
198 /** calculates the hash of a module image using its path */
199 
200 static uint32
201 module_image_hash(void *_module, const void *_key, uint32 range)
202 {
203 	module_image *image = (module_image *)_module;
204 	const char *path = (const char *)_key;
205 
206 	if (image != NULL)
207 		return hash_hash_string(image->path) % range;
208 
209 	if (path != NULL)
210 		return hash_hash_string(path) % range;
211 
212 	return 0;
213 }
214 
215 
216 /** compares a module image to a path */
217 
218 static int
219 module_image_compare(void *_module, const void *_key)
220 {
221 	module_image *image = (module_image *)_module;
222 	const char *path = (const char *)_key;
223 	if (path == NULL)
224 		return -1;
225 
226 	return strcmp(image->path, path);
227 }
228 
229 
230 static inline void
231 inc_module_ref_count(struct module *module)
232 {
233 	module->ref_count++;
234 }
235 
236 
237 static inline void
238 dec_module_ref_count(struct module *module)
239 {
240 	module->ref_count--;
241 }
242 
243 
244 /** Try to load the module image at the specified location.
245  *	If it could be loaded, it returns B_OK, and stores a pointer
246  *	to the module_image object in "_moduleImage".
247  */
248 
249 static status_t
250 load_module_image(const char *path, module_image **_moduleImage)
251 {
252 	module_image *moduleImage;
253 	status_t status;
254 	image_id image;
255 
256 	TRACE(("load_module_image(path = \"%s\", _image = %p)\n", path, _moduleImage));
257 	ASSERT(_moduleImage != NULL);
258 
259 	image = load_kernel_add_on(path);
260 	if (image < 0) {
261 		dprintf("load_module_image(%s) failed: %s\n", path, strerror(image));
262 		return image;
263 	}
264 
265 	moduleImage = (module_image *)malloc(sizeof(module_image));
266 	if (!moduleImage) {
267 		status = B_NO_MEMORY;
268 		goto err;
269 	}
270 
271 	if (get_image_symbol(image, "modules", B_SYMBOL_TYPE_DATA,
272 			(void **)&moduleImage->info) != B_OK) {
273 		TRACE(("load_module_image: Failed to load \"%s\" due to lack of 'modules' symbol\n", path));
274 		status = B_BAD_TYPE;
275 		goto err1;
276 	}
277 
278 	moduleImage->dependencies = NULL;
279 	get_image_symbol(image, "module_dependencies", B_SYMBOL_TYPE_DATA,
280 		(void **)&moduleImage->dependencies);
281 		// this is allowed to be NULL
282 
283 	moduleImage->path = strdup(path);
284 	if (!moduleImage->path) {
285 		status = B_NO_MEMORY;
286 		goto err1;
287 	}
288 
289 	moduleImage->image = image;
290 	moduleImage->ref_count = 0;
291 	moduleImage->keep_loaded = false;
292 
293 	recursive_lock_lock(&sModulesLock);
294 	hash_insert(sModuleImagesHash, moduleImage);
295 	recursive_lock_unlock(&sModulesLock);
296 
297 	*_moduleImage = moduleImage;
298 	return B_OK;
299 
300 err1:
301 	free(moduleImage);
302 err:
303 	unload_kernel_add_on(image);
304 
305 	return status;
306 }
307 
308 
309 static status_t
310 unload_module_image(module_image *moduleImage, const char *path)
311 {
312 	TRACE(("unload_module_image(image = %p, path = %s)\n", moduleImage, path));
313 
314 	recursive_lock_lock(&sModulesLock);
315 
316 	if (moduleImage == NULL) {
317 		// if no image was specified, lookup it up in the hash table
318 		moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
319 		if (moduleImage == NULL) {
320 			recursive_lock_unlock(&sModulesLock);
321 			return B_ENTRY_NOT_FOUND;
322 		}
323 	}
324 
325 	if (moduleImage->ref_count != 0) {
326 		FATAL(("Can't unload %s due to ref_cnt = %ld\n", moduleImage->path, moduleImage->ref_count));
327 		return B_ERROR;
328 	}
329 
330 	hash_remove(sModuleImagesHash, moduleImage);
331 	recursive_lock_unlock(&sModulesLock);
332 
333 	unload_kernel_add_on(moduleImage->image);
334 	free(moduleImage->path);
335 	free(moduleImage);
336 
337 	return B_OK;
338 }
339 
340 
341 static void
342 put_module_image(module_image *image)
343 {
344 	int32 refCount = atomic_add(&image->ref_count, -1);
345 	ASSERT(refCount > 0);
346 
347 	// Don't unload anything when there is no boot device yet
348 	// (because chances are that we will never be able to access it again)
349 
350 	if (refCount == 1 && !image->keep_loaded && gBootDevice > 0)
351 		unload_module_image(image, NULL);
352 }
353 
354 
355 static status_t
356 get_module_image(const char *path, module_image **_image)
357 {
358 	struct module_image *image;
359 
360 	TRACE(("get_module_image(path = \"%s\", _image = %p)\n", path, _image));
361 
362 	image = (module_image *)hash_lookup(sModuleImagesHash, path);
363 	if (image == NULL) {
364 		status_t status = load_module_image(path, &image);
365 		if (status < B_OK)
366 			return status;
367 	}
368 
369 	atomic_add(&image->ref_count, 1);
370 	*_image = image;
371 
372 	return B_OK;
373 }
374 
375 
376 /** Extract the information from the module_info structure pointed at
377  *	by "info" and create the entries required for access to it's details.
378  */
379 
380 static status_t
381 create_module(module_info *info, const char *file, int offset, module **_module)
382 {
383 	module *module;
384 
385 	TRACE(("create_module(info = %p, file = \"%s\", offset = %d, _module = %p)\n",
386 		info, file, offset, _module));
387 
388 	if (!info->name)
389 		return B_BAD_VALUE;
390 
391 	module = (struct module *)hash_lookup(sModulesHash, info->name);
392 	if (module) {
393 		FATAL(("Duplicate module name (%s) detected... ignoring new one\n", info->name));
394 		return B_FILE_EXISTS;
395 	}
396 
397 	if ((module = (struct module *)malloc(sizeof(struct module))) == NULL)
398 		return B_NO_MEMORY;
399 
400 	TRACE(("create_module: name = \"%s\", file = \"%s\"\n", info->name, file));
401 
402 	module->module_image = NULL;
403 	module->name = strdup(info->name);
404 	if (module->name == NULL) {
405 		free(module);
406 		return B_NO_MEMORY;
407 	}
408 
409 	module->file = strdup(file);
410 	if (module->file == NULL) {
411 		free(module->name);
412 		free(module);
413 		return B_NO_MEMORY;
414 	}
415 
416 	module->state = MODULE_QUERIED;
417 	module->info = info;
418 	module->offset = offset;
419 		// record where the module_info can be found in the module_info array
420 	module->ref_count = 0;
421 	module->flags = info->flags;
422 
423 	recursive_lock_lock(&sModulesLock);
424 	hash_insert(sModulesHash, module);
425 	recursive_lock_unlock(&sModulesLock);
426 
427 	if (_module)
428 		*_module = module;
429 
430 	return B_OK;
431 }
432 
433 
434 /** Loads the file at "path" and scans all modules contained therein.
435  *	Returns B_OK if "searchedName" could be found under those modules,
436  *	B_ENTRY_NOT_FOUND if not.
437  *	Must only be called for files that haven't been scanned yet.
438  *	"searchedName" is allowed to be NULL (if all modules should be scanned)
439  */
440 
441 static status_t
442 check_module_image(const char *path, const char *searchedName)
443 {
444 	module_image *image;
445 	module_info **info;
446 	int index = 0, match = B_ENTRY_NOT_FOUND;
447 
448 	TRACE(("check_module_image(path = \"%s\", searchedName = \"%s\")\n", path, searchedName));
449 	ASSERT(hash_lookup(sModuleImagesHash, path) == NULL);
450 
451 	if (load_module_image(path, &image) < B_OK)
452 		return B_ENTRY_NOT_FOUND;
453 
454 	for (info = image->info; *info; info++) {
455 		// try to create a module for every module_info, check if the
456 		// name matches if it was a new entry
457 		if (create_module(*info, path, index++, NULL) == B_OK) {
458 			if (searchedName && !strcmp((*info)->name, searchedName))
459 				match = B_OK;
460 		}
461 	}
462 
463 	// The module we looked for couldn't be found, so we can unload the
464 	// loaded module at this point
465 	if (match != B_OK) {
466 		TRACE(("check_module_file: unloading module file \"%s\" (not used yet)\n", path));
467 		unload_module_image(image, path);
468 	}
469 
470 	return match;
471 }
472 
473 
474 /** This is only called if we fail to find a module already in our cache...
475  *	saves us some extra checking here :)
476  */
477 
478 static module *
479 search_module(const char *name)
480 {
481 	status_t status = B_ENTRY_NOT_FOUND;
482 	uint32 i;
483 
484 	TRACE(("search_module(%s)\n", name));
485 
486 	for (i = 0; i < NUM_MODULE_PATHS; i++) {
487 		char path[B_FILE_NAME_LENGTH];
488 
489 		if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH)
490 			return NULL;
491 
492 		// let the VFS find that module for us
493 
494 		status = vfs_get_module_path(sModulePaths[i], name, path, sizeof(path));
495 		if (status == B_OK) {
496 			status = check_module_image(path, name);
497 			if (status == B_OK)
498 				break;
499 		}
500 	}
501 
502 	if (status != B_OK)
503 		return NULL;
504 
505 	return (module *)hash_lookup(sModulesHash, name);
506 }
507 
508 
509 static status_t
510 put_dependent_modules(struct module *module)
511 {
512 	module_dependency *dependencies;
513 	int32 i = 0;
514 
515 	if (module->module_image == NULL
516 		|| (dependencies = module->module_image->dependencies) == NULL)
517 		return B_OK;
518 
519 	for (; dependencies[i].name != NULL; i++) {
520 		status_t status = put_module(dependencies[i].name);
521 		if (status < B_OK)
522 			return status;
523 	}
524 
525 	return B_OK;
526 }
527 
528 
529 static status_t
530 get_dependent_modules(struct module *module)
531 {
532 	module_dependency *dependencies;
533 	int32 i = 0;
534 
535 	// built-in modules don't have a module_image structure
536 	if (module->module_image == NULL
537 		|| (dependencies = module->module_image->dependencies) == NULL)
538 		return B_OK;
539 
540 	TRACE(("resolving module dependencies...\n"));
541 
542 	for (; dependencies[i].name != NULL; i++) {
543 		status_t status = get_module(dependencies[i].name, dependencies[i].info);
544 		if (status < B_OK) {
545 			TRACE(("loading dependent module \"%s\" failed!\n", dependencies[i].name));
546 			return status;
547 		}
548 	}
549 
550 	return B_OK;
551 }
552 
553 
554 /** Initializes a loaded module depending on its state */
555 
556 static inline status_t
557 init_module(module *module)
558 {
559 	switch (module->state) {
560 		case MODULE_QUERIED:
561 		case MODULE_LOADED:
562 		{
563 			status_t status;
564 			module->state = MODULE_INIT;
565 
566 			// resolve dependencies
567 
568 			status = get_dependent_modules(module);
569 			if (status < B_OK) {
570 				module->state = MODULE_LOADED;
571 				return status;
572 			}
573 
574 			// init module
575 
576 			TRACE(("initializing module %s (at %p)... \n", module->name, module->info->std_ops));
577 			status = module->info->std_ops(B_MODULE_INIT);
578 			TRACE(("...done (%s)\n", strerror(status)));
579 
580 			if (status >= B_OK)
581 				module->state = MODULE_READY;
582 			else {
583 				put_dependent_modules(module);
584 				module->state = MODULE_LOADED;
585 			}
586 
587 			return status;
588 		}
589 
590 		case MODULE_READY:
591 			return B_OK;
592 
593 		case MODULE_INIT:
594 			FATAL(("circular reference to %s\n", module->name));
595 			return B_ERROR;
596 
597 		case MODULE_UNINIT:
598 			FATAL(("tried to load module %s which is currently unloading\n", module->name));
599 			return B_ERROR;
600 
601 		case MODULE_ERROR:
602 			FATAL(("cannot load module %s because its earlier unloading failed\n", module->name));
603 			return B_ERROR;
604 
605 		default:
606 			return B_ERROR;
607 	}
608 	// never trespasses here
609 }
610 
611 
612 /** Uninitializes a module depeding on its state */
613 
614 static inline int
615 uninit_module(module *module)
616 {
617 	TRACE(("uninit_module(%s)\n", module->name));
618 
619 	switch (module->state) {
620 		case MODULE_QUERIED:
621 		case MODULE_LOADED:
622 			return B_NO_ERROR;
623 
624 		case MODULE_INIT:
625 			panic("Trying to unload module %s which is initializing\n", module->name);
626 			return B_ERROR;
627 
628 		case MODULE_UNINIT:
629 			panic("Trying to unload module %s which is un-initializing\n", module->name);
630 			return B_ERROR;
631 
632 		case MODULE_READY:
633 		{
634 			status_t status;
635 
636 			module->state = MODULE_UNINIT;
637 
638 			TRACE(("uninitializing module %s...\n", module->name));
639 			status = module->info->std_ops(B_MODULE_UNINIT);
640 			TRACE(("...done (%s)\n", strerror(status)));
641 
642 			if (status == B_NO_ERROR) {
643 				module->state = MODULE_LOADED;
644 
645 				put_dependent_modules(module);
646 				return 0;
647 			}
648 
649 			FATAL(("Error unloading module %s (%s)\n", module->name, strerror(status)));
650 
651 			module->state = MODULE_ERROR;
652 			module->flags |= B_KEEP_LOADED;
653 
654 			return status;
655 		}
656 		default:
657 			return B_ERROR;
658 	}
659 	// never trespasses here
660 }
661 
662 
663 static const char *
664 iterator_pop_path_from_stack(module_iterator *iterator, uint32 *_baseLength)
665 {
666 	if (iterator->stack_current <= 0)
667 		return NULL;
668 
669 	if (_baseLength)
670 		*_baseLength = iterator->stack[iterator->stack_current - 1].base_length;
671 
672 	return iterator->stack[--iterator->stack_current].name;
673 }
674 
675 
676 static status_t
677 iterator_push_path_on_stack(module_iterator *iterator, const char *path, uint32 baseLength)
678 {
679 	if (iterator->stack_current + 1 > iterator->stack_size) {
680 		// allocate new space on the stack
681 		module_path *stack = (module_path *)realloc(iterator->stack,
682 			(iterator->stack_size + 8) * sizeof(module_path));
683 		if (stack == NULL)
684 			return B_NO_MEMORY;
685 
686 		iterator->stack = stack;
687 		iterator->stack_size += 8;
688 	}
689 
690 	iterator->stack[iterator->stack_current].name = path;
691 	iterator->stack[iterator->stack_current++].base_length = baseLength;
692 	return B_OK;
693 }
694 
695 
696 static status_t
697 iterator_get_next_module(module_iterator *iterator, char *buffer,
698 	size_t *_bufferSize)
699 {
700 	status_t status;
701 
702 	TRACE(("iterator_get_next_module() -- start\n"));
703 
704 	if (iterator->builtin_modules) {
705 		for (int32 i = iterator->module_offset; sBuiltInModules[i] != NULL; i++) {
706 			// the module name must fit the prefix
707 			if (strncmp(sBuiltInModules[i]->name, iterator->prefix,
708 					iterator->prefix_length))
709 				continue;
710 
711 			*_bufferSize = strlcpy(buffer, sBuiltInModules[i]->name,
712 				*_bufferSize);
713 			iterator->module_offset = i + 1;
714 			return B_OK;
715 		}
716 		iterator->builtin_modules = false;
717 	}
718 
719 	if (iterator->loaded_modules) {
720 		recursive_lock_lock(&sModulesLock);
721 		hash_iterator hashIterator;
722 		hash_open(sModulesHash, &hashIterator);
723 
724 		struct module *module = (struct module *)hash_next(sModulesHash,
725 			&hashIterator);
726 		for (int32 i = 0; module != NULL; i++) {
727 			if (i >= iterator->module_offset) {
728 				if (!strncmp(module->name, iterator->prefix,
729 						iterator->prefix_length)) {
730 					*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
731 					iterator->module_offset = i + 1;
732 
733 					hash_close(sModulesHash, &hashIterator, false);
734 					recursive_lock_unlock(&sModulesLock);
735 					return B_OK;
736 				}
737 			}
738 			module = (struct module *)hash_next(sModulesHash, &hashIterator);
739 		}
740 
741 		hash_close(sModulesHash, &hashIterator, false);
742 		recursive_lock_unlock(&sModulesLock);
743 
744 		// prevent from falling into modules hash iteration again
745 		iterator->loaded_modules = false;
746 	}
747 
748 nextPath:
749 	if (iterator->current_dir == NULL) {
750 		// get next directory path from the stack
751 		const char *path = iterator_pop_path_from_stack(iterator,
752 			&iterator->path_base_length);
753 		if (path == NULL) {
754 			// we are finished, there are no more entries on the stack
755 			return B_ENTRY_NOT_FOUND;
756 		}
757 
758 		free((void *)iterator->current_path);
759 		iterator->current_path = path;
760 		iterator->current_dir = opendir(path);
761 		TRACE(("open directory at %s -> %p\n", path, iterator->current_dir));
762 
763 		if (iterator->current_dir == NULL) {
764 			// we don't throw an error here, but silently go to
765 			// the next directory on the stack
766 			goto nextPath;
767 		}
768 	}
769 
770 nextModuleImage:
771 	if (iterator->current_header == NULL) {
772 		// get next entry from the current directory
773 
774 		errno = 0;
775 
776 		struct dirent *dirent;
777 		if ((dirent = readdir(iterator->current_dir)) == NULL) {
778 			closedir(iterator->current_dir);
779 			iterator->current_dir = NULL;
780 
781 			if (errno < B_OK)
782 				return errno;
783 
784 			goto nextPath;
785 		}
786 
787 		// check if the prefix matches
788 		int32 passedOffset, commonLength;
789 		passedOffset = strlen(iterator->current_path) + 1;
790 		commonLength = iterator->path_base_length + iterator->prefix_length
791 			- passedOffset;
792 
793 		if (commonLength > 0) {
794 			// the prefix still reaches into the new path part
795 			int32 length = strlen(dirent->d_name);
796 			if (commonLength > length)
797 				commonLength = length;
798 
799 			if (strncmp(dirent->d_name, iterator->prefix + passedOffset
800 					- iterator->path_base_length, commonLength))
801 				goto nextModuleImage;
802 		}
803 
804 		// we're not interested in traversing these again
805 		if (!strcmp(dirent->d_name, ".")
806 			|| !strcmp(dirent->d_name, ".."))
807 			goto nextModuleImage;
808 
809 		// build absolute path to current file
810 		KPath path(iterator->current_path);
811 		if (path.InitCheck() != B_OK)
812 			return B_NO_MEMORY;
813 
814 		if (path.Append(dirent->d_name) != B_OK)
815 			return B_BUFFER_OVERFLOW;
816 
817 		// find out if it's a directory or a file
818 		struct stat st;
819 		if (stat(path.Path(), &st) < 0)
820 			return errno;
821 
822 		iterator->current_module_path = strdup(path.Path());
823 		if (iterator->current_module_path == NULL)
824 			return B_NO_MEMORY;
825 
826 		if (S_ISDIR(st.st_mode)) {
827 			status = iterator_push_path_on_stack(iterator,
828 				iterator->current_module_path, iterator->path_base_length);
829 			if (status < B_OK)
830 				return status;
831 
832 			iterator->current_module_path = NULL;
833 			goto nextModuleImage;
834 		}
835 
836 		if (!S_ISREG(st.st_mode))
837 			return B_BAD_TYPE;
838 
839 		TRACE(("open module at %s\n", path.Path()));
840 
841 		status = get_module_image(path.Path(), &iterator->module_image);
842 		if (status < B_OK) {
843 			free((void *)iterator->current_module_path);
844 			iterator->current_module_path = NULL;
845 			goto nextModuleImage;
846 		}
847 
848 		iterator->current_header = iterator->module_image->info;
849 		iterator->module_offset = 0;
850 	}
851 
852 	// search the current module image until we've got a match
853 	while (*iterator->current_header != NULL) {
854 		module_info *info = *iterator->current_header;
855 
856 		// ToDo: we might want to create a module here and cache it in the hash table
857 
858 		iterator->current_header++;
859 		iterator->module_offset++;
860 
861 		if (strncmp(info->name, iterator->prefix, iterator->prefix_length))
862 			continue;
863 
864 		*_bufferSize = strlcpy(buffer, info->name, *_bufferSize);
865 		return B_OK;
866 	}
867 
868 	// leave this module and get the next one
869 
870 	iterator->current_header = NULL;
871 	free((void *)iterator->current_module_path);
872 	iterator->current_module_path = NULL;
873 
874 	put_module_image(iterator->module_image);
875 	iterator->module_image = NULL;
876 
877 	goto nextModuleImage;
878 }
879 
880 
881 static void
882 register_builtin_modules(struct module_info **info)
883 {
884 	for (; *info; info++) {
885 		(*info)->flags |= B_BUILT_IN_MODULE;
886 			// this is an internal flag, it doesn't have to be set by modules itself
887 
888 		if (create_module(*info, "", -1, NULL) != B_OK)
889 			dprintf("creation of built-in module \"%s\" failed!\n", (*info)->name);
890 	}
891 }
892 
893 
894 static status_t
895 register_preloaded_module_image(struct preloaded_image *image)
896 {
897 	module_image *moduleImage;
898 	struct module_info **info;
899 	status_t status;
900 	int32 index = 0;
901 
902 	TRACE(("register_preloaded_module_image(image = \"%s\")\n", image->name));
903 
904 	if (image->id < 0)
905 		return B_BAD_VALUE;
906 
907 	moduleImage = (module_image *)malloc(sizeof(module_image));
908 	if (moduleImage == NULL)
909 		return B_NO_MEMORY;
910 
911 	if (get_image_symbol(image->id, "modules", B_SYMBOL_TYPE_DATA,
912 			(void **)&moduleImage->info) != B_OK) {
913 		status = B_BAD_TYPE;
914 		goto error;
915 	}
916 
917 	moduleImage->dependencies = NULL;
918 	get_image_symbol(image->id, "module_dependencies", B_SYMBOL_TYPE_DATA,
919 		(void **)&moduleImage->dependencies);
920 		// this is allowed to be NULL
921 
922 	// Try to recreate the full module path, so that we don't try to load the
923 	// image again when asked for a module it does not export (would only be
924 	// problematic if it had got replaced and the new file actually exports
925 	// that module). Also helpful for recurse_directory().
926 	{
927 		// ToDo: this is kind of a hack to have the full path in the hash
928 		//	(it always assumes the preloaded add-ons to be in the system directory)
929 		char path[B_FILE_NAME_LENGTH];
930 		const char *name, *suffix;
931 		if (moduleImage->info[0]
932 			&& (suffix = strstr(name = moduleImage->info[0]->name, image->name)) != NULL) {
933 			// even if strlcpy() is used here, it's by no means safe against buffer overflows
934 			size_t length = strlcpy(path, "/boot/beos/system/add-ons/kernel/", sizeof(path));
935 			strlcpy(path + length, name, strlen(image->name) + 1 + (suffix - name));
936 
937 			moduleImage->path = strdup(path);
938 		} else
939 			moduleImage->path = strdup(image->name);
940 	}
941 	if (moduleImage->path == NULL) {
942 		status = B_NO_MEMORY;
943 		goto error;
944 	}
945 
946 	moduleImage->image = image->id;
947 	moduleImage->ref_count = 0;
948 	moduleImage->keep_loaded = false;
949 
950 	hash_insert(sModuleImagesHash, moduleImage);
951 
952 	for (info = moduleImage->info; *info; info++) {
953 		create_module(*info, moduleImage->path, index++, NULL);
954 	}
955 
956 	return B_OK;
957 
958 error:
959 	free(moduleImage);
960 
961 	// we don't need this image anymore
962 	unload_kernel_add_on(image->id);
963 
964 	return status;
965 }
966 
967 
968 static int
969 dump_modules(int argc, char **argv)
970 {
971 	hash_iterator iterator;
972 	struct module_image *image;
973 	struct module *module;
974 
975 	hash_rewind(sModulesHash, &iterator);
976 	dprintf("-- known modules:\n");
977 
978 	while ((module = (struct module *)hash_next(sModulesHash, &iterator)) != NULL) {
979 		dprintf("%p: \"%s\", \"%s\" (%ld), refcount = %ld, state = %d, mimage = %p\n",
980 			module, module->name, module->file, module->offset, module->ref_count,
981 			module->state, module->module_image);
982 	}
983 
984 	hash_rewind(sModuleImagesHash, &iterator);
985 	dprintf("\n-- loaded module images:\n");
986 
987 	while ((image = (struct module_image *)hash_next(sModuleImagesHash, &iterator)) != NULL) {
988 		dprintf("%p: \"%s\" (image_id = %ld), info = %p, refcount = %ld, %s\n", image,
989 			image->path, image->image, image->info, image->ref_count,
990 			image->keep_loaded ? "keep loaded" : "can be unloaded");
991 	}
992 	return 0;
993 }
994 
995 
996 //	#pragma mark -
997 //	Exported Kernel API (private part)
998 
999 
1000 /**	Unloads a module in case it's not in use. This is the counterpart
1001  *	to load_module().
1002  */
1003 
1004 status_t
1005 unload_module(const char *path)
1006 {
1007 	struct module_image *moduleImage;
1008 
1009 	recursive_lock_lock(&sModulesLock);
1010 	moduleImage = (module_image *)hash_lookup(sModuleImagesHash, path);
1011 	recursive_lock_unlock(&sModulesLock);
1012 
1013 	if (moduleImage == NULL)
1014 		return B_ENTRY_NOT_FOUND;
1015 
1016 	put_module_image(moduleImage);
1017 	return B_OK;
1018 }
1019 
1020 
1021 /**	Unlike get_module(), this function lets you specify the add-on to
1022  *	be loaded by path.
1023  *	However, you must not use the exported modules without having called
1024  *	get_module() on them. When you're done with the NULL terminated
1025  *	\a modules array, you have to call unload_module(), no matter if
1026  *	you're actually using any of the modules or not - of course, the
1027  *	add-on won't be unloaded until the last put_module().
1028  */
1029 
1030 status_t
1031 load_module(const char *path, module_info ***_modules)
1032 {
1033 	module_image *moduleImage;
1034 	status_t status = get_module_image(path, &moduleImage);
1035 	if (status != B_OK)
1036 		return status;
1037 
1038 	*_modules = moduleImage->info;
1039 	return B_OK;
1040 }
1041 
1042 
1043 /** Setup the module structures and data for use - must be called
1044  *	before any other module call.
1045  */
1046 
1047 status_t
1048 module_init(kernel_args *args)
1049 {
1050 	struct preloaded_image *image;
1051 
1052 	if (recursive_lock_init(&sModulesLock, "modules rlock") < B_OK)
1053 		return B_ERROR;
1054 
1055 	sModulesHash = hash_init(MODULE_HASH_SIZE, 0, module_compare, module_hash);
1056 	if (sModulesHash == NULL)
1057 		return B_NO_MEMORY;
1058 
1059 	sModuleImagesHash = hash_init(MODULE_HASH_SIZE, 0, module_image_compare, module_image_hash);
1060 	if (sModuleImagesHash == NULL)
1061 		return B_NO_MEMORY;
1062 
1063 	// register built-in modules
1064 
1065 	register_builtin_modules(sBuiltInModules);
1066 
1067 	// register preloaded images
1068 
1069 	for (image = args->preloaded_images; image != NULL; image = image->next) {
1070 		status_t status = register_preloaded_module_image(image);
1071 		if (status != B_OK)
1072 			dprintf("Could not register image \"%s\": %s\n", image->name, strerror(status));
1073 	}
1074 
1075 	// ToDo: set sDisableUserAddOns from kernel_args!
1076 
1077 	add_debugger_command("modules", &dump_modules, "list all known & loaded modules");
1078 
1079 	return B_OK;
1080 }
1081 
1082 
1083 //	#pragma mark -
1084 //	Exported Kernel API (public part)
1085 
1086 
1087 /** This returns a pointer to a structure that can be used to
1088  *	iterate through a list of all modules available under
1089  *	a given prefix.
1090  *	All paths will be searched and the returned list will
1091  *	contain all modules available under the prefix.
1092  *	The structure is then used by read_next_module_name(), and
1093  *	must be freed by calling close_module_list().
1094  */
1095 
1096 void *
1097 open_module_list(const char *prefix)
1098 {
1099 	module_iterator *iterator;
1100 	uint32 i;
1101 
1102 	TRACE(("open_module_list(prefix = %s)\n", prefix));
1103 
1104 	if (sModulesHash == NULL) {
1105 		dprintf("open_module_list() called too early!\n");
1106 		return NULL;
1107 	}
1108 
1109 	iterator = (module_iterator *)malloc(sizeof(module_iterator));
1110 	if (!iterator)
1111 		return NULL;
1112 
1113 	memset(iterator, 0, sizeof(module_iterator));
1114 
1115 	iterator->prefix = strdup(prefix != NULL ? prefix : "");
1116 	if (iterator->prefix == NULL) {
1117 		free(iterator);
1118 		return NULL;
1119 	}
1120 	iterator->prefix_length = strlen(iterator->prefix);
1121 
1122 	if (gBootDevice > 0) {
1123 		// We do have a boot device to scan
1124 
1125 		// first, we'll traverse over the built-in modules
1126 		iterator->builtin_modules = true;
1127 		iterator->loaded_modules = false;
1128 
1129 		// put all search paths on the stack
1130 		for (i = 0; i < NUM_MODULE_PATHS; i++) {
1131 			if (sDisableUserAddOns && i >= FIRST_USER_MODULE_PATH)
1132 				break;
1133 
1134 			// Build path component: base path + '/' + prefix
1135 			size_t length = strlen(sModulePaths[i]);
1136 			char *path = (char *)malloc(length + iterator->prefix_length + 2);
1137 			if (path == NULL) {
1138 				// ToDo: should we abort the whole operation here?
1139 				//	if we do, don't forget to empty the stack
1140 				continue;
1141 			}
1142 
1143 			memcpy(path, sModulePaths[i], length);
1144 			path[length] = '/';
1145 			memcpy(path + length + 1, iterator->prefix,
1146 				iterator->prefix_length + 1);
1147 
1148 			iterator_push_path_on_stack(iterator, path, length + 1);
1149 		}
1150 	} else {
1151 		// include loaded modules in case there is no boot device yet
1152 		iterator->builtin_modules = false;
1153 		iterator->loaded_modules = true;
1154 	}
1155 
1156 	return (void *)iterator;
1157 }
1158 
1159 
1160 /** Frees the cookie allocated by open_module_list()
1161  */
1162 
1163 status_t
1164 close_module_list(void *cookie)
1165 {
1166 	module_iterator *iterator = (module_iterator *)cookie;
1167 	const char *path;
1168 
1169 	TRACE(("close_module_list()\n"));
1170 
1171 	if (iterator == NULL)
1172 		return B_BAD_VALUE;
1173 
1174 	// free stack
1175 	while ((path = iterator_pop_path_from_stack(iterator, NULL)) != NULL)
1176 		free((void *)path);
1177 
1178 	// close what have been left open
1179 	if (iterator->module_image != NULL)
1180 		put_module_image(iterator->module_image);
1181 
1182 	if (iterator->current_dir != NULL)
1183 		closedir(iterator->current_dir);
1184 
1185 	free(iterator->stack);
1186 	free((void *)iterator->current_path);
1187 	free((void *)iterator->current_module_path);
1188 
1189 	free(iterator->prefix);
1190 	free(iterator);
1191 
1192 	return 0;
1193 }
1194 
1195 
1196 /** Return the next module name from the available list, using
1197  *	a structure previously created by a call to open_module_list().
1198  *	Returns B_OK as long as it found another module, B_ENTRY_NOT_FOUND
1199  *	when done.
1200  */
1201 
1202 status_t
1203 read_next_module_name(void *cookie, char *buffer, size_t *_bufferSize)
1204 {
1205 	module_iterator *iterator = (module_iterator *)cookie;
1206 	status_t status;
1207 
1208 	TRACE(("read_next_module_name: looking for next module\n"));
1209 
1210 	if (iterator == NULL || buffer == NULL || _bufferSize == NULL)
1211 		return B_BAD_VALUE;
1212 
1213 	if (iterator->status < B_OK)
1214 		return iterator->status;
1215 
1216 	status = iterator->status;
1217 	recursive_lock_lock(&sModulesLock);
1218 
1219 	status = iterator_get_next_module(iterator, buffer, _bufferSize);
1220 
1221 	iterator->status = status;
1222 	recursive_lock_unlock(&sModulesLock);
1223 
1224 	TRACE(("read_next_module_name: finished with status %s\n", strerror(status)));
1225 	return status;
1226 }
1227 
1228 
1229 /** Iterates through all loaded modules, and stores its path in "buffer".
1230  *	ToDo: check if the function in BeOS really does that (could also mean:
1231  *		iterate through all modules that are currently loaded; have a valid
1232  *		module_image pointer, which would be hard to test for)
1233  */
1234 
1235 status_t
1236 get_next_loaded_module_name(uint32 *_cookie, char *buffer, size_t *_bufferSize)
1237 {
1238 	if (sModulesHash == NULL) {
1239 		dprintf("get_next_loaded_module_name() called too early!\n");
1240 		return NULL;
1241 	}
1242 
1243 	//TRACE(("get_next_loaded_module_name(\"%s\")\n", buffer));
1244 
1245 	if (_cookie == NULL || buffer == NULL || _bufferSize == NULL)
1246 		return B_BAD_VALUE;
1247 
1248 	status_t status = B_ENTRY_NOT_FOUND;
1249 	uint32 offset = *_cookie;
1250 
1251 	recursive_lock_lock(&sModulesLock);
1252 
1253 	hash_iterator iterator;
1254 	hash_open(sModulesHash, &iterator);
1255 	struct module *module = (struct module *)hash_next(sModulesHash,
1256 		&iterator);
1257 
1258 	for (uint32 i = 0; module != NULL; i++) {
1259 		if (i >= offset) {
1260 			*_bufferSize = strlcpy(buffer, module->name, *_bufferSize);
1261 			*_cookie = i + 1;
1262 			status = B_OK;
1263 			break;
1264 		}
1265 		module = (struct module *)hash_next(sModulesHash, &iterator);
1266 	}
1267 
1268 	hash_close(sModulesHash, &iterator, false);
1269 	recursive_lock_unlock(&sModulesLock);
1270 
1271 	return status;
1272 }
1273 
1274 
1275 status_t
1276 get_module(const char *path, module_info **_info)
1277 {
1278 	module_image *moduleImage;
1279 	module *module;
1280 	status_t status;
1281 
1282 	TRACE(("get_module(%s)\n", path));
1283 
1284 	if (path == NULL)
1285 		return B_BAD_VALUE;
1286 
1287 	recursive_lock_lock(&sModulesLock);
1288 
1289 	module = (struct module *)hash_lookup(sModulesHash, path);
1290 
1291 	// if we don't have it cached yet, search for it
1292 	if (module == NULL) {
1293 		module = search_module(path);
1294 		if (module == NULL) {
1295 			FATAL(("module: Search for %s failed.\n", path));
1296 			goto err;
1297 		}
1298 	}
1299 
1300 	if ((module->flags & B_BUILT_IN_MODULE) == 0) {
1301 		/* We now need to find the module_image for the module. This should
1302 		 * be in memory if we have just run search_module(), but may not be
1303 		 * if we are using cached information.
1304 		 * We can't use the module->module_image pointer, because it is not
1305 		 * reliable at this point (it won't be set to NULL when the module_image
1306 		 * is unloaded).
1307 		 */
1308 		if (get_module_image(module->file, &moduleImage) < B_OK)
1309 			goto err;
1310 
1311 		// (re)set in-memory data for the loaded module
1312 		module->info = moduleImage->info[module->offset];
1313 		module->module_image = moduleImage;
1314 
1315 		// the module image must not be unloaded anymore
1316 		if (module->flags & B_KEEP_LOADED)
1317 			module->module_image->keep_loaded = true;
1318 	}
1319 
1320 	// The state will be adjusted by the call to init_module
1321 	// if we have just loaded the file
1322 	if (module->ref_count == 0)
1323 		status = init_module(module);
1324 	else
1325 		status = B_OK;
1326 
1327 	if (status == B_OK) {
1328 		inc_module_ref_count(module);
1329 		*_info = module->info;
1330 	} else if ((module->flags & B_BUILT_IN_MODULE) == 0)
1331 		put_module_image(module->module_image);
1332 
1333 	recursive_lock_unlock(&sModulesLock);
1334 	return status;
1335 
1336 err:
1337 	recursive_lock_unlock(&sModulesLock);
1338 	return B_ENTRY_NOT_FOUND;
1339 }
1340 
1341 
1342 status_t
1343 put_module(const char *path)
1344 {
1345 	module *module;
1346 
1347 	TRACE(("put_module(path = %s)\n", path));
1348 
1349 	recursive_lock_lock(&sModulesLock);
1350 
1351 	module = (struct module *)hash_lookup(sModulesHash, path);
1352 	if (module == NULL) {
1353 		FATAL(("module: We don't seem to have a reference to module %s\n", path));
1354 		recursive_lock_unlock(&sModulesLock);
1355 		return B_BAD_VALUE;
1356 	}
1357 
1358 	if ((module->flags & B_KEEP_LOADED) == 0) {
1359 		dec_module_ref_count(module);
1360 
1361 		if (module->ref_count == 0)
1362 			uninit_module(module);
1363 	}
1364 
1365 	if ((module->flags & B_BUILT_IN_MODULE) == 0)
1366 		put_module_image(module->module_image);
1367 
1368 	recursive_lock_unlock(&sModulesLock);
1369 	return B_OK;
1370 }
1371