root/kernel/module.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_modules
  2. rename_module_symbol
  3. sys_create_module
  4. sys_init_module
  5. sys_delete_module
  6. sys_get_kernel_syms
  7. get_mod_name
  8. find_module
  9. drop_refs
  10. free_modules
  11. get_module_list
  12. get_ksyms_list
  13. register_symtab
  14. sys_create_module
  15. sys_init_module
  16. sys_delete_module
  17. sys_get_kernel_syms
  18. register_symtab

   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][next][first][last][top][bottom][index][help] */
  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][next][first][last][top][bottom][index][help] */
  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][next][first][last][top][bottom][index][help] */
 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][next][first][last][top][bottom][index][help] */
 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 + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
 232                 return -EINVAL;
 233         memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
 234         memset((char *)mp->addr + sizeof (long) + codesize, 0,
 235                 mp->size * PAGE_SIZE - (codesize + sizeof (long)));
 236         PRINTK(( "module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
 237                 (unsigned long) rt.init, (unsigned long) rt.cleanup));
 238         mp->cleanup = rt.cleanup;
 239 
 240         /* update kernel symbol table */
 241         if (symtab) { /* symtab == NULL means no new entries to handle */
 242                 struct internal_symbol *sym;
 243                 struct module_ref *ref;
 244                 int size;
 245                 int i;
 246                 int legal_start;
 247 
 248                 if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
 249                         return error;
 250                 size = get_user(&symtab->size);
 251 
 252                 if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
 253                         return -ENOMEM;
 254                 }
 255 
 256                 if ((error = verify_area(VERIFY_READ, symtab, size))) {
 257                         kfree_s(newtab, size);
 258                         return error;
 259                 }
 260                 memcpy_fromfs((char *)(newtab), symtab, size);
 261 
 262                 /* sanity check */
 263                 legal_start = sizeof(struct symbol_table) +
 264                         newtab->n_symbols * sizeof(struct internal_symbol) +
 265                         newtab->n_refs * sizeof(struct module_ref);
 266 
 267                 if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
 268                         printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
 269                                newtab->n_symbols, newtab->n_refs);
 270                         kfree_s(newtab, size);
 271                         return -EINVAL;
 272                 }
 273 
 274                 /* relocate name pointers, index referred from start of table */
 275                 for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
 276                         if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
 277                                 printk("Rejecting illegal symbol table\n");
 278                                 kfree_s(newtab, size);
 279                                 return -EINVAL;
 280                         }
 281                         /* else */
 282                         sym->name += (long)newtab;
 283                 }
 284                 mp->symtab = newtab;
 285 
 286                 /* Update module references.
 287                  * On entry, from "insmod", ref->module points to
 288                  * the referenced module!
 289                  * Now it will point to the current module instead!
 290                  * The ref structure becomes the first link in the linked
 291                  * list of references to the referenced module.
 292                  * Also, "sym" from above, points to the first ref entry!!!
 293                  */
 294                 for (ref = (struct module_ref *)sym, i = 0;
 295                         i < newtab->n_refs; ++ref, ++i) {
 296 
 297                         /* Check for valid reference */
 298                         struct module *link = module_list;
 299                         while (link && (ref->module != link))
 300                                 link = link->next;
 301 
 302                         if (link == (struct module *)0) {
 303                                 printk("Non-module reference! Rejected!\n");
 304                                 return -EINVAL;
 305                         }
 306 
 307                         ref->next = ref->module->ref;
 308                         ref->module->ref = ref;
 309                         ref->module = mp;
 310                 }
 311         }
 312 
 313         module_init_flag = 1; /* Hmm... */
 314         if ((*rt.init)() != 0) {
 315                 module_init_flag = 0; /* Hmm... */
 316                 return -EBUSY;
 317         }
 318         module_init_flag = 0; /* Hmm... */
 319         mp->state = MOD_RUNNING;
 320 
 321         return 0;
 322 }
 323 
 324 asmlinkage int
 325 sys_delete_module(char *module_name)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327         struct module *mp;
 328         char name[MOD_MAX_NAME];
 329         int error;
 330 
 331         if (!suser())
 332                 return -EPERM;
 333         /* else */
 334         if (module_name != NULL) {
 335                 if ((error = get_mod_name(module_name, name)) != 0)
 336                         return error;
 337                 if ((mp = find_module(name)) == NULL)
 338                         return -ENOENT;
 339                 if ((mp->ref != NULL) || (GET_USE_COUNT(mp) != 0))
 340                         return -EBUSY;
 341                 if (mp->state == MOD_RUNNING)
 342                         (*mp->cleanup)();
 343                 mp->state = MOD_DELETED;
 344         }
 345         free_modules();
 346         return 0;
 347 }
 348 
 349 
 350 /*
 351  * Copy the kernel symbol table to user space.  If the argument is null,
 352  * just return the size of the table.
 353  *
 354  * Note that the transient module symbols are copied _first_,
 355  * in lifo order!!!
 356  *
 357  * The symbols to "insmod" are according to the "old" format: struct kernel_sym,
 358  * which is actually quite handy for this purpose.
 359  * Note that insmod inserts a struct symbol_table later on...
 360  * (as that format is quite handy for the kernel...)
 361  *
 362  * For every module, the first (pseudo)symbol copied is the module name
 363  * and the address of the module struct.
 364  * This lets "insmod" keep track of references, and build the array of
 365  * struct module_refs in the symbol table.
 366  * The format of the module name is "#module", so that "insmod" can easily
 367  * notice when a module name comes along. Also, this will make it possible
 368  * to use old versions of "insmod", albeit with reduced functionality...
 369  * The "kernel" module has an empty name.
 370  */
 371 asmlinkage int
 372 sys_get_kernel_syms(struct kernel_sym *table)
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374         struct internal_symbol *from;
 375         struct kernel_sym isym;
 376         struct kernel_sym *to;
 377         struct module *mp = module_list;
 378         int i;
 379         int nmodsyms = 0;
 380 
 381         for (mp = module_list; mp; mp = mp->next) {
 382                 if (mp->symtab && mp->symtab->n_symbols) {
 383                         /* include the count for the module name! */
 384                         nmodsyms += mp->symtab->n_symbols + 1;
 385                 }
 386                 else
 387                         /* include the count for the module name! */
 388                         nmodsyms += 1; /* return modules without symbols too */
 389         }
 390 
 391         if (table != NULL) {
 392                 to = table;
 393 
 394                 if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
 395                         return i;
 396 
 397                 /* copy all module symbols first (always LIFO order) */
 398                 for (mp = module_list; mp; mp = mp->next) {
 399                         if (mp->state == MOD_RUNNING) {
 400                                 /* magic: write module info as a pseudo symbol */
 401                                 isym.value = (unsigned long)mp;
 402                                 sprintf(isym.name, "#%s", mp->name);
 403                                 memcpy_tofs(to, &isym, sizeof isym);
 404                                 ++to;
 405 
 406                                 if (mp->symtab != NULL) {
 407                                         for (i = mp->symtab->n_symbols,
 408                                                 from = mp->symtab->symbol;
 409                                                 i > 0; --i, ++from, ++to) {
 410 
 411                                                 isym.value = (unsigned long)from->addr;
 412                                                 strncpy(isym.name, from->name, sizeof isym.name);
 413                                                 memcpy_tofs(to, &isym, sizeof isym);
 414                                         }
 415                                 }
 416                         }
 417                 }
 418         }
 419 
 420         return nmodsyms;
 421 }
 422 
 423 
 424 /*
 425  * Copy the name of a module from user space.
 426  */
 427 int
 428 get_mod_name(char *user_name, char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 429 {
 430         int i;
 431 
 432         i = 0;
 433         for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
 434                 if (++i >= MOD_MAX_NAME)
 435                         return -E2BIG;
 436         }
 437         return 0;
 438 }
 439 
 440 
 441 /*
 442  * Look for a module by name, ignoring modules marked for deletion.
 443  */
 444 struct module *
 445 find_module( const char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447         struct module *mp;
 448 
 449         for (mp = module_list ; mp ; mp = mp->next) {
 450                 if (mp->state == MOD_DELETED)
 451                         continue;
 452                 if (!strcmp(mp->name, name))
 453                         break;
 454         }
 455         return mp;
 456 }
 457 
 458 static void
 459 drop_refs(struct module *mp)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461         struct module *step;
 462         struct module_ref *prev;
 463         struct module_ref *ref;
 464 
 465         for (step = module_list; step; step = step->next) {
 466                 for (prev = ref = step->ref; ref; ref = prev->next) {
 467                         if (ref->module == mp) {
 468                                 if (ref == step->ref)
 469                                         step->ref = ref->next;
 470                                 else
 471                                         prev->next = ref->next;
 472                                 break; /* every module only references once! */
 473                         }
 474                         else
 475                                 prev = ref;
 476                 }
 477         }
 478 }
 479 
 480 /*
 481  * Try to free modules which have been marked for deletion.  Returns nonzero
 482  * if a module was actually freed.
 483  */
 484 int
 485 free_modules( void)
     /* [previous][next][first][last][top][bottom][index][help] */
 486 {
 487         struct module *mp;
 488         struct module **mpp;
 489         int did_deletion;
 490 
 491         did_deletion = 0;
 492         freeing_modules = 0;
 493         mpp = &module_list;
 494         while ((mp = *mpp) != NULL) {
 495                 if (mp->state != MOD_DELETED) {
 496                         mpp = &mp->next;
 497                 } else {
 498                         if (GET_USE_COUNT(mp) != 0) {
 499                                 freeing_modules = 1;
 500                                 mpp = &mp->next;
 501                         } else {        /* delete it */
 502                                 *mpp = mp->next;
 503                                 if (mp->symtab) {
 504                                         if (mp->symtab->n_refs)
 505                                                 drop_refs(mp);
 506                                         if (mp->symtab->size)
 507                                                 kfree_s(mp->symtab, mp->symtab->size);
 508                                 }
 509                                 vfree(mp->addr);
 510                                 kfree_s(mp, sizeof(struct module) + MOD_MAX_NAME);
 511                                 did_deletion = 1;
 512                         }
 513                 }
 514         }
 515         return did_deletion;
 516 }
 517 
 518 
 519 /*
 520  * Called by the /proc file system to return a current list of modules.
 521  */
 522 int get_module_list(char *buf)
     /* [previous][next][first][last][top][bottom][index][help] */
 523 {
 524         char *p;
 525         const char *q;
 526         int i;
 527         struct module *mp;
 528         struct module_ref *ref;
 529         char size[32];
 530 
 531         p = buf;
 532         /* Do not show the kernel pseudo module */
 533         for (mp = module_list ; mp && mp->next; mp = mp->next) {
 534                 if (p - buf > 4096 - 100)
 535                         break;                  /* avoid overflowing buffer */
 536                 q = mp->name;
 537                 if (*q == '\0' && mp->size == 0 && mp->ref == NULL)
 538                         continue; /* don't list modules for kernel syms */
 539                 i = 20;
 540                 while (*q) {
 541                         *p++ = *q++;
 542                         i--;
 543                 }
 544                 sprintf(size, "%d", mp->size);
 545                 i -= strlen(size);
 546                 if (i <= 0)
 547                         i = 1;
 548                 while (--i >= 0)
 549                         *p++ = ' ';
 550                 q = size;
 551                 while (*q)
 552                         *p++ = *q++;
 553                 if (mp->state == MOD_UNINITIALIZED)
 554                         q = "  (uninitialized)";
 555                 else if (mp->state == MOD_RUNNING) {
 556                         sprintf(size,"\t%ld",GET_USE_COUNT(mp));
 557                         q=size;
 558                 }
 559                 else if (mp->state == MOD_DELETED)
 560                         q = "  (deleted)";
 561                 else
 562                         q = "  (bad state)";
 563                 while (*q)
 564                         *p++ = *q++;
 565 
 566                 if ((ref = mp->ref) != NULL) {
 567                         *p++ = '\t';
 568                         *p++ = '[';
 569                         for (; ref; ref = ref->next) {
 570                                 q = ref->module->name;
 571                                 while (*q)
 572                                         *p++ = *q++;
 573                                 if (ref->next)
 574                                         *p++ = ' ';
 575                         }
 576                         *p++ = ']';
 577                 }
 578                 *p++ = '\n';
 579         }
 580         return p - buf;
 581 }
 582 
 583 
 584 /*
 585  * Called by the /proc file system to return a current list of ksyms.
 586  */
 587 int get_ksyms_list(char *buf, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 588 {
 589         struct module *mp;
 590         struct internal_symbol *sym;
 591         int i;
 592         char *p = buf;
 593         int len     = 0;        /* code from  net/ipv4/proc.c */
 594         off_t pos   = 0;
 595         off_t begin = 0;
 596 
 597         for (mp = module_list; mp; mp = mp->next) {
 598                 if ((mp->state == MOD_RUNNING) &&
 599                     (mp->symtab != NULL) &&
 600                     (mp->symtab->n_symbols > 0)) {
 601                         for (i = mp->symtab->n_symbols,
 602                                 sym = mp->symtab->symbol;
 603                                 i > 0; --i, ++sym) {
 604 
 605                                 p = buf + len;
 606                                 if (mp->name[0]) {
 607                                         len += sprintf(p, "%08lx %s\t[%s]\n",
 608                                                        (long)sym->addr,
 609                                                        sym->name, mp->name);
 610                                 } else {
 611                                         len += sprintf(p, "%08lx %s\n",
 612                                                        (long)sym->addr,
 613                                                        sym->name);
 614                                 }
 615                                 pos = begin + len;
 616                                 if (pos < offset) {
 617                                         len   = 0;
 618                                         begin = pos;
 619                                 }
 620                                 pos = begin + len;
 621                                 if (pos > offset+length)
 622                                         goto leave_the_loop;
 623                         }
 624                 }
 625         }
 626     leave_the_loop:
 627         *start = buf + (offset - begin);
 628         len -= (offset - begin);
 629         if (len > length)
 630                 len = length;
 631         return len;
 632 }
 633 
 634 /*
 635  * Rules:
 636  * - The new symbol table should be statically allocated, or else you _have_
 637  *   to set the "size" field of the struct to the number of bytes allocated.
 638  *
 639  * - The strings that name the symbols will not be copied, maybe the pointers
 640  *
 641  * - For a loadable module, the function should only be called in the
 642  *   context of init_module
 643  *
 644  * Those are the only restrictions! (apart from not being reentrant...)
 645  *
 646  * If you want to remove a symbol table for a loadable module,
 647  * the call looks like: "register_symtab(0)".
 648  *
 649  * The look of the code is mostly dictated by the format of
 650  * the frozen struct symbol_table, due to compatibility demands.
 651  */
 652 #define INTSIZ sizeof(struct internal_symbol)
 653 #define REFSIZ sizeof(struct module_ref)
 654 #define SYMSIZ sizeof(struct symbol_table)
 655 #define MODSIZ sizeof(struct module)
 656 static struct symbol_table nulltab;
 657 
 658 int
 659 register_symtab(struct symbol_table *intab)
     /* [previous][next][first][last][top][bottom][index][help] */
 660 {
 661         struct module *mp;
 662         struct module *link;
 663         struct symbol_table *oldtab;
 664         struct symbol_table *newtab;
 665         struct module_ref *newref;
 666         int size;
 667 
 668         if (intab && (intab->n_symbols == 0)) {
 669                 struct internal_symbol *sym;
 670                 /* How many symbols, really? */
 671 
 672                 for (sym = intab->symbol; sym->name; ++sym)
 673                         intab->n_symbols +=1;
 674         }
 675 
 676 #if 1
 677         if (module_init_flag == 0) { /* Hmm... */
 678 #else
 679         if (module_list == &kernel_module) {
 680 #endif
 681                 /* Aha! Called from an "internal" module */
 682                 if (!intab)
 683                         return 0; /* or -ESILLY_PROGRAMMER :-) */
 684 
 685                 /* create a pseudo module! */
 686                 if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
 687                         /* panic time! */
 688                         printk("Out of memory for new symbol table!\n");
 689                         return -ENOMEM;
 690                 }
 691                 /* else  OK */
 692                 memset(mp, 0, MODSIZ);
 693                 mp->state = MOD_RUNNING; /* Since it is resident... */
 694                 mp->name = ""; /* This is still the "kernel" symbol table! */
 695                 mp->symtab = intab;
 696 
 697                 /* link it in _after_ the resident symbol table */
 698                 mp->next = kernel_module.next;
 699                 kernel_module.next = mp;
 700 
 701                 return 0;
 702         }
 703 
 704         /* else ******** Called from a loadable module **********/
 705 
 706         /*
 707          * This call should _only_ be done in the context of the
 708          * call to  init_module  i.e. when loading the module!!
 709          * Or else...
 710          */
 711         mp = module_list; /* true when doing init_module! */
 712 
 713         /* Any table there before? */
 714         if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
 715                 /* No, just insert it! */
 716                 mp->symtab = intab;
 717                 return 0;
 718         }
 719 
 720         /* else  ****** we have to replace the module symbol table ******/
 721 #if 0
 722         if (oldtab->n_symbols > 0) {
 723                 /* Oh dear, I have to drop the old ones... */
 724                 printk("Warning, dropping old symbols\n");
 725         }
 726 #endif
 727 
 728         if (oldtab->n_refs == 0) { /* no problems! */
 729                 mp->symtab = intab;
 730                 /* if the old table was kmalloc-ed, drop it */
 731                 if (oldtab->size > 0)
 732                         kfree_s(oldtab, oldtab->size);
 733 
 734                 return 0;
 735         }
 736 
 737         /* else */
 738         /***** The module references other modules... insmod said so! *****/
 739         /* We have to allocate a new symbol table, or we lose them! */
 740         if (intab == (struct symbol_table*)0)
 741                 intab = &nulltab; /* easier code with zeroes in place */
 742 
 743         /* the input symbol table space does not include the string table */
 744         /* (it does for symbol tables that insmod creates) */
 745 
 746         if (!(newtab = (struct symbol_table*)kmalloc(
 747                 size = SYMSIZ + intab->n_symbols * INTSIZ +
 748                         oldtab->n_refs * REFSIZ,
 749                 GFP_KERNEL))) {
 750                 /* panic time! */
 751                 printk("Out of memory for new symbol table!\n");
 752                 return -ENOMEM;
 753         }
 754 
 755         /* copy up to, and including, the new symbols */
 756         memcpy(newtab, intab, SYMSIZ + intab->n_symbols * INTSIZ);
 757 
 758         newtab->size = size;
 759         newtab->n_refs = oldtab->n_refs;
 760 
 761         /* copy references */
 762         memcpy( ((char *)newtab) + SYMSIZ + intab->n_symbols * INTSIZ,
 763                 ((char *)oldtab) + SYMSIZ + oldtab->n_symbols * INTSIZ,
 764                 oldtab->n_refs * REFSIZ);
 765 
 766         /* relink references from the old table to the new one */
 767 
 768         /* pointer to the first reference entry in newtab! Really! */
 769         newref = (struct module_ref*) &(newtab->symbol[newtab->n_symbols]);
 770 
 771         /* check for reference links from previous modules */
 772         for (   link = module_list;
 773                 link && (link != &kernel_module);
 774                 link = link->next) {
 775 
 776                 if (link->ref && (link->ref->module == mp))
 777                         link->ref = newref++;
 778         }
 779 
 780         mp->symtab = newtab;
 781 
 782         /* all references (if any) have been handled */
 783 
 784         /* if the old table was kmalloc-ed, drop it */
 785         if (oldtab->size > 0)
 786                 kfree_s(oldtab, oldtab->size);
 787 
 788         return 0;
 789 }
 790 
 791 #else           /* CONFIG_MODULES */
 792 
 793 /* Dummy syscalls for people who don't want modules */
 794 
 795 asmlinkage unsigned long sys_create_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 796 {
 797         return -ENOSYS;
 798 }
 799 
 800 asmlinkage int sys_init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 801 {
 802         return -ENOSYS;
 803 }
 804 
 805 asmlinkage int sys_delete_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 806 {
 807         return -ENOSYS;
 808 }
 809 
 810 asmlinkage int sys_get_kernel_syms(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 811 {
 812         return -ENOSYS;
 813 }
 814 
 815 int register_symtab(struct symbol_table *intab)
     /* [previous][next][first][last][top][bottom][index][help] */
 816 {
 817         return 0;
 818 }
 819 
 820 #endif  /* CONFIG_MODULES */
 821 

/* [previous][next][first][last][top][bottom][index][help] */