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