OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [kernel/] [module.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.