blob: 0b06b5c409fd4bf33d4c08b68fdd2e6265886898 [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>
Eric Andersen999bf722000-07-09 06:59:58 +000041#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000042#include <sys/utsname.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
Eric Andersenc86e5e62000-08-21 19:38:49 +000073#ident "$Id: insmod.c,v 1.21 2000/08/21 19:38:49 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +000074
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
Eric Andersenc86e5e62000-08-21 19:38:49 +0000279#ident "$Id: insmod.c,v 1.21 2000/08/21 19:38:49 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000280
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 +0000558
Eric Andersen9f16d612000-06-12 23:11:16 +0000559/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000560
Eric Andersen9f16d612000-06-12 23:11:16 +0000561
562static int findNamedModule(const char *fileName, struct stat *statbuf,
563 void *userDate)
564{
565 char *fullName = (char *) userDate;
566
567
568 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000569 return (FALSE);
570 else {
571 char *tmp = strrchr(fileName, '/');
572
573 if (tmp == NULL)
574 tmp = (char *) fileName;
575 else
576 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000577 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000578 /* Stop searching if we find a match */
579 memcpy(m_filename, fileName, strlen(fileName));
580 return (FALSE);
581 }
Erik Andersend387d011999-12-21 02:55:11 +0000582 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000583 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000584}
585
Erik Andersen02104321999-12-17 18:57:34 +0000586
Eric Andersen9f16d612000-06-12 23:11:16 +0000587/*======================================================================*/
588
589struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000590{
Eric Andersen9f16d612000-06-12 23:11:16 +0000591 struct i386_file *f;
592 f = xmalloc(sizeof(*f));
593 f->got = NULL;
594 return &f->root;
595}
596
597struct obj_section *arch_new_section(void)
598{
599 return xmalloc(sizeof(struct obj_section));
600}
601
602struct obj_symbol *arch_new_symbol(void)
603{
604 struct i386_symbol *sym;
605 sym = xmalloc(sizeof(*sym));
606 memset(&sym->gotent, 0, sizeof(sym->gotent));
607 return &sym->root;
608}
609enum obj_reloc
610arch_apply_relocation(struct obj_file *f,
611 struct obj_section *targsec,
612 struct obj_section *symsec,
613 struct obj_symbol *sym,
614 Elf32_Rel * rel, Elf32_Addr v)
615{
616 struct i386_file *ifile = (struct i386_file *) f;
617 struct i386_symbol *isym = (struct i386_symbol *) sym;
618
619 Elf32_Addr *loc = (Elf32_Addr *) (targsec->contents + rel->r_offset);
620 Elf32_Addr dot = targsec->header.sh_addr + rel->r_offset;
621 Elf32_Addr got = ifile->got ? ifile->got->header.sh_addr : 0;
622
623 enum obj_reloc ret = obj_reloc_ok;
624
625 switch (ELF32_R_TYPE(rel->r_info)) {
626 case R_386_NONE:
627 break;
628
629 case R_386_32:
630 *loc += v;
631 break;
632
633 case R_386_PLT32:
634 case R_386_PC32:
635 *loc += v - dot;
636 break;
637
638 case R_386_GLOB_DAT:
639 case R_386_JMP_SLOT:
640 *loc = v;
641 break;
642
643 case R_386_RELATIVE:
644 *loc += f->baseaddr;
645 break;
646
647 case R_386_GOTPC:
648 assert(got != 0);
649 *loc += got - dot;
650 break;
651
652 case R_386_GOT32:
653 assert(isym != NULL);
654 if (!isym->gotent.reloc_done) {
655 isym->gotent.reloc_done = 1;
656 *(Elf32_Addr *) (ifile->got->contents + isym->gotent.offset) =
657 v;
658 }
659 *loc += isym->gotent.offset;
660 break;
661
662 case R_386_GOTOFF:
663 assert(got != 0);
664 *loc += v - got;
665 break;
666
667 default:
668 ret = obj_reloc_unhandled;
669 break;
670 }
671
672 return ret;
673}
674
675int arch_create_got(struct obj_file *f)
676{
677 struct i386_file *ifile = (struct i386_file *) f;
678 int i, n, offset = 0, gotneeded = 0;
679
680 n = ifile->root.header.e_shnum;
681 for (i = 0; i < n; ++i) {
682 struct obj_section *relsec, *symsec, *strsec;
683 Elf32_Rel *rel, *relend;
684 Elf32_Sym *symtab;
685 const char *strtab;
686
687 relsec = ifile->root.sections[i];
688 if (relsec->header.sh_type != SHT_REL)
689 continue;
690
691 symsec = ifile->root.sections[relsec->header.sh_link];
692 strsec = ifile->root.sections[symsec->header.sh_link];
693
694 rel = (Elf32_Rel *) relsec->contents;
695 relend = rel + (relsec->header.sh_size / sizeof(Elf32_Rel));
696 symtab = (Elf32_Sym *) symsec->contents;
697 strtab = (const char *) strsec->contents;
698
699 for (; rel < relend; ++rel) {
700 Elf32_Sym *extsym;
701 struct i386_symbol *intsym;
702 const char *name;
703
704 switch (ELF32_R_TYPE(rel->r_info)) {
705 case R_386_GOTPC:
706 case R_386_GOTOFF:
707 gotneeded = 1;
708 default:
709 continue;
710
711 case R_386_GOT32:
712 break;
713 }
714
715 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
716 if (extsym->st_name)
717 name = strtab + extsym->st_name;
718 else
719 name = f->sections[extsym->st_shndx]->name;
720 intsym =
721 (struct i386_symbol *) obj_find_symbol(&ifile->root, name);
722
723 if (!intsym->gotent.offset_done) {
724 intsym->gotent.offset_done = 1;
725 intsym->gotent.offset = offset;
726 offset += 4;
727 }
728 }
729 }
730
731 if (offset > 0 || gotneeded)
732 ifile->got =
733 obj_create_alloced_section(&ifile->root, ".got", 4, offset);
734
735 return 1;
736}
737
738int arch_init_module(struct obj_file *f, struct new_module *mod)
739{
740 return 1;
741}
742
743
744/*======================================================================*/
745
746/* Standard ELF hash function. */
747inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
748{
749 unsigned long h = 0;
750 unsigned long g;
751 unsigned char ch;
752
753 while (n > 0) {
754 ch = *name++;
755 h = (h << 4) + ch;
756 if ((g = (h & 0xf0000000)) != 0) {
757 h ^= g >> 24;
758 h &= ~g;
759 }
760 n--;
761 }
762 return h;
763}
764
765unsigned long obj_elf_hash(const char *name)
766{
767 return obj_elf_hash_n(name, strlen(name));
768}
769
770#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
771/* Get the kernel version in the canonical integer form. */
772
773static int get_kernel_version(char str[STRVERSIONLEN])
774{
775 struct utsname uts_info;
776 char *p, *q;
777 int a, b, c;
778
779 if (uname(&uts_info) < 0)
780 return -1;
781 strncpy(str, uts_info.release, STRVERSIONLEN);
782 p = uts_info.release;
783
784 a = strtoul(p, &p, 10);
785 if (*p != '.')
786 return -1;
787 b = strtoul(p + 1, &p, 10);
788 if (*p != '.')
789 return -1;
790 c = strtoul(p + 1, &q, 10);
791 if (p + 1 == q)
792 return -1;
793
794 return a << 16 | b << 8 | c;
795}
796
797/* String comparison for non-co-versioned kernel and module. */
798
799static int ncv_strcmp(const char *a, const char *b)
800{
801 size_t alen = strlen(a), blen = strlen(b);
802
803 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
804 return strncmp(a, b, alen);
805 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
806 return strncmp(a, b, blen);
807 else
808 return strcmp(a, b);
809}
810
811/* String hashing for non-co-versioned kernel and module. Here
812 we are simply forced to drop the crc from the hash. */
813
814static unsigned long ncv_symbol_hash(const char *str)
815{
816 size_t len = strlen(str);
817 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
818 len -= 10;
819 return obj_elf_hash_n(str, len);
820}
821
822void
823obj_set_symbol_compare(struct obj_file *f,
824 int (*cmp) (const char *, const char *),
825 unsigned long (*hash) (const char *))
826{
827 if (cmp)
828 f->symbol_cmp = cmp;
829 if (hash) {
830 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
831 int i;
832
833 f->symbol_hash = hash;
834
835 memcpy(tmptab, f->symtab, sizeof(tmptab));
836 memset(f->symtab, 0, sizeof(f->symtab));
837
838 for (i = 0; i < HASH_BUCKETS; ++i)
839 for (sym = tmptab[i]; sym; sym = next) {
840 unsigned long h = hash(sym->name) % HASH_BUCKETS;
841 next = sym->next;
842 sym->next = f->symtab[h];
843 f->symtab[h] = sym;
844 }
845 }
846}
847
848#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
849
850
851struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
852 unsigned long symidx, int info,
853 int secidx, ElfW(Addr) value,
854 unsigned long size)
855{
856 struct obj_symbol *sym;
857 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
858 int n_type = ELFW(ST_TYPE) (info);
859 int n_binding = ELFW(ST_BIND) (info);
860
861 for (sym = f->symtab[hash]; sym; sym = sym->next)
862 if (f->symbol_cmp(sym->name, name) == 0) {
863 int o_secidx = sym->secidx;
864 int o_info = sym->info;
865 int o_type = ELFW(ST_TYPE) (o_info);
866 int o_binding = ELFW(ST_BIND) (o_info);
867
868 /* A redefinition! Is it legal? */
869
870 if (secidx == SHN_UNDEF)
871 return sym;
872 else if (o_secidx == SHN_UNDEF)
873 goto found;
874 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
875 /* Cope with local and global symbols of the same name
876 in the same object file, as might have been created
877 by ld -r. The only reason locals are now seen at this
878 level at all is so that we can do semi-sensible things
879 with parameters. */
880
881 struct obj_symbol *nsym, **p;
882
883 nsym = arch_new_symbol();
884 nsym->next = sym->next;
885 nsym->ksymidx = -1;
886
887 /* Excise the old (local) symbol from the hash chain. */
888 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
889 continue;
890 *p = sym = nsym;
891 goto found;
892 } else if (n_binding == STB_LOCAL) {
893 /* Another symbol of the same name has already been defined.
894 Just add this to the local table. */
895 sym = arch_new_symbol();
896 sym->next = NULL;
897 sym->ksymidx = -1;
898 f->local_symtab[symidx] = sym;
899 goto found;
900 } else if (n_binding == STB_WEAK)
901 return sym;
902 else if (o_binding == STB_WEAK)
903 goto found;
904 /* Don't unify COMMON symbols with object types the programmer
905 doesn't expect. */
906 else if (secidx == SHN_COMMON
907 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
908 return sym;
909 else if (o_secidx == SHN_COMMON
910 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
911 goto found;
912 else {
913 /* Don't report an error if the symbol is coming from
914 the kernel or some external module. */
915 if (secidx <= SHN_HIRESERVE)
Matt Kraaid537a952000-07-14 01:51:25 +0000916 errorMsg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000917 return sym;
918 }
919 }
920
921 /* Completely new symbol. */
922 sym = arch_new_symbol();
923 sym->next = f->symtab[hash];
924 f->symtab[hash] = sym;
925 sym->ksymidx = -1;
926
927 if (ELFW(ST_BIND) (info) == STB_LOCAL)
928 f->local_symtab[symidx] = sym;
929
930 found:
931 sym->name = name;
932 sym->value = value;
933 sym->size = size;
934 sym->secidx = secidx;
935 sym->info = info;
936
937 return sym;
938}
939
940struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
941{
942 struct obj_symbol *sym;
943 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
944
945 for (sym = f->symtab[hash]; sym; sym = sym->next)
946 if (f->symbol_cmp(sym->name, name) == 0)
947 return sym;
948
949 return NULL;
950}
951
952ElfW(Addr)
953 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
954{
955 if (sym) {
956 if (sym->secidx >= SHN_LORESERVE)
957 return sym->value;
958
959 return sym->value + f->sections[sym->secidx]->header.sh_addr;
960 } else {
961 /* As a special case, a NULL sym has value zero. */
962 return 0;
963 }
964}
965
966struct obj_section *obj_find_section(struct obj_file *f, const char *name)
967{
968 int i, n = f->header.e_shnum;
969
970 for (i = 0; i < n; ++i)
971 if (strcmp(f->sections[i]->name, name) == 0)
972 return f->sections[i];
973
974 return NULL;
975}
976
977static int obj_load_order_prio(struct obj_section *a)
978{
979 unsigned long af, ac;
980
981 af = a->header.sh_flags;
982
983 ac = 0;
984 if (a->name[0] != '.' || strlen(a->name) != 10 ||
985 strcmp(a->name + 5, ".init"))
986 ac |= 32;
987 if (af & SHF_ALLOC)
988 ac |= 16;
989 if (!(af & SHF_WRITE))
990 ac |= 8;
991 if (af & SHF_EXECINSTR)
992 ac |= 4;
993 if (a->header.sh_type != SHT_NOBITS)
994 ac |= 2;
995
996 return ac;
997}
998
999void
1000obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1001{
1002 struct obj_section **p;
1003 int prio = obj_load_order_prio(sec);
1004 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1005 if (obj_load_order_prio(*p) < prio)
1006 break;
1007 sec->load_next = *p;
1008 *p = sec;
1009}
1010
1011struct obj_section *obj_create_alloced_section(struct obj_file *f,
1012 const char *name,
1013 unsigned long align,
1014 unsigned long size)
1015{
1016 int newidx = f->header.e_shnum++;
1017 struct obj_section *sec;
1018
1019 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1020 f->sections[newidx] = sec = arch_new_section();
1021
1022 memset(sec, 0, sizeof(*sec));
1023 sec->header.sh_type = SHT_PROGBITS;
1024 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1025 sec->header.sh_size = size;
1026 sec->header.sh_addralign = align;
1027 sec->name = name;
1028 sec->idx = newidx;
1029 if (size)
1030 sec->contents = xmalloc(size);
1031
1032 obj_insert_section_load_order(f, sec);
1033
1034 return sec;
1035}
1036
1037struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1038 const char *name,
1039 unsigned long align,
1040 unsigned long size)
1041{
1042 int newidx = f->header.e_shnum++;
1043 struct obj_section *sec;
1044
1045 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1046 f->sections[newidx] = sec = arch_new_section();
1047
1048 memset(sec, 0, sizeof(*sec));
1049 sec->header.sh_type = SHT_PROGBITS;
1050 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1051 sec->header.sh_size = size;
1052 sec->header.sh_addralign = align;
1053 sec->name = name;
1054 sec->idx = newidx;
1055 if (size)
1056 sec->contents = xmalloc(size);
1057
1058 sec->load_next = f->load_order;
1059 f->load_order = sec;
1060 if (f->load_order_search_start == &f->load_order)
1061 f->load_order_search_start = &sec->load_next;
1062
1063 return sec;
1064}
1065
1066void *obj_extend_section(struct obj_section *sec, unsigned long more)
1067{
1068 unsigned long oldsize = sec->header.sh_size;
1069 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1070 return sec->contents + oldsize;
1071}
1072
1073
1074
1075/* Conditionally add the symbols from the given symbol set to the
1076 new module. */
1077
1078static int
1079add_symbols_from(
1080 struct obj_file *f,
1081 int idx, struct new_module_symbol *syms, size_t nsyms)
1082{
1083 struct new_module_symbol *s;
1084 size_t i;
1085 int used = 0;
1086
1087 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1088
1089 /* Only add symbols that are already marked external. If we
1090 override locals we may cause problems for argument initialization.
1091 We will also create a false dependency on the module. */
1092 struct obj_symbol *sym;
1093
1094 sym = obj_find_symbol(f, (char *) s->name);
1095 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1096 sym = obj_add_symbol(f, (char *) s->name, -1,
1097 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1098 idx, s->value, 0);
1099 /* Did our symbol just get installed? If so, mark the
1100 module as "used". */
1101 if (sym->secidx == idx)
1102 used = 1;
1103 }
1104 }
1105
1106 return used;
1107}
1108
1109static void add_kernel_symbols(struct obj_file *f)
1110{
1111 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001112 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001113
1114 /* Add module symbols first. */
1115
1116 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1117 if (m->nsyms
1118 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1119 m->nsyms)) m->used = 1, ++nused;
1120
1121 n_ext_modules_used = nused;
1122
1123 /* And finally the symbols from the kernel proper. */
1124
1125 if (nksyms)
1126 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1127}
1128
1129static char *get_modinfo_value(struct obj_file *f, const char *key)
1130{
1131 struct obj_section *sec;
1132 char *p, *v, *n, *ep;
1133 size_t klen = strlen(key);
1134
1135 sec = obj_find_section(f, ".modinfo");
1136 if (sec == NULL)
1137 return NULL;
1138 p = sec->contents;
1139 ep = p + sec->header.sh_size;
1140 while (p < ep) {
1141 v = strchr(p, '=');
1142 n = strchr(p, '\0');
1143 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001144 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001145 return v + 1;
1146 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001147 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001148 return n;
1149 }
1150 p = n + 1;
1151 }
1152
1153 return NULL;
1154}
1155
1156
1157/*======================================================================*/
1158/* Functions relating to module loading in pre 2.1 kernels. */
1159
1160static int
1161old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1162{
1163 while (argc > 0) {
1164 char *p, *q;
1165 struct obj_symbol *sym;
1166 int *loc;
1167
1168 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001169 if ((q = strchr(p, '=')) == NULL) {
1170 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001171 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001172 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001173 *q++ = '\0';
1174
1175 sym = obj_find_symbol(f, p);
1176
1177 /* Also check that the parameter was not resolved from the kernel. */
1178 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001179 errorMsg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001180 return 0;
1181 }
1182
1183 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1184
1185 /* Do C quoting if we begin with a ". */
1186 if (*q == '"') {
1187 char *r, *str;
1188
1189 str = alloca(strlen(q));
1190 for (r = str, q++; *q != '"'; ++q, ++r) {
1191 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001192 errorMsg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001193 return 0;
1194 } else if (*q == '\\')
1195 switch (*++q) {
1196 case 'a':
1197 *r = '\a';
1198 break;
1199 case 'b':
1200 *r = '\b';
1201 break;
1202 case 'e':
1203 *r = '\033';
1204 break;
1205 case 'f':
1206 *r = '\f';
1207 break;
1208 case 'n':
1209 *r = '\n';
1210 break;
1211 case 'r':
1212 *r = '\r';
1213 break;
1214 case 't':
1215 *r = '\t';
1216 break;
1217
1218 case '0':
1219 case '1':
1220 case '2':
1221 case '3':
1222 case '4':
1223 case '5':
1224 case '6':
1225 case '7':
1226 {
1227 int c = *q - '0';
1228 if (q[1] >= '0' && q[1] <= '7') {
1229 c = (c * 8) + *++q - '0';
1230 if (q[1] >= '0' && q[1] <= '7')
1231 c = (c * 8) + *++q - '0';
1232 }
1233 *r = c;
1234 }
1235 break;
1236
1237 default:
1238 *r = *q;
1239 break;
1240 } else
1241 *r = *q;
1242 }
1243 *r = '\0';
1244 obj_string_patch(f, sym->secidx, sym->value, str);
1245 } else if (*q >= '0' && *q <= '9') {
1246 do
1247 *loc++ = strtoul(q, &q, 0);
1248 while (*q++ == ',');
1249 } else {
1250 char *contents = f->sections[sym->secidx]->contents;
1251 char *loc = contents + sym->value;
1252 char *r; /* To search for commas */
1253
1254 /* Break the string with comas */
1255 while ((r = strchr(q, ',')) != (char *) NULL) {
1256 *r++ = '\0';
1257 obj_string_patch(f, sym->secidx, loc - contents, q);
1258 loc += sizeof(char *);
1259 q = r;
1260 }
1261
1262 /* last part */
1263 obj_string_patch(f, sym->secidx, loc - contents, q);
1264 }
1265
1266 argc--, argv++;
1267 }
1268
1269 return 1;
1270}
1271
1272#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1273static int old_is_module_checksummed(struct obj_file *f)
1274{
1275 return obj_find_symbol(f, "Using_Versions") != NULL;
1276}
1277/* Get the module's kernel version in the canonical integer form. */
1278
1279static int
1280old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1281{
1282 struct obj_symbol *sym;
1283 char *p, *q;
1284 int a, b, c;
1285
1286 sym = obj_find_symbol(f, "kernel_version");
1287 if (sym == NULL)
1288 return -1;
1289
1290 p = f->sections[sym->secidx]->contents + sym->value;
1291 strncpy(str, p, STRVERSIONLEN);
1292
1293 a = strtoul(p, &p, 10);
1294 if (*p != '.')
1295 return -1;
1296 b = strtoul(p + 1, &p, 10);
1297 if (*p != '.')
1298 return -1;
1299 c = strtoul(p + 1, &q, 10);
1300 if (p + 1 == q)
1301 return -1;
1302
1303 return a << 16 | b << 8 | c;
1304}
1305
1306#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1307
1308#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
1309
1310/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1311
1312static int old_get_kernel_symbols(void)
1313{
1314 struct old_kernel_sym *ks, *k;
1315 struct new_module_symbol *s;
1316 struct external_module *mod;
1317 int nks, nms, nmod, i;
1318
1319 nks = get_kernel_syms(NULL);
1320 if (nks < 0) {
Eric Andersen8a24a672000-06-22 18:19:31 +00001321 errorMsg("get_kernel_syms: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001322 return 0;
1323 }
1324
1325 ks = k = xmalloc(nks * sizeof(*ks));
1326
1327 if (get_kernel_syms(ks) != nks) {
1328 perror("inconsistency with get_kernel_syms -- is someone else "
1329 "playing with modules?");
1330 free(ks);
1331 return 0;
1332 }
1333
1334 /* Collect the module information. */
1335
1336 mod = NULL;
1337 nmod = -1;
1338
1339 while (k->name[0] == '#' && k->name[1]) {
1340 struct old_kernel_sym *k2;
1341 struct new_module_symbol *s;
1342
1343 /* Find out how many symbols this module has. */
1344 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1345 continue;
1346 nms = k2 - k - 1;
1347
1348 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1349 mod[nmod].name = k->name + 1;
1350 mod[nmod].addr = k->value;
1351 mod[nmod].used = 0;
1352 mod[nmod].nsyms = nms;
1353 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1354
1355 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1356 s->name = (unsigned long) k->name;
1357 s->value = k->value;
1358 }
1359
1360 k = k2;
1361 }
1362
1363 ext_modules = mod;
1364 n_ext_modules = nmod + 1;
1365
1366 /* Now collect the symbols for the kernel proper. */
1367
1368 if (k->name[0] == '#')
1369 ++k;
1370
1371 nksyms = nms = nks - (k - ks);
1372 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1373
1374 for (i = 0; i < nms; ++i, ++s, ++k) {
1375 s->name = (unsigned long) k->name;
1376 s->value = k->value;
1377 }
1378
1379 return 1;
1380}
1381
1382/* Return the kernel symbol checksum version, or zero if not used. */
1383
1384static int old_is_kernel_checksummed(void)
1385{
1386 /* Using_Versions is the first symbol. */
1387 if (nksyms > 0
1388 && strcmp((char *) ksyms[0].name,
1389 "Using_Versions") == 0) return ksyms[0].value;
1390 else
1391 return 0;
1392}
1393
1394
1395static int old_create_mod_use_count(struct obj_file *f)
1396{
1397 struct obj_section *sec;
1398
1399 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1400 sizeof(long));
1401
1402 obj_add_symbol(f, "mod_use_count_", -1,
1403 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1404 sizeof(long));
1405
1406 return 1;
1407}
1408
1409static int
1410old_init_module(const char *m_name, struct obj_file *f,
1411 unsigned long m_size)
1412{
1413 char *image;
1414 struct old_mod_routines routines;
1415 struct old_symbol_table *symtab;
1416 int ret;
1417
1418 /* Create the symbol table */
1419 {
1420 int nsyms = 0, strsize = 0, total;
1421
1422 /* Size things first... */
1423 if (flag_export) {
1424 int i;
1425 for (i = 0; i < HASH_BUCKETS; ++i) {
1426 struct obj_symbol *sym;
1427 for (sym = f->symtab[i]; sym; sym = sym->next)
1428 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1429 && sym->secidx <= SHN_HIRESERVE)
1430 {
1431 sym->ksymidx = nsyms++;
1432 strsize += strlen(sym->name) + 1;
1433 }
1434 }
1435 }
1436
1437 total = (sizeof(struct old_symbol_table)
1438 + nsyms * sizeof(struct old_module_symbol)
1439 + n_ext_modules_used * sizeof(struct old_module_ref)
1440 + strsize);
1441 symtab = xmalloc(total);
1442 symtab->size = total;
1443 symtab->n_symbols = nsyms;
1444 symtab->n_refs = n_ext_modules_used;
1445
1446 if (flag_export && nsyms) {
1447 struct old_module_symbol *ksym;
1448 char *str;
1449 int i;
1450
1451 ksym = symtab->symbol;
1452 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1453 + n_ext_modules_used * sizeof(struct old_module_ref));
1454
1455 for (i = 0; i < HASH_BUCKETS; ++i) {
1456 struct obj_symbol *sym;
1457 for (sym = f->symtab[i]; sym; sym = sym->next)
1458 if (sym->ksymidx >= 0) {
1459 ksym->addr = obj_symbol_final_value(f, sym);
1460 ksym->name =
1461 (unsigned long) str - (unsigned long) symtab;
1462
1463 str = stpcpy(str, sym->name) + 1;
1464 ksym++;
1465 }
1466 }
1467 }
1468
1469 if (n_ext_modules_used) {
1470 struct old_module_ref *ref;
1471 int i;
1472
1473 ref = (struct old_module_ref *)
1474 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1475
1476 for (i = 0; i < n_ext_modules; ++i)
1477 if (ext_modules[i].used)
1478 ref++->module = ext_modules[i].addr;
1479 }
1480 }
1481
1482 /* Fill in routines. */
1483
1484 routines.init =
1485 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1486 routines.cleanup =
1487 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1488
1489 /* Whew! All of the initialization is complete. Collect the final
1490 module image and give it to the kernel. */
1491
1492 image = xmalloc(m_size);
1493 obj_create_image(f, image);
1494
1495 /* image holds the complete relocated module, accounting correctly for
1496 mod_use_count. However the old module kernel support assume that
1497 it is receiving something which does not contain mod_use_count. */
1498 ret = old_sys_init_module(m_name, image + sizeof(long),
1499 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1500 : 0), &routines, symtab);
1501 if (ret)
Eric Andersen8a24a672000-06-22 18:19:31 +00001502 errorMsg("init_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001503
1504 free(image);
1505 free(symtab);
1506
1507 return ret == 0;
1508}
1509
1510#else
1511
1512#define old_create_mod_use_count(x) TRUE
1513#define old_init_module(x, y, z) TRUE
1514
1515#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
1516
1517
1518
1519/*======================================================================*/
1520/* Functions relating to module loading after 2.1.18. */
1521
1522static int
1523new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1524{
1525 while (argc > 0) {
1526 char *p, *q, *key;
1527 struct obj_symbol *sym;
1528 char *contents, *loc;
1529 int min, max, n;
1530
1531 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001532 if ((q = strchr(p, '=')) == NULL) {
1533 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001534 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001535 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001536
1537 key = alloca(q - p + 6);
1538 memcpy(key, "parm_", 5);
1539 memcpy(key + 5, p, q - p);
1540 key[q - p + 5] = 0;
1541
1542 p = get_modinfo_value(f, key);
1543 key += 5;
1544 if (p == NULL) {
Matt Kraaid537a952000-07-14 01:51:25 +00001545 errorMsg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001546 return 0;
1547 }
1548
1549 sym = obj_find_symbol(f, key);
1550
1551 /* Also check that the parameter was not resolved from the kernel. */
1552 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaid537a952000-07-14 01:51:25 +00001553 errorMsg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001554 return 0;
1555 }
1556
1557 if (isdigit(*p)) {
1558 min = strtoul(p, &p, 10);
1559 if (*p == '-')
1560 max = strtoul(p + 1, &p, 10);
1561 else
1562 max = min;
1563 } else
1564 min = max = 1;
1565
1566 contents = f->sections[sym->secidx]->contents;
1567 loc = contents + sym->value;
1568 n = (*++q != '\0');
1569
1570 while (1) {
1571 if ((*p == 's') || (*p == 'c')) {
1572 char *str;
1573
1574 /* Do C quoting if we begin with a ", else slurp the lot. */
1575 if (*q == '"') {
1576 char *r;
1577
1578 str = alloca(strlen(q));
1579 for (r = str, q++; *q != '"'; ++q, ++r) {
1580 if (*q == '\0') {
Matt Kraaid537a952000-07-14 01:51:25 +00001581 errorMsg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001582 key);
1583 return 0;
1584 } else if (*q == '\\')
1585 switch (*++q) {
1586 case 'a':
1587 *r = '\a';
1588 break;
1589 case 'b':
1590 *r = '\b';
1591 break;
1592 case 'e':
1593 *r = '\033';
1594 break;
1595 case 'f':
1596 *r = '\f';
1597 break;
1598 case 'n':
1599 *r = '\n';
1600 break;
1601 case 'r':
1602 *r = '\r';
1603 break;
1604 case 't':
1605 *r = '\t';
1606 break;
1607
1608 case '0':
1609 case '1':
1610 case '2':
1611 case '3':
1612 case '4':
1613 case '5':
1614 case '6':
1615 case '7':
1616 {
1617 int c = *q - '0';
1618 if (q[1] >= '0' && q[1] <= '7') {
1619 c = (c * 8) + *++q - '0';
1620 if (q[1] >= '0' && q[1] <= '7')
1621 c = (c * 8) + *++q - '0';
1622 }
1623 *r = c;
1624 }
1625 break;
1626
1627 default:
1628 *r = *q;
1629 break;
1630 } else
1631 *r = *q;
1632 }
1633 *r = '\0';
1634 ++q;
1635 } else {
1636 char *r;
1637
1638 /* In this case, the string is not quoted. We will break
1639 it using the coma (like for ints). If the user wants to
1640 include comas in a string, he just has to quote it */
1641
1642 /* Search the next coma */
1643 r = strchr(q, ',');
1644
1645 /* Found ? */
1646 if (r != (char *) NULL) {
1647 /* Recopy the current field */
1648 str = alloca(r - q + 1);
1649 memcpy(str, q, r - q);
1650
1651 /* I don't know if it is usefull, as the previous case
1652 doesn't null terminate the string ??? */
1653 str[r - q] = '\0';
1654
1655 /* Keep next fields */
1656 q = r;
1657 } else {
1658 /* last string */
1659 str = q;
1660 q = "";
1661 }
1662 }
1663
1664 if (*p == 's') {
1665 /* Normal string */
1666 obj_string_patch(f, sym->secidx, loc - contents, str);
1667 loc += tgt_sizeof_char_p;
1668 } else {
1669 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001670 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001671
1672 /* Get the size of each member */
1673 /* Probably we should do that outside the loop ? */
1674 if (!isdigit(*(p + 1))) {
Matt Kraaid537a952000-07-14 01:51:25 +00001675 errorMsg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001676 " the maximum size\n", key);
1677 return 0;
1678 }
1679 charssize = strtoul(p + 1, (char **) NULL, 10);
1680
1681 /* Check length */
1682 if (strlen(str) >= charssize) {
Matt Kraaid537a952000-07-14 01:51:25 +00001683 errorMsg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001684 charssize - 1);
1685 return 0;
1686 }
1687
1688 /* Copy to location */
1689 strcpy((char *) loc, str);
1690 loc += charssize;
1691 }
1692 } else {
1693 long v = strtoul(q, &q, 0);
1694 switch (*p) {
1695 case 'b':
1696 *loc++ = v;
1697 break;
1698 case 'h':
1699 *(short *) loc = v;
1700 loc += tgt_sizeof_short;
1701 break;
1702 case 'i':
1703 *(int *) loc = v;
1704 loc += tgt_sizeof_int;
1705 break;
1706 case 'l':
1707 *(long *) loc = v;
1708 loc += tgt_sizeof_long;
1709 break;
1710
1711 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001712 errorMsg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001713 return 0;
1714 }
1715 }
1716
1717 retry_end_of_value:
1718 switch (*q) {
1719 case '\0':
1720 goto end_of_arg;
1721
1722 case ' ':
1723 case '\t':
1724 case '\n':
1725 case '\r':
1726 ++q;
1727 goto retry_end_of_value;
1728
1729 case ',':
1730 if (++n > max) {
Matt Kraaid537a952000-07-14 01:51:25 +00001731 errorMsg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001732 return 0;
1733 }
1734 ++q;
1735 break;
1736
1737 default:
Matt Kraaid537a952000-07-14 01:51:25 +00001738 errorMsg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001739 return 0;
1740 }
1741 }
1742
1743 end_of_arg:
1744 if (n < min) {
Matt Kraaid537a952000-07-14 01:51:25 +00001745 errorMsg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001746 return 0;
1747 }
1748
1749 argc--, argv++;
1750 }
1751
1752 return 1;
1753}
1754
1755#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1756static int new_is_module_checksummed(struct obj_file *f)
1757{
1758 const char *p = get_modinfo_value(f, "using_checksums");
1759 if (p)
1760 return atoi(p);
1761 else
1762 return 0;
1763}
1764
1765/* Get the module's kernel version in the canonical integer form. */
1766
1767static int
1768new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1769{
1770 char *p, *q;
1771 int a, b, c;
1772
1773 p = get_modinfo_value(f, "kernel_version");
1774 if (p == NULL)
1775 return -1;
1776 strncpy(str, p, STRVERSIONLEN);
1777
1778 a = strtoul(p, &p, 10);
1779 if (*p != '.')
1780 return -1;
1781 b = strtoul(p + 1, &p, 10);
1782 if (*p != '.')
1783 return -1;
1784 c = strtoul(p + 1, &q, 10);
1785 if (p + 1 == q)
1786 return -1;
1787
1788 return a << 16 | b << 8 | c;
1789}
1790
1791#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1792
1793
1794#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
1795
1796/* Fetch the loaded modules, and all currently exported symbols. */
1797
1798static int new_get_kernel_symbols(void)
1799{
1800 char *module_names, *mn;
1801 struct external_module *modules, *m;
1802 struct new_module_symbol *syms, *s;
1803 size_t ret, bufsize, nmod, nsyms, i, j;
1804
1805 /* Collect the loaded modules. */
1806
1807 module_names = xmalloc(bufsize = 256);
1808 retry_modules_load:
1809 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
1810 if (errno == ENOSPC) {
1811 module_names = xrealloc(module_names, bufsize = ret);
1812 goto retry_modules_load;
1813 }
Eric Andersen8a24a672000-06-22 18:19:31 +00001814 errorMsg("QM_MODULES: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001815 return 0;
1816 }
1817
1818 n_ext_modules = nmod = ret;
1819 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
1820 memset(modules, 0, nmod * sizeof(*modules));
1821
1822 /* Collect the modules' symbols. */
1823
1824 for (i = 0, mn = module_names, m = modules;
1825 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
1826 struct new_module_info info;
1827
1828 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
1829 if (errno == ENOENT) {
1830 /* The module was removed out from underneath us. */
1831 continue;
1832 }
Eric Andersen8a24a672000-06-22 18:19:31 +00001833 errorMsg("query_module: QM_INFO: %s: %s", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001834 return 0;
1835 }
1836
1837 syms = xmalloc(bufsize = 1024);
1838 retry_mod_sym_load:
1839 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
1840 switch (errno) {
1841 case ENOSPC:
1842 syms = xrealloc(syms, bufsize = ret);
1843 goto retry_mod_sym_load;
1844 case ENOENT:
1845 /* The module was removed out from underneath us. */
1846 continue;
1847 default:
Eric Andersen8a24a672000-06-22 18:19:31 +00001848 errorMsg("query_module: QM_SYMBOLS: %s: %s", mn, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001849 return 0;
1850 }
1851 }
1852 nsyms = ret;
1853
1854 m->name = mn;
1855 m->addr = info.addr;
1856 m->nsyms = nsyms;
1857 m->syms = syms;
1858
1859 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1860 s->name += (unsigned long) syms;
1861 }
1862 }
1863
1864 /* Collect the kernel's symbols. */
1865
1866 syms = xmalloc(bufsize = 16 * 1024);
1867 retry_kern_sym_load:
1868 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
1869 if (errno == ENOSPC) {
1870 syms = xrealloc(syms, bufsize = ret);
1871 goto retry_kern_sym_load;
1872 }
Eric Andersen8a24a672000-06-22 18:19:31 +00001873 errorMsg("kernel: QM_SYMBOLS: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00001874 return 0;
1875 }
1876 nksyms = nsyms = ret;
1877 ksyms = syms;
1878
1879 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
1880 s->name += (unsigned long) syms;
1881 }
1882 return 1;
1883}
1884
1885
1886/* Return the kernel symbol checksum version, or zero if not used. */
1887
1888static int new_is_kernel_checksummed(void)
1889{
1890 struct new_module_symbol *s;
1891 size_t i;
1892
1893 /* Using_Versions is not the first symbol, but it should be in there. */
1894
1895 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
1896 if (strcmp((char *) s->name, "Using_Versions") == 0)
1897 return s->value;
1898
1899 return 0;
1900}
1901
1902
1903static int new_create_this_module(struct obj_file *f, const char *m_name)
1904{
1905 struct obj_section *sec;
1906
1907 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
1908 sizeof(struct new_module));
1909 memset(sec->contents, 0, sizeof(struct new_module));
1910
1911 obj_add_symbol(f, "__this_module", -1,
1912 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1913 sizeof(struct new_module));
1914
1915 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
1916 m_name);
1917
1918 return 1;
1919}
1920
1921
1922static int new_create_module_ksymtab(struct obj_file *f)
1923{
1924 struct obj_section *sec;
1925 int i;
1926
1927 /* We must always add the module references. */
1928
1929 if (n_ext_modules_used) {
1930 struct new_module_ref *dep;
1931 struct obj_symbol *tm;
1932
1933 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
1934 (sizeof(struct new_module_ref)
1935 * n_ext_modules_used));
1936 if (!sec)
1937 return 0;
1938
1939 tm = obj_find_symbol(f, "__this_module");
1940 dep = (struct new_module_ref *) sec->contents;
1941 for (i = 0; i < n_ext_modules; ++i)
1942 if (ext_modules[i].used) {
1943 dep->dep = ext_modules[i].addr;
1944 obj_symbol_patch(f, sec->idx,
1945 (char *) &dep->ref - sec->contents, tm);
1946 dep->next_ref = 0;
1947 ++dep;
1948 }
1949 }
1950
1951 if (flag_export && !obj_find_section(f, "__ksymtab")) {
1952 size_t nsyms;
1953 int *loaded;
1954
1955 sec =
1956 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
1957 0);
1958
1959 /* We don't want to export symbols residing in sections that
1960 aren't loaded. There are a number of these created so that
1961 we make sure certain module options don't appear twice. */
1962
1963 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
1964 while (--i >= 0)
1965 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
1966
1967 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
1968 struct obj_symbol *sym;
1969 for (sym = f->symtab[i]; sym; sym = sym->next)
1970 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1971 && sym->secidx <= SHN_HIRESERVE
1972 && (sym->secidx >= SHN_LORESERVE
1973 || loaded[sym->secidx])) {
1974 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
1975
1976 obj_symbol_patch(f, sec->idx, ofs, sym);
1977 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
1978 sym->name);
1979
1980 nsyms++;
1981 }
1982 }
1983
1984 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
1985 }
1986
1987 return 1;
1988}
1989
1990
1991static int
1992new_init_module(const char *m_name, struct obj_file *f,
1993 unsigned long m_size)
1994{
1995 struct new_module *module;
1996 struct obj_section *sec;
1997 void *image;
1998 int ret;
1999 tgt_long m_addr;
2000
2001 sec = obj_find_section(f, ".this");
2002 module = (struct new_module *) sec->contents;
2003 m_addr = sec->header.sh_addr;
2004
2005 module->size_of_struct = sizeof(*module);
2006 module->size = m_size;
2007 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2008
2009 sec = obj_find_section(f, "__ksymtab");
2010 if (sec && sec->header.sh_size) {
2011 module->syms = sec->header.sh_addr;
2012 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2013 }
2014
2015 if (n_ext_modules_used) {
2016 sec = obj_find_section(f, ".kmodtab");
2017 module->deps = sec->header.sh_addr;
2018 module->ndeps = n_ext_modules_used;
2019 }
2020
2021 module->init =
2022 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2023 module->cleanup =
2024 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2025
2026 sec = obj_find_section(f, "__ex_table");
2027 if (sec) {
2028 module->ex_table_start = sec->header.sh_addr;
2029 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2030 }
2031
2032 sec = obj_find_section(f, ".text.init");
2033 if (sec) {
2034 module->runsize = sec->header.sh_addr - m_addr;
2035 }
2036 sec = obj_find_section(f, ".data.init");
2037 if (sec) {
2038 if (!module->runsize ||
2039 module->runsize > sec->header.sh_addr - m_addr)
2040 module->runsize = sec->header.sh_addr - m_addr;
2041 }
2042
2043 if (!arch_init_module(f, module))
2044 return 0;
2045
2046 /* Whew! All of the initialization is complete. Collect the final
2047 module image and give it to the kernel. */
2048
2049 image = xmalloc(m_size);
2050 obj_create_image(f, image);
2051
2052 ret = new_sys_init_module(m_name, (struct new_module *) image);
2053 if (ret)
Eric Andersen8a24a672000-06-22 18:19:31 +00002054 errorMsg("init_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002055
2056 free(image);
2057
2058 return ret == 0;
2059}
2060
2061#else
2062
2063#define new_init_module(x, y, z) TRUE
2064#define new_create_this_module(x, y) 0
2065#define new_create_module_ksymtab(x)
2066
2067#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
2068
2069
2070/*======================================================================*/
2071
2072int
2073obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2074 const char *string)
2075{
2076 struct obj_string_patch *p;
2077 struct obj_section *strsec;
2078 size_t len = strlen(string) + 1;
2079 char *loc;
2080
2081 p = xmalloc(sizeof(*p));
2082 p->next = f->string_patches;
2083 p->reloc_secidx = secidx;
2084 p->reloc_offset = offset;
2085 f->string_patches = p;
2086
2087 strsec = obj_find_section(f, ".kstrtab");
2088 if (strsec == NULL) {
2089 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2090 p->string_offset = 0;
2091 loc = strsec->contents;
2092 } else {
2093 p->string_offset = strsec->header.sh_size;
2094 loc = obj_extend_section(strsec, len);
2095 }
2096 memcpy(loc, string, len);
2097
2098 return 1;
2099}
2100
2101int
2102obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2103 struct obj_symbol *sym)
2104{
2105 struct obj_symbol_patch *p;
2106
2107 p = xmalloc(sizeof(*p));
2108 p->next = f->symbol_patches;
2109 p->reloc_secidx = secidx;
2110 p->reloc_offset = offset;
2111 p->sym = sym;
2112 f->symbol_patches = p;
2113
2114 return 1;
2115}
2116
2117int obj_check_undefineds(struct obj_file *f)
2118{
2119 unsigned long i;
2120 int ret = 1;
2121
2122 for (i = 0; i < HASH_BUCKETS; ++i) {
2123 struct obj_symbol *sym;
2124 for (sym = f->symtab[i]; sym; sym = sym->next)
2125 if (sym->secidx == SHN_UNDEF) {
2126 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2127 sym->secidx = SHN_ABS;
2128 sym->value = 0;
2129 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002130 errorMsg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002131 ret = 0;
2132 }
2133 }
2134 }
2135
2136 return ret;
2137}
2138
2139void obj_allocate_commons(struct obj_file *f)
2140{
2141 struct common_entry {
2142 struct common_entry *next;
2143 struct obj_symbol *sym;
2144 } *common_head = NULL;
2145
2146 unsigned long i;
2147
2148 for (i = 0; i < HASH_BUCKETS; ++i) {
2149 struct obj_symbol *sym;
2150 for (sym = f->symtab[i]; sym; sym = sym->next)
2151 if (sym->secidx == SHN_COMMON) {
2152 /* Collect all COMMON symbols and sort them by size so as to
2153 minimize space wasted by alignment requirements. */
2154 {
2155 struct common_entry **p, *n;
2156 for (p = &common_head; *p; p = &(*p)->next)
2157 if (sym->size <= (*p)->sym->size)
2158 break;
2159
2160 n = alloca(sizeof(*n));
2161 n->next = *p;
2162 n->sym = sym;
2163 *p = n;
2164 }
2165 }
2166 }
2167
2168 for (i = 1; i < f->local_symtab_size; ++i) {
2169 struct obj_symbol *sym = f->local_symtab[i];
2170 if (sym && sym->secidx == SHN_COMMON) {
2171 struct common_entry **p, *n;
2172 for (p = &common_head; *p; p = &(*p)->next)
2173 if (sym == (*p)->sym)
2174 break;
2175 else if (sym->size < (*p)->sym->size) {
2176 n = alloca(sizeof(*n));
2177 n->next = *p;
2178 n->sym = sym;
2179 *p = n;
2180 break;
2181 }
2182 }
2183 }
2184
2185 if (common_head) {
2186 /* Find the bss section. */
2187 for (i = 0; i < f->header.e_shnum; ++i)
2188 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2189 break;
2190
2191 /* If for some reason there hadn't been one, create one. */
2192 if (i == f->header.e_shnum) {
2193 struct obj_section *sec;
2194
2195 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2196 f->sections[i] = sec = arch_new_section();
2197 f->header.e_shnum = i + 1;
2198
2199 memset(sec, 0, sizeof(*sec));
2200 sec->header.sh_type = SHT_PROGBITS;
2201 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2202 sec->name = ".bss";
2203 sec->idx = i;
2204 }
2205
2206 /* Allocate the COMMONS. */
2207 {
2208 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2209 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2210 struct common_entry *c;
2211
2212 for (c = common_head; c; c = c->next) {
2213 ElfW(Addr) align = c->sym->value;
2214
2215 if (align > max_align)
2216 max_align = align;
2217 if (bss_size & (align - 1))
2218 bss_size = (bss_size | (align - 1)) + 1;
2219
2220 c->sym->secidx = i;
2221 c->sym->value = bss_size;
2222
2223 bss_size += c->sym->size;
2224 }
2225
2226 f->sections[i]->header.sh_size = bss_size;
2227 f->sections[i]->header.sh_addralign = max_align;
2228 }
2229 }
2230
2231 /* For the sake of patch relocation and parameter initialization,
2232 allocate zeroed data for NOBITS sections now. Note that after
2233 this we cannot assume NOBITS are really empty. */
2234 for (i = 0; i < f->header.e_shnum; ++i) {
2235 struct obj_section *s = f->sections[i];
2236 if (s->header.sh_type == SHT_NOBITS) {
2237 s->contents = memset(xmalloc(s->header.sh_size),
2238 0, s->header.sh_size);
2239 s->header.sh_type = SHT_PROGBITS;
2240 }
2241 }
2242}
2243
2244unsigned long obj_load_size(struct obj_file *f)
2245{
2246 unsigned long dot = 0;
2247 struct obj_section *sec;
2248
2249 /* Finalize the positions of the sections relative to one another. */
2250
2251 for (sec = f->load_order; sec; sec = sec->load_next) {
2252 ElfW(Addr) align;
2253
2254 align = sec->header.sh_addralign;
2255 if (align && (dot & (align - 1)))
2256 dot = (dot | (align - 1)) + 1;
2257
2258 sec->header.sh_addr = dot;
2259 dot += sec->header.sh_size;
2260 }
2261
2262 return dot;
2263}
2264
2265int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2266{
2267 int i, n = f->header.e_shnum;
2268 int ret = 1;
2269
2270 /* Finalize the addresses of the sections. */
2271
2272 f->baseaddr = base;
2273 for (i = 0; i < n; ++i)
2274 f->sections[i]->header.sh_addr += base;
2275
2276 /* And iterate over all of the relocations. */
2277
2278 for (i = 0; i < n; ++i) {
2279 struct obj_section *relsec, *symsec, *targsec, *strsec;
2280 ElfW(RelM) * rel, *relend;
2281 ElfW(Sym) * symtab;
2282 const char *strtab;
2283
2284 relsec = f->sections[i];
2285 if (relsec->header.sh_type != SHT_RELM)
2286 continue;
2287
2288 symsec = f->sections[relsec->header.sh_link];
2289 targsec = f->sections[relsec->header.sh_info];
2290 strsec = f->sections[symsec->header.sh_link];
2291
2292 rel = (ElfW(RelM) *) relsec->contents;
2293 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2294 symtab = (ElfW(Sym) *) symsec->contents;
2295 strtab = (const char *) strsec->contents;
2296
2297 for (; rel < relend; ++rel) {
2298 ElfW(Addr) value = 0;
2299 struct obj_symbol *intsym = NULL;
2300 unsigned long symndx;
2301 ElfW(Sym) * extsym = 0;
2302 const char *errmsg;
2303
2304 /* Attempt to find a value to use for this relocation. */
2305
2306 symndx = ELFW(R_SYM) (rel->r_info);
2307 if (symndx) {
2308 /* Note we've already checked for undefined symbols. */
2309
2310 extsym = &symtab[symndx];
2311 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2312 /* Local symbols we look up in the local table to be sure
2313 we get the one that is really intended. */
2314 intsym = f->local_symtab[symndx];
2315 } else {
2316 /* Others we look up in the hash table. */
2317 const char *name;
2318 if (extsym->st_name)
2319 name = strtab + extsym->st_name;
2320 else
2321 name = f->sections[extsym->st_shndx]->name;
2322 intsym = obj_find_symbol(f, name);
2323 }
2324
2325 value = obj_symbol_final_value(f, intsym);
2326 intsym->referenced = 1;
2327 }
2328#if SHT_RELM == SHT_RELA
2329#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2330 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2331 if (!extsym || !extsym->st_name ||
2332 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2333#endif
2334 value += rel->r_addend;
2335#endif
2336
2337 /* Do it! */
2338 switch (arch_apply_relocation
2339 (f, targsec, symsec, intsym, rel, value)) {
2340 case obj_reloc_ok:
2341 break;
2342
2343 case obj_reloc_overflow:
2344 errmsg = "Relocation overflow";
2345 goto bad_reloc;
2346 case obj_reloc_dangerous:
2347 errmsg = "Dangerous relocation";
2348 goto bad_reloc;
2349 case obj_reloc_unhandled:
2350 errmsg = "Unhandled relocation";
2351 bad_reloc:
2352 if (extsym) {
Matt Kraaid537a952000-07-14 01:51:25 +00002353 errorMsg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002354 (long) ELFW(R_TYPE) (rel->r_info),
2355 strtab + extsym->st_name);
2356 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002357 errorMsg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002358 (long) ELFW(R_TYPE) (rel->r_info));
2359 }
2360 ret = 0;
2361 break;
2362 }
2363 }
2364 }
2365
2366 /* Finally, take care of the patches. */
2367
2368 if (f->string_patches) {
2369 struct obj_string_patch *p;
2370 struct obj_section *strsec;
2371 ElfW(Addr) strsec_base;
2372 strsec = obj_find_section(f, ".kstrtab");
2373 strsec_base = strsec->header.sh_addr;
2374
2375 for (p = f->string_patches; p; p = p->next) {
2376 struct obj_section *targsec = f->sections[p->reloc_secidx];
2377 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2378 = strsec_base + p->string_offset;
2379 }
2380 }
2381
2382 if (f->symbol_patches) {
2383 struct obj_symbol_patch *p;
2384
2385 for (p = f->symbol_patches; p; p = p->next) {
2386 struct obj_section *targsec = f->sections[p->reloc_secidx];
2387 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2388 = obj_symbol_final_value(f, p->sym);
2389 }
2390 }
2391
2392 return ret;
2393}
2394
2395int obj_create_image(struct obj_file *f, char *image)
2396{
2397 struct obj_section *sec;
2398 ElfW(Addr) base = f->baseaddr;
2399
2400 for (sec = f->load_order; sec; sec = sec->load_next) {
2401 char *secimg;
2402
2403 if (sec->header.sh_size == 0)
2404 continue;
2405
2406 secimg = image + (sec->header.sh_addr - base);
2407
2408 /* Note that we allocated data for NOBITS sections earlier. */
2409 memcpy(secimg, sec->contents, sec->header.sh_size);
2410 }
2411
2412 return 1;
2413}
2414
2415/*======================================================================*/
2416
2417struct obj_file *obj_load(FILE * fp)
2418{
2419 struct obj_file *f;
2420 ElfW(Shdr) * section_headers;
2421 int shnum, i;
2422 char *shstrtab;
2423
2424 /* Read the file header. */
2425
2426 f = arch_new_file();
2427 memset(f, 0, sizeof(*f));
2428 f->symbol_cmp = strcmp;
2429 f->symbol_hash = obj_elf_hash;
2430 f->load_order_search_start = &f->load_order;
2431
2432 fseek(fp, 0, SEEK_SET);
2433 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002434 errorMsg("error reading ELF header: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002435 return NULL;
2436 }
2437
2438 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2439 || f->header.e_ident[EI_MAG1] != ELFMAG1
2440 || f->header.e_ident[EI_MAG2] != ELFMAG2
2441 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaid537a952000-07-14 01:51:25 +00002442 errorMsg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002443 return NULL;
2444 }
2445 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2446 || f->header.e_ident[EI_DATA] != ELFDATAM
2447 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2448 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaid537a952000-07-14 01:51:25 +00002449 errorMsg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002450 return NULL;
2451 }
2452 if (f->header.e_type != ET_REL) {
Matt Kraaid537a952000-07-14 01:51:25 +00002453 errorMsg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002454 return NULL;
2455 }
2456
2457 /* Read the section headers. */
2458
2459 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002460 errorMsg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002461 (unsigned long) f->header.e_shentsize,
2462 (unsigned long) sizeof(ElfW(Shdr)));
2463 return NULL;
2464 }
2465
2466 shnum = f->header.e_shnum;
2467 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2468 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2469
2470 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2471 fseek(fp, f->header.e_shoff, SEEK_SET);
2472 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002473 errorMsg("error reading ELF section headers: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002474 return NULL;
2475 }
2476
2477 /* Read the section data. */
2478
2479 for (i = 0; i < shnum; ++i) {
2480 struct obj_section *sec;
2481
2482 f->sections[i] = sec = arch_new_section();
2483 memset(sec, 0, sizeof(*sec));
2484
2485 sec->header = section_headers[i];
2486 sec->idx = i;
2487
2488 switch (sec->header.sh_type) {
2489 case SHT_NULL:
2490 case SHT_NOTE:
2491 case SHT_NOBITS:
2492 /* ignore */
2493 break;
2494
2495 case SHT_PROGBITS:
2496 case SHT_SYMTAB:
2497 case SHT_STRTAB:
2498 case SHT_RELM:
2499 if (sec->header.sh_size > 0) {
2500 sec->contents = xmalloc(sec->header.sh_size);
2501 fseek(fp, sec->header.sh_offset, SEEK_SET);
2502 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Eric Andersen8a24a672000-06-22 18:19:31 +00002503 errorMsg("error reading ELF section data: %s", strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002504 return NULL;
2505 }
2506 } else {
2507 sec->contents = NULL;
2508 }
2509 break;
2510
2511#if SHT_RELM == SHT_REL
2512 case SHT_RELA:
Matt Kraaid537a952000-07-14 01:51:25 +00002513 errorMsg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002514 return NULL;
2515#else
2516 case SHT_REL:
Matt Kraaid537a952000-07-14 01:51:25 +00002517 errorMsg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002518 return NULL;
2519#endif
2520
2521 default:
2522 if (sec->header.sh_type >= SHT_LOPROC) {
2523 /* Assume processor specific section types are debug
2524 info and can safely be ignored. If this is ever not
2525 the case (Hello MIPS?), don't put ifdefs here but
2526 create an arch_load_proc_section(). */
2527 break;
2528 }
2529
Matt Kraaid537a952000-07-14 01:51:25 +00002530 errorMsg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002531 (long) sec->header.sh_type);
2532 return NULL;
2533 }
2534 }
2535
2536 /* Do what sort of interpretation as needed by each section. */
2537
2538 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2539
2540 for (i = 0; i < shnum; ++i) {
2541 struct obj_section *sec = f->sections[i];
2542 sec->name = shstrtab + sec->header.sh_name;
2543 }
2544
2545 for (i = 0; i < shnum; ++i) {
2546 struct obj_section *sec = f->sections[i];
2547
2548 if (sec->header.sh_flags & SHF_ALLOC)
2549 obj_insert_section_load_order(f, sec);
2550
2551 switch (sec->header.sh_type) {
2552 case SHT_SYMTAB:
2553 {
2554 unsigned long nsym, j;
2555 char *strtab;
2556 ElfW(Sym) * sym;
2557
2558 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002559 errorMsg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 (unsigned long) sec->header.sh_entsize,
2561 (unsigned long) sizeof(ElfW(Sym)));
2562 return NULL;
2563 }
2564
2565 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2566 strtab = f->sections[sec->header.sh_link]->contents;
2567 sym = (ElfW(Sym) *) sec->contents;
2568
2569 /* Allocate space for a table of local symbols. */
2570 j = f->local_symtab_size = sec->header.sh_info;
2571 f->local_symtab = xmalloc(j *=
2572 sizeof(struct obj_symbol *));
2573 memset(f->local_symtab, 0, j);
2574
2575 /* Insert all symbols into the hash table. */
2576 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2577 const char *name;
2578 if (sym->st_name)
2579 name = strtab + sym->st_name;
2580 else
2581 name = f->sections[sym->st_shndx]->name;
2582
2583 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2584 sym->st_value, sym->st_size);
2585 }
2586 }
2587 break;
2588
2589 case SHT_RELM:
2590 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaid537a952000-07-14 01:51:25 +00002591 errorMsg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002592 (unsigned long) sec->header.sh_entsize,
2593 (unsigned long) sizeof(ElfW(RelM)));
2594 return NULL;
2595 }
2596 break;
2597 }
2598 }
2599
2600 return f;
2601}
2602
2603static void hide_special_symbols(struct obj_file *f)
2604{
2605 static const char *const specials[] = {
2606 "cleanup_module",
2607 "init_module",
2608 "kernel_version",
2609 NULL
2610 };
2611
2612 struct obj_symbol *sym;
2613 const char *const *p;
2614
2615 for (p = specials; *p; ++p)
2616 if ((sym = obj_find_symbol(f, *p)) != NULL)
2617 sym->info =
2618 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2619}
2620
2621
2622
2623extern int insmod_main( int argc, char **argv)
2624{
2625 int k_crcs;
2626 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002627 int len;
2628 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002629 unsigned long m_size;
2630 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002631 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002632 struct obj_file *f;
2633 char m_name[BUFSIZ + 1] = "\0";
2634 int exit_status = FALSE;
2635 int m_has_modinfo;
2636#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2637 int k_version;
2638 char k_strversion[STRVERSIONLEN];
2639 char m_strversion[STRVERSIONLEN];
2640 int m_version;
2641 int m_crcs;
2642#endif
2643
Erik Andersen02104321999-12-17 18:57:34 +00002644
Erik Andersene49d5ec2000-02-08 19:58:47 +00002645 if (argc <= 1) {
Erik Andersen02104321999-12-17 18:57:34 +00002646 usage(insmod_usage);
Erik Andersen02104321999-12-17 18:57:34 +00002647 }
Erik Andersen02104321999-12-17 18:57:34 +00002648
Erik Andersene49d5ec2000-02-08 19:58:47 +00002649 /* Parse any options */
2650 while (--argc > 0 && **(++argv) == '-') {
2651 while (*(++(*argv))) {
2652 switch (**argv) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002653 case 'f': /* force loading */
2654 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002655 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002656 case 'k': /* module loaded by kerneld, auto-cleanable */
2657 flag_autoclean = 1;
2658 break;
2659 case 'v': /* verbose output */
2660 flag_verbose = 1;
2661 break;
2662 case 'x': /* do not export externs */
2663 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002664 break;
2665 default:
2666 usage(insmod_usage);
2667 }
2668 }
Erik Andersend387d011999-12-21 02:55:11 +00002669 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002670
Eric Andersen9f16d612000-06-12 23:11:16 +00002671 if (argc <= 0) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002672 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002673 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002674 /* Grab the module name */
Eric Andersen9f16d612000-06-12 23:11:16 +00002675 if ((tmp = strrchr(*argv, '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002676 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002677 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002678 tmp = *argv;
Eric Andersen9f16d612000-06-12 23:11:16 +00002679 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002680 len = strlen(tmp);
2681
2682 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2683 len -= 2;
2684 memcpy(m_name, tmp, len);
2685 strcpy(m_fullName, m_name);
2686 strcat(m_fullName, ".o");
2687
2688 /* Get a filedesc for the module */
2689 if ((fp = fopen(*argv, "r")) == NULL) {
2690 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
2691 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002692 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002694 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002695 || ((fp = fopen(m_filename, "r")) == NULL))
2696 {
Eric Andersen8a24a672000-06-22 18:19:31 +00002697 errorMsg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002698 exit(FALSE);
2699 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002700 } else
2701 fatalError("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002702 } else
2703 memcpy(m_filename, *argv, strlen(*argv));
Erik Andersend387d011999-12-21 02:55:11 +00002704
2705
Erik Andersene49d5ec2000-02-08 19:58:47 +00002706 if ((f = obj_load(fp)) == NULL) {
2707 perror("Could not load the module\n");
2708 exit(FALSE);
Erik Andersend387d011999-12-21 02:55:11 +00002709 }
Erik Andersend387d011999-12-21 02:55:11 +00002710
Eric Andersen9f16d612000-06-12 23:11:16 +00002711 if (get_modinfo_value(f, "kernel_version") == NULL)
2712 m_has_modinfo = 0;
2713 else
2714 m_has_modinfo = 1;
2715
2716#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2717 /* Version correspondence? */
2718
2719 k_version = get_kernel_version(k_strversion);
2720 if (m_has_modinfo) {
2721 m_version = new_get_module_version(f, m_strversion);
2722 } else {
2723 m_version = old_get_module_version(f, m_strversion);
2724 if (m_version == -1) {
Matt Kraaid537a952000-07-14 01:51:25 +00002725 errorMsg("couldn't find the kernel version the module was "
2726 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002727 goto out;
2728 }
2729 }
2730
2731 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2732 if (flag_force_load) {
Matt Kraaid537a952000-07-14 01:51:25 +00002733 errorMsg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002734 "\t%s was compiled for kernel version %s\n"
2735 "\twhile this kernel is version %s\n",
2736 m_filename, m_strversion, k_strversion);
2737 } else {
Matt Kraaid537a952000-07-14 01:51:25 +00002738 errorMsg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002739 "\t%s was compiled for kernel version %s\n"
2740 "\twhile this kernel is version %s.\n",
2741 m_filename, m_strversion, k_strversion);
2742 goto out;
2743 }
2744 }
2745 k_crcs = 0;
2746#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2747
2748 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2749
2750 if (k_new_syscalls) {
2751#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
2752 if (!new_get_kernel_symbols())
2753 goto out;
2754 k_crcs = new_is_kernel_checksummed();
2755#else
Matt Kraaid537a952000-07-14 01:51:25 +00002756 errorMsg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002757 goto out;
2758#endif
2759 } else {
2760#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
2761 if (!old_get_kernel_symbols())
2762 goto out;
2763 k_crcs = old_is_kernel_checksummed();
2764#else
Matt Kraaid537a952000-07-14 01:51:25 +00002765 errorMsg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002766 goto out;
2767#endif
2768 }
2769
2770#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2771 if (m_has_modinfo)
2772 m_crcs = new_is_module_checksummed(f);
2773 else
2774 m_crcs = old_is_module_checksummed(f);
2775
2776 if (m_crcs != k_crcs)
2777 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
2778#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2779
Erik Andersene49d5ec2000-02-08 19:58:47 +00002780 /* Let the module know about the kernel symbols. */
2781 add_kernel_symbols(f);
2782
Eric Andersen9f16d612000-06-12 23:11:16 +00002783 /* Allocate common symbols, symbol tables, and string tables. */
2784
2785 if (k_new_syscalls
2786 ? !new_create_this_module(f, m_name)
2787 : !old_create_mod_use_count(f))
2788 {
2789 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002790 }
2791
Eric Andersen9f16d612000-06-12 23:11:16 +00002792 if (!obj_check_undefineds(f)) {
2793 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002794 }
2795 obj_allocate_commons(f);
2796
Eric Andersen9f16d612000-06-12 23:11:16 +00002797 if (optind < argc) {
2798 if (m_has_modinfo
2799 ? !new_process_module_arguments(f, argc - optind, argv + optind)
2800 : !old_process_module_arguments(f, argc - optind, argv + optind))
2801 {
2802 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002803 }
2804 }
2805
Eric Andersen9f16d612000-06-12 23:11:16 +00002806 arch_create_got(f);
2807 hide_special_symbols(f);
2808
2809 if (k_new_syscalls)
2810 new_create_module_ksymtab(f);
2811
Erik Andersene49d5ec2000-02-08 19:58:47 +00002812 /* Find current size of the module */
2813 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00002814
2815
Erik Andersene49d5ec2000-02-08 19:58:47 +00002816 errno = 0;
2817 m_addr = create_module(m_name, m_size);
2818 switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002819 case 0:
2820 break;
2821 case EEXIST:
Matt Kraaid537a952000-07-14 01:51:25 +00002822 errorMsg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002823 goto out;
2824 case ENOMEM:
Matt Kraaid537a952000-07-14 01:51:25 +00002825 errorMsg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002826 m_size);
2827 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00002828 default:
Eric Andersen8a24a672000-06-22 18:19:31 +00002829 errorMsg("create_module: %s: %s", m_name, strerror(errno));
Eric Andersen9f16d612000-06-12 23:11:16 +00002830 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002831 }
Erik Andersend387d011999-12-21 02:55:11 +00002832
Eric Andersen9f16d612000-06-12 23:11:16 +00002833 if (!obj_relocate(f, m_addr)) {
2834 delete_module(m_name);
2835 goto out;
2836 }
Erik Andersend387d011999-12-21 02:55:11 +00002837
Eric Andersen9f16d612000-06-12 23:11:16 +00002838 if (k_new_syscalls
2839 ? !new_init_module(m_name, f, m_size)
2840 : !old_init_module(m_name, f, m_size))
2841 {
2842 delete_module(m_name);
2843 goto out;
2844 }
2845
2846 exit_status = TRUE;
2847
2848out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00002849 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00002850 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00002851}