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