1 #include <linux/errno.h>
2 #include <linux/kernel.h>
3 #include <asm/segment.h>
4 #include <linux/mm.h> /* defines GFP_KERNEL */
5 #include <linux/string.h>
6 #include <linux/module.h>
7 #include <linux/sched.h>
8 #include <linux/malloc.h>
9 #include <linux/config.h>
10 /*
11 * Originally by Anonymous (as far as I know...)
12 * Linux version by Bas Laarhoven <bas@vimec.nl>
13 * 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
14 *
15 * Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
16 * This source is covered by the GNU GPL, the same as all kernel sources.
17 *
18 * Features:
19 * - Supports stacked modules (removable only of there are no dependents).
20 * - Supports table of symbols defined by the modules.
21 * - Supports /proc/ksyms, showing value, name and owner of all
22 * the symbols defined by all modules (in stack order).
23 * - Added module dependencies information into /proc/modules
24 * - Supports redefines of all symbols, for streams-like behaviour.
25 * - Compatible with older versions of insmod.
26 *
27 * New addition in December 1994: (Bjorn Ekwall, idea from Jacques Gelinas)
28 * - Externally callable function:
29 *
30 * "int register_symtab(struct symbol_table *)"
31 *
32 * This function can be called from within the kernel,
33 * and ALSO from loadable modules.
34 * The goal is to assist in modularizing the kernel even more,
35 * and finally: reducing the number of entries in ksyms.c
36 * since every subsystem should now be able to decide and
37 * control exactly what symbols it wants to export, locally!
38 *
39 * On 1-Aug-95: <Matti.Aarnio@utu.fi> altered code to use same style as
40 * do /proc/net/XXX "files". Namely allow more than 4kB
41 * (or what the block size if) output.
42 *
43 * - Use dummy syscall functions for users who disable all
44 * module support. Similar to kernel/sys.c (Paul Gortmaker)
45 */
46
47 #ifdef CONFIG_MODULES /* a *big* #ifdef block... */
48
49 #ifdef DEBUG_MODULE
50 #define PRINTK(a) printk a
51 #else
52 #define PRINTK(a) /* */
53 #endif
54
55 static struct module kernel_module;
56 static struct module *module_list = &kernel_module;
57
58 static int freeing_modules; /* true if some modules are marked for deletion */
59
60 static struct module *find_module( const char *name);
61 static int get_mod_name( char *user_name, char *buf);
62 static int free_modules( void);
63
64 static int module_init_flag = 0; /* Hmm... */
65
66 extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
67
68 /*
69 * Called at boot time
70 */
71 void init_modules(void) {
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
72 struct internal_symbol *sym;
73 int i;
74
75 for (i = 0, sym = symbol_table.symbol; sym->name; ++sym, ++i)
76 ;
77 symbol_table.n_symbols = i;
78
79 kernel_module.symtab = &symbol_table;
80 kernel_module.state = MOD_RUNNING; /* Hah! */
81 kernel_module.name = "";
82 }
83
84 int
85 rename_module_symbol(char *old_name, char *new_name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
86 {
87 struct internal_symbol *sym;
88 int i = 0; /* keep gcc silent */
89
90 if (module_list->symtab) {
91 sym = module_list->symtab->symbol;
92 for (i = module_list->symtab->n_symbols; i > 0; ++sym, --i) {
93 if (strcmp(sym->name, old_name) == 0) { /* found it! */
94 sym->name = new_name; /* done! */
95 PRINTK(("renamed %s to %s\n", old_name, new_name));
96 return 1; /* it worked! */
97 }
98 }
99 }
100 printk("rename %s to %s failed!\n", old_name, new_name);
101 return 0; /* not there... */
102
103 /*
104 * This one will change the name of the first matching symbol!
105 *
106 * With this function, you can replace the name of a symbol defined
107 * in the current module with a new name, e.g. when you want to insert
108 * your own function instead of a previously defined function
109 * with the same name.
110 *
111 * "Normal" usage:
112 *
113 * bogus_function(int params)
114 * {
115 * do something "smart";
116 * return real_function(params);
117 * }
118 *
119 * ...
120 *
121 * init_module()
122 * {
123 * if (rename_module_symbol("_bogus_function", "_real_function"))
124 * printk("yep!\n");
125 * else
126 * printk("no way!\n");
127 * ...
128 * }
129 *
130 * When loading this module, real_function will be resolved
131 * to the real function address.
132 * All later loaded modules that refer to "real_function()" will
133 * then really call "bogus_function()" instead!!!
134 *
135 * This feature will give you ample opportunities to get to know
136 * the taste of your foot when you stuff it into your mouth!!!
137 */
138 }
139
140 /*
141 * Allocate space for a module.
142 */
143 asmlinkage unsigned long
144 sys_create_module(char *module_name, unsigned long size)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
145 {
146 struct module *mp;
147 void* addr;
148 int error;
149 int npages;
150 int sspace = sizeof(struct module) + MOD_MAX_NAME;
151 char name[MOD_MAX_NAME];
152
153 if (!suser())
154 return -EPERM;
155 if (module_name == NULL || size == 0)
156 return -EINVAL;
157 if ((error = get_mod_name(module_name, name)) != 0)
158 return error;
159 if (find_module(name) != NULL) {
160 return -EEXIST;
161 }
162
163 if ((mp = (struct module*) kmalloc(sspace, GFP_KERNEL)) == NULL) {
164 return -ENOMEM;
165 }
166 strcpy((char *)(mp + 1), name); /* why not? */
167
168 npages = (size + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE;
169 if ((addr = vmalloc(npages * PAGE_SIZE)) == 0) {
170 kfree_s(mp, sspace);
171 return -ENOMEM;
172 }
173
174 mp->next = module_list;
175 mp->ref = NULL;
176 mp->symtab = NULL;
177 mp->name = (char *)(mp + 1);
178 mp->size = npages;
179 mp->addr = addr;
180 mp->state = MOD_UNINITIALIZED;
181 mp->cleanup = NULL;
182
183 * (long *) addr = 0; /* set use count to zero */
184 module_list = mp; /* link it in */
185
186 PRINTK(("module `%s' (%lu pages @ 0x%08lx) created\n",
187 mp->name, (unsigned long) mp->size, (unsigned long) mp->addr));
188 return (unsigned long) addr;
189 }
190
191 /*
192 * Initialize a module.
193 */
194 asmlinkage int
195 sys_init_module(char *module_name, char *code, unsigned codesize,
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
196 struct mod_routines *routines,
197 struct symbol_table *symtab)
198 {
199 struct module *mp;
200 struct symbol_table *newtab;
201 char name[MOD_MAX_NAME];
202 int error;
203 struct mod_routines rt;
204
205 if (!suser())
206 return -EPERM;
207
208 #ifdef __i386__
209 /* A little bit of protection... we "know" where the user stack is... */
210
211 if (symtab && ((unsigned long)symtab > 0xb0000000)) {
212 printk("warning: you are using an old insmod, no symbols will be inserted!\n");
213 symtab = NULL;
214 }
215 #endif
216
217 /*
218 * First reclaim any memory from dead modules that where not
219 * freed when deleted. Should I think be done by timers when
220 * the module was deleted - Jon.
221 */
222 free_modules();
223
224 if ((error = get_mod_name(module_name, name)) != 0)
225 return error;
226 PRINTK(("initializing module `%s', %d (0x%x) bytes\n",
227 name, codesize, codesize));
228 memcpy_fromfs(&rt, routines, sizeof rt);
229 if ((mp = find_module(name)) == NULL)
230 return -ENOENT;
231 if (codesize & MOD_AUTOCLEAN) {
232 /*
233 * set autoclean marker from codesize...
234 * set useage count to "zero"
235 */
236 codesize &= ~MOD_AUTOCLEAN;
237 GET_USE_COUNT(mp) = MOD_AUTOCLEAN;
238 }
239 if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
240 return -EINVAL;
241 memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
242 memset((char *)mp->addr + sizeof (long) + codesize, 0,
243 mp->size * PAGE_SIZE - (codesize + sizeof (long)));
244 PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
245 (unsigned long) rt.init, (unsigned long) rt.cleanup));
246 mp->cleanup = rt.cleanup;
247
248 /* update kernel symbol table */
249 if (symtab) { /* symtab == NULL means no new entries to handle */
250 struct internal_symbol *sym;
251 struct module_ref *ref;
252 int size;
253 int i;
254 int legal_start;
255
256 if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
257 return error;
258 size = get_user(&symtab->size);
259
260 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
261 return -ENOMEM;
262 }
263
264 if ((error = verify_area(VERIFY_READ, symtab, size))) {
265 kfree_s(newtab, size);
266 return error;
267 }
268 memcpy_fromfs((char *)(newtab), symtab, size);
269
270 /* sanity check */
271 legal_start = sizeof(struct symbol_table) +
272 newtab->n_symbols * sizeof(struct internal_symbol) +
273 newtab->n_refs * sizeof(struct module_ref);
274
275 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
276 printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
277 newtab->n_symbols, newtab->n_refs);
278 kfree_s(newtab, size);
279 return -EINVAL;
280 }
281
282 /* relocate name pointers, index referred from start of table */
283 for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
284 if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
285 printk("Rejecting illegal symbol table\n");
286 kfree_s(newtab, size);
287 return -EINVAL;
288 }
289 /* else */
290 sym->name += (long)newtab;
291 }
292 mp->symtab = newtab;
293
294 /* Update module references.
295 * On entry, from "insmod", ref->module points to
296 * the referenced module!
297 * Now it will point to the current module instead!
298 * The ref structure becomes the first link in the linked
299 * list of references to the referenced module.
300 * Also, "sym" from above, points to the first ref entry!!!
301 */
302 for (ref = (struct module_ref *)sym, i = 0;
303 i < newtab->n_refs; ++ref, ++i) {
304
305 /* Check for valid reference */
306 struct module *link = module_list;
307 while (link && (ref->module != link))
308 link = link->next;
309
310 if (link == (struct module *)0) {
311 printk("Non-module reference! Rejected!\n");
312 return -EINVAL;
313 }
314
315 ref->next = ref->module->ref;
316 ref->module->ref = ref;
317 ref->module = mp;
318 }
319 }
320
321 module_init_flag = 1; /* Hmm... */
322 if ((*rt.init)() != 0) {
323 module_init_flag = 0; /* Hmm... */
324 return -EBUSY;
325 }
326 module_init_flag = 0; /* Hmm... */
327 mp->state = MOD_RUNNING;
328
329 return 0;
330 }
331
332 asmlinkage int
333 sys_delete_module(char *module_name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
334 {
335 struct module *mp;
336 char name[MOD_MAX_NAME];
337 int error;
338
339 if (!suser())
340 return -EPERM;
341 /* else */
342 if (module_name != NULL) {
343 if ((error = get_mod_name(module_name, name)) != 0)
344 return error;
345 if ((mp = find_module(name)) == NULL)
346 return -ENOENT;
347 if ((mp->ref != NULL) || ((GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN) != 0))
348 return -EBUSY;
349 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
350 if (mp->state == MOD_RUNNING)
351 (*mp->cleanup)();
352 mp->state = MOD_DELETED;
353 free_modules();
354 }
355 /* for automatic reaping */
356 else {
357 for (mp = module_list; mp != &kernel_module; mp = mp->next) {
358 if ((mp->ref == NULL) && (GET_USE_COUNT(mp) == MOD_AUTOCLEAN) &&
359 (mp->state == MOD_RUNNING)) {
360 GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
361 (*mp->cleanup)();
362 mp->state = MOD_DELETED;
363 free_modules();
364 }
365 }
366 }
367 return 0;
368 }
369
370
371 /*
372 * Copy the kernel symbol table to user space. If the argument is null,
373 * just return the size of the table.
374 *
375 * Note that the transient module symbols are copied _first_,
376 * in lifo order!!!
377 *
378 * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
379 * which is actually quite handy for this purpose.
380 * Note that insmod inserts a struct symbol_table later on...
381 * (as that format is quite handy for the kernel...)
382 *
383 * For every module, the first (pseudo)symbol copied is the module name
384 * and the address of the module struct.
385 * This lets "insmod" keep track of references, and build the array of
386 * struct module_refs in the symbol table.
387 * The format of the module name is "#module", so that "insmod" can easily
388 * notice when a module name comes along. Also, this will make it possible
389 * to use old versions of "insmod", albeit with reduced functionality...
390 * The "kernel" module has an empty name.
391 */
392 asmlinkage int
393 sys_get_kernel_syms(struct kernel_sym *table)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
394 {
395 struct internal_symbol *from;
396 struct kernel_sym isym;
397 struct kernel_sym *to;
398 struct module *mp = module_list;
399 int i;
400 int nmodsyms = 0;
401
402 for (mp = module_list; mp; mp = mp->next) {
403 if (mp->symtab && mp->symtab->n_symbols) {
404 /* include the count for the module name! */
405 nmodsyms += mp->symtab->n_symbols + 1;
406 }
407 else
408 /* include the count for the module name! */
409 nmodsyms += 1; /* return modules without symbols too */
410 }
411
412 if (table != NULL) {
413 to = table;
414
415 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
416 return i;
417
418 /* copy all module symbols first (always LIFO order) */
419 for (mp = module_list; mp; mp = mp->next) {
420 if (mp->state == MOD_RUNNING) {
421 /* magic: write module info as a pseudo symbol */
422 isym.value = (unsigned long)mp;
423 sprintf(isym.name, "#%s", mp->name);
424 memcpy_tofs(to, &isym, sizeof isym);
425 ++to;
426
427 if (mp->symtab != NULL) {
428 for (i = mp->symtab->n_symbols,
429 from = mp->symtab->symbol;
430 i > 0; --i, ++from, ++to) {
431
432 isym.value = (unsigned long)from->addr;
433 strncpy(isym.name, from->name, sizeof isym.name);
434 memcpy_tofs(to, &isym, sizeof isym);
435 }
436 }
437 }
438 }
439 }
440
441 return nmodsyms;
442 }
443
444
445 /*
446 * Copy the name of a module from user space.
447 */
448 int
449 get_mod_name(char *user_name, char *buf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
450 {
451 int i;
452
453 i = 0;
454 for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
455 if (++i >= MOD_MAX_NAME)
456 return -E2BIG;
457 }
458 return 0;
459 }
460
461
462 /*
463 * Look for a module by name, ignoring modules marked for deletion.
464 */
465 struct module *
466 find_module( const char *name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
467 {
468 struct module *mp;
469
470 for (mp = module_list ; mp ; mp = mp->next) {
471 if (mp->state == MOD_DELETED)
472 continue;
473 if (!strcmp(mp->name, name))
474 break;
475 }
476 return mp;
477 }
478
479 static void
480 drop_refs(struct module *mp)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
481 {
482 struct module *step;
483 struct module_ref *prev;
484 struct module_ref *ref;
485
486 for (step = module_list; step; step = step->next) {
487 for (prev = ref = step->ref; ref; ref = prev->next) {
488 if (ref->module == mp) {
489 if (ref == step->ref)
490 step->ref = ref->next;
491 else
492 prev->next = ref->next;
493 break; /* every module only references once! */
494 }
495 else
496 prev = ref;
497 }
498 }
499 }
500
501 /*
502 * Try to free modules which have been marked for deletion. Returns nonzero
503 * if a module was actually freed.
504 */
505 int
506 free_modules( void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
507 {
508 struct module *mp;
509 struct module **mpp;
510 int did_deletion;
511
512 did_deletion = 0;
513 freeing_modules = 0;
514 mpp = &module_list;
515 while ((mp = *mpp) != NULL) {
516 if (mp->state != MOD_DELETED) {
517 mpp = &mp->next;
518 } else {
519 if ((GET_USE_COUNT(mp) != 0) || (mp->ref != NULL)) {
520 freeing_modules = 1;
521 mpp = &mp->next;
522 } else { /* delete it */
523 *mpp = mp->next;
524 if (mp->symtab) {
525 if (mp->symtab->n_refs)
526 drop_refs(mp);
527 if (mp->symtab->size)
528 kfree_s(mp->symtab, mp->symtab->size);
529 }
530 vfree(mp->addr);
531 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
532 did_deletion = 1;
533 }
534 }
535 }
536 return did_deletion;
537 }
538
539
540 /*
541 * Called by the /proc file system to return a current list of modules.
542 */
543 int get_module_list(char *buf)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
544 {
545 char *p;
546 const char *q;
547 int i;
548 struct module *mp;
549 struct module_ref *ref;
550 char size[32];
551
552 p = buf;
553 /* Do not show the kernel pseudo module */
554 for (mp = module_list ; mp && mp->next; mp = mp->next) {
555 if (p - buf > 4096 - 100)
556 break; /* avoid overflowing buffer */
557 q = mp->name;
558 if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
559 continue; /* don't list modules for kernel syms */
560 i = 20;
561 while (*q) {
562 *p++ = *q++;
563 i--;
564 }
565 sprintf(size, "%d", mp->size);
566 i -= strlen(size);
567 if (i <= 0)
568 i = 1;
569 while (--i >= 0)
570 *p++ = ' ';
571 q = size;
572 while (*q)
573 *p++ = *q++;
574 if (mp->state == MOD_UNINITIALIZED)
575 q = " (uninitialized)";
576 else if (mp->state == MOD_RUNNING)
577 q = "";
578 else if (mp->state == MOD_DELETED)
579 q = " (deleted)";
580 else
581 q = " (bad state)";
582 while (*q)
583 *p++ = *q++;
584
585 if ((ref = mp->ref) != NULL) {
586 *p++ = '\t';
587 *p++ = '[';
588 for (; ref; ref = ref->next) {
589 q = ref->module->name;
590 while (*q)
591 *p++ = *q++;
592 if (ref->next)
593 *p++ = ' ';
594 }
595 *p++ = ']';
596 }
597 if (mp->state == MOD_RUNNING) {
598 sprintf(size,"\t%ld%s",
599 GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN,
600 ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
601 " (autoclean)":""));
602 q = size;
603 while (*q)
604 *p++ = *q++;
605 }
606 *p++ = '\n';
607 }
608 return p - buf;
609 }
610
611
612 /*
613 * Called by the /proc file system to return a current list of ksyms.
614 */
615 int get_ksyms_list(char *buf, char **start, off_t offset, int length)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
616 {
617 struct module *mp;
618 struct internal_symbol *sym;
619 int i;
620 char *p = buf;
621 int len = 0; /* code from net/ipv4/proc.c */
622 off_t pos = 0;
623 off_t begin = 0;
624
625 for (mp = module_list; mp; mp = mp->next) {
626 if ((mp->state == MOD_RUNNING) &&
627 (mp->symtab != NULL) &&
628 (mp->symtab->n_symbols > 0)) {
629 for (i = mp->symtab->n_symbols,
630 sym = mp->symtab->symbol;
631 i > 0; --i, ++sym) {
632
633 p = buf + len;
634 if (mp->name[0]) {
635 len += sprintf(p, "%08lx %s\t[%s]\n",
636 (long)sym->addr,
637 sym->name, mp->name);
638 } else {
639 len += sprintf(p, "%08lx %s\n",
640 (long)sym->addr,
641 sym->name);
642 }
643 pos = begin + len;
644 if (pos < offset) {
645 len = 0;
646 begin = pos;
647 }
648 pos = begin + len;
649 if (pos > offset+length)
650 goto leave_the_loop;
651 }
652 }
653 }
654 leave_the_loop:
655 *start = buf + (offset - begin);
656 len -= (offset - begin);
657 if (len > length)
658 len = length;
659 return len;
660 }
661
662 /*
663 * Rules:
664 * - The new symbol table should be statically allocated, or else you _have_
665 * to set the "size" field of the struct to the number of bytes allocated.
666 *
667 * - The strings that name the symbols will not be copied, maybe the pointers
668 *
669 * - For a loadable module, the function should only be called in the
670 * context of init_module
671 *
672 * Those are the only restrictions! (apart from not being reentrant...)
673 *
674 * If you want to remove a symbol table for a loadable module,
675 * the call looks like: "register_symtab(0)".
676 *
677 * The look of the code is mostly dictated by the format of
678 * the frozen struct symbol_table, due to compatibility demands.
679 */
680 #define INTSIZ sizeof(struct internal_symbol)
681 #define REFSIZ sizeof(struct module_ref)
682 #define SYMSIZ sizeof(struct symbol_table)
683 #define MODSIZ sizeof(struct module)
684 static struct symbol_table nulltab;
685
686 int
687 register_symtab(struct symbol_table *intab)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
688 {
689 struct module *mp;
690 struct module *link;
691 struct symbol_table *oldtab;
692 struct symbol_table *newtab;
693 struct module_ref *newref;
694 int size;
695
696 if (intab && (intab->n_symbols == 0)) {
697 struct internal_symbol *sym;
698 /* How many symbols, really? */
699
700 for (sym = intab->symbol; sym->name; ++sym)
701 intab->n_symbols +=1;
702 }
703
704 #if 1
705 if (module_init_flag == 0) { /* Hmm... */
706 #else
707 if (module_list == &kernel_module) {
708 #endif
709 /* Aha! Called from an "internal" module */
710 if (!intab)
711 return 0; /* or -ESILLY_PROGRAMMER :-) */
712
713 /* create a pseudo module! */
714 if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
715 /* panic time! */
716 printk("Out of memory for new symbol table!\n");
717 return -ENOMEM;
718 }
719 /* else OK */
720 memset(mp, 0, MODSIZ);
721 mp->state = MOD_RUNNING; /* Since it is resident... */
722 mp->name = ""; /* This is still the "kernel" symbol table! */
723 mp->symtab = intab;
724
725 /* link it in _after_ the resident symbol table */
726 mp->next = kernel_module.next;
727 kernel_module.next = mp;
728
729 return 0;
730 }
731
732 /* else ******** Called from a loadable module **********/
733
734 /*
735 * This call should _only_ be done in the context of the
736 * call to init_module i.e. when loading the module!!
737 * Or else...
738 */
739 mp = module_list; /* true when doing init_module! */
740
741 /* Any table there before? */
742 if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
743 /* No, just insert it! */
744 mp->symtab = intab;
745 return 0;
746 }
747
748 /* else ****** we have to replace the module symbol table ******/
749 #if 0
750 if (oldtab->n_symbols > 0) {
751 /* Oh dear, I have to drop the old ones... */
752 printk("Warning, dropping old symbols\n");
753 }
754 #endif
755
756 if (oldtab->n_refs == 0) { /* no problems! */
757 mp->symtab = intab;
758 /* if the old table was kmalloc-ed, drop it */
759 if (oldtab->size > 0)
760 kfree_s(oldtab, oldtab->size);
761
762 return 0;
763 }
764
765 /* else */
766 /***** The module references other modules... insmod said so! *****/
767 /* We have to allocate a new symbol table, or we lose them! */
768 if (intab == (struct symbol_table*)0)
769 intab = &nulltab; /* easier code with zeroes in place */
770
771 /* the input symbol table space does not include the string table */
772 /* (it does for symbol tables that insmod creates) */
773
774 if (!(newtab = (struct symbol_table*)kmalloc(
775 size = SYMSIZ + intab->n_symbols * INTSIZ +
776 oldtab->n_refs * REFSIZ,
777 GFP_KERNEL))) {
778 /* panic time! */
779 printk("Out of memory for new symbol table!\n");
780 return -ENOMEM;
781 }
782
783 /* copy up to, and including, the new symbols */
784 memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
785
786 newtab->size = size;
787 newtab->n_refs = oldtab->n_refs;
788
789 /* copy references */
790 memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
791 ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
792 oldtab->n_refs * REFSIZ);
793
794 /* relink references from the old table to the new one */
795
796 /* pointer to the first reference entry in newtab! Really! */
797 newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
798
799 /* check for reference links from previous modules */
800 for ( link = module_list;
801 link && (link != &kernel_module);
802 link = link->next) {
803
804 if (link->ref && (link->ref->module == mp))
805 link->ref = newref++;
806 }
807
808 mp->symtab = newtab;
809
810 /* all references (if any) have been handled */
811
812 /* if the old table was kmalloc-ed, drop it */
813 if (oldtab->size > 0)
814 kfree_s(oldtab, oldtab->size);
815
816 return 0;
817 }
818
819 #else /* CONFIG_MODULES */
820
821 /* Dummy syscalls for people who don't want modules */
822
823 asmlinkage unsigned long sys_create_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
824 {
825 return -ENOSYS;
826 }
827
828 asmlinkage int sys_init_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
829 {
830 return -ENOSYS;
831 }
832
833 asmlinkage int sys_delete_module(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
834 {
835 return -ENOSYS;
836 }
837
838 asmlinkage int sys_get_kernel_syms(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
839 {
840 return -ENOSYS;
841 }
842
843 int register_symtab(struct symbol_table *intab)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
844 {
845 return 0;
846 }
847
848 #endif /* CONFIG_MODULES */
849