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