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