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