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