linux-old/kernel/module.c
<<
>>
Prefs
   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
  45static struct module kernel_module;
  46static struct module *module_list = &kernel_module;
  47
  48static int freeing_modules; /* true if some modules are marked for deletion */
  49
  50static struct module *find_module( const char *name);
  51static int get_mod_name( char *user_name, char *buf);
  52static int free_modules( void);
  53
  54static int module_init_flag = 0; /* Hmm... */
  55
  56/*
  57 * Called at boot time
  58 */
  59void init_modules(void) {
  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
  73int
  74rename_module_symbol(char *old_name, char *new_name)
  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 */
 132asmlinkage unsigned long
 133sys_create_module(char *module_name, unsigned long size)
 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 */
 183asmlinkage int
 184sys_init_module(char *module_name, char *code, unsigned codesize,
 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
 311asmlinkage int
 312sys_delete_module(char *module_name)
 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 */
 358asmlinkage int
 359sys_get_kernel_syms(struct kernel_sym *table)
 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 */
 414int
 415get_mod_name(char *user_name, char *buf)
 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 */
 431struct module *
 432find_module( const char *name)
 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
 445static void
 446drop_refs(struct module *mp)
 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 */
 471int
 472free_modules( void)
 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 */
 509int get_module_list(char *buf)
 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 */
 570int get_ksyms_list(char *buf)
 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)
 628static struct symbol_table nulltab;
 629
 630int
 631register_symtab(struct symbol_table *intab)
 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 && (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}
 762
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.