f6575c97fe77f36c04c71a4e405d400d17401c27
[oweals/busybox.git] / insmod.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini insmod implementation for busybox
4  *
5  * Copyright (C) 1999,2000 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>
7  * and Ron Alder <alder@lineo.com>
8  *
9  * Based almost entirely on the Linux modutils-2.3.11 implementation.
10  *   Copyright 1996, 1997 Linux International.
11  *   New implementation contributed by Richard Henderson <rth@tamu.edu>
12  *   Based on original work by Bjorn Ekwall <bj0rn@blox.se>
13  *   Restructured (and partly rewritten) by:
14  *   Björn Ekwall <bj0rn@blox.se> February 1999
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29  *
30  */
31
32 #include "internal.h"
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <stddef.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <dirent.h>
39 #include <ctype.h>
40 #include <assert.h>
41 #include <sys/utsname.h>
42 #include <sys/syscall.h>
43 #include <linux/unistd.h>
44
45 //----------------------------------------------------------------------------
46 //--------modutils module.h, lines 45-242
47 //----------------------------------------------------------------------------
48
49 /* Definitions for the Linux module syscall interface.
50    Copyright 1996, 1997 Linux International.
51
52    Contributed by Richard Henderson <rth@tamu.edu>
53
54    This file is part of the Linux modutils.
55
56    This program is free software; you can redistribute it and/or modify it
57    under the terms of the GNU General Public License as published by the
58    Free Software Foundation; either version 2 of the License, or (at your
59    option) any later version.
60
61    This program is distributed in the hope that it will be useful, but
62    WITHOUT ANY WARRANTY; without even the implied warranty of
63    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
64    General Public License for more details.
65
66    You should have received a copy of the GNU General Public License
67    along with this program; if not, write to the Free Software Foundation,
68    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
69
70
71 #ifndef MODUTILS_MODULE_H
72 #define MODUTILS_MODULE_H 1
73
74 #ident "$Id: insmod.c,v 1.10 2000/06/22 18:19:31 andersen Exp $"
75
76 /* This file contains the structures used by the 2.0 and 2.1 kernels.
77    We do not use the kernel headers directly because we do not wish
78    to be dependant on a particular kernel version to compile insmod.  */
79
80
81 /*======================================================================*/
82 /* The structures used by Linux 2.0.  */
83
84 /* The symbol format used by get_kernel_syms(2).  */
85 struct old_kernel_sym
86 {
87   unsigned long value;
88   char name[60];
89 };
90
91 struct old_module_ref
92 {
93   unsigned long module;         /* kernel addresses */
94   unsigned long next;
95 };
96
97 struct old_module_symbol
98 {
99   unsigned long addr;
100   unsigned long name;
101 };
102
103 struct old_symbol_table
104 {
105   int size;                     /* total, including string table!!! */
106   int n_symbols;
107   int n_refs;
108   struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
109   struct old_module_ref ref[0]; /* actual size defined by n_refs */
110 };
111
112 struct old_mod_routines
113 {
114   unsigned long init;
115   unsigned long cleanup;
116 };
117
118 struct old_module
119 {
120   unsigned long next;
121   unsigned long ref;            /* the list of modules that refer to me */
122   unsigned long symtab;
123   unsigned long name;
124   int size;                     /* size of module in pages */
125   unsigned long addr;           /* address of module */
126   int state;
127   unsigned long cleanup;        /* cleanup routine */
128 };
129
130 /* Sent to init_module(2) or'ed into the code size parameter.  */
131 #define OLD_MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */
132
133 int get_kernel_syms(struct old_kernel_sym *);
134 int old_sys_init_module(const char *name, char *code, unsigned codesize,
135                         struct old_mod_routines *, struct old_symbol_table *);
136
137 /*======================================================================*/
138 /* For sizeof() which are related to the module platform and not to the
139    environment isnmod is running in, use sizeof_xx instead of sizeof(xx).  */
140
141 #define tgt_sizeof_char         sizeof(char)
142 #define tgt_sizeof_short        sizeof(short)
143 #define tgt_sizeof_int          sizeof(int)
144 #define tgt_sizeof_long         sizeof(long)
145 #define tgt_sizeof_char_p       sizeof(char *)
146 #define tgt_sizeof_void_p       sizeof(void *)
147 #define tgt_long                long
148
149 #if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
150 #undef tgt_sizeof_long
151 #undef tgt_sizeof_char_p
152 #undef tgt_sizeof_void_p
153 #undef tgt_long
154 #define tgt_sizeof_long         8
155 #define tgt_sizeof_char_p       8
156 #define tgt_sizeof_void_p       8
157 #define tgt_long                long long
158 #endif
159
160 /*======================================================================*/
161 /* The structures used in Linux 2.1.  */
162
163 /* Note: new_module_symbol does not use tgt_long intentionally */
164 struct new_module_symbol
165 {
166   unsigned long value;
167   unsigned long name;
168 };
169
170 struct new_module_persist;
171
172 struct new_module_ref
173 {
174   unsigned tgt_long dep;                /* kernel addresses */
175   unsigned tgt_long ref;
176   unsigned tgt_long next_ref;
177 };
178
179 struct new_module
180 {
181   unsigned tgt_long size_of_struct;     /* == sizeof(module) */
182   unsigned tgt_long next;
183   unsigned tgt_long name;
184   unsigned tgt_long size;
185
186   tgt_long usecount;
187   unsigned tgt_long flags;              /* AUTOCLEAN et al */
188
189   unsigned nsyms;
190   unsigned ndeps;
191
192   unsigned tgt_long syms;
193   unsigned tgt_long deps;
194   unsigned tgt_long refs;
195   unsigned tgt_long init;
196   unsigned tgt_long cleanup;
197   unsigned tgt_long ex_table_start;
198   unsigned tgt_long ex_table_end;
199 #ifdef __alpha__
200   unsigned tgt_long gp;
201 #endif
202   /* Everything after here is extension.  */
203   unsigned tgt_long persist_start;
204   unsigned tgt_long persist_end;
205   unsigned tgt_long can_unload;
206   unsigned tgt_long runsize;
207 };
208
209 struct new_module_info
210 {
211   unsigned long addr;
212   unsigned long size;
213   unsigned long flags;
214            long usecount;
215 };
216
217 /* Bits of module.flags.  */
218 #define NEW_MOD_RUNNING         1
219 #define NEW_MOD_DELETED         2
220 #define NEW_MOD_AUTOCLEAN       4
221 #define NEW_MOD_VISITED         8
222 #define NEW_MOD_USED_ONCE       16
223
224 int new_sys_init_module(const char *name, const struct new_module *);
225 int query_module(const char *name, int which, void *buf, size_t bufsize,
226                  size_t *ret);
227
228 /* Values for query_module's which.  */
229
230 #define QM_MODULES      1
231 #define QM_DEPS         2
232 #define QM_REFS         3
233 #define QM_SYMBOLS      4
234 #define QM_INFO         5
235
236 /*======================================================================*/
237 /* The system calls unchanged between 2.0 and 2.1.  */
238
239 unsigned long create_module(const char *, size_t);
240 int delete_module(const char *);
241
242
243 #endif /* module.h */
244
245 //----------------------------------------------------------------------------
246 //--------end of modutils module.h
247 //----------------------------------------------------------------------------
248
249
250
251 //----------------------------------------------------------------------------
252 //--------modutils obj.h, lines 253-462
253 //----------------------------------------------------------------------------
254
255 /* Elf object file loading and relocation routines.
256    Copyright 1996, 1997 Linux International.
257
258    Contributed by Richard Henderson <rth@tamu.edu>
259
260    This file is part of the Linux modutils.
261
262    This program is free software; you can redistribute it and/or modify it
263    under the terms of the GNU General Public License as published by the
264    Free Software Foundation; either version 2 of the License, or (at your
265    option) any later version.
266
267    This program is distributed in the hope that it will be useful, but
268    WITHOUT ANY WARRANTY; without even the implied warranty of
269    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
270    General Public License for more details.
271
272    You should have received a copy of the GNU General Public License
273    along with this program; if not, write to the Free Software Foundation,
274    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
275
276
277 #ifndef MODUTILS_OBJ_H
278 #define MODUTILS_OBJ_H 1
279
280 #ident "$Id: insmod.c,v 1.10 2000/06/22 18:19:31 andersen Exp $"
281
282 /* The relocatable object is manipulated using elfin types.  */
283
284 #include <stdio.h>
285 #include <elf.h>
286
287
288 /* Machine-specific elf macros for i386 et al.  */
289
290 #define ELFCLASSM       ELFCLASS32
291 #define ELFDATAM        ELFDATA2LSB
292
293 #define MATCH_MACHINE(x)  (x == EM_386 || x == EM_486)
294
295 #define SHT_RELM        SHT_REL
296 #define Elf32_RelM      Elf32_Rel
297
298
299 #ifndef ElfW
300 # if ELFCLASSM == ELFCLASS32
301 #  define ElfW(x)  Elf32_ ## x
302 #  define ELFW(x)  ELF32_ ## x
303 # else
304 #  define ElfW(x)  Elf64_ ## x
305 #  define ELFW(x)  ELF64_ ## x
306 # endif
307 #endif
308
309 /* For some reason this is missing from libc5.  */
310 #ifndef ELF32_ST_INFO
311 # define ELF32_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
312 #endif
313
314 #ifndef ELF64_ST_INFO
315 # define ELF64_ST_INFO(bind, type)       (((bind) << 4) + ((type) & 0xf))
316 #endif
317
318 struct obj_string_patch;
319 struct obj_symbol_patch;
320
321 struct obj_section
322 {
323   ElfW(Shdr) header;
324   const char *name;
325   char *contents;
326   struct obj_section *load_next;
327   int idx;
328 };
329
330 struct obj_symbol
331 {
332   struct obj_symbol *next;      /* hash table link */
333   const char *name;
334   unsigned long value;
335   unsigned long size;
336   int secidx;                   /* the defining section index/module */
337   int info;
338   int ksymidx;                  /* for export to the kernel symtab */
339   int referenced;               /* actually used in the link */
340 };
341
342 /* Hardcode the hash table size.  We shouldn't be needing so many
343    symbols that we begin to degrade performance, and we get a big win
344    by giving the compiler a constant divisor.  */
345
346 #define HASH_BUCKETS  521
347
348 struct obj_file
349 {
350   ElfW(Ehdr) header;
351   ElfW(Addr) baseaddr;
352   struct obj_section **sections;
353   struct obj_section *load_order;
354   struct obj_section **load_order_search_start;
355   struct obj_string_patch *string_patches;
356   struct obj_symbol_patch *symbol_patches;
357   int (*symbol_cmp)(const char *, const char *);
358   unsigned long (*symbol_hash)(const char *);
359   unsigned long local_symtab_size;
360   struct obj_symbol **local_symtab;
361   struct obj_symbol *symtab[HASH_BUCKETS];
362 };
363
364 enum obj_reloc
365 {
366   obj_reloc_ok,
367   obj_reloc_overflow,
368   obj_reloc_dangerous,
369   obj_reloc_unhandled
370 };
371
372 struct obj_string_patch
373 {
374   struct obj_string_patch *next;
375   int reloc_secidx;
376   ElfW(Addr) reloc_offset;
377   ElfW(Addr) string_offset;
378 };
379
380 struct obj_symbol_patch
381 {
382   struct obj_symbol_patch *next;
383   int reloc_secidx;
384   ElfW(Addr) reloc_offset;
385   struct obj_symbol *sym;
386 };
387
388
389 /* Generic object manipulation routines.  */
390
391 unsigned long obj_elf_hash(const char *);
392
393 unsigned long obj_elf_hash_n(const char *, unsigned long len);
394
395 struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
396                                    unsigned long symidx, int info, int secidx,
397                                    ElfW(Addr) value, unsigned long size);
398
399 struct obj_symbol *obj_find_symbol (struct obj_file *f,
400                                          const char *name);
401
402 ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
403                                   struct obj_symbol *sym);
404
405 void obj_set_symbol_compare(struct obj_file *f,
406                             int (*cmp)(const char *, const char *),
407                             unsigned long (*hash)(const char *));
408
409 struct obj_section *obj_find_section (struct obj_file *f,
410                                            const char *name);
411
412 void obj_insert_section_load_order (struct obj_file *f,
413                                     struct obj_section *sec);
414
415 struct obj_section *obj_create_alloced_section (struct obj_file *f,
416                                                 const char *name,
417                                                 unsigned long align,
418                                                 unsigned long size);
419
420 struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
421                                                       const char *name,
422                                                       unsigned long align,
423                                                       unsigned long size);
424
425 void *obj_extend_section (struct obj_section *sec, unsigned long more);
426
427 int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
428                      const char *string);
429
430 int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
431                      struct obj_symbol *sym);
432
433 int obj_check_undefineds(struct obj_file *f);
434
435 void obj_allocate_commons(struct obj_file *f);
436
437 unsigned long obj_load_size (struct obj_file *f);
438
439 int obj_relocate (struct obj_file *f, ElfW(Addr) base);
440
441 struct obj_file *obj_load(FILE *f);
442
443 int obj_create_image (struct obj_file *f, char *image);
444
445 /* Architecture specific manipulation routines.  */
446
447 struct obj_file *arch_new_file (void);
448
449 struct obj_section *arch_new_section (void);
450
451 struct obj_symbol *arch_new_symbol (void);
452
453 enum obj_reloc arch_apply_relocation (struct obj_file *f,
454                                       struct obj_section *targsec,
455                                       struct obj_section *symsec,
456                                       struct obj_symbol *sym,
457                                       ElfW(RelM) *rel, ElfW(Addr) value);
458
459 int arch_create_got (struct obj_file *f);
460
461 struct new_module;
462 int arch_init_module (struct obj_file *f, struct new_module *);
463
464 #endif /* obj.h */
465 //----------------------------------------------------------------------------
466 //--------end of modutils obj.h
467 //----------------------------------------------------------------------------
468
469
470
471
472
473 #define _PATH_MODULES   "/lib/modules"
474 #define STRVERSIONLEN   32
475
476 #if !defined(BB_FEATURE_INSMOD_NEW_KERNEL) && !defined(BB_FEATURE_INSMOD_OLD_KERNEL)
477 #error "Must have ether BB_FEATURE_INSMOD_NEW_KERNEL or BB_FEATURE_INSMOD_OLD_KERNEL defined"
478 #endif
479
480 /*======================================================================*/
481
482 int flag_force_load = 0;
483 int flag_autoclean = 0;
484 int flag_verbose = 0;
485 int flag_export = 1;
486
487
488 /*======================================================================*/
489
490 struct i386_got_entry {
491         int offset;
492         unsigned offset_done:1;
493         unsigned reloc_done:1;
494 };
495
496 struct i386_file {
497         struct obj_file root;
498         struct obj_section *got;
499 };
500
501 struct i386_symbol {
502         struct obj_symbol root;
503         struct i386_got_entry gotent;
504 };
505
506
507
508 struct external_module {
509         const char *name;
510         ElfW(Addr) addr;
511         int used;
512         size_t nsyms;
513         struct new_module_symbol *syms;
514 };
515
516 struct new_module_symbol *ksyms;
517 size_t nksyms;
518
519 struct external_module *ext_modules;
520 int n_ext_modules;
521 int n_ext_modules_used;
522
523
524
525 /* Some firendly syscalls to cheer everyone's day...  */
526 #define __NR_new_sys_init_module  __NR_init_module
527 _syscall2(int, new_sys_init_module, const char *, name,
528                   const struct new_module *, info)
529 #define __NR_old_sys_init_module  __NR_init_module
530 _syscall5(int, old_sys_init_module, const char *, name, char *, code,
531                   unsigned, codesize, struct old_mod_routines *, routines,
532                   struct old_symbol_table *, symtab)
533 _syscall5(int, query_module, const char *, name, int, which,
534                 void *, buf, size_t, bufsize, size_t*, ret);
535 #ifndef BB_RMMOD
536 _syscall1(int, delete_module, const char *, name)
537 #else
538 extern int delete_module(const char *);
539 #endif
540
541 #if defined(__i386__) || defined(__m68k__) || defined(__arm__)
542 /* Jump through hoops to fixup error return codes */
543 #define __NR__create_module  __NR_create_module
544 static inline _syscall2(long, _create_module, const char *, name, size_t,
545                                                 size)
546 unsigned long create_module(const char *name, size_t size)
547 {
548         long ret = _create_module(name, size);
549
550         if (ret == -1 && errno > 125) {
551                 ret = -errno;
552                 errno = 0;
553         }
554         return ret;
555 }
556 #else
557 _syscall2(unsigned long, create_module, const char *, name, size_t, size)
558 #endif
559 static char m_filename[BUFSIZ + 1] = "\0";
560 static char m_fullName[BUFSIZ + 1] = "\0";
561 static const char insmod_usage[] =
562         "insmod [OPTION]... MODULE [symbol=value]...\n"
563 #ifndef BB_FEATURE_TRIVIAL_HELP
564         "\nLoads the specified kernel modules into the kernel.\n\n"
565         "Options:\n"
566         "\t-f\tForce module to load into the wrong kernel version.\n"
567         "\t-k\tMake module autoclean-able.\n"
568         "\t-v\tverbose output\n" "\t-x\tdo not export externs\n"
569 #endif
570 ;
571
572 /*======================================================================*/
573
574 void *xrealloc(void *old, size_t size)
575 {
576         void *ptr = realloc(old, size);
577         if (!ptr) {
578                 perror("Out of memory");
579                 exit(1);
580         }
581         return ptr;
582 }
583
584
585 static int findNamedModule(const char *fileName, struct stat *statbuf,
586                                                    void *userDate)
587 {
588         char *fullName = (char *) userDate;
589
590
591         if (fullName[0] == '\0')
592                 return (FALSE);
593         else {
594                 char *tmp = strrchr(fileName, '/');
595
596                 if (tmp == NULL)
597                         tmp = (char *) fileName;
598                 else
599                         tmp++;
600                 if (check_wildcard_match(tmp, fullName) == TRUE) {
601                         /* Stop searching if we find a match */
602                         memcpy(m_filename, fileName, strlen(fileName));
603                         return (FALSE);
604                 }
605         }
606         return (TRUE);
607 }
608
609
610 /*======================================================================*/
611
612 struct obj_file *arch_new_file(void)
613 {
614         struct i386_file *f;
615         f = xmalloc(sizeof(*f));
616         f->got = NULL;
617         return &f->root;
618 }
619
620 struct obj_section *arch_new_section(void)
621 {
622         return xmalloc(sizeof(struct obj_section));
623 }
624
625 struct obj_symbol *arch_new_symbol(void)
626 {
627         struct i386_symbol *sym;
628         sym = xmalloc(sizeof(*sym));
629         memset(&sym->gotent, 0, sizeof(sym->gotent));
630         return &sym->root;
631 }
632 enum obj_reloc
633 arch_apply_relocation(struct obj_file *f,
634                                           struct obj_section *targsec,
635                                           struct obj_section *symsec,
636                                           struct obj_symbol *sym,
637                                           Elf32_Rel * rel, Elf32_Addr v)
638 {
639         struct i386_file *ifile = (struct i386_file *) f;
640         struct i386_symbol *isym = (struct i386_symbol *) sym;
641
642         Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset);
643         Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
644         Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
645
646         enum obj_reloc ret = obj_reloc_ok;
647
648         switch (ELF32_R_TYPE(rel->r_info)) {
649         case R_386_NONE:
650                 break;
651
652         case R_386_32:
653                 *loc += v;
654                 break;
655
656         case R_386_PLT32:
657         case R_386_PC32:
658                 *loc += v - dot;
659                 break;
660
661         case R_386_GLOB_DAT:
662         case R_386_JMP_SLOT:
663                 *loc = v;
664                 break;
665
666         case R_386_RELATIVE:
667                 *loc += f->baseaddr;
668                 break;
669
670         case R_386_GOTPC:
671                 assert(got != 0);
672                 *loc += got - dot;
673                 break;
674
675         case R_386_GOT32:
676                 assert(isym != NULL);
677                 if (!isym->gotent.reloc_done) {
678                         isym->gotent.reloc_done = 1;
679                         *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
680                                 v;
681                 }
682                 *loc += isym->gotent.offset;
683                 break;
684
685         case R_386_GOTOFF:
686                 assert(got != 0);
687                 *loc += v - got;
688                 break;
689
690         default:
691                 ret = obj_reloc_unhandled;
692                 break;
693         }
694
695         return ret;
696 }
697
698 int arch_create_got(struct obj_file *f)
699 {
700         struct i386_file *ifile = (struct i386_file *) f;
701         int i, n, offset = 0, gotneeded = 0;
702
703         n = ifile->root.header.e_shnum;
704         for (i = 0; i < n; ++i) {
705                 struct obj_section *relsec, *symsec, *strsec;
706                 Elf32_Rel *rel, *relend;
707                 Elf32_Sym *symtab;
708                 const char *strtab;
709
710                 relsec = ifile->root.sections[i];
711                 if (relsec->header.sh_type != SHT_REL)
712                         continue;
713
714                 symsec = ifile->root.sections[relsec->header.sh_link];
715                 strsec = ifile->root.sections[symsec->header.sh_link];
716
717                 rel = (Elf32_Rel *) relsec->contents;
718                 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
719                 symtab = (Elf32_Sym *) symsec->contents;
720                 strtab = (const char *) strsec->contents;
721
722                 for (; rel < relend; ++rel) {
723                         Elf32_Sym *extsym;
724                         struct i386_symbol *intsym;
725                         const char *name;
726
727                         switch (ELF32_R_TYPE(rel->r_info)) {
728                         case R_386_GOTPC:
729                         case R_386_GOTOFF:
730                                 gotneeded = 1;
731                         default:
732                                 continue;
733
734                         case R_386_GOT32:
735                                 break;
736                         }
737
738                         extsym = &symtab[ELF32_R_SYM(rel->r_info)];
739                         if (extsym->st_name)
740                                 name = strtab + extsym->st_name;
741                         else
742                                 name = f->sections[extsym->st_shndx]->name;
743                         intsym =
744                                 (struct i386_symbol *) obj_find_symbol(&ifile->root, name);
745
746                         if (!intsym->gotent.offset_done) {
747                                 intsym->gotent.offset_done = 1;
748                                 intsym->gotent.offset = offset;
749                                 offset += 4;
750                         }
751                 }
752         }
753
754         if (offset > 0 || gotneeded)
755                 ifile->got =
756                         obj_create_alloced_section(&ifile->root, ".got", 4, offset);
757
758         return 1;
759 }
760
761 int arch_init_module(struct obj_file *f, struct new_module *mod)
762 {
763         return 1;
764 }
765
766
767 /*======================================================================*/
768
769 /* Standard ELF hash function.  */
770 inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
771 {
772         unsigned long h = 0;
773         unsigned long g;
774         unsigned char ch;
775
776         while (n > 0) {
777                 ch = *name++;
778                 h = (h << 4) + ch;
779                 if ((g = (h & 0xf0000000)) != 0) {
780                         h ^= g >> 24;
781                         h &= ~g;
782                 }
783                 n--;
784         }
785         return h;
786 }
787
788 unsigned long obj_elf_hash(const char *name)
789 {
790         return obj_elf_hash_n(name, strlen(name));
791 }
792
793 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
794 /* Get the kernel version in the canonical integer form.  */
795
796 static int get_kernel_version(char str[STRVERSIONLEN])
797 {
798         struct utsname uts_info;
799         char *p, *q;
800         int a, b, c;
801
802         if (uname(&uts_info) < 0)
803                 return -1;
804         strncpy(str, uts_info.release, STRVERSIONLEN);
805         p = uts_info.release;
806
807         a = strtoul(p, &p, 10);
808         if (*p != '.')
809                 return -1;
810         b = strtoul(p + 1, &p, 10);
811         if (*p != '.')
812                 return -1;
813         c = strtoul(p + 1, &q, 10);
814         if (p + 1 == q)
815                 return -1;
816
817         return a << 16 | b << 8 | c;
818 }
819
820 /* String comparison for non-co-versioned kernel and module.  */
821
822 static int ncv_strcmp(const char *a, const char *b)
823 {
824         size_t alen = strlen(a), blen = strlen(b);
825
826         if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
827                 return strncmp(a, b, alen);
828         else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
829                 return strncmp(a, b, blen);
830         else
831                 return strcmp(a, b);
832 }
833
834 /* String hashing for non-co-versioned kernel and module.  Here
835    we are simply forced to drop the crc from the hash.  */
836
837 static unsigned long ncv_symbol_hash(const char *str)
838 {
839         size_t len = strlen(str);
840         if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
841                 len -= 10;
842         return obj_elf_hash_n(str, len);
843 }
844
845 void
846 obj_set_symbol_compare(struct obj_file *f,
847                                            int (*cmp) (const char *, const char *),
848                                            unsigned long (*hash) (const char *))
849 {
850         if (cmp)
851                 f->symbol_cmp = cmp;
852         if (hash) {
853                 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
854                 int i;
855
856                 f->symbol_hash = hash;
857
858                 memcpy(tmptab, f->symtab, sizeof(tmptab));
859                 memset(f->symtab, 0, sizeof(f->symtab));
860
861                 for (i = 0; i < HASH_BUCKETS; ++i)
862                         for (sym = tmptab[i]; sym; sym = next) {
863                                 unsigned long h = hash(sym->name) % HASH_BUCKETS;
864                                 next = sym->next;
865                                 sym->next = f->symtab[h];
866                                 f->symtab[h] = sym;
867                         }
868         }
869 }
870
871 #endif                                                  /* BB_FEATURE_INSMOD_VERSION_CHECKING */
872
873
874 struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
875                                                                   unsigned long symidx, int info,
876                                                                   int secidx, ElfW(Addr) value,
877                                                                   unsigned long size)
878 {
879         struct obj_symbol *sym;
880         unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
881         int n_type = ELFW(ST_TYPE) (info);
882         int n_binding = ELFW(ST_BIND) (info);
883
884         for (sym = f->symtab[hash]; sym; sym = sym->next)
885                 if (f->symbol_cmp(sym->name, name) == 0) {
886                         int o_secidx = sym->secidx;
887                         int o_info = sym->info;
888                         int o_type = ELFW(ST_TYPE) (o_info);
889                         int o_binding = ELFW(ST_BIND) (o_info);
890
891                         /* A redefinition!  Is it legal?  */
892
893                         if (secidx == SHN_UNDEF)
894                                 return sym;
895                         else if (o_secidx == SHN_UNDEF)
896                                 goto found;
897                         else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
898                                 /* Cope with local and global symbols of the same name
899                                    in the same object file, as might have been created
900                                    by ld -r.  The only reason locals are now seen at this
901                                    level at all is so that we can do semi-sensible things
902                                    with parameters.  */
903
904                                 struct obj_symbol *nsym, **p;
905
906                                 nsym = arch_new_symbol();
907                                 nsym->next = sym->next;
908                                 nsym->ksymidx = -1;
909
910                                 /* Excise the old (local) symbol from the hash chain.  */
911                                 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
912                                         continue;
913                                 *p = sym = nsym;
914                                 goto found;
915                         } else if (n_binding == STB_LOCAL) {
916                                 /* Another symbol of the same name has already been defined.
917                                    Just add this to the local table.  */
918                                 sym = arch_new_symbol();
919                                 sym->next = NULL;
920                                 sym->ksymidx = -1;
921                                 f->local_symtab[symidx] = sym;
922                                 goto found;
923                         } else if (n_binding == STB_WEAK)
924                                 return sym;
925                         else if (o_binding == STB_WEAK)
926                                 goto found;
927                         /* Don't unify COMMON symbols with object types the programmer
928                            doesn't expect.  */
929                         else if (secidx == SHN_COMMON
930                                          && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
931                                 return sym;
932                         else if (o_secidx == SHN_COMMON
933                                          && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
934                                 goto found;
935                         else {
936                                 /* Don't report an error if the symbol is coming from
937                                    the kernel or some external module.  */
938                                 if (secidx <= SHN_HIRESERVE)
939                                         fprintf(stderr, "%s multiply defined\n", name);
940                                 return sym;
941                         }
942                 }
943
944         /* Completely new symbol.  */
945         sym = arch_new_symbol();
946         sym->next = f->symtab[hash];
947         f->symtab[hash] = sym;
948         sym->ksymidx = -1;
949
950         if (ELFW(ST_BIND) (info) == STB_LOCAL)
951                 f->local_symtab[symidx] = sym;
952
953   found:
954         sym->name = name;
955         sym->value = value;
956         sym->size = size;
957         sym->secidx = secidx;
958         sym->info = info;
959
960         return sym;
961 }
962
963 struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
964 {
965         struct obj_symbol *sym;
966         unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
967
968         for (sym = f->symtab[hash]; sym; sym = sym->next)
969                 if (f->symbol_cmp(sym->name, name) == 0)
970                         return sym;
971
972         return NULL;
973 }
974
975 ElfW(Addr)
976         obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
977 {
978         if (sym) {
979                 if (sym->secidx >= SHN_LORESERVE)
980                         return sym->value;
981
982                 return sym->value + f->sections[sym->secidx]->header.sh_addr;
983         } else {
984                 /* As a special case, a NULL sym has value zero.  */
985                 return 0;
986         }
987 }
988
989 struct obj_section *obj_find_section(struct obj_file *f, const char *name)
990 {
991         int i, n = f->header.e_shnum;
992
993         for (i = 0; i < n; ++i)
994                 if (strcmp(f->sections[i]->name, name) == 0)
995                         return f->sections[i];
996
997         return NULL;
998 }
999
1000 static int obj_load_order_prio(struct obj_section *a)
1001 {
1002         unsigned long af, ac;
1003
1004         af = a->header.sh_flags;
1005
1006         ac = 0;
1007         if (a->name[0] != '.' || strlen(a->name) != 10 ||
1008                 strcmp(a->name + 5, ".init"))
1009                 ac |= 32;
1010         if (af & SHF_ALLOC)
1011                 ac |= 16;
1012         if (!(af & SHF_WRITE))
1013                 ac |= 8;
1014         if (af & SHF_EXECINSTR)
1015                 ac |= 4;
1016         if (a->header.sh_type != SHT_NOBITS)
1017                 ac |= 2;
1018
1019         return ac;
1020 }
1021
1022 void
1023 obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1024 {
1025         struct obj_section **p;
1026         int prio = obj_load_order_prio(sec);
1027         for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1028                 if (obj_load_order_prio(*p) < prio)
1029                         break;
1030         sec->load_next = *p;
1031         *p = sec;
1032 }
1033
1034 struct obj_section *obj_create_alloced_section(struct obj_file *f,
1035                                                                                            const char *name,
1036                                                                                            unsigned long align,
1037                                                                                            unsigned long size)
1038 {
1039         int newidx = f->header.e_shnum++;
1040         struct obj_section *sec;
1041
1042         f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1043         f->sections[newidx] = sec = arch_new_section();
1044
1045         memset(sec, 0, sizeof(*sec));
1046         sec->header.sh_type = SHT_PROGBITS;
1047         sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1048         sec->header.sh_size = size;
1049         sec->header.sh_addralign = align;
1050         sec->name = name;
1051         sec->idx = newidx;
1052         if (size)
1053                 sec->contents = xmalloc(size);
1054
1055         obj_insert_section_load_order(f, sec);
1056
1057         return sec;
1058 }
1059
1060 struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1061                                                                                                          const char *name,
1062                                                                                                          unsigned long align,
1063                                                                                                          unsigned long size)
1064 {
1065         int newidx = f->header.e_shnum++;
1066         struct obj_section *sec;
1067
1068         f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1069         f->sections[newidx] = sec = arch_new_section();
1070
1071         memset(sec, 0, sizeof(*sec));
1072         sec->header.sh_type = SHT_PROGBITS;
1073         sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1074         sec->header.sh_size = size;
1075         sec->header.sh_addralign = align;
1076         sec->name = name;
1077         sec->idx = newidx;
1078         if (size)
1079                 sec->contents = xmalloc(size);
1080
1081         sec->load_next = f->load_order;
1082         f->load_order = sec;
1083         if (f->load_order_search_start == &f->load_order)
1084                 f->load_order_search_start = &sec->load_next;
1085
1086         return sec;
1087 }
1088
1089 void *obj_extend_section(struct obj_section *sec, unsigned long more)
1090 {
1091         unsigned long oldsize = sec->header.sh_size;
1092         sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1093         return sec->contents + oldsize;
1094 }
1095
1096
1097
1098 /* Conditionally add the symbols from the given symbol set to the
1099    new module.  */
1100
1101 static int
1102 add_symbols_from(
1103                                  struct obj_file *f,
1104                                  int idx, struct new_module_symbol *syms, size_t nsyms)
1105 {
1106         struct new_module_symbol *s;
1107         size_t i;
1108         int used = 0;
1109
1110         for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1111
1112                 /* Only add symbols that are already marked external.  If we
1113                    override locals we may cause problems for argument initialization.
1114                    We will also create a false dependency on the module.  */
1115                 struct obj_symbol *sym;
1116
1117                 sym = obj_find_symbol(f, (char *) s->name);
1118                 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1119                         sym = obj_add_symbol(f, (char *) s->name, -1,
1120                                                                  ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1121                                                                  idx, s->value, 0);
1122                         /* Did our symbol just get installed?  If so, mark the
1123                            module as "used".  */
1124                         if (sym->secidx == idx)
1125                                 used = 1;
1126                 }
1127         }
1128
1129         return used;
1130 }
1131
1132 static void add_kernel_symbols(struct obj_file *f)
1133 {
1134         struct external_module *m;
1135         size_t i, nused = 0;
1136
1137         /* Add module symbols first.  */
1138
1139         for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1140                 if (m->nsyms
1141                         && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1142                                                                 m->nsyms)) m->used = 1, ++nused;
1143
1144         n_ext_modules_used = nused;
1145
1146         /* And finally the symbols from the kernel proper.  */
1147
1148         if (nksyms)
1149                 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1150 }
1151
1152 static char *get_modinfo_value(struct obj_file *f, const char *key)
1153 {
1154         struct obj_section *sec;
1155         char *p, *v, *n, *ep;
1156         size_t klen = strlen(key);
1157
1158         sec = obj_find_section(f, ".modinfo");
1159         if (sec == NULL)
1160                 return NULL;
1161         p = sec->contents;
1162         ep = p + sec->header.sh_size;
1163         while (p < ep) {
1164                 v = strchr(p, '=');
1165                 n = strchr(p, '\0');
1166                 if (v) {
1167                         if (v - p == klen && strncmp(p, key, klen) == 0)
1168                                 return v + 1;
1169                 } else {
1170                         if (n - p == klen && strcmp(p, key) == 0)
1171                                 return n;
1172                 }
1173                 p = n + 1;
1174         }
1175
1176         return NULL;
1177 }
1178
1179
1180 /*======================================================================*/
1181 /* Functions relating to module loading in pre 2.1 kernels.  */
1182
1183 static int
1184 old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1185 {
1186         while (argc > 0) {
1187                 char *p, *q;
1188                 struct obj_symbol *sym;
1189                 int *loc;
1190
1191                 p = *argv;
1192                 if ((q = strchr(p, '=')) == NULL)
1193                         continue;
1194                 *q++ = '\0';
1195
1196                 sym = obj_find_symbol(f, p);
1197
1198                 /* Also check that the parameter was not resolved from the kernel.  */
1199                 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
1200                         fprintf(stderr, "symbol for parameter %s not found\n", p);
1201                         return 0;
1202                 }
1203
1204                 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1205
1206                 /* Do C quoting if we begin with a ".  */
1207                 if (*q == '"') {
1208                         char *r, *str;
1209
1210                         str = alloca(strlen(q));
1211                         for (r = str, q++; *q != '"'; ++q, ++r) {
1212                                 if (*q == '\0') {
1213                                         fprintf(stderr, "improperly terminated string argument for %s\n", p);
1214                                         return 0;
1215                                 } else if (*q == '\\')
1216                                         switch (*++q) {
1217                                         case 'a':
1218                                                 *r = '\a';
1219                                                 break;
1220                                         case 'b':
1221                                                 *r = '\b';
1222                                                 break;
1223                                         case 'e':
1224                                                 *r = '\033';
1225                                                 break;
1226                                         case 'f':
1227                                                 *r = '\f';
1228                                                 break;
1229                                         case 'n':
1230                                                 *r = '\n';
1231                                                 break;
1232                                         case 'r':
1233                                                 *r = '\r';
1234                                                 break;
1235                                         case 't':
1236                                                 *r = '\t';
1237                                                 break;
1238
1239                                         case '0':
1240                                         case '1':
1241                                         case '2':
1242                                         case '3':
1243                                         case '4':
1244                                         case '5':
1245                                         case '6':
1246                                         case '7':
1247                                                 {
1248                                                         int c = *q - '0';
1249                                                         if (q[1] >= '0' && q[1] <= '7') {
1250                                                                 c = (c * 8) + *++q - '0';
1251                                                                 if (q[1] >= '0' && q[1] <= '7')
1252                                                                         c = (c * 8) + *++q - '0';
1253                                                         }
1254                                                         *r = c;
1255                                                 }
1256                                                 break;
1257
1258                                         default:
1259                                                 *r = *q;
1260                                                 break;
1261                                 } else
1262                                         *r = *q;
1263                         }
1264                         *r = '\0';
1265                         obj_string_patch(f, sym->secidx, sym->value, str);
1266                 } else if (*q >= '0' && *q <= '9') {
1267                         do
1268                                 *loc++ = strtoul(q, &q, 0);
1269                         while (*q++ == ',');
1270                 } else {
1271                         char *contents = f->sections[sym->secidx]->contents;
1272                         char *loc = contents + sym->value;
1273                         char *r;                        /* To search for commas */
1274
1275                         /* Break the string with comas */
1276                         while ((r = strchr(q, ',')) != (char *) NULL) {
1277                                 *r++ = '\0';
1278                                 obj_string_patch(f, sym->secidx, loc - contents, q);
1279                                 loc += sizeof(char *);
1280                                 q = r;
1281                         }
1282
1283                         /* last part */
1284                         obj_string_patch(f, sym->secidx, loc - contents, q);
1285                 }
1286
1287                 argc--, argv++;
1288         }
1289
1290         return 1;
1291 }
1292
1293 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1294 static int old_is_module_checksummed(struct obj_file *f)
1295 {
1296         return obj_find_symbol(f, "Using_Versions") != NULL;
1297 }
1298 /* Get the module's kernel version in the canonical integer form.  */
1299
1300 static int
1301 old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1302 {
1303         struct obj_symbol *sym;
1304         char *p, *q;
1305         int a, b, c;
1306
1307         sym = obj_find_symbol(f, "kernel_version");
1308         if (sym == NULL)
1309                 return -1;
1310
1311         p = f->sections[sym->secidx]->contents + sym->value;
1312         strncpy(str, p, STRVERSIONLEN);
1313
1314         a = strtoul(p, &p, 10);
1315         if (*p != '.')
1316                 return -1;
1317         b = strtoul(p + 1, &p, 10);
1318         if (*p != '.')
1319                 return -1;
1320         c = strtoul(p + 1, &q, 10);
1321         if (p + 1 == q)
1322                 return -1;
1323
1324         return a << 16 | b << 8 | c;
1325 }
1326
1327 #endif   /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1328
1329 #ifdef BB_FEATURE_INSMOD_OLD_KERNEL
1330
1331 /* Fetch all the symbols and divvy them up as appropriate for the modules.  */
1332
1333 static int old_get_kernel_symbols(void)
1334 {
1335         struct old_kernel_sym *ks, *k;
1336         struct new_module_symbol *s;
1337         struct external_module *mod;
1338         int nks, nms, nmod, i;
1339
1340         nks = get_kernel_syms(NULL);
1341         if (nks < 0) {
1342                 errorMsg("get_kernel_syms: %s: %s", m_name, strerror(errno));
1343                 return 0;
1344         }
1345
1346         ks = k = xmalloc(nks * sizeof(*ks));
1347
1348         if (get_kernel_syms(ks) != nks) {
1349                 perror("inconsistency with get_kernel_syms -- is someone else "
1350                            "playing with modules?");
1351                 free(ks);
1352                 return 0;
1353         }
1354
1355         /* Collect the module information.  */
1356
1357         mod = NULL;
1358         nmod = -1;
1359
1360         while (k->name[0] == '#' && k->name[1]) {
1361                 struct old_kernel_sym *k2;
1362                 struct new_module_symbol *s;
1363
1364                 /* Find out how many symbols this module has.  */
1365                 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1366                         continue;
1367                 nms = k2 - k - 1;
1368
1369                 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1370                 mod[nmod].name = k->name + 1;
1371                 mod[nmod].addr = k->value;
1372                 mod[nmod].used = 0;
1373                 mod[nmod].nsyms = nms;
1374                 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1375
1376                 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1377                         s->name = (unsigned long) k->name;
1378                         s->value = k->value;
1379                 }
1380
1381                 k = k2;
1382         }
1383
1384         ext_modules = mod;
1385         n_ext_modules = nmod + 1;
1386
1387         /* Now collect the symbols for the kernel proper.  */
1388
1389         if (k->name[0] == '#')
1390                 ++k;
1391
1392         nksyms = nms = nks - (k - ks);
1393         ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1394
1395         for (i = 0; i < nms; ++i, ++s, ++k) {
1396                 s->name = (unsigned long) k->name;
1397                 s->value = k->value;
1398         }
1399
1400         return 1;
1401 }
1402
1403 /* Return the kernel symbol checksum version, or zero if not used.  */
1404
1405 static int old_is_kernel_checksummed(void)
1406 {
1407         /* Using_Versions is the first symbol.  */
1408         if (nksyms > 0
1409                 && strcmp((char *) ksyms[0].name,
1410                                   "Using_Versions") == 0) return ksyms[0].value;
1411         else
1412                 return 0;
1413 }
1414
1415
1416 static int old_create_mod_use_count(struct obj_file *f)
1417 {
1418         struct obj_section *sec;
1419
1420         sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1421                                                                                    sizeof(long));
1422
1423         obj_add_symbol(f, "mod_use_count_", -1,
1424                                    ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1425                                    sizeof(long));
1426
1427         return 1;
1428 }
1429
1430 static int
1431 old_init_module(const char *m_name, struct obj_file *f,
1432                                 unsigned long m_size)
1433 {
1434         char *image;
1435         struct old_mod_routines routines;
1436         struct old_symbol_table *symtab;
1437         int ret;
1438
1439         /* Create the symbol table */
1440         {
1441                 int nsyms = 0, strsize = 0, total;
1442
1443                 /* Size things first... */
1444                 if (flag_export) {
1445                         int i;
1446                         for (i = 0; i < HASH_BUCKETS; ++i) {
1447                                 struct obj_symbol *sym;
1448                                 for (sym = f->symtab[i]; sym; sym = sym->next)
1449                                         if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1450                                                 && sym->secidx <= SHN_HIRESERVE) 
1451                                         {
1452                                                 sym->ksymidx = nsyms++;
1453                                                 strsize += strlen(sym->name) + 1;
1454                                         }
1455                         }
1456                 }
1457
1458                 total = (sizeof(struct old_symbol_table)
1459                                  + nsyms * sizeof(struct old_module_symbol)
1460                                  + n_ext_modules_used * sizeof(struct old_module_ref)
1461                                  + strsize);
1462                 symtab = xmalloc(total);
1463                 symtab->size = total;
1464                 symtab->n_symbols = nsyms;
1465                 symtab->n_refs = n_ext_modules_used;
1466
1467                 if (flag_export && nsyms) {
1468                         struct old_module_symbol *ksym;
1469                         char *str;
1470                         int i;
1471
1472                         ksym = symtab->symbol;
1473                         str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1474                                    + n_ext_modules_used * sizeof(struct old_module_ref));
1475
1476                         for (i = 0; i < HASH_BUCKETS; ++i) {
1477                                 struct obj_symbol *sym;
1478                                 for (sym = f->symtab[i]; sym; sym = sym->next)
1479                                         if (sym->ksymidx >= 0) {
1480                                                 ksym->addr = obj_symbol_final_value(f, sym);
1481                                                 ksym->name =
1482                                                         (unsigned long) str - (unsigned long) symtab;
1483
1484                                                 str = stpcpy(str, sym->name) + 1;
1485                                                 ksym++;
1486                                         }
1487                         }
1488                 }
1489
1490                 if (n_ext_modules_used) {
1491                         struct old_module_ref *ref;
1492                         int i;
1493
1494                         ref = (struct old_module_ref *)
1495                                 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1496
1497                         for (i = 0; i < n_ext_modules; ++i)
1498                                 if (ext_modules[i].used)
1499                                         ref++->module = ext_modules[i].addr;
1500                 }
1501         }
1502
1503         /* Fill in routines.  */
1504
1505         routines.init =
1506                 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1507         routines.cleanup =
1508                 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1509
1510         /* Whew!  All of the initialization is complete.  Collect the final
1511            module image and give it to the kernel.  */
1512
1513         image = xmalloc(m_size);
1514         obj_create_image(f, image);
1515
1516         /* image holds the complete relocated module, accounting correctly for
1517            mod_use_count.  However the old module kernel support assume that
1518            it is receiving something which does not contain mod_use_count.  */
1519         ret = old_sys_init_module(m_name, image + sizeof(long),
1520                                                           m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1521                                                                                 : 0), &routines, symtab);
1522         if (ret)
1523                 errorMsg("init_module: %s: %s", m_name, strerror(errno));
1524
1525         free(image);
1526         free(symtab);
1527
1528         return ret == 0;
1529 }
1530
1531 #else
1532
1533 #define old_create_mod_use_count(x) TRUE
1534 #define old_init_module(x, y, z) TRUE
1535
1536 #endif                                                  /* BB_FEATURE_INSMOD_OLD_KERNEL */
1537
1538
1539
1540 /*======================================================================*/
1541 /* Functions relating to module loading after 2.1.18.  */
1542
1543 static int
1544 new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1545 {
1546         while (argc > 0) {
1547                 char *p, *q, *key;
1548                 struct obj_symbol *sym;
1549                 char *contents, *loc;
1550                 int min, max, n;
1551
1552                 p = *argv;
1553                 if ((q = strchr(p, '=')) == NULL)
1554                         continue;
1555
1556                 key = alloca(q - p + 6);
1557                 memcpy(key, "parm_", 5);
1558                 memcpy(key + 5, p, q - p);
1559                 key[q - p + 5] = 0;
1560
1561                 p = get_modinfo_value(f, key);
1562                 key += 5;
1563                 if (p == NULL) {
1564                         fprintf(stderr, "invalid parameter %s\n", key);
1565                         return 0;
1566                 }
1567
1568                 sym = obj_find_symbol(f, key);
1569
1570                 /* Also check that the parameter was not resolved from the kernel.  */
1571                 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
1572                         fprintf(stderr, "symbol for parameter %s not found\n", key);
1573                         return 0;
1574                 }
1575
1576                 if (isdigit(*p)) {
1577                         min = strtoul(p, &p, 10);
1578                         if (*p == '-')
1579                                 max = strtoul(p + 1, &p, 10);
1580                         else
1581                                 max = min;
1582                 } else
1583                         min = max = 1;
1584
1585                 contents = f->sections[sym->secidx]->contents;
1586                 loc = contents + sym->value;
1587                 n = (*++q != '\0');
1588
1589                 while (1) {
1590                         if ((*p == 's') || (*p == 'c')) {
1591                                 char *str;
1592
1593                                 /* Do C quoting if we begin with a ", else slurp the lot.  */
1594                                 if (*q == '"') {
1595                                         char *r;
1596
1597                                         str = alloca(strlen(q));
1598                                         for (r = str, q++; *q != '"'; ++q, ++r) {
1599                                                 if (*q == '\0') {
1600                                                         fprintf(stderr,
1601                                                                         "improperly terminated string argument for %s\n",
1602                                                                         key);
1603                                                         return 0;
1604                                                 } else if (*q == '\\')
1605                                                         switch (*++q) {
1606                                                         case 'a':
1607                                                                 *r = '\a';
1608                                                                 break;
1609                                                         case 'b':
1610                                                                 *r = '\b';
1611                                                                 break;
1612                                                         case 'e':
1613                                                                 *r = '\033';
1614                                                                 break;
1615                                                         case 'f':
1616                                                                 *r = '\f';
1617                                                                 break;
1618                                                         case 'n':
1619                                                                 *r = '\n';
1620                                                                 break;
1621                                                         case 'r':
1622                                                                 *r = '\r';
1623                                                                 break;
1624                                                         case 't':
1625                                                                 *r = '\t';
1626                                                                 break;
1627
1628                                                         case '0':
1629                                                         case '1':
1630                                                         case '2':
1631                                                         case '3':
1632                                                         case '4':
1633                                                         case '5':
1634                                                         case '6':
1635                                                         case '7':
1636                                                                 {
1637                                                                         int c = *q - '0';
1638                                                                         if (q[1] >= '0' && q[1] <= '7') {
1639                                                                                 c = (c * 8) + *++q - '0';
1640                                                                                 if (q[1] >= '0' && q[1] <= '7')
1641                                                                                         c = (c * 8) + *++q - '0';
1642                                                                         }
1643                                                                         *r = c;
1644                                                                 }
1645                                                                 break;
1646
1647                                                         default:
1648                                                                 *r = *q;
1649                                                                 break;
1650                                                 } else
1651                                                         *r = *q;
1652                                         }
1653                                         *r = '\0';
1654                                         ++q;
1655                                 } else {
1656                                         char *r;
1657
1658                                         /* In this case, the string is not quoted. We will break
1659                                            it using the coma (like for ints). If the user wants to
1660                                            include comas in a string, he just has to quote it */
1661
1662                                         /* Search the next coma */
1663                                         r = strchr(q, ',');
1664
1665                                         /* Found ? */
1666                                         if (r != (char *) NULL) {
1667                                                 /* Recopy the current field */
1668                                                 str = alloca(r - q + 1);
1669                                                 memcpy(str, q, r - q);
1670
1671                                                 /* I don't know if it is usefull, as the previous case
1672                                                    doesn't null terminate the string ??? */
1673                                                 str[r - q] = '\0';
1674
1675                                                 /* Keep next fields */
1676                                                 q = r;
1677                                         } else {
1678                                                 /* last string */
1679                                                 str = q;
1680                                                 q = "";
1681                                         }
1682                                 }
1683
1684                                 if (*p == 's') {
1685                                         /* Normal string */
1686                                         obj_string_patch(f, sym->secidx, loc - contents, str);
1687                                         loc += tgt_sizeof_char_p;
1688                                 } else {
1689                                         /* Array of chars (in fact, matrix !) */
1690                                         long charssize; /* size of each member */
1691
1692                                         /* Get the size of each member */
1693                                         /* Probably we should do that outside the loop ? */
1694                                         if (!isdigit(*(p + 1))) {
1695                                                 fprintf(stderr,
1696                                                                 "parameter type 'c' for %s must be followed by"
1697                                                                 " the maximum size\n", key);
1698                                                 return 0;
1699                                         }
1700                                         charssize = strtoul(p + 1, (char **) NULL, 10);
1701
1702                                         /* Check length */
1703                                         if (strlen(str) >= charssize) {
1704                                                 fprintf(stderr,
1705                                                                 "string too long for %s (max %ld)\n", key,
1706                                                                 charssize - 1);
1707                                                 return 0;
1708                                         }
1709
1710                                         /* Copy to location */
1711                                         strcpy((char *) loc, str);
1712                                         loc += charssize;
1713                                 }
1714                         } else {
1715                                 long v = strtoul(q, &q, 0);
1716                                 switch (*p) {
1717                                 case 'b':
1718                                         *loc++ = v;
1719                                         break;
1720                                 case 'h':
1721                                         *(short *) loc = v;
1722                                         loc += tgt_sizeof_short;
1723                                         break;
1724                                 case 'i':
1725                                         *(int *) loc = v;
1726                                         loc += tgt_sizeof_int;
1727                                         break;
1728                                 case 'l':
1729                                         *(long *) loc = v;
1730                                         loc += tgt_sizeof_long;
1731                                         break;
1732
1733                                 default:
1734                                         fprintf(stderr, "unknown parameter type '%c' for %s\n",
1735                                                         *p, key);
1736                                         return 0;
1737                                 }
1738                         }
1739
1740                   retry_end_of_value:
1741                         switch (*q) {
1742                         case '\0':
1743                                 goto end_of_arg;
1744
1745                         case ' ':
1746                         case '\t':
1747                         case '\n':
1748                         case '\r':
1749                                 ++q;
1750                                 goto retry_end_of_value;
1751
1752                         case ',':
1753                                 if (++n > max) {
1754                                         fprintf(stderr, "too many values for %s (max %d)\n",
1755                                                         key, max);
1756                                         return 0;
1757                                 }
1758                                 ++q;
1759                                 break;
1760
1761                         default:
1762                                 fprintf(stderr, "invalid argument syntax for %s\n", key);
1763                                 return 0;
1764                         }
1765                 }
1766
1767           end_of_arg:
1768                 if (n < min) {
1769                         fprintf(stderr, "too few values for %s (min %d)\n", key, min);
1770                         return 0;
1771                 }
1772
1773                 argc--, argv++;
1774         }
1775
1776         return 1;
1777 }
1778
1779 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1780 static int new_is_module_checksummed(struct obj_file *f)
1781 {
1782         const char *p = get_modinfo_value(f, "using_checksums");
1783         if (p)
1784                 return atoi(p);
1785         else
1786                 return 0;
1787 }
1788
1789 /* Get the module's kernel version in the canonical integer form.  */
1790
1791 static int
1792 new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1793 {
1794         char *p, *q;
1795         int a, b, c;
1796
1797         p = get_modinfo_value(f, "kernel_version");
1798         if (p == NULL)
1799                 return -1;
1800         strncpy(str, p, STRVERSIONLEN);
1801
1802         a = strtoul(p, &p, 10);
1803         if (*p != '.')
1804                 return -1;
1805         b = strtoul(p + 1, &p, 10);
1806         if (*p != '.')
1807                 return -1;
1808         c = strtoul(p + 1, &q, 10);
1809         if (p + 1 == q)
1810                 return -1;
1811
1812         return a << 16 | b << 8 | c;
1813 }
1814
1815 #endif   /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1816
1817
1818 #ifdef BB_FEATURE_INSMOD_NEW_KERNEL
1819
1820 /* Fetch the loaded modules, and all currently exported symbols.  */
1821
1822 static int new_get_kernel_symbols(void)
1823 {
1824         char *module_names, *mn;
1825         struct external_module *modules, *m;
1826         struct new_module_symbol *syms, *s;
1827         size_t ret, bufsize, nmod, nsyms, i, j;
1828
1829         /* Collect the loaded modules.  */
1830
1831         module_names = xmalloc(bufsize = 256);
1832   retry_modules_load:
1833         if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
1834                 if (errno == ENOSPC) {
1835                         module_names = xrealloc(module_names, bufsize = ret);
1836                         goto retry_modules_load;
1837                 }
1838                 errorMsg("QM_MODULES: %s", strerror(errno));
1839                 return 0;
1840         }
1841
1842         n_ext_modules = nmod = ret;
1843         ext_modules = modules = xmalloc(nmod * sizeof(*modules));
1844         memset(modules, 0, nmod * sizeof(*modules));
1845
1846         /* Collect the modules' symbols.  */
1847
1848         for (i = 0, mn = module_names, m = modules;
1849                  i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
1850                 struct new_module_info info;
1851
1852                 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
1853                         if (errno == ENOENT) {
1854                                 /* The module was removed out from underneath us.  */
1855                                 continue;
1856                         }
1857                         errorMsg("query_module: QM_INFO: %s: %s", mn, strerror(errno));
1858                         return 0;
1859                 }
1860
1861                 syms = xmalloc(bufsize = 1024);
1862           retry_mod_sym_load:
1863                 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
1864                         switch (errno) {
1865                         case ENOSPC:
1866                                 syms = xrealloc(syms, bufsize = ret);
1867                                 goto retry_mod_sym_load;
1868                         case ENOENT:
1869                                 /* The module was removed out from underneath us.  */
1870                                 continue;
1871                         default:
1872                                 errorMsg("query_module: QM_SYMBOLS: %s: %s", mn, strerror(errno));
1873                                 return 0;
1874                         }
1875                 }
1876                 nsyms = ret;
1877
1878                 m->name = mn;
1879                 m->addr = info.addr;
1880                 m->nsyms = nsyms;
1881                 m->syms = syms;
1882
1883                 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1884                         s->name += (unsigned long) syms;
1885                 }
1886         }
1887
1888         /* Collect the kernel's symbols.  */
1889
1890         syms = xmalloc(bufsize = 16 * 1024);
1891   retry_kern_sym_load:
1892         if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
1893                 if (errno == ENOSPC) {
1894                         syms = xrealloc(syms, bufsize = ret);
1895                         goto retry_kern_sym_load;
1896                 }
1897                 errorMsg("kernel: QM_SYMBOLS: %s", strerror(errno));
1898                 return 0;
1899         }
1900         nksyms = nsyms = ret;
1901         ksyms = syms;
1902
1903         for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1904                 s->name += (unsigned long) syms;
1905         }
1906         return 1;
1907 }
1908
1909
1910 /* Return the kernel symbol checksum version, or zero if not used.  */
1911
1912 static int new_is_kernel_checksummed(void)
1913 {
1914         struct new_module_symbol *s;
1915         size_t i;
1916
1917         /* Using_Versions is not the first symbol, but it should be in there.  */
1918
1919         for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
1920                 if (strcmp((char *) s->name, "Using_Versions") == 0)
1921                         return s->value;
1922
1923         return 0;
1924 }
1925
1926
1927 static int new_create_this_module(struct obj_file *f, const char *m_name)
1928 {
1929         struct obj_section *sec;
1930
1931         sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
1932                                                                                    sizeof(struct new_module));
1933         memset(sec->contents, 0, sizeof(struct new_module));
1934
1935         obj_add_symbol(f, "__this_module", -1,
1936                                    ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1937                                    sizeof(struct new_module));
1938
1939         obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
1940                                          m_name);
1941
1942         return 1;
1943 }
1944
1945
1946 static int new_create_module_ksymtab(struct obj_file *f)
1947 {
1948         struct obj_section *sec;
1949         int i;
1950
1951         /* We must always add the module references.  */
1952
1953         if (n_ext_modules_used) {
1954                 struct new_module_ref *dep;
1955                 struct obj_symbol *tm;
1956
1957                 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
1958                                                                                  (sizeof(struct new_module_ref)
1959                                                                                   * n_ext_modules_used));
1960                 if (!sec)
1961                         return 0;
1962
1963                 tm = obj_find_symbol(f, "__this_module");
1964                 dep = (struct new_module_ref *) sec->contents;
1965                 for (i = 0; i < n_ext_modules; ++i)
1966                         if (ext_modules[i].used) {
1967                                 dep->dep = ext_modules[i].addr;
1968                                 obj_symbol_patch(f, sec->idx,
1969                                                                  (char *) &dep->ref - sec->contents, tm);
1970                                 dep->next_ref = 0;
1971                                 ++dep;
1972                         }
1973         }
1974
1975         if (flag_export && !obj_find_section(f, "__ksymtab")) {
1976                 size_t nsyms;
1977                 int *loaded;
1978
1979                 sec =
1980                         obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
1981                                                                            0);
1982
1983                 /* We don't want to export symbols residing in sections that
1984                    aren't loaded.  There are a number of these created so that
1985                    we make sure certain module options don't appear twice.  */
1986
1987                 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
1988                 while (--i >= 0)
1989                         loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
1990
1991                 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
1992                         struct obj_symbol *sym;
1993                         for (sym = f->symtab[i]; sym; sym = sym->next)
1994                                 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1995                                         && sym->secidx <= SHN_HIRESERVE
1996                                         && (sym->secidx >= SHN_LORESERVE
1997                                                 || loaded[sym->secidx])) {
1998                                         ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
1999
2000                                         obj_symbol_patch(f, sec->idx, ofs, sym);
2001                                         obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2002                                                                          sym->name);
2003
2004                                         nsyms++;
2005                                 }
2006                 }
2007
2008                 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2009         }
2010
2011         return 1;
2012 }
2013
2014
2015 static int
2016 new_init_module(const char *m_name, struct obj_file *f,
2017                                 unsigned long m_size)
2018 {
2019         struct new_module *module;
2020         struct obj_section *sec;
2021         void *image;
2022         int ret;
2023         tgt_long m_addr;
2024
2025         sec = obj_find_section(f, ".this");
2026         module = (struct new_module *) sec->contents;
2027         m_addr = sec->header.sh_addr;
2028
2029         module->size_of_struct = sizeof(*module);
2030         module->size = m_size;
2031         module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2032
2033         sec = obj_find_section(f, "__ksymtab");
2034         if (sec && sec->header.sh_size) {
2035                 module->syms = sec->header.sh_addr;
2036                 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2037         }
2038
2039         if (n_ext_modules_used) {
2040                 sec = obj_find_section(f, ".kmodtab");
2041                 module->deps = sec->header.sh_addr;
2042                 module->ndeps = n_ext_modules_used;
2043         }
2044
2045         module->init =
2046                 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2047         module->cleanup =
2048                 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2049
2050         sec = obj_find_section(f, "__ex_table");
2051         if (sec) {
2052                 module->ex_table_start = sec->header.sh_addr;
2053                 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2054         }
2055
2056         sec = obj_find_section(f, ".text.init");
2057         if (sec) {
2058                 module->runsize = sec->header.sh_addr - m_addr;
2059         }
2060         sec = obj_find_section(f, ".data.init");
2061         if (sec) {
2062                 if (!module->runsize ||
2063                         module->runsize > sec->header.sh_addr - m_addr)
2064                                 module->runsize = sec->header.sh_addr - m_addr;
2065         }
2066
2067         if (!arch_init_module(f, module))
2068                 return 0;
2069
2070         /* Whew!  All of the initialization is complete.  Collect the final
2071            module image and give it to the kernel.  */
2072
2073         image = xmalloc(m_size);
2074         obj_create_image(f, image);
2075
2076         ret = new_sys_init_module(m_name, (struct new_module *) image);
2077         if (ret)
2078                 errorMsg("init_module: %s: %s", m_name, strerror(errno));
2079
2080         free(image);
2081
2082         return ret == 0;
2083 }
2084
2085 #else
2086
2087 #define new_init_module(x, y, z) TRUE
2088 #define new_create_this_module(x, y) 0
2089 #define new_create_module_ksymtab(x)
2090
2091 #endif                                                  /* BB_FEATURE_INSMOD_OLD_KERNEL */
2092
2093
2094 /*======================================================================*/
2095
2096 int
2097 obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2098                                  const char *string)
2099 {
2100         struct obj_string_patch *p;
2101         struct obj_section *strsec;
2102         size_t len = strlen(string) + 1;
2103         char *loc;
2104
2105         p = xmalloc(sizeof(*p));
2106         p->next = f->string_patches;
2107         p->reloc_secidx = secidx;
2108         p->reloc_offset = offset;
2109         f->string_patches = p;
2110
2111         strsec = obj_find_section(f, ".kstrtab");
2112         if (strsec == NULL) {
2113                 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2114                 p->string_offset = 0;
2115                 loc = strsec->contents;
2116         } else {
2117                 p->string_offset = strsec->header.sh_size;
2118                 loc = obj_extend_section(strsec, len);
2119         }
2120         memcpy(loc, string, len);
2121
2122         return 1;
2123 }
2124
2125 int
2126 obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2127                                  struct obj_symbol *sym)
2128 {
2129         struct obj_symbol_patch *p;
2130
2131         p = xmalloc(sizeof(*p));
2132         p->next = f->symbol_patches;
2133         p->reloc_secidx = secidx;
2134         p->reloc_offset = offset;
2135         p->sym = sym;
2136         f->symbol_patches = p;
2137
2138         return 1;
2139 }
2140
2141 int obj_check_undefineds(struct obj_file *f)
2142 {
2143         unsigned long i;
2144         int ret = 1;
2145
2146         for (i = 0; i < HASH_BUCKETS; ++i) {
2147                 struct obj_symbol *sym;
2148                 for (sym = f->symtab[i]; sym; sym = sym->next)
2149                         if (sym->secidx == SHN_UNDEF) {
2150                                 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2151                                         sym->secidx = SHN_ABS;
2152                                         sym->value = 0;
2153                                 } else {
2154                                         fprintf(stderr, "unresolved symbol %s\n", sym->name);
2155                                         ret = 0;
2156                                 }
2157                         }
2158         }
2159
2160         return ret;
2161 }
2162
2163 void obj_allocate_commons(struct obj_file *f)
2164 {
2165         struct common_entry {
2166                 struct common_entry *next;
2167                 struct obj_symbol *sym;
2168         } *common_head = NULL;
2169
2170         unsigned long i;
2171
2172         for (i = 0; i < HASH_BUCKETS; ++i) {
2173                 struct obj_symbol *sym;
2174                 for (sym = f->symtab[i]; sym; sym = sym->next)
2175                         if (sym->secidx == SHN_COMMON) {
2176                                 /* Collect all COMMON symbols and sort them by size so as to
2177                                    minimize space wasted by alignment requirements.  */
2178                                 {
2179                                         struct common_entry **p, *n;
2180                                         for (p = &common_head; *p; p = &(*p)->next)
2181                                                 if (sym->size <= (*p)->sym->size)
2182                                                         break;
2183
2184                                         n = alloca(sizeof(*n));
2185                                         n->next = *p;
2186                                         n->sym = sym;
2187                                         *p = n;
2188                                 }
2189                         }
2190         }
2191
2192         for (i = 1; i < f->local_symtab_size; ++i) {
2193                 struct obj_symbol *sym = f->local_symtab[i];
2194                 if (sym && sym->secidx == SHN_COMMON) {
2195                         struct common_entry **p, *n;
2196                         for (p = &common_head; *p; p = &(*p)->next)
2197                                 if (sym == (*p)->sym)
2198                                         break;
2199                                 else if (sym->size < (*p)->sym->size) {
2200                                         n = alloca(sizeof(*n));
2201                                         n->next = *p;
2202                                         n->sym = sym;
2203                                         *p = n;
2204                                         break;
2205                                 }
2206                 }
2207         }
2208
2209         if (common_head) {
2210                 /* Find the bss section.  */
2211                 for (i = 0; i < f->header.e_shnum; ++i)
2212                         if (f->sections[i]->header.sh_type == SHT_NOBITS)
2213                                 break;
2214
2215                 /* If for some reason there hadn't been one, create one.  */
2216                 if (i == f->header.e_shnum) {
2217                         struct obj_section *sec;
2218
2219                         f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2220                         f->sections[i] = sec = arch_new_section();
2221                         f->header.e_shnum = i + 1;
2222
2223                         memset(sec, 0, sizeof(*sec));
2224                         sec->header.sh_type = SHT_PROGBITS;
2225                         sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2226                         sec->name = ".bss";
2227                         sec->idx = i;
2228                 }
2229
2230                 /* Allocate the COMMONS.  */
2231                 {
2232                         ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2233                         ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2234                         struct common_entry *c;
2235
2236                         for (c = common_head; c; c = c->next) {
2237                                 ElfW(Addr) align = c->sym->value;
2238
2239                                 if (align > max_align)
2240                                         max_align = align;
2241                                 if (bss_size & (align - 1))
2242                                         bss_size = (bss_size | (align - 1)) + 1;
2243
2244                                 c->sym->secidx = i;
2245                                 c->sym->value = bss_size;
2246
2247                                 bss_size += c->sym->size;
2248                         }
2249
2250                         f->sections[i]->header.sh_size = bss_size;
2251                         f->sections[i]->header.sh_addralign = max_align;
2252                 }
2253         }
2254
2255         /* For the sake of patch relocation and parameter initialization,
2256            allocate zeroed data for NOBITS sections now.  Note that after
2257            this we cannot assume NOBITS are really empty.  */
2258         for (i = 0; i < f->header.e_shnum; ++i) {
2259                 struct obj_section *s = f->sections[i];
2260                 if (s->header.sh_type == SHT_NOBITS) {
2261                         s->contents = memset(xmalloc(s->header.sh_size),
2262                                                                  0, s->header.sh_size);
2263                         s->header.sh_type = SHT_PROGBITS;
2264                 }
2265         }
2266 }
2267
2268 unsigned long obj_load_size(struct obj_file *f)
2269 {
2270         unsigned long dot = 0;
2271         struct obj_section *sec;
2272
2273         /* Finalize the positions of the sections relative to one another.  */
2274
2275         for (sec = f->load_order; sec; sec = sec->load_next) {
2276                 ElfW(Addr) align;
2277
2278                 align = sec->header.sh_addralign;
2279                 if (align && (dot & (align - 1)))
2280                         dot = (dot | (align - 1)) + 1;
2281
2282                 sec->header.sh_addr = dot;
2283                 dot += sec->header.sh_size;
2284         }
2285
2286         return dot;
2287 }
2288
2289 int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2290 {
2291         int i, n = f->header.e_shnum;
2292         int ret = 1;
2293
2294         /* Finalize the addresses of the sections.  */
2295
2296         f->baseaddr = base;
2297         for (i = 0; i < n; ++i)
2298                 f->sections[i]->header.sh_addr += base;
2299
2300         /* And iterate over all of the relocations.  */
2301
2302         for (i = 0; i < n; ++i) {
2303                 struct obj_section *relsec, *symsec, *targsec, *strsec;
2304                 ElfW(RelM) * rel, *relend;
2305                 ElfW(Sym) * symtab;
2306                 const char *strtab;
2307
2308                 relsec = f->sections[i];
2309                 if (relsec->header.sh_type != SHT_RELM)
2310                         continue;
2311
2312                 symsec = f->sections[relsec->header.sh_link];
2313                 targsec = f->sections[relsec->header.sh_info];
2314                 strsec = f->sections[symsec->header.sh_link];
2315
2316                 rel = (ElfW(RelM) *) relsec->contents;
2317                 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2318                 symtab = (ElfW(Sym) *) symsec->contents;
2319                 strtab = (const char *) strsec->contents;
2320
2321                 for (; rel < relend; ++rel) {
2322                         ElfW(Addr) value = 0;
2323                         struct obj_symbol *intsym = NULL;
2324                         unsigned long symndx;
2325                         ElfW(Sym) * extsym = 0;
2326                         const char *errmsg;
2327
2328                         /* Attempt to find a value to use for this relocation.  */
2329
2330                         symndx = ELFW(R_SYM) (rel->r_info);
2331                         if (symndx) {
2332                                 /* Note we've already checked for undefined symbols.  */
2333
2334                                 extsym = &symtab[symndx];
2335                                 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2336                                         /* Local symbols we look up in the local table to be sure
2337                                            we get the one that is really intended.  */
2338                                         intsym = f->local_symtab[symndx];
2339                                 } else {
2340                                         /* Others we look up in the hash table.  */
2341                                         const char *name;
2342                                         if (extsym->st_name)
2343                                                 name = strtab + extsym->st_name;
2344                                         else
2345                                                 name = f->sections[extsym->st_shndx]->name;
2346                                         intsym = obj_find_symbol(f, name);
2347                                 }
2348
2349                                 value = obj_symbol_final_value(f, intsym);
2350                                 intsym->referenced = 1;
2351                         }
2352 #if SHT_RELM == SHT_RELA
2353 #if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2354                         /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9.  */
2355                         if (!extsym || !extsym->st_name ||
2356                                 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2357 #endif
2358                                 value += rel->r_addend;
2359 #endif
2360
2361                         /* Do it! */
2362                         switch (arch_apply_relocation
2363                                         (f, targsec, symsec, intsym, rel, value)) {
2364                         case obj_reloc_ok:
2365                                 break;
2366
2367                         case obj_reloc_overflow:
2368                                 errmsg = "Relocation overflow";
2369                                 goto bad_reloc;
2370                         case obj_reloc_dangerous:
2371                                 errmsg = "Dangerous relocation";
2372                                 goto bad_reloc;
2373                         case obj_reloc_unhandled:
2374                                 errmsg = "Unhandled relocation";
2375                           bad_reloc:
2376                                 if (extsym) {
2377                                         fprintf(stderr, "%s of type %ld for %s\n", errmsg,
2378                                                         (long) ELFW(R_TYPE) (rel->r_info),
2379                                                         strtab + extsym->st_name);
2380                                 } else {
2381                                         fprintf(stderr, "%s of type %ld\n", errmsg,
2382                                                         (long) ELFW(R_TYPE) (rel->r_info));
2383                                 }
2384                                 ret = 0;
2385                                 break;
2386                         }
2387                 }
2388         }
2389
2390         /* Finally, take care of the patches.  */
2391
2392         if (f->string_patches) {
2393                 struct obj_string_patch *p;
2394                 struct obj_section *strsec;
2395                 ElfW(Addr) strsec_base;
2396                 strsec = obj_find_section(f, ".kstrtab");
2397                 strsec_base = strsec->header.sh_addr;
2398
2399                 for (p = f->string_patches; p; p = p->next) {
2400                         struct obj_section *targsec = f->sections[p->reloc_secidx];
2401                         *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2402                                 = strsec_base + p->string_offset;
2403                 }
2404         }
2405
2406         if (f->symbol_patches) {
2407                 struct obj_symbol_patch *p;
2408
2409                 for (p = f->symbol_patches; p; p = p->next) {
2410                         struct obj_section *targsec = f->sections[p->reloc_secidx];
2411                         *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2412                                 = obj_symbol_final_value(f, p->sym);
2413                 }
2414         }
2415
2416         return ret;
2417 }
2418
2419 int obj_create_image(struct obj_file *f, char *image)
2420 {
2421         struct obj_section *sec;
2422         ElfW(Addr) base = f->baseaddr;
2423
2424         for (sec = f->load_order; sec; sec = sec->load_next) {
2425                 char *secimg;
2426
2427                 if (sec->header.sh_size == 0)
2428                         continue;
2429
2430                 secimg = image + (sec->header.sh_addr - base);
2431
2432                 /* Note that we allocated data for NOBITS sections earlier.  */
2433                 memcpy(secimg, sec->contents, sec->header.sh_size);
2434         }
2435
2436         return 1;
2437 }
2438
2439 /*======================================================================*/
2440
2441 struct obj_file *obj_load(FILE * fp)
2442 {
2443         struct obj_file *f;
2444         ElfW(Shdr) * section_headers;
2445         int shnum, i;
2446         char *shstrtab;
2447
2448         /* Read the file header.  */
2449
2450         f = arch_new_file();
2451         memset(f, 0, sizeof(*f));
2452         f->symbol_cmp = strcmp;
2453         f->symbol_hash = obj_elf_hash;
2454         f->load_order_search_start = &f->load_order;
2455
2456         fseek(fp, 0, SEEK_SET);
2457         if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
2458                 errorMsg("error reading ELF header: %s", strerror(errno));
2459                 return NULL;
2460         }
2461
2462         if (f->header.e_ident[EI_MAG0] != ELFMAG0
2463                 || f->header.e_ident[EI_MAG1] != ELFMAG1
2464                 || f->header.e_ident[EI_MAG2] != ELFMAG2
2465                 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
2466                 fprintf(stderr, "not an ELF file\n");
2467                 return NULL;
2468         }
2469         if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2470                 || f->header.e_ident[EI_DATA] != ELFDATAM
2471                 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2472                 || !MATCH_MACHINE(f->header.e_machine)) {
2473                 fprintf(stderr, "ELF file not for this architecture\n");
2474                 return NULL;
2475         }
2476         if (f->header.e_type != ET_REL) {
2477                 fprintf(stderr, "ELF file not a relocatable object\n");
2478                 return NULL;
2479         }
2480
2481         /* Read the section headers.  */
2482
2483         if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
2484                 fprintf(stderr, "section header size mismatch: %lu != %lu\n",
2485                                 (unsigned long) f->header.e_shentsize,
2486                                 (unsigned long) sizeof(ElfW(Shdr)));
2487                 return NULL;
2488         }
2489
2490         shnum = f->header.e_shnum;
2491         f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2492         memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2493
2494         section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2495         fseek(fp, f->header.e_shoff, SEEK_SET);
2496         if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
2497                 errorMsg("error reading ELF section headers: %s", strerror(errno));
2498                 return NULL;
2499         }
2500
2501         /* Read the section data.  */
2502
2503         for (i = 0; i < shnum; ++i) {
2504                 struct obj_section *sec;
2505
2506                 f->sections[i] = sec = arch_new_section();
2507                 memset(sec, 0, sizeof(*sec));
2508
2509                 sec->header = section_headers[i];
2510                 sec->idx = i;
2511
2512                 switch (sec->header.sh_type) {
2513                 case SHT_NULL:
2514                 case SHT_NOTE:
2515                 case SHT_NOBITS:
2516                         /* ignore */
2517                         break;
2518
2519                 case SHT_PROGBITS:
2520                 case SHT_SYMTAB:
2521                 case SHT_STRTAB:
2522                 case SHT_RELM:
2523                         if (sec->header.sh_size > 0) {
2524                                 sec->contents = xmalloc(sec->header.sh_size);
2525                                 fseek(fp, sec->header.sh_offset, SEEK_SET);
2526                                 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
2527                                         errorMsg("error reading ELF section data: %s", strerror(errno));
2528                                         return NULL;
2529                                 }
2530                         } else {
2531                                 sec->contents = NULL;
2532                         }
2533                         break;
2534
2535 #if SHT_RELM == SHT_REL
2536                 case SHT_RELA:
2537                         fprintf(stderr,
2538                                         "RELA relocations not supported on this architecture\n");
2539                         return NULL;
2540 #else
2541                 case SHT_REL:
2542                         fprintf(stderr,
2543                                         "REL relocations not supported on this architecture\n");
2544                         return NULL;
2545 #endif
2546
2547                 default:
2548                         if (sec->header.sh_type >= SHT_LOPROC) {
2549                                 /* Assume processor specific section types are debug
2550                                    info and can safely be ignored.  If this is ever not
2551                                    the case (Hello MIPS?), don't put ifdefs here but
2552                                    create an arch_load_proc_section().  */
2553                                 break;
2554                         }
2555
2556                         fprintf(stderr, "can't handle sections of type %ld\n",
2557                                         (long) sec->header.sh_type);
2558                         return NULL;
2559                 }
2560         }
2561
2562         /* Do what sort of interpretation as needed by each section.  */
2563
2564         shstrtab = f->sections[f->header.e_shstrndx]->contents;
2565
2566         for (i = 0; i < shnum; ++i) {
2567                 struct obj_section *sec = f->sections[i];
2568                 sec->name = shstrtab + sec->header.sh_name;
2569         }
2570
2571         for (i = 0; i < shnum; ++i) {
2572                 struct obj_section *sec = f->sections[i];
2573
2574                 if (sec->header.sh_flags & SHF_ALLOC)
2575                         obj_insert_section_load_order(f, sec);
2576
2577                 switch (sec->header.sh_type) {
2578                 case SHT_SYMTAB:
2579                         {
2580                                 unsigned long nsym, j;
2581                                 char *strtab;
2582                                 ElfW(Sym) * sym;
2583
2584                                 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
2585                                         fprintf(stderr, "symbol size mismatch: %lu != %lu\n",
2586                                                         (unsigned long) sec->header.sh_entsize,
2587                                                         (unsigned long) sizeof(ElfW(Sym)));
2588                                         return NULL;
2589                                 }
2590
2591                                 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2592                                 strtab = f->sections[sec->header.sh_link]->contents;
2593                                 sym = (ElfW(Sym) *) sec->contents;
2594
2595                                 /* Allocate space for a table of local symbols.  */
2596                                 j = f->local_symtab_size = sec->header.sh_info;
2597                                 f->local_symtab = xmalloc(j *=
2598                                                                                   sizeof(struct obj_symbol *));
2599                                 memset(f->local_symtab, 0, j);
2600
2601                                 /* Insert all symbols into the hash table.  */
2602                                 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2603                                         const char *name;
2604                                         if (sym->st_name)
2605                                                 name = strtab + sym->st_name;
2606                 else
2607                                                 name = f->sections[sym->st_shndx]->name;
2608
2609                                         obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2610                                                                    sym->st_value, sym->st_size);
2611                 }
2612         }
2613                         break;
2614
2615                 case SHT_RELM:
2616                         if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
2617                                 fprintf(stderr,
2618                                                 "relocation entry size mismatch: %lu != %lu\n",
2619                                                 (unsigned long) sec->header.sh_entsize,
2620                                                 (unsigned long) sizeof(ElfW(RelM)));
2621                                 return NULL;
2622                         }
2623                         break;
2624                 }
2625         }
2626
2627         return f;
2628 }
2629
2630 static void hide_special_symbols(struct obj_file *f)
2631 {
2632         static const char *const specials[] = {
2633                 "cleanup_module",
2634                 "init_module",
2635                 "kernel_version",
2636                 NULL
2637         };
2638
2639         struct obj_symbol *sym;
2640         const char *const *p;
2641
2642         for (p = specials; *p; ++p)
2643                 if ((sym = obj_find_symbol(f, *p)) != NULL)
2644                         sym->info =
2645                                 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2646 }
2647
2648
2649
2650 extern int insmod_main( int argc, char **argv)
2651 {
2652         int k_crcs;
2653         int k_new_syscalls;
2654         int len;
2655         char *tmp;
2656         unsigned long m_size;
2657         ElfW(Addr) m_addr;
2658         FILE *fp;
2659         struct obj_file *f;
2660         char m_name[BUFSIZ + 1] = "\0";
2661         int exit_status = FALSE;
2662         int m_has_modinfo;
2663 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2664         int k_version;
2665         char k_strversion[STRVERSIONLEN];
2666         char m_strversion[STRVERSIONLEN];
2667         int m_version;
2668         int m_crcs;
2669 #endif
2670
2671
2672         if (argc <= 1) {
2673                 usage(insmod_usage);
2674         }
2675
2676         /* Parse any options */
2677         while (--argc > 0 && **(++argv) == '-') {
2678                 while (*(++(*argv))) {
2679                         switch (**argv) {
2680                         case 'f':                       /* force loading */
2681                                 flag_force_load = 1;
2682                                 break;
2683                         case 'k':                       /* module loaded by kerneld, auto-cleanable */
2684                                 flag_autoclean = 1;
2685                                 break;
2686                         case 'v':                       /* verbose output */
2687                                 flag_verbose = 1;
2688                                 break;
2689                         case 'x':                       /* do not export externs */
2690                                 flag_export = 0;
2691                                 break;
2692                         default:
2693                                 usage(insmod_usage);
2694                         }
2695                 }
2696         }
2697
2698         if (argc <= 0) {
2699                 usage(insmod_usage);
2700         }
2701         /* Grab the module name */
2702         if ((tmp = strrchr(*argv, '/')) != NULL) {
2703                 tmp++;
2704         } else {
2705                 tmp = *argv;
2706         }
2707         len = strlen(tmp);
2708
2709         if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2710                 len -= 2;
2711         memcpy(m_name, tmp, len);
2712         strcpy(m_fullName, m_name);
2713         strcat(m_fullName, ".o");
2714
2715         /* Get a filedesc for the module */
2716         if ((fp = fopen(*argv, "r")) == NULL) {
2717                 /* Hmpf.  Could not open it. Search through _PATH_MODULES to find a module named m_name */
2718                 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
2719                                                         findNamedModule, 0, m_fullName) == TRUE) 
2720                 {
2721                         if (m_filename[0] == '\0'
2722                                 || ((fp = fopen(m_filename, "r")) == NULL)) 
2723                         {
2724                                 errorMsg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
2725                                 exit(FALSE);
2726                         }
2727                 }
2728         } else
2729                 memcpy(m_filename, *argv, strlen(*argv));
2730
2731
2732         if ((f = obj_load(fp)) == NULL) {
2733                 perror("Could not load the module\n");
2734                 exit(FALSE);
2735         }
2736
2737         if (get_modinfo_value(f, "kernel_version") == NULL)
2738                 m_has_modinfo = 0;
2739         else
2740                 m_has_modinfo = 1;
2741
2742 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2743         /* Version correspondence?  */
2744
2745         k_version = get_kernel_version(k_strversion);
2746         if (m_has_modinfo) {
2747                 m_version = new_get_module_version(f, m_strversion);
2748         } else {
2749                 m_version = old_get_module_version(f, m_strversion);
2750                 if (m_version == -1) {
2751                         fprintf(stderr,
2752                                         "couldn't find the kernel version the module was compiled for\n");
2753                         goto out;
2754                 }
2755         }
2756
2757         if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2758                 if (flag_force_load) {
2759                         fprintf(stderr, "Warning: kernel-module version mismatch\n"
2760                                         "\t%s was compiled for kernel version %s\n"
2761                                         "\twhile this kernel is version %s\n",
2762                                         m_filename, m_strversion, k_strversion);
2763                 } else {
2764                         fprintf(stderr, "kernel-module version mismatch\n"
2765                                         "\t%s was compiled for kernel version %s\n"
2766                                         "\twhile this kernel is version %s.\n",
2767                                         m_filename, m_strversion, k_strversion);
2768                         goto out;
2769                 }
2770         }
2771         k_crcs = 0;
2772 #endif                                                  /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2773
2774         k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2775
2776         if (k_new_syscalls) {
2777 #ifdef BB_FEATURE_INSMOD_NEW_KERNEL
2778                 if (!new_get_kernel_symbols())
2779                         goto out;
2780                 k_crcs = new_is_kernel_checksummed();
2781 #else
2782                 fprintf(stderr, "Not configured to support new kernels\n");
2783                 goto out;
2784 #endif
2785         } else {
2786 #ifdef BB_FEATURE_INSMOD_OLD_KERNEL
2787                 if (!old_get_kernel_symbols())
2788                         goto out;
2789                 k_crcs = old_is_kernel_checksummed();
2790 #else
2791                 fprintf(stderr, "Not configured to support old kernels\n");
2792                 goto out;
2793 #endif
2794         }
2795
2796 #ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2797         if (m_has_modinfo)
2798                 m_crcs = new_is_module_checksummed(f);
2799         else
2800                 m_crcs = old_is_module_checksummed(f);
2801
2802         if (m_crcs != k_crcs)
2803                 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
2804 #endif                                                  /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2805
2806         /* Let the module know about the kernel symbols.  */
2807         add_kernel_symbols(f);
2808
2809         /* Allocate common symbols, symbol tables, and string tables.  */
2810
2811         if (k_new_syscalls 
2812                 ? !new_create_this_module(f, m_name)
2813                 : !old_create_mod_use_count(f)) 
2814         {
2815                 goto out;
2816         }
2817
2818         if (!obj_check_undefineds(f)) {
2819                 goto out;
2820         }
2821         obj_allocate_commons(f);
2822
2823         if (optind < argc) {
2824                 if (m_has_modinfo
2825                         ? !new_process_module_arguments(f, argc - optind, argv + optind) 
2826                         : !old_process_module_arguments(f, argc - optind, argv + optind)) 
2827                 {
2828                         goto out;
2829                 }
2830         }
2831
2832         arch_create_got(f);
2833         hide_special_symbols(f);
2834
2835         if (k_new_syscalls)
2836                 new_create_module_ksymtab(f);
2837
2838         /* Find current size of the module */
2839         m_size = obj_load_size(f);
2840
2841
2842         errno = 0;
2843         m_addr = create_module(m_name, m_size);
2844         switch (errno) {
2845         case 0:
2846                 break;
2847         case EEXIST:
2848                 fprintf(stderr, "A module named %s already exists\n", m_name);
2849                 goto out;
2850         case ENOMEM:
2851                 fprintf(stderr,
2852                                 "Can't allocate kernel memory for module; needed %lu bytes\n",
2853                                 m_size);
2854                 goto out;
2855         default:
2856                 errorMsg("create_module: %s: %s", m_name, strerror(errno));
2857                 goto out;
2858         }
2859
2860         if (!obj_relocate(f, m_addr)) {
2861                 delete_module(m_name);
2862                 goto out;
2863         }
2864
2865         if (k_new_syscalls 
2866                 ? !new_init_module(m_name, f, m_size)
2867                 : !old_init_module(m_name, f, m_size)) 
2868         {
2869                 delete_module(m_name);
2870                 goto out;
2871         }
2872
2873         exit_status = TRUE;
2874
2875 out:
2876         fclose(fp);
2877         return(exit_status);
2878 }