~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/insmod/insmod.c

Version: ~ [ linux-2.2.14 ] ~ [ modutils-2.3.10 ] ~
DefVersion: ~ [ linux-2.2.14 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Insert a module into a running kernel.
  2    Copyright 1996, 1997 Linux International.
  3 
  4    New implementation contributed by Richard Henderson <rth@tamu.edu>
  5    Based on original work by Bjorn Ekwall <bj0rn@blox.se>
  6    Restructured (and partly rewritten) by:
  7         Björn Ekwall <bj0rn@blox.se> February 1999
  8 
  9    This file is part of the Linux modutils.
 10 
 11    This program is free software; you can redistribute it and/or modify it
 12    under the terms of the GNU General Public License as published by the
 13    Free Software Foundation; either version 2 of the License, or (at your
 14    option) any later version.
 15 
 16    This program is distributed in the hope that it will be useful, but
 17    WITHOUT ANY WARRANTY; without even the implied warranty of
 18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19    General Public License for more details.
 20 
 21    You should have received a copy of the GNU General Public License
 22    along with this program; if not, write to the Free Software Foundation,
 23    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 24   */
 25 
 26   /*
 27      Fixes:
 28 
 29      Adjust module size for mod_use_count in old_init_module:
 30      B. James Phillippe <bryan@terran.org>
 31 
 32      Merged modprobe + many fixes: Björn Ekwall <bj0rn@blox.se> February 1999
 33      SMP "friendliness" (and -P): Bill Zumach <zumach+@transarc.com>
 34 
 35      Ksymoops support: Keith Owens <kaos@ocs.com.au> August 1999.
 36 
 37      Add -r flag: Keith Owens <kaos@ocs.com.au> October 1999.
 38 
 39      More flexible recognition of the way the utility was called.
 40      Suggested by Stepan Kasal, implemented in a different way by Keith
 41      Owens <kaos@ocs.com.au> December 1999.
 42  
 43      Rationalize common code for 32/64 bit architectures.
 44        Keith Owens <kaos@ocs.com.au> December 1999.
 45      Add arch64().
 46        Keith Owens <kaos@ocs.com.au> December 1999.
 47    */
 48 
 49 #ident "$Id: insmod.c 1.12 Wed, 15 Mar 2000 23:50:08 +1100 keith $"
 50 
 51 #include <sys/types.h>
 52 #include <stdlib.h>
 53 #include <unistd.h>
 54 #include <string.h>
 55 #include <alloca.h>
 56 #include <limits.h>
 57 #include <ctype.h>
 58 #include <errno.h>
 59 #include <stddef.h>
 60 #include <getopt.h>
 61 #include <sys/stat.h>
 62 #include <sys/file.h>
 63 
 64 #include "module.h"
 65 #include "obj.h"
 66 #include "util.h"
 67 #include "version.h"
 68 
 69 #include "modstat.h"
 70 #include "config.h"
 71 
 72 #define STRVERSIONLEN   32
 73 
 74 /*======================================================================*/
 75 
 76 static int flag_force_load = 0;
 77 static int flag_silent_poll = 0;
 78 static int flag_verbose = 0;
 79 static int flag_export = 1;
 80 static int flag_load_map = 0;
 81 static int flag_ksymoops = 1;
 82 
 83 static int n_ext_modules_used;
 84 static int m_has_modinfo;
 85 
 86 extern int insmod_main(int argc, char **argv);
 87 extern int insmod_main_32(int argc, char **argv);
 88 extern int insmod_main_64(int argc, char **argv);
 89 extern int modprobe_main(int argc, char **argv);
 90 extern int rmmod_main(int argc, char **argv);
 91 extern int ksyms_main(int argc, char **argv);
 92 extern int lsmod_main(int argc, char **argv);
 93 
 94 /*======================================================================*/
 95 
 96 /* Get the kernel version in the canonical integer form.  */
 97 
 98 static int get_kernel_version(char str[STRVERSIONLEN])
 99 {
100         char *p, *q;
101         int a, b, c;
102 
103         strncpy(str, uts_info.release, STRVERSIONLEN);
104         p = uts_info.release;
105 
106         a = strtoul(p, &p, 10);
107         if (*p != '.')
108                 return -1;
109         b = strtoul(p + 1, &p, 10);
110         if (*p != '.')
111                 return -1;
112         c = strtoul(p + 1, &q, 10);
113         if (p + 1 == q)
114                 return -1;
115 
116         return a << 16 | b << 8 | c;
117 }
118 
119 /* String comparison for non-co-versioned kernel and module. 
120  * prefix should be the same as used by genksyms for this kernel.
121  */
122 static char *ncv_prefix = NULL; /* Overridden by --prefix option */
123 static int ncv_plen = 0;
124 
125 /* Only set prefix once. If set by the user, use it.  If not set by the
126  * user, look for a well known kernel symbol and derive the prefix from
127  * there.  Otherwise set the prefix depending on whether uts_info
128  * includes SMP or not for backwards compatibility.
129  */
130 static void set_ncv_prefix(char *prefix)
131 {
132         static char derived_prefix[256];
133         static const char well_known_symbol[] = "get_module_symbol_R";
134         struct module_symbol *s;
135         int i, l, pl;
136         const char *name;
137         char *p;
138 
139         if (ncv_prefix)
140                 return;
141 
142         if (prefix)
143                 ncv_prefix = prefix;
144         else {
145                 /* Extract the prefix (if any) from the well known symbol */
146                 for (i = 0, s = ksyms; i < nksyms; ++i, ++s) {
147                         name = (char *) s->name;
148                         if (strncmp(name, well_known_symbol, sizeof(well_known_symbol)-1) == 0) {
149                                 l = strlen(name);
150                                 pl = l - sizeof(well_known_symbol) - 7;
151                                 if (pl < 0 || pl > sizeof(derived_prefix)-1)
152                                         continue;       /* Prefix is wrong length */
153                                 /* Must end with 8 hex digits */
154                                 (void) strtoul(name+l-8, &p, 16);
155                                 if (*p == 0) {
156                                         strncpy(derived_prefix, name+sizeof(well_known_symbol)-1, pl);
157                                         *(derived_prefix+pl) = '\0';
158                                         ncv_prefix = derived_prefix;
159                                         break;
160                                 }
161                         }
162                 }
163         }
164         if (!ncv_prefix) {
165                 p = strchr(uts_info.version, ' ');
166                 if (p && *(++p) && !strncmp(p, "SMP ", 4))
167                         ncv_prefix = "smp_";
168                 else
169                         ncv_prefix = "";
170         }
171         ncv_plen = strlen(ncv_prefix);
172         if (flag_verbose)
173                 printf("Symbol version prefix '%s'\n", ncv_prefix);
174 }
175 
176 static int ncv_strcmp(const char *a, const char *b)
177 {
178         size_t alen = strlen(a), blen = strlen(b);
179 
180         if (blen == alen + 10 + ncv_plen &&
181             b[alen] == '_' &&
182             b[alen + 1] == 'R' &&
183             !(ncv_plen && strncmp(b + alen + 2, ncv_prefix, ncv_plen))) {
184                 return strncmp(a, b, alen);
185         } else if (alen == blen + 10 + ncv_plen &&
186                    a[blen] == '_' && a[blen + 1] == 'R' &&
187                    !(ncv_plen && strncmp(a + blen + 2, ncv_prefix, ncv_plen))) {
188                 return strncmp(a, b, blen);
189         } else
190                 return strcmp(a, b);
191 }
192 
193 /*
194  * String hashing for non-co-versioned kernel and module.
195  * Here we are simply forced to drop the crc from the hash.
196  */
197 static unsigned long ncv_symbol_hash(const char *str)
198 {
199         size_t len = strlen(str);
200 
201         if (len > 10 + ncv_plen &&
202             str[len - 10 - ncv_plen] == '_' &&
203             str[len - 9 - ncv_plen] == 'R' &&
204             !(
205               ncv_plen &&
206               strncmp(str + len - (8 + ncv_plen), ncv_prefix, ncv_plen)
207              ))
208                 len -= 10 + ncv_plen;
209         return obj_elf_hash_n(str, len);
210 }
211 
212 /*
213  * Conditionally add the symbols from the given symbol set
214  * to the new module.
215  */
216 static int add_symbols_from(struct obj_file *f, int idx,
217                             struct module_symbol *syms, size_t nsyms)
218 {
219         struct module_symbol *s;
220         size_t i;
221         int used = 0;
222 
223         for (i = 0, s = syms; i < nsyms; ++i, ++s) {
224                 /*
225                  * Only add symbols that are already marked external.
226                  * If we override locals we may cause problems for
227                  * argument initialization.
228                  * We will also create a false dependency on the module.
229                  */
230                 struct obj_symbol *sym;
231 
232                 sym = obj_find_symbol(f, (char *) s->name);
233                 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
234                         sym = obj_add_symbol(f, (char *) s->name, -1,
235                                   ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
236                                              idx, s->value, 0);
237                         /*
238                          * Did our symbol just get installed?
239                          * If so, mark the module as "used".
240                          */
241                         if (sym->secidx == idx)
242                                 used = 1;
243                 }
244         }
245 
246         return used;
247 }
248 
249 static void add_kernel_symbols(struct obj_file *f)
250 {
251         struct module_stat *m;
252         size_t i, nused = 0;
253 
254         /* Add module symbols first.  */
255         for (i = 0, m = module_stat; i < n_module_stat; ++i, ++m)
256                 if (m->nsyms &&
257                     add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms))
258                         m->status = 1 /* used */, ++nused;
259         n_ext_modules_used = nused;
260 
261         /* And finally the symbols from the kernel proper.  */
262         if (nksyms)
263                 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
264 }
265 
266 static void hide_special_symbols(struct obj_file *f)
267 {
268         struct obj_symbol *sym;
269         const char *const *p;
270         static const char *const specials[] =
271         {
272                 "cleanup_module",
273                 "init_module",
274                 "kernel_version",
275                 NULL
276         };
277 
278         for (p = specials; *p; ++p)
279                 if ((sym = obj_find_symbol(f, *p)) != NULL)
280                         sym->info = ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
281 }
282 
283 static void print_load_map(struct obj_file *f)
284 {
285         struct obj_symbol *sym;
286         struct obj_symbol **all, **p;
287         struct obj_section *sec;
288         int load_map_cmp(const void *a, const void *b) {
289                 struct obj_symbol **as = (struct obj_symbol **) a;
290                 struct obj_symbol **bs = (struct obj_symbol **) b;
291                 unsigned long aa = obj_symbol_final_value(f, *as);
292                 unsigned long ba = obj_symbol_final_value(f, *bs);
293                  return aa < ba ? -1 : aa > ba ? 1 : 0;
294         }
295         int i, nsyms, *loaded;
296 
297         /* Report on the section layout.  */
298 
299         lprintf("Sections:       Size      %-*s  Align",
300                 (int) (2 * sizeof(void *)), "Address");
301 
302         for (sec = f->load_order; sec; sec = sec->load_next) {
303                 int a;
304                 unsigned long tmp;
305 
306                 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
307                         tmp >>= 1;
308                 if (a == -1)
309                         a = 0;
310 
311                 lprintf("%-16s%08lx  %0*lx  2**%d",
312                         sec->name,
313                         (long)sec->header.sh_size,
314                         (int) (2 * sizeof(void *)),
315                         (long)sec->header.sh_addr,
316                         a);
317         }
318 
319         /* Quick reference which section indicies are loaded.  */
320 
321         loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
322         while (--i >= 0)
323                 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
324 
325         /* Collect the symbols we'll be listing.  */
326 
327         for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
328                 for (sym = f->symtab[i]; sym; sym = sym->next)
329                         if (sym->secidx <= SHN_HIRESERVE
330                             && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
331                                 ++nsyms;
332 
333         all = alloca(nsyms * sizeof(struct obj_symbol *));
334 
335         for (i = 0, p = all; i < HASH_BUCKETS; ++i)
336                 for (sym = f->symtab[i]; sym; sym = sym->next)
337                         if (sym->secidx <= SHN_HIRESERVE
338                             && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
339                                 *p++ = sym;
340 
341         /* Sort them by final value.  */
342         qsort(all, nsyms, sizeof(struct obj_file *), load_map_cmp);
343 
344         /* And list them.  */
345         lprintf("\nSymbols:");
346         for (p = all; p < all + nsyms; ++p) {
347                 char type = '?';
348                 unsigned long value;
349 
350                 sym = *p;
351                 if (sym->secidx == SHN_ABS) {
352                         type = 'A';
353                         value = sym->value;
354                 } else if (sym->secidx == SHN_UNDEF) {
355                         type = 'U';
356                         value = 0;
357                 } else {
358                         struct obj_section *sec = f->sections[sym->secidx];
359 
360                         if (sec->header.sh_type == SHT_NOBITS)
361                                 type = 'B';
362                         else if (sec->header.sh_flags & SHF_ALLOC) {
363                                 if (sec->header.sh_flags & SHF_EXECINSTR)
364                                         type = 'T';
365                                 else if (sec->header.sh_flags & SHF_WRITE)
366                                         type = 'D';
367                                 else
368                                         type = 'R';
369                         }
370                         value = sym->value + sec->header.sh_addr;
371                 }
372 
373                 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
374                         type = tolower(type);
375 
376                 lprintf("%0*lx %c %s", (int) (2 * sizeof(void *)), value,
377                         type, sym->name);
378         }
379 }
380 
381 /************************************************************************/
382 /* begin compat */
383 
384 static char * get_modinfo_value(struct obj_file *f, const char *key)
385 {
386         struct obj_section *sec;
387         char *p, *v, *n, *ep;
388         size_t klen = strlen(key);
389 
390         sec = obj_find_section(f, ".modinfo");
391         if (sec == NULL)
392                 return NULL;
393 
394         p = sec->contents;
395         ep = p + sec->header.sh_size;
396         while (p < ep) {
397                 v = strchr(p, '=');
398                 n = strchr(p, '\0');
399                 if (v) {
400                         if (v - p == klen && strncmp(p, key, klen) == 0)
401                                 return v + 1;
402                 } else {
403                         if (n - p == klen && strcmp(p, key) == 0)
404                                 return n;
405                 }
406                 p = n + 1;
407         }
408 
409         return NULL;
410 }
411 
412 static int create_this_module(struct obj_file *f, const char *m_name)
413 {
414         struct obj_section *sec;
415 
416         sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
417                                                sizeof(struct module));
418         memset(sec->contents, 0, sizeof(struct module));
419 
420         obj_add_symbol(f, "__this_module", -1, ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT),
421                        sec->idx, 0, sizeof(struct module));
422 
423         obj_string_patch(f, sec->idx, offsetof(struct module, name), m_name);
424 
425         return 1;
426 }
427 
428 #ifdef COMPAT_2_0
429 static int old_create_mod_use_count(struct obj_file *f)
430 {
431         struct obj_section *sec;
432         struct obj_symbol  *got;
433 
434         sec = obj_create_alloced_section_first(f, ".moduse",
435                                                sizeof(long), sizeof(long));
436 
437         obj_add_symbol(f, "mod_use_count_",
438                        -1, ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT),
439                        sec->idx, 0, sizeof(long));
440 
441         /*
442          * patb: if there is a _GLOBAL_OFFSET_TABLE_,
443          * add .got section for PIC type modules;
444          * we have to do this here, because obj_* calls are not made until
445          * after obj_check_undefined
446          * is there a better place for this exception?
447          */
448         got = obj_find_symbol(f, "_GLOBAL_OFFSET_TABLE_");
449         if (got)
450 {
451                 sec = obj_create_alloced_section(f, ".got",
452                                                  sizeof(long), sizeof(long));
453                 got->secidx = sec->idx; /* mark the symbol as defined */
454         }
455         return 1;
456 }
457 #endif
458 
459 /* add an entry to the __ksymtab section, creating it if necessary */
460 static void add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
461 {
462         struct obj_section *sec;
463         ElfW(Addr) ofs;
464 
465         /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
466          * If __ksymtab is defined but not marked alloc, x out the first character
467          * (no obj_delete routine) and create a new __ksymtab with the correct
468          * characteristics.
469          */
470         sec = obj_find_section(f, "__ksymtab");
471         if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
472                 *((char *)(sec->name)) = 'x';   /* override const */
473                 sec = NULL;
474         }
475         if (!sec)
476                 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
477         if (!sec)
478                 return;
479         sec->header.sh_flags |= SHF_ALLOC;
480 
481         ofs = sec->header.sh_size;
482         obj_symbol_patch(f, sec->idx, ofs, sym);
483         obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
484         obj_extend_section(sec, 2 * tgt_sizeof_char_p);
485 }
486 
487 static int create_module_ksymtab(struct obj_file *f)
488 {
489         struct obj_section *sec;
490         int i;
491 
492         /* We must always add the module references.  */
493 
494         if (n_ext_modules_used) {
495                 struct module_ref *dep;
496                 struct obj_symbol *tm;
497 
498                 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
499                                            (sizeof(struct module_ref)
500                                             * n_ext_modules_used));
501                 if (!sec)
502                         return 0;
503 
504                 tm = obj_find_symbol(f, "__this_module");
505                 dep = (struct module_ref *) sec->contents;
506                 for (i = 0; i < n_module_stat; ++i)
507                         if (module_stat[i].status /* used */) {
508                                 dep->dep = module_stat[i].addr;
509                                 obj_symbol_patch(f, sec->idx, (char *) &dep->ref - sec->contents, tm);
510                                 dep->next_ref = 0;
511                                 ++dep;
512                         }
513         }
514         if (flag_export && !obj_find_section(f, "__ksymtab")) {
515                 int *loaded;
516 
517                 /* We don't want to export symbols residing in sections that
518                    aren't loaded.  There are a number of these created so that
519                    we make sure certain module options don't appear twice.  */
520 
521                 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
522                 while (--i >= 0)
523                         loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
524 
525                 for (i = 0; i < HASH_BUCKETS; ++i) {
526                         struct obj_symbol *sym;
527                         for (sym = f->symtab[i]; sym; sym = sym->next) {
528                                 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
529                                     && sym->secidx <= SHN_HIRESERVE
530                                     && (sym->secidx >= SHN_LORESERVE
531                                         || loaded[sym->secidx])) {
532                                         add_ksymtab(f, sym);
533                                 }
534                         }
535                 }
536         }
537         return 1;
538 }
539 
540 /* Get the module's kernel version in the canonical integer form.  */
541 static int get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
542 {
543         int a, b, c;
544         char *p, *q;
545 
546         if ((p = get_modinfo_value(f, "kernel_version")) == NULL) {
547                 struct obj_symbol *sym;
548 
549                 m_has_modinfo = 0;
550                 if ((sym = obj_find_symbol(f, "kernel_version")) == NULL)
551                         sym = obj_find_symbol(f, "__module_kernel_version");
552                 if (sym == NULL)
553                         return -1;
554                 p = f->sections[sym->secidx]->contents + sym->value;
555         } else
556                 m_has_modinfo = 1;
557 
558         strncpy(str, p, STRVERSIONLEN);
559 
560         a = strtoul(p, &p, 10);
561         if (*p != '.')
562                 return -1;
563         b = strtoul(p + 1, &p, 10);
564         if (*p != '.')
565                 return -1;
566         c = strtoul(p + 1, &q, 10);
567         if (p + 1 == q)
568                 return -1;
569 
570         return a << 16 | b << 8 | c;
571 }
572 
573 /* Return the kernel symbol checksum version, or zero if not used. */
574 static int is_kernel_checksummed(void)
575 {
576         struct module_symbol *s;
577         size_t i;
578 
579         /*
580          * Using_Versions might not be the first symbol,
581          * but it should be in there.
582          */
583         for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
584                 if (strcmp((char *) s->name, "Using_Versions") == 0)
585                         return s->value;
586 
587         return 0;
588 }
589 
590 static int is_module_checksummed(struct obj_file *f)
591 {
592         if (m_has_modinfo) {
593                 const char *p = get_modinfo_value(f, "using_checksums");
594                 if (p)
595                         return atoi(p);
596                 else
597                         return 0;
598         } else
599                 return obj_find_symbol(f, "Using_Versions") != NULL;
600 }
601 
602 /* add module source, timestamp, kernel version and a symbol for the start of some sections.
603  * this info is used by ksymoops to do better debugging.
604  */
605 static void add_ksymoops_symbols(struct obj_file *f, const char *filename, const char *m_name)
606 {
607         struct obj_section *sec;
608         struct obj_symbol *sym;
609         char *name;
610         char str[STRVERSIONLEN];
611         const char symprefix[] = "__insmod_";
612         int i, l, lm_name, lfilename, use_ksymtab, version;
613         struct stat statbuf;
614 
615         static const char *section_names[] = {
616                 ".text",
617                 ".rodata",
618                 ".data",
619                 ".bss"
620         };
621 
622         lm_name = strlen(m_name);
623         lfilename = strlen(filename);
624 
625         /* add to ksymtab if it already exists or there is no ksymtab and other symbols
626          * are not to be exported.  otherwise leave ksymtab alone for now, the
627          * "export all symbols" compatibility code will export these symbols later.
628          */
629 
630         use_ksymtab =  obj_find_section(f, "__ksymtab") || !flag_export;
631 
632         if ((sec = obj_find_section(f, ".this"))) {
633                 /* tag the module header with the object name, last modified
634                  * timestamp and module version.  worst case for module version
635                  * is 0xffffff, decimal 16777215.  putting all three fields in
636                  * one symbol is less readable but saves kernel space.
637                  */
638                 l = sizeof(symprefix)+                  /* "__insmod_" */
639                     lm_name+                            /* module name */
640                     2+                                  /* "_O" */
641                     lfilename+                          /* object filename */
642                     2+                                  /* "_M" */
643                     2*sizeof(statbuf.st_mtime)+         /* mtime in hex */
644                     2+                                  /* "_V" */
645                     8+                                  /* version in dec */
646                     1;                                  /* nul */
647                 name = xmalloc(l);
648                 if (stat(filename, &statbuf) != 0)
649                         statbuf.st_mtime = 0;
650                 version = get_module_version(f, str);   /* -1 if not found */
651                 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
652                          symprefix, m_name, filename,
653                          2*sizeof(statbuf.st_mtime), statbuf.st_mtime,
654                          version);
655                 sym = obj_add_symbol(f, name, -1,
656                                      ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
657                                      sec->idx, sec->header.sh_addr, 0);
658                 if (use_ksymtab)
659                         add_ksymtab(f, sym);
660         }
661 
662         /* tag the desired sections if size is non-zero */
663 
664         for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
665                 if ((sec = obj_find_section(f, section_names[i])) &&
666                     sec->header.sh_size) {
667                         l = sizeof(symprefix)+          /* "__insmod_" */
668                                 lm_name+                /* module name */
669                                 2+                      /* "_S" */
670                                 strlen(sec->name)+      /* section name */
671                                 2+                      /* "_L" */
672                                 8+                      /* length in dec */
673                                 1;                      /* nul */
674                         name = xmalloc(l);
675                         snprintf(name, l, "%s%s_S%s_L%ld",
676                                  symprefix, m_name, sec->name,
677                                  (long)sec->header.sh_size);
678                         sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
679                                              sec->idx, sec->header.sh_addr, 0);
680                         if (use_ksymtab)
681                                 add_ksymtab(f, sym);
682                 }
683         }
684 }
685 
686 static int process_module_arguments(struct obj_file *f, int argc, char **argv)
687 {
688         for (; argc > 0; ++argv, --argc) {
689                 struct obj_symbol *sym;
690                 int c;
691                 int min, max;
692                 int n;
693                 char *contents;
694                 char *input;
695                 char *fmt;
696                 char *key;
697                 char *loc;
698 
699                 if ((input = strchr(*argv, '=')) == NULL)
700                         continue;
701 
702                 n = input - *argv;
703                 input += 1; /* skip '=' */
704 
705                 key = alloca(n + 6);
706 
707                 if (m_has_modinfo) {
708                         memcpy(key, "parm_", 5);
709                         memcpy(key + 5, *argv, n);
710                         key[n + 5] = '\0';
711                         if ((fmt = get_modinfo_value(f, key)) == NULL) {
712                                 error("invalid parameter %s", key);
713                                 return 0;
714                         }
715                         key += 5;
716 
717                         if (isdigit(*fmt)) {
718                                 min = strtoul(fmt, &fmt, 10);
719                                 if (*fmt == '-')
720                                         max = strtoul(fmt + 1, &fmt, 10);
721                                 else
722                                         max = min;
723                         } else
724                                 min = max = 1;
725                 } else { /* not m_has_modinfo */
726                         memcpy(key, *argv, n);
727                         key[n] = '\0';
728 
729                         if (isdigit(*input))
730                                 fmt = "i";
731                         else
732                                 fmt = "s";
733                         min = max = 0;
734                 }
735 
736                 sym = obj_find_symbol(f, key);
737 
738                 /*
739                  * Also check that the parameter was not
740                  * resolved from the kernel.
741                  */
742                 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
743                         error("symbol for parameter %s not found", key);
744                         return 0;
745                 }
746 
747                 contents = f->sections[sym->secidx]->contents;
748                 loc = contents + sym->value;
749                 n = 1;
750 
751                 while (*input) {
752                         char *str;
753 
754                         switch (*fmt) {
755                         case 's':
756                         case 'c':
757                                 /*
758                                  * Do C quoting if we begin with a ",
759                                  * else slurp the lot.
760                                  */
761                                 if (*input == '"') {
762                                         char *r;
763 
764                                         str = alloca(strlen(input));
765                                         for (r = str, input++; *input != '"'; ++input, ++r) {
766                                                 if (*input == '\0') {
767                                                         error("improperly terminated string argument for %s", key);
768                                                         return 0;
769                                                 }
770                                                 /* else */
771                                                 if (*input != '\\') {
772                                                         *r = *input;
773                                                         continue;
774                                                 }
775                                                 /* else  handle \ */
776                                                 switch (*++input) {
777                                                 case 'a': *r = '\a'; break;
778                                                 case 'b': *r = '\b'; break;
779                                                 case 'e': *r = '\033'; break;
780                                                 case 'f': *r = '\f'; break;
781                                                 case 'n': *r = '\n'; break;
782                                                 case 'r': *r = '\r'; break;
783                                                 case 't': *r = '\t'; break;
784 
785                                                 case '':
786                                                 case '1':
787                                                 case '2':
788                                                 case '3':
789                                                 case '4':
790                                                 case '5':
791                                                 case '6':
792                                                 case '7':
793                                                         c = *input - '';
794                                                         if ('' <= input[1] && input[1] <= '7') {
795                                                                 c = (c * 8) + *++input - '';
796                                                                 if ('' <= input[1] && input[1] <= '7')
797                                                                         c = (c * 8) + *++input - '';
798                                                         }
799                                                         *r = c;
800                                                         break;
801 
802                                                 default: *r = *input; break;
803                                                 }
804                                         }
805                                         *r = '\0';
806                                         ++input;
807                                 } else {
808                                         /*
809                                          * The string is not quoted.
810                                          * We will break it using the comma
811                                          * (like for ints).
812                                          * If the user wants to include commas
813                                          * in a string, he just has to quote it
814                                          */
815                                         char *r;
816 
817                                         /* Search the next comma */
818                                         if ((r = strchr(input, ',')) != NULL) {
819                                                 /*
820                                                  * Found a comma
821                                                  * Recopy the current field
822                                                  */
823                                                 str = alloca(r - input + 1);
824                                                 memcpy(str, input, r - input);
825                                                 str[r - input] = '\0';
826                                                 /* Keep next fields */
827                                                 input = r;
828                                         } else {
829                                                 /* last string */
830                                                 str = input;
831                                                 input = "";
832                                         }
833                                 }
834 
835                                 if (*fmt == 's') {
836                                         /* Normal string */
837                                         obj_string_patch(f, sym->secidx, loc - contents, str);
838                                         loc += tgt_sizeof_char_p;
839                                 } else {
840                                         /* Array of chars (in fact, matrix !) */
841                                         long charssize; /* size of each member */
842 
843                                         /* Get the size of each member */
844                                         /* Probably we should do that outside the loop ? */
845                                         if (!isdigit(*(fmt + 1))) {
846                                                 error("parameter type 'c' for %s must be followed by"
847                                                 " the maximum size", key);
848                                                 return 0;
849                                         }
850                                         charssize = strtoul(fmt + 1, (char **) NULL, 10);
851 
852                                         /* Check length */
853                                         if (strlen(str) >= charssize) {
854                                                 error("string too long for %s (max %ld)",
855                                                       key, charssize - 1);
856                                                 return 0;
857                                         }
858                                         /* Copy to location */
859                                         strcpy((char *) loc, str);
860                                         loc += charssize;
861                                 }
862                                 /*
863                                  * End of 's' and 'c'
864                                  */
865                                 break;
866 
867                         case 'b':
868                                 *loc++ = strtoul(input, &input, 0);
869                                 break;
870 
871                         case 'h':
872                                 *(short *) loc = strtoul(input, &input, 0);
873                                 loc += tgt_sizeof_short;
874                                 break;
875 
876                         case 'i':
877                                 *(int *) loc = strtoul(input, &input, 0);
878                                 loc += tgt_sizeof_int;
879                                 break;
880 
881                         case 'l':
882                                 *(long *) loc = strtoul(input, &input, 0);
883                                 loc += tgt_sizeof_long;
884                                 break;
885 
886                         default:
887                                 error("unknown parameter type '%c' for %s",
888                                       *fmt, key);
889                                 return 0;
890                         }
891                         /*
892                          * end of switch (*fmt)
893                          */
894 
895                         while (*input && isspace(*input))
896                                 ++input;
897                         if (*input == '\0')
898                                 break; /* while (*input) */
899                         /* else */
900 
901                         if (*input == ',') {
902                                 if (max && (++n > max)) {
903                                         error("too many values for %s (max %d)", key, max);
904                                         return 0;
905                                 }
906                                 ++input;
907                                 /* continue with while (*input) */
908                         } else {
909                                 error("invalid argument syntax for %s: '%c'",
910                                       key, *input);
911                                 return 0;
912                         }
913                 } /* end of while (*input) */
914 
915                 if (min && (n < min)) {
916                         error("too few values for %s (min %d)", key, min);
917                         return 0;
918                 }
919         } /* end of for (;argc > 0;) */
920 
921         return 1;
922 }
923 
924 static int init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
925 {
926         struct module *module;
927         struct obj_section *sec;
928         void *image;
929         int ret;
930         tgt_long m_addr;
931 
932         sec = obj_find_section(f, ".this");
933         module = (struct module *) sec->contents;
934         m_addr = sec->header.sh_addr;
935 
936         module->size_of_struct = sizeof(*module);
937         module->size = m_size;
938         module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
939 
940         sec = obj_find_section(f, "__ksymtab");
941         if (sec && sec->header.sh_size) {
942                 module->syms = sec->header.sh_addr;
943                 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
944         }
945         if (n_ext_modules_used) {
946                 sec = obj_find_section(f, ".kmodtab");
947                 module->deps = sec->header.sh_addr;
948                 module->ndeps = n_ext_modules_used;
949         }
950         module->init = obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
951         module->cleanup = obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
952 
953         sec = obj_find_section(f, "__ex_table");
954         if (sec) {
955                 module->ex_table_start = sec->header.sh_addr;
956                 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
957         }
958         sec = obj_find_section(f, ".text.init");
959         if (sec) {
960                 module->runsize = sec->header.sh_addr - m_addr;
961         }
962         sec = obj_find_section(f, ".data.init");
963         if (sec) {
964                 if (!module->runsize ||
965                     module->runsize > sec->header.sh_addr - m_addr)
966                         module->runsize = sec->header.sh_addr - m_addr;
967         }
968         if (!arch_init_module(f, module))
969                 return 0;
970 
971         /*
972          * Whew!  All of the initialization is complete.
973          * Collect the final module image and give it to the kernel.
974          */
975         image = xmalloc(m_size);
976         obj_create_image(f, image);
977 
978         ret = sys_init_module(m_name, (struct module *) image);
979         if (ret) {
980                 error("init_module: %m");
981                 if (ret == -EBUSY)
982                         lprintf("Hint: this error can be caused by incorrect module parameters, "
983                                 "including invalid IO and IRQ parameters\n");
984         }
985 
986         free(image);
987 
988         return ret == 0;
989 }
990 
991 #ifdef COMPAT_2_0
992 static int old_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
993 {
994         char *image;
995         struct old_mod_routines routines;
996         struct old_symbol_table *symtab;
997         int ret;
998         int nsyms = 0, strsize = 0, total;
999 
1000         /* Create the symbol table */
1001         /* Size things first... */
1002         if (flag_export) {
1003                 int i;
1004                 for (i = 0; i < HASH_BUCKETS; ++i) {
1005                         struct obj_symbol *sym;
1006 
1007                         for (sym = f->symtab[i]; sym; sym = sym->next)
1008                                 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL &&
1009                                     sym->secidx <= SHN_HIRESERVE) {
1010                                         sym->ksymidx = nsyms++;
1011                                         strsize += strlen(sym->name) + 1;
1012                                 }
1013                 }
1014         }
1015         total = (sizeof(struct old_symbol_table) +
1016                  nsyms * sizeof(struct old_module_symbol) +
1017                  n_ext_modules_used * sizeof(struct old_module_ref) +
1018                  strsize);
1019         symtab = xmalloc(total);
1020         symtab->size = total;
1021         symtab->n_symbols = nsyms;
1022         symtab->n_refs = n_ext_modules_used;
1023 
1024         if (flag_export && nsyms) {
1025                 struct old_module_symbol *ksym;
1026                 char *str;
1027                 int i;
1028 
1029                 ksym = symtab->symbol;
1030                 str = ((char *) ksym +
1031                        nsyms * sizeof(struct old_module_symbol) +
1032                        n_ext_modules_used * sizeof(struct old_module_ref));
1033 
1034                 for (i = 0; i < HASH_BUCKETS; ++i) {
1035                         struct obj_symbol *sym;
1036                         for (sym = f->symtab[i]; sym; sym = sym->next)
1037                                 if (sym->ksymidx >= 0) {
1038                                         ksym->addr = obj_symbol_final_value(f, sym);
1039                                         ksym->name = (unsigned long) str - (unsigned long) symtab;
1040 
1041                                         str = stpcpy(str, sym->name) + 1;
1042                                         ksym++;
1043                                 }
1044                 }
1045         }
1046 
1047         if (n_ext_modules_used) {
1048                 struct old_module_ref *ref;
1049                 int i;
1050 
1051                 ref = (struct old_module_ref *)
1052                     ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1053 
1054                 for (i = 0; i < n_module_stat; ++i) {
1055                         if (module_stat[i].status /* used */) {
1056                                 ref++->module = module_stat[i].modstruct;
1057                         }
1058                 }
1059         }
1060 
1061         /* Fill in routines.  */
1062 
1063         routines.init = obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1064         routines.cleanup = obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1065 
1066         /*
1067          * Whew!  All of the initialization is complete.
1068          * Collect the final module image and give it to the kernel.
1069          */
1070         image = xmalloc(m_size);
1071         obj_create_image(f, image);
1072 
1073         /*
1074          * image holds the complete relocated module,
1075          * accounting correctly for mod_use_count.
1076          * However the old module kernel support assume that it
1077          * is receiving something which does not contain mod_use_count.
1078          */
1079         ret = old_sys_init_module(m_name, image + sizeof(long),
1080                                   (m_size - sizeof(long)) |
1081                                   (flag_autoclean ? OLD_MOD_AUTOCLEAN : 0),
1082                                   &routines,
1083                                   symtab);
1084         if (ret)
1085                 error("init_module: %m");
1086 
1087         free(image);
1088         free(symtab);
1089 
1090         return ret == 0;
1091 }
1092 #endif
1093 /* end compat */
1094 /************************************************************************/
1095 
1096 
1097 /* For common 3264 code, only compile the usage message once, in the 64 bit version */
1098 #if defined(COMMON_3264) && defined(ONLY_32)
1099 extern void insmod_usage(void);         /* Use the copy in the 64 bit version */
1100 #else   /* Common 64 bit version or any non common code - compile usage routine */
1101 void insmod_usage(void)
1102 {
1103         fputs("Usage:\n"
1104               "insmod [-fkmopsvVxXyY] [-o name] [-P prefix] module [[sym=value]...]\n"
1105 
1106               "\n"
1107               "  module                Filename of a loadable kernel module (*.o)\n"
1108               "  -f, --force           Force loading under wrong kernel version\n"
1109               "  -k, --autoclean       Make module autoclean-able\n"
1110               "  -m, --map             Generate load map (so crashes can be traced)\n"
1111               "  -n, --noload          Don't load, just show\n"
1112               "  -o NAME, --name=NAME  Set internal module name to NAME\n"
1113               "  -p, --poll            Poll mode; check if the module matches the kernel\n"
1114               "  -s, --syslog          Report errors via syslog\n"
1115               "  -v, --verbose         Verbose output\n"
1116               "  -L, --lock            Prevent simultaneous loads of the same module\n"
1117               "  -V, --version         Show version\n"
1118               "  -x                    Do not export externs\n"
1119               "  -X                    Do export externs (default)\n"
1120               "  -y                    Do not add ksymoops symbols\n"
1121               "  -Y                    Do add ksymoops symbols (default)\n"
1122               "  -r                    Allow root to load modules not owned by root\n"
1123               "  -P PREFIX\n"
1124               "      --prefix=PREFIX   Prefix for kernel or module symbols\n"
1125               ,stderr);
1126         exit(1);
1127 }
1128 #endif  /* defined(COMMON_3264) && defined(ONLY_32) */
1129 
1130 #if defined(COMMON_3264) && defined(ONLY_32)
1131 #define INSMOD_MAIN insmod_main_32      /* 32 bit version */
1132 #elif defined(COMMON_3264) && defined(ONLY_64)
1133 #define INSMOD_MAIN insmod_main_64      /* 64 bit version */
1134 #else
1135 #define INSMOD_MAIN insmod_main         /* Not common code */
1136 #endif
1137 
1138 int INSMOD_MAIN(int argc, char **argv)
1139 {
1140         int k_version;
1141         int k_crcs;
1142         char k_strversion[STRVERSIONLEN];
1143         struct option long_opts[] = {
1144                 {"force", 0, 0, 'f'},
1145                 {"autoclean", 0, 0, 'k'},
1146                 {"map", 0, 0, 'm'},
1147                 {"noload", 0, 0, 'n'},
1148                 {"name", 1, 0, 'o'},
1149                 {"poll", 0, 0, 'p'},
1150                 {"syslog", 0, 0, 's'},
1151                 {"verbose", 0, 0, 'v'},
1152                 {"version", 0, 0, 'V'},
1153                 {"lock", 0, 0, 'L'},
1154                 {"prefix", 1, 0, 'P'},
1155                 {"noexport", 0, 0, 'x'},
1156                 {"export", 0, 0, 'X'},
1157                 {"quiet", 0, 0, 'q'},
1158                 {"noksymoops", 0, 0, 'y'},
1159                 {"ksymoops", 0, 0, 'Y'},
1160                 {"root", 0, 0, 'r'},
1161                 {0, 0, 0, 0}
1162         };
1163         char *m_name = NULL;
1164         int m_version;
1165         ElfW(Addr) m_addr;
1166         unsigned long m_size;
1167         int m_crcs;
1168         char m_strversion[STRVERSIONLEN];
1169         char *filename;
1170         FILE *fp;
1171         struct obj_file *f;
1172         int o;
1173         int noload = 0;
1174         int dolock = 1; /*Note: was: 0; */
1175         int quiet = 0;
1176         int exit_status = 1;
1177         int i;
1178 
1179         error_file = "insmod";
1180 
1181         /* To handle repeated calls from combined modprobe */
1182         errors = optind = 0;
1183 
1184         /* Process the command line.  */
1185         while ((o = getopt_long(argc, argv, "fkmno:pqsvVxXLP:yYr",
1186                                 &long_opts[0], NULL)) != EOF)
1187                 switch (o) {
1188                 case 'f':       /* force loading */
1189                         flag_force_load = 1;
1190                         break;
1191                 case 'k':       /* module loaded by kerneld, auto-cleanable */
1192                         flag_autoclean = 1;
1193                         break;
1194                 case 'L':       /* protect against recursion.  */
1195                         dolock = 1;
1196                         break;
1197                 case 'm':       /* generate load map */
1198                         flag_load_map = 1;
1199                         break;
1200                 case 'n':       /* don't load, just check */
1201                         noload = 1;
1202                         break;
1203                 case 'o':       /* name the output module */
1204                         m_name = optarg;
1205                         break;
1206                 case 'p':       /* silent poll mode */
1207                         flag_silent_poll = 1;
1208                         break;
1209                 case 'q':       /* Don't print unresolved symbols */
1210                         quiet = 1;
1211                         break;
1212                 case 's':       /* start syslog */
1213                         setsyslog("insmod");
1214                         break;
1215                 case 'v':       /* verbose output */
1216                         flag_verbose = 1;
1217                         break;
1218                 case 'V':
1219                         fputs("insmod version " MODUTILS_VERSION "\n", stderr);
1220                         break;
1221                 case 'x':       /* do not export externs */
1222                         flag_export = 0;
1223                         break;
1224                 case 'X':       /* do export externs */
1225                         flag_export = 1;
1226                         break;
1227                 case 'y':       /* do not define ksymoops symbols */
1228                         flag_ksymoops = 0;
1229                         break;
1230                 case 'Y':       /* do define ksymoops symbols */
1231                         flag_ksymoops = 1;
1232                         break;
1233                 case 'r':       /* allow root to load non-root modules */
1234                         root_check_off = 1;
1235                         break;
1236                 case 'P':       /* use prefix on crc */
1237                         set_ncv_prefix(optarg);
1238                         break;
1239                 default:
1240                         insmod_usage();
1241                         break;
1242                 }
1243 
1244         if (optind >= argc) {
1245                 insmod_usage();
1246         }
1247         filename = argv[optind++];
1248 
1249         if (config_read(0, NULL, NULL, NULL) < 0) {
1250                 error("Failed handle configuration");
1251         }
1252 
1253         if (m_name == NULL) {
1254                 size_t len;
1255                 char *p;
1256 
1257                 if ((p = strrchr(filename, '/')) != NULL)
1258                         p++;
1259                 else
1260                         p = filename;
1261                 len = strlen(p);
1262                 if (len > 2 && p[len - 2] == '.' && p[len - 1] == 'o')
1263                         len -= 2;
1264                 else if (len > 4 && p[len - 4] == '.' && p[len - 3] == 'm'
1265                          && p[len - 2] == 'o' && p[len - 1] == 'd')
1266                         len -= 4;
1267 
1268                 m_name = xmalloc(len + 1);
1269                 memcpy(m_name, p, len);
1270                 m_name[len] = '\0';
1271         }
1272 
1273         /* Locate the file to be loaded.  */
1274         if (!strchr(filename, '/') && !strchr(filename, '.')) {
1275                 char *tmp = search_module_path(filename);
1276                 if (tmp == NULL) {
1277                         error("%s: no module by that name found", filename);
1278                         return 1;
1279                 }
1280                 filename = tmp;
1281                 printf("Using %s\n", filename);
1282         } else if (flag_verbose)
1283                 printf("Using %s\n", filename);
1284 
1285         /* And open it.  */
1286         if ((fp = fopen(filename, "r")) == NULL) {
1287                 error_file = filename;
1288                 error("%s: %m", filename);
1289                 return 1;
1290         }
1291         /* Try to prevent multiple simultaneous loads.  */
1292         if (dolock)
1293                 flock(fileno(fp), LOCK_EX);
1294 
1295         if (!get_kernel_info(K_SYMBOLS))
1296                 goto out;
1297 
1298         /*
1299          * Set the genksyms prefix if this is a versioned kernel
1300          * and it's not already set.
1301          */
1302         set_ncv_prefix(NULL);
1303 
1304         for (i = 0; i < n_module_stat; ++i) {
1305                 if (strcmp(module_stat[i].name, m_name) == 0) {
1306                         error("a module named %s already exists", m_name);
1307                         goto out;
1308                 }
1309         }
1310 
1311         error_file = filename;
1312         if ((f = obj_load(fp)) == NULL)
1313                 goto out;
1314 
1315         /* Version correspondence?  */
1316         k_version = get_kernel_version(k_strversion);
1317         m_version = get_module_version(f, m_strversion);
1318         if (m_version == -1) {
1319                 error("couldn't find the kernel version the module was compiled for");
1320                 goto out;
1321         }
1322 
1323         k_crcs = is_kernel_checksummed();
1324         m_crcs = is_module_checksummed(f);
1325         if ((m_crcs == 0 || k_crcs == 0) &&
1326             strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
1327                 if (flag_force_load) {
1328                         lprintf("Warning: kernel-module version mismatch\n"
1329                               "\t%s was compiled for kernel version %s\n"
1330                                 "\twhile this kernel is version %s\n",
1331                                 filename, m_strversion, k_strversion);
1332                 } else {
1333                         if (!quiet)
1334                                 error("kernel-module version mismatch\n"
1335                                       "\t%s was compiled for kernel version %s\n"
1336                                       "\twhile this kernel is version %s.",
1337                                       filename, m_strversion, k_strversion);
1338                         goto out;
1339                 }
1340         }
1341         if (m_crcs != k_crcs)
1342                 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
1343 
1344         /* Let the module know about the kernel symbols.  */
1345         add_kernel_symbols(f);
1346 
1347         /* Allocate common symbols, symbol tables, and string tables.  */
1348 #ifdef COMPAT_2_0
1349         if (k_new_syscalls
1350             ? !create_this_module(f, m_name)
1351             : !old_create_mod_use_count(f))
1352                 goto out;
1353 #else
1354         if (!create_this_module(f, m_name))
1355                 goto out;
1356 #endif
1357 
1358         if (!obj_check_undefineds(f, quiet))
1359                 goto out;
1360         obj_allocate_commons(f);
1361 
1362         if (optind < argc) {
1363                 if (!process_module_arguments(f, argc - optind, argv + optind))
1364                         goto out;
1365         }
1366         arch_create_got(f);
1367         hide_special_symbols(f);
1368         if (flag_ksymoops)
1369                 add_ksymoops_symbols(f, filename, m_name);
1370 
1371         if (k_new_syscalls)
1372                 create_module_ksymtab(f);
1373 
1374         if (errors)
1375                 goto out;
1376 
1377         /* If we were just checking, we made it.  */
1378         if (flag_silent_poll) {
1379                 exit_status = 0;
1380                 goto out;
1381         }
1382         /* Module has now finished growing; find its size and install it.  */
1383         m_size = obj_load_size(f);
1384 
1385         if (noload) {
1386                 /* Don't bother actually touching the kernel.  */
1387                 m_addr = 0x12340000;
1388         } else {
1389                 errno = 0;
1390                 m_addr = create_module(m_name, m_size);
1391                 switch (errno) {
1392                 case 0:
1393                         break;
1394                 case EEXIST:
1395                         if (dolock) {
1396                                 /*
1397                                  * Assume that we were just invoked
1398                                  * simultaneous with another insmod
1399                                  * and return success.
1400                                  */
1401                                 exit_status = 0;
1402                                 goto out;
1403                         }
1404                         error("a module named %s already exists", m_name);
1405                         goto out;
1406                 case ENOMEM:
1407                         error("can't allocate kernel memory for module; needed %lu bytes",
1408                               m_size);
1409                         goto out;
1410                 default:
1411                         error("create_module: %m");
1412                         goto out;
1413                 }
1414         }
1415 
1416         if (!obj_relocate(f, m_addr)) {
1417                 if (!noload)
1418                         delete_module(m_name);
1419                 goto out;
1420         }
1421         if (!noload) {
1422 #ifdef COMPAT_2_0
1423                 if (k_new_syscalls)
1424                         init_module(m_name, f, m_size);
1425                 else
1426                         old_init_module(m_name, f, m_size);
1427 #else
1428                 init_module(m_name, f, m_size);
1429 #endif
1430         }
1431         if (errors) {
1432                 if (!noload)
1433                         delete_module(m_name);
1434                 goto out;
1435         }
1436         if (flag_load_map)
1437                 print_load_map(f);
1438         exit_status = 0;
1439 
1440       out:
1441         if (dolock)
1442                 flock(fileno(fp), LOCK_UN);
1443         fclose(fp);
1444         if (!noload)
1445                 snap_shot(NULL, 0);
1446 
1447         return exit_status;
1448 }
1449 
1450 /* For common 3264 code, add an overall insmod_main, in the 64 bit version. */
1451 #if defined(COMMON_3264) && defined(ONLY_64)
1452 int insmod_main(int argc, char **argv)
1453 {
1454         if (arch64())
1455                 return insmod_main_64(argc, argv);
1456         else
1457                 return insmod_main_32(argc, argv);
1458 }
1459 #endif  /* defined(COMMON_3264) && defined(ONLY_64) */
1460 
1461 
1462 /* For common 3264 code, only compile main in the 64 bit version. */
1463 #if defined(COMMON_3264) && defined(ONLY_32)
1464 /* Use the main in the 64 bit version */
1465 #else
1466 /* This mainline looks at the name it was invoked under, checks that the name
1467  * contains exactly one of the possible combined targets and invokes the
1468  * corresponding handler for that function.
1469  */
1470 int main(int argc, char **argv)
1471 {
1472         /* List of possible program names and the corresponding mainline routines */
1473         static struct { char *name; int (*handler)(int, char **); } mains[] =
1474                 {
1475                         { "insmod", &insmod_main },
1476         #ifdef COMBINE_modprobe
1477                         { "modprobe", &modprobe_main },
1478         #endif
1479         #ifdef COMBINE_rmmod
1480                         { "rmmod", &rmmod_main },
1481         #endif
1482         #ifdef COMBINE_ksyms
1483                         { "ksyms", &ksyms_main },
1484         #endif
1485         #ifdef COMBINE_lsmod
1486                         { "lsmod", &lsmod_main },
1487         #endif
1488                 };
1489         #define MAINS_NO (sizeof(mains)/sizeof(mains[0]))
1490         static int mains_match;
1491         static int mains_which;
1492 
1493         char *p = strrchr(argv[0], '/');
1494         char error_id1[2048] = "The ";          /* Way oversized */
1495         char error_id2[2048] = "";              /* Way oversized */
1496         int i;
1497 
1498         p = p ? p + 1 : argv[0];
1499 
1500         for (i = 0; i < MAINS_NO; ++i) {
1501                 if (i) {
1502                         strcat(error_id1, "/");
1503                         if (i == MAINS_NO-1)
1504                                 strcat(error_id2, " or ");
1505                         else
1506                                 strcat(error_id2, ", ");
1507                 }
1508                 strcat(error_id1, mains[i].name);
1509                 strcat(error_id2, mains[i].name);
1510                 if (strstr(p, mains[i].name)) {
1511                         ++mains_match;
1512                         mains_which = i;
1513                 }
1514         }
1515 
1516         /* Finish the error identifiers */
1517         if (MAINS_NO != 1)
1518                 strcat(error_id1, " combined");
1519         strcat(error_id1, " binary");
1520 
1521         if (mains_match == 0 && MAINS_NO == 1)
1522                 ++mains_match;          /* Not combined, any name will do */
1523         if (mains_match == 0) {
1524                 error("%s does not have a recognisable name, the name must contain one of %s.",
1525                         error_id1, error_id2);
1526                 return(1);
1527         }
1528         else if (mains_match > 1) {
1529                 error("%s has an ambiguous name, it must contain %s%s.",
1530                         error_id1, MAINS_NO == 1 ? "" : "exactly one of ", error_id2);
1531                 return(1);
1532         }
1533         else
1534                 return((mains[mains_which].handler)(argc, argv));
1535 }
1536 #endif  /* defined(COMMON_3264) && defined(ONLY_32) */
1537 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.