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