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