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