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