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

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