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

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