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

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

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