blob: 57a152c013f8ae0ef7c7a36d974ae5cfc6fdf0ac [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 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00005 * Copyright (C) 1999,2000,2001 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 *
Eric Andersenfe4208f2000-09-24 03:44:29 +00009 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000010 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
11 *
12 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
13 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
14 * very minor changes required to also work with StrongArm and presumably
15 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 *
Eric Andersen9f16d612000-06-12 23:11:16 +000017 * Based almost entirely on the Linux modutils-2.3.11 implementation.
18 * Copyright 1996, 1997 Linux International.
19 * New implementation contributed by Richard Henderson <rth@tamu.edu>
20 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
21 * Restructured (and partly rewritten) by:
22 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000023 *
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32 * General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License
35 * along with this program; if not, write to the Free Software
36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
37 *
38 */
39
Eric Andersen3570a342000-09-25 21:45:58 +000040#include "busybox.h"
Erik Andersen02104321999-12-17 18:57:34 +000041#include <stdlib.h>
42#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000043#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000044#include <errno.h>
45#include <unistd.h>
46#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000047#include <ctype.h>
48#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000049#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000050#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000051#include <sys/utsname.h>
Eric Andersened3ef502001-01-27 08:24:39 +000052#include <sys/syscall.h>
53#include <linux/unistd.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000054
55//----------------------------------------------------------------------------
56//--------modutils module.h, lines 45-242
57//----------------------------------------------------------------------------
58
59/* Definitions for the Linux module syscall interface.
60 Copyright 1996, 1997 Linux International.
61
62 Contributed by Richard Henderson <rth@tamu.edu>
63
64 This file is part of the Linux modutils.
65
66 This program is free software; you can redistribute it and/or modify it
67 under the terms of the GNU General Public License as published by the
68 Free Software Foundation; either version 2 of the License, or (at your
69 option) any later version.
70
71 This program is distributed in the hope that it will be useful, but
72 WITHOUT ANY WARRANTY; without even the implied warranty of
73 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74 General Public License for more details.
75
76 You should have received a copy of the GNU General Public License
77 along with this program; if not, write to the Free Software Foundation,
78 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
79
80
81#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +000082static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +000083
Eric Andersen8ec10a92001-01-27 09:33:39 +000084#ident "$Id: insmod.c,v 1.44 2001/01/27 09:33:38 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +000085
86/* This file contains the structures used by the 2.0 and 2.1 kernels.
87 We do not use the kernel headers directly because we do not wish
88 to be dependant on a particular kernel version to compile insmod. */
89
90
91/*======================================================================*/
92/* The structures used by Linux 2.0. */
93
94/* The symbol format used by get_kernel_syms(2). */
95struct old_kernel_sym
96{
97 unsigned long value;
98 char name[60];
99};
100
101struct old_module_ref
102{
103 unsigned long module; /* kernel addresses */
104 unsigned long next;
105};
106
107struct old_module_symbol
108{
109 unsigned long addr;
110 unsigned long name;
111};
112
113struct old_symbol_table
114{
115 int size; /* total, including string table!!! */
116 int n_symbols;
117 int n_refs;
118 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
119 struct old_module_ref ref[0]; /* actual size defined by n_refs */
120};
121
122struct old_mod_routines
123{
124 unsigned long init;
125 unsigned long cleanup;
126};
127
128struct old_module
129{
130 unsigned long next;
131 unsigned long ref; /* the list of modules that refer to me */
132 unsigned long symtab;
133 unsigned long name;
134 int size; /* size of module in pages */
135 unsigned long addr; /* address of module */
136 int state;
137 unsigned long cleanup; /* cleanup routine */
138};
139
140/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000141static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000142
143int get_kernel_syms(struct old_kernel_sym *);
144int old_sys_init_module(const char *name, char *code, unsigned codesize,
145 struct old_mod_routines *, struct old_symbol_table *);
146
147/*======================================================================*/
148/* For sizeof() which are related to the module platform and not to the
149 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
150
151#define tgt_sizeof_char sizeof(char)
152#define tgt_sizeof_short sizeof(short)
153#define tgt_sizeof_int sizeof(int)
154#define tgt_sizeof_long sizeof(long)
155#define tgt_sizeof_char_p sizeof(char *)
156#define tgt_sizeof_void_p sizeof(void *)
157#define tgt_long long
158
159#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
160#undef tgt_sizeof_long
161#undef tgt_sizeof_char_p
162#undef tgt_sizeof_void_p
163#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000164static const int tgt_sizeof_long = 8;
165static const int tgt_sizeof_char_p = 8;
166static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000167#define tgt_long long long
168#endif
169
170/*======================================================================*/
171/* The structures used in Linux 2.1. */
172
173/* Note: new_module_symbol does not use tgt_long intentionally */
174struct new_module_symbol
175{
176 unsigned long value;
177 unsigned long name;
178};
179
180struct new_module_persist;
181
182struct new_module_ref
183{
184 unsigned tgt_long dep; /* kernel addresses */
185 unsigned tgt_long ref;
186 unsigned tgt_long next_ref;
187};
188
189struct new_module
190{
191 unsigned tgt_long size_of_struct; /* == sizeof(module) */
192 unsigned tgt_long next;
193 unsigned tgt_long name;
194 unsigned tgt_long size;
195
196 tgt_long usecount;
197 unsigned tgt_long flags; /* AUTOCLEAN et al */
198
199 unsigned nsyms;
200 unsigned ndeps;
201
202 unsigned tgt_long syms;
203 unsigned tgt_long deps;
204 unsigned tgt_long refs;
205 unsigned tgt_long init;
206 unsigned tgt_long cleanup;
207 unsigned tgt_long ex_table_start;
208 unsigned tgt_long ex_table_end;
209#ifdef __alpha__
210 unsigned tgt_long gp;
211#endif
212 /* Everything after here is extension. */
213 unsigned tgt_long persist_start;
214 unsigned tgt_long persist_end;
215 unsigned tgt_long can_unload;
216 unsigned tgt_long runsize;
217};
218
219struct new_module_info
220{
221 unsigned long addr;
222 unsigned long size;
223 unsigned long flags;
224 long usecount;
225};
226
227/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000228static const int NEW_MOD_RUNNING = 1;
229static const int NEW_MOD_DELETED = 2;
230static const int NEW_MOD_AUTOCLEAN = 4;
231static const int NEW_MOD_VISITED = 8;
232static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000233
234int new_sys_init_module(const char *name, const struct new_module *);
235int query_module(const char *name, int which, void *buf, size_t bufsize,
236 size_t *ret);
237
238/* Values for query_module's which. */
239
Mark Whitley59ab0252001-01-23 22:30:04 +0000240static const int QM_MODULES = 1;
241static const int QM_DEPS = 2;
242static const int QM_REFS = 3;
243static const int QM_SYMBOLS = 4;
244static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000245
246/*======================================================================*/
247/* The system calls unchanged between 2.0 and 2.1. */
248
249unsigned long create_module(const char *, size_t);
250int delete_module(const char *);
251
252
253#endif /* module.h */
254
255//----------------------------------------------------------------------------
256//--------end of modutils module.h
257//----------------------------------------------------------------------------
258
259
260
261//----------------------------------------------------------------------------
262//--------modutils obj.h, lines 253-462
263//----------------------------------------------------------------------------
264
265/* Elf object file loading and relocation routines.
266 Copyright 1996, 1997 Linux International.
267
268 Contributed by Richard Henderson <rth@tamu.edu>
269
270 This file is part of the Linux modutils.
271
272 This program is free software; you can redistribute it and/or modify it
273 under the terms of the GNU General Public License as published by the
274 Free Software Foundation; either version 2 of the License, or (at your
275 option) any later version.
276
277 This program is distributed in the hope that it will be useful, but
278 WITHOUT ANY WARRANTY; without even the implied warranty of
279 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
280 General Public License for more details.
281
282 You should have received a copy of the GNU General Public License
283 along with this program; if not, write to the Free Software Foundation,
284 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
285
286
287#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000288static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000289
Eric Andersen8ec10a92001-01-27 09:33:39 +0000290#ident "$Id: insmod.c,v 1.44 2001/01/27 09:33:38 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000291
292/* The relocatable object is manipulated using elfin types. */
293
294#include <stdio.h>
295#include <elf.h>
296
297
298/* Machine-specific elf macros for i386 et al. */
299
Eric Andersenfe4208f2000-09-24 03:44:29 +0000300/* the SH changes have only been tested on the SH4 in =little endian= mode */
301/* I'm not sure about big endian, so let's warn: */
302
303#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
304#error insmod.c may require changes for use on big endian SH4/SH3
305#endif
306
307/* it may or may not work on the SH1/SH2... So let's error on those
308 also */
309#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
310#error insmod.c may require changes for non-SH3/SH4 use
311#endif
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313#define ELFCLASSM ELFCLASS32
314#define ELFDATAM ELFDATA2LSB
315
Eric Andersen9f16d612000-06-12 23:11:16 +0000316
Eric Andersenfe4208f2000-09-24 03:44:29 +0000317
318#if defined(__sh__)
319
320#define MATCH_MACHINE(x) (x == EM_SH)
321#define SHT_RELM SHT_RELA
322#define Elf32_RelM Elf32_Rela
323
Eric Andersen21adca72000-12-06 18:18:26 +0000324#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000325
Eric Andersen21adca72000-12-06 18:18:26 +0000326#define MATCH_MACHINE(x) (x == EM_ARM)
327#define SHT_RELM SHT_REL
328#define Elf32_RelM Elf32_Rel
329
330#elif defined(__i386__)
331
332/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000333/* this is the previous behavior, but it does result in
334 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000335#ifndef EM_486
336#define MATCH_MACHINE(x) (x == EM_386)
337#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000338#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000339#endif
340
Eric Andersen9f16d612000-06-12 23:11:16 +0000341#define SHT_RELM SHT_REL
342#define Elf32_RelM Elf32_Rel
343
Eric Andersen21adca72000-12-06 18:18:26 +0000344#else
Eric Andersend5cad142001-01-26 02:23:57 +0000345#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000346#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000347
348#ifndef ElfW
349# if ELFCLASSM == ELFCLASS32
350# define ElfW(x) Elf32_ ## x
351# define ELFW(x) ELF32_ ## x
352# else
353# define ElfW(x) Elf64_ ## x
354# define ELFW(x) ELF64_ ## x
355# endif
356#endif
357
358/* For some reason this is missing from libc5. */
359#ifndef ELF32_ST_INFO
360# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
361#endif
362
363#ifndef ELF64_ST_INFO
364# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
365#endif
366
367struct obj_string_patch;
368struct obj_symbol_patch;
369
370struct obj_section
371{
372 ElfW(Shdr) header;
373 const char *name;
374 char *contents;
375 struct obj_section *load_next;
376 int idx;
377};
378
379struct obj_symbol
380{
381 struct obj_symbol *next; /* hash table link */
382 const char *name;
383 unsigned long value;
384 unsigned long size;
385 int secidx; /* the defining section index/module */
386 int info;
387 int ksymidx; /* for export to the kernel symtab */
388 int referenced; /* actually used in the link */
389};
390
391/* Hardcode the hash table size. We shouldn't be needing so many
392 symbols that we begin to degrade performance, and we get a big win
393 by giving the compiler a constant divisor. */
394
395#define HASH_BUCKETS 521
396
397struct obj_file
398{
399 ElfW(Ehdr) header;
400 ElfW(Addr) baseaddr;
401 struct obj_section **sections;
402 struct obj_section *load_order;
403 struct obj_section **load_order_search_start;
404 struct obj_string_patch *string_patches;
405 struct obj_symbol_patch *symbol_patches;
406 int (*symbol_cmp)(const char *, const char *);
407 unsigned long (*symbol_hash)(const char *);
408 unsigned long local_symtab_size;
409 struct obj_symbol **local_symtab;
410 struct obj_symbol *symtab[HASH_BUCKETS];
411};
412
413enum obj_reloc
414{
415 obj_reloc_ok,
416 obj_reloc_overflow,
417 obj_reloc_dangerous,
418 obj_reloc_unhandled
419};
420
421struct obj_string_patch
422{
423 struct obj_string_patch *next;
424 int reloc_secidx;
425 ElfW(Addr) reloc_offset;
426 ElfW(Addr) string_offset;
427};
428
429struct obj_symbol_patch
430{
431 struct obj_symbol_patch *next;
432 int reloc_secidx;
433 ElfW(Addr) reloc_offset;
434 struct obj_symbol *sym;
435};
436
437
438/* Generic object manipulation routines. */
439
440unsigned long obj_elf_hash(const char *);
441
442unsigned long obj_elf_hash_n(const char *, unsigned long len);
443
444struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
445 unsigned long symidx, int info, int secidx,
446 ElfW(Addr) value, unsigned long size);
447
448struct obj_symbol *obj_find_symbol (struct obj_file *f,
449 const char *name);
450
451ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
452 struct obj_symbol *sym);
453
454void obj_set_symbol_compare(struct obj_file *f,
455 int (*cmp)(const char *, const char *),
456 unsigned long (*hash)(const char *));
457
458struct obj_section *obj_find_section (struct obj_file *f,
459 const char *name);
460
461void obj_insert_section_load_order (struct obj_file *f,
462 struct obj_section *sec);
463
464struct obj_section *obj_create_alloced_section (struct obj_file *f,
465 const char *name,
466 unsigned long align,
467 unsigned long size);
468
469struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
470 const char *name,
471 unsigned long align,
472 unsigned long size);
473
474void *obj_extend_section (struct obj_section *sec, unsigned long more);
475
476int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
477 const char *string);
478
479int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
480 struct obj_symbol *sym);
481
482int obj_check_undefineds(struct obj_file *f);
483
484void obj_allocate_commons(struct obj_file *f);
485
486unsigned long obj_load_size (struct obj_file *f);
487
488int obj_relocate (struct obj_file *f, ElfW(Addr) base);
489
490struct obj_file *obj_load(FILE *f);
491
492int obj_create_image (struct obj_file *f, char *image);
493
494/* Architecture specific manipulation routines. */
495
496struct obj_file *arch_new_file (void);
497
498struct obj_section *arch_new_section (void);
499
500struct obj_symbol *arch_new_symbol (void);
501
502enum obj_reloc arch_apply_relocation (struct obj_file *f,
503 struct obj_section *targsec,
504 struct obj_section *symsec,
505 struct obj_symbol *sym,
506 ElfW(RelM) *rel, ElfW(Addr) value);
507
508int arch_create_got (struct obj_file *f);
509
510struct new_module;
511int arch_init_module (struct obj_file *f, struct new_module *);
512
513#endif /* obj.h */
514//----------------------------------------------------------------------------
515//--------end of modutils obj.h
516//----------------------------------------------------------------------------
517
518
519
520
Erik Andersen02104321999-12-17 18:57:34 +0000521
Erik Andersend387d011999-12-21 02:55:11 +0000522#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000523static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000524
Eric Andersen9f16d612000-06-12 23:11:16 +0000525/*======================================================================*/
526
527int flag_force_load = 0;
528int flag_autoclean = 0;
529int flag_verbose = 0;
530int flag_export = 1;
531
532
533/*======================================================================*/
534
Eric Andersenfe4208f2000-09-24 03:44:29 +0000535/* previously, these were named i386_* but since we could be
536 compiling for the sh, I've renamed them to the more general
537 arch_* These structures are the same between the x86 and SH,
538 and we can't support anything else right now anyway. In the
539 future maybe they should be #if defined'd */
540
Eric Andersen21adca72000-12-06 18:18:26 +0000541/* Done ;-) */
542
543#if defined(__arm__)
544struct arm_plt_entry
545{
546 int offset;
547 int allocated:1;
548 int inited:1; /* has been set up */
549};
550#endif
551
Eric Andersenfe4208f2000-09-24 03:44:29 +0000552struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000553 int offset;
554 unsigned offset_done:1;
555 unsigned reloc_done:1;
556};
557
Eric Andersenfe4208f2000-09-24 03:44:29 +0000558struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000559 struct obj_file root;
Eric Andersen21adca72000-12-06 18:18:26 +0000560#if defined(__arm__)
561 struct obj_section *plt;
562#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000563 struct obj_section *got;
564};
565
Eric Andersenfe4208f2000-09-24 03:44:29 +0000566struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000567 struct obj_symbol root;
Eric Andersen21adca72000-12-06 18:18:26 +0000568#if defined(__arm__)
569 struct arm_plt_entry pltent;
570#endif
Eric Andersenfe4208f2000-09-24 03:44:29 +0000571 struct arch_got_entry gotent;
Eric Andersen9f16d612000-06-12 23:11:16 +0000572};
573
574
Eric Andersen9f16d612000-06-12 23:11:16 +0000575struct external_module {
576 const char *name;
577 ElfW(Addr) addr;
578 int used;
579 size_t nsyms;
580 struct new_module_symbol *syms;
581};
582
583struct new_module_symbol *ksyms;
584size_t nksyms;
585
586struct external_module *ext_modules;
587int n_ext_modules;
588int n_ext_modules_used;
589
Erik Andersend387d011999-12-21 02:55:11 +0000590
591
Erik Andersen02104321999-12-17 18:57:34 +0000592/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000593#define __NR_new_sys_init_module __NR_init_module
594_syscall2(int, new_sys_init_module, const char *, name,
595 const struct new_module *, info)
596#define __NR_old_sys_init_module __NR_init_module
597_syscall5(int, old_sys_init_module, const char *, name, char *, code,
598 unsigned, codesize, struct old_mod_routines *, routines,
599 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000600#ifndef BB_RMMOD
601_syscall1(int, delete_module, const char *, name)
602#else
603extern int delete_module(const char *);
604#endif
605
Eric Andersenfe4208f2000-09-24 03:44:29 +0000606/* This is kind of troublesome. See, we don't actually support
607 the m68k or the arm the same way we support i386 and (now)
608 sh. In doing my SH patch, I just assumed that whatever works
609 for i386 also works for m68k and arm since currently insmod.c
610 does nothing special for them. If this isn't true, the below
611 line is rather misleading IMHO, and someone should either
612 change it or add more proper architecture-dependent support
613 for these boys.
614
615 -- Bryan Rittmeyer <bryan@ixiacom.com> */
616
Eric Andersenf5d5e772001-01-24 23:34:48 +0000617#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen21adca72000-12-06 18:18:26 +0000618_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
619#endif
620
Erik Andersen02104321999-12-17 18:57:34 +0000621#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
622/* Jump through hoops to fixup error return codes */
623#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000624static inline _syscall2(long, _create_module, const char *, name, size_t,
625 size)
Erik Andersen02104321999-12-17 18:57:34 +0000626unsigned long create_module(const char *name, size_t size)
627{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000628 long ret = _create_module(name, size);
629
630 if (ret == -1 && errno > 125) {
631 ret = -errno;
632 errno = 0;
633 }
634 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000635}
636#else
637_syscall2(unsigned long, create_module, const char *, name, size_t, size)
638#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000639static char m_filename[BUFSIZ + 1] = "\0";
640static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000641
Eric Andersen9f16d612000-06-12 23:11:16 +0000642/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000643
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
645static int findNamedModule(const char *fileName, struct stat *statbuf,
646 void *userDate)
647{
648 char *fullName = (char *) userDate;
649
650
651 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000652 return (FALSE);
653 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000654 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000655
656 if (tmp == NULL)
657 tmp = (char *) fileName;
658 else
659 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000660 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000661 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000662 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000663 return (FALSE);
664 }
Erik Andersend387d011999-12-21 02:55:11 +0000665 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000666 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000667}
668
Erik Andersen02104321999-12-17 18:57:34 +0000669
Eric Andersen9f16d612000-06-12 23:11:16 +0000670/*======================================================================*/
671
672struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000673{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000674 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000675 f = xmalloc(sizeof(*f));
676 f->got = NULL;
677 return &f->root;
678}
679
680struct obj_section *arch_new_section(void)
681{
682 return xmalloc(sizeof(struct obj_section));
683}
684
685struct obj_symbol *arch_new_symbol(void)
686{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000687 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000688 sym = xmalloc(sizeof(*sym));
689 memset(&sym->gotent, 0, sizeof(sym->gotent));
690 return &sym->root;
691}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000692
Eric Andersen9f16d612000-06-12 23:11:16 +0000693enum obj_reloc
694arch_apply_relocation(struct obj_file *f,
695 struct obj_section *targsec,
696 struct obj_section *symsec,
697 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000698 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000699{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000700 struct arch_file *ifile = (struct arch_file *) f;
701 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000702
Eric Andersen21adca72000-12-06 18:18:26 +0000703 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
704 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
705 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
706#if defined(__arm__)
707 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
708
709 struct arm_plt_entry *pe;
710 unsigned long *ip;
711#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000712
713 enum obj_reloc ret = obj_reloc_ok;
714
715 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000716
717/* even though these constants seem to be the same for
718 the i386 and the sh, we "#if define" them for clarity
719 and in case that ever changes */
720#if defined(__sh__)
721 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000722#elif defined(__arm__)
723 case R_ARM_NONE:
724#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000725 case R_386_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000726#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000727 break;
728
Eric Andersenfe4208f2000-09-24 03:44:29 +0000729#if defined(__sh__)
730 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000731#elif defined(__arm__)
732 case R_ARM_ABS32:
733#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000734 case R_386_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000735#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000736 *loc += v;
737 break;
738
Eric Andersen21adca72000-12-06 18:18:26 +0000739#if defined(__arm__)
740#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000741 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000742 *loc += v - dot;
743 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000744#elif defined(__i386__)
745 case R_386_PLT32:
746 case R_386_PC32:
747 *loc += v - dot;
748 break;
749#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000750
Eric Andersenfe4208f2000-09-24 03:44:29 +0000751#if defined(__sh__)
752 case R_SH_PLT32:
753 *loc = v - dot;
754 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000755#elif defined(__arm__)
756 case R_ARM_PC24:
757 case R_ARM_PLT32:
758 /* find the plt entry and initialize it if necessary */
759 assert(isym != NULL);
760 pe = (struct arm_plt_entry*) &isym->pltent;
761 if (! pe->inited) {
762 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
763 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
764 ip[1] = v; /* sym@ */
765 pe->inited = 1;
766 }
767
768 /* relative distance to target */
769 v -= dot;
770 /* if the target is too far away.... */
771 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
772 /* go via the plt */
773 v = plt + pe->offset - dot;
774 }
775 if (v & 3)
776 ret = obj_reloc_dangerous;
777
778 /* Convert to words. */
779 v >>= 2;
780
781 /* merge the offset into the instruction. */
782 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
783 break;
784#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000785#endif
786
787
Eric Andersen21adca72000-12-06 18:18:26 +0000788#if defined(__arm__)
789#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 case R_SH_GLOB_DAT:
791 case R_SH_JMP_SLOT:
792 *loc = v;
793 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000794#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000795 case R_386_GLOB_DAT:
796 case R_386_JMP_SLOT:
797 *loc = v;
798 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000799#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000800
Eric Andersen21adca72000-12-06 18:18:26 +0000801#if defined(__arm__)
802#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000803 case R_SH_RELATIVE:
804 *loc += f->baseaddr + rel->r_addend;
805 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000806#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000807 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000808 *loc += f->baseaddr;
809 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000810#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000811
Eric Andersenfe4208f2000-09-24 03:44:29 +0000812#if defined(__sh__)
813 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +0000814#elif defined(__arm__)
815 case R_ARM_GOTPC:
816#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000817 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000818#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000819 assert(got != 0);
820#if defined(__sh__)
821 *loc += got - dot + rel->r_addend;;
822#elif defined(__i386__) || defined(__arm__)
823 *loc += got - dot;
824#endif
825 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000826
Eric Andersenfe4208f2000-09-24 03:44:29 +0000827#if defined(__sh__)
828 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000829#elif defined(__arm__)
830 case R_ARM_GOT32:
831#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000833#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000834 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +0000835 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +0000836 if (!isym->gotent.reloc_done) {
837 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000838 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +0000839 }
Eric Andersen21adca72000-12-06 18:18:26 +0000840 /* make the reloc with_respect_to_.got */
841#if defined(__sh__)
842 *loc += isym->gotent.offset + rel->r_addend;
843#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000844 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000845#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000846 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000847
Eric Andersen21adca72000-12-06 18:18:26 +0000848 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +0000849#if defined(__sh__)
850 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +0000851#elif defined(__arm__)
852 case R_ARM_GOTOFF:
853#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000854 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000855#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000856 assert(got != 0);
857 *loc += v - got;
858 break;
859
860 default:
Eric Andersen21125542000-12-13 16:41:29 +0000861 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +0000862 ret = obj_reloc_unhandled;
863 break;
864 }
865
866 return ret;
867}
868
869int arch_create_got(struct obj_file *f)
870{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000871 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen21adca72000-12-06 18:18:26 +0000872 int i, got_offset = 0, gotneeded = 0;
873#if defined(__arm__)
874 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000875#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000876 struct obj_section *relsec, *symsec, *strsec;
877 ElfW(RelM) *rel, *relend;
878 ElfW(Sym) *symtab, *extsym;
879 const char *strtab, *name;
880 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000881
Eric Andersen21adca72000-12-06 18:18:26 +0000882 for (i = 0; i < f->header.e_shnum; ++i) {
883 relsec = f->sections[i];
884 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +0000885 continue;
886
Eric Andersen21adca72000-12-06 18:18:26 +0000887 symsec = f->sections[relsec->header.sh_link];
888 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +0000889
Eric Andersen21adca72000-12-06 18:18:26 +0000890 rel = (ElfW(RelM) *) relsec->contents;
891 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
892 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +0000893 strtab = (const char *) strsec->contents;
894
895 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +0000896 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +0000897
898 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +0000899#if defined(__arm__)
900 case R_ARM_GOT32:
901#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000902 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000903#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000904 case R_386_GOT32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000905#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000906 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000907
908#if defined(__arm__)
909 case R_ARM_PC24:
910 case R_ARM_PLT32:
911 pltneeded = 1;
912 break;
913
914 case R_ARM_GOTPC:
915 case R_ARM_GOTOFF:
916 gotneeded = 1;
917 if (got_offset == 0)
918 got_offset = 4;
919#elif defined(__sh__)
920 case R_SH_GOTPC:
921 case R_SH_GOTOFF:
922 gotneeded = 1;
923#elif defined(__i386__)
924 case R_386_GOTPC:
925 case R_386_GOTOFF:
926 gotneeded = 1;
927#endif
928
929 default:
930 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +0000931 }
932
Eric Andersen21adca72000-12-06 18:18:26 +0000933 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +0000934 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +0000935 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +0000936 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +0000937 }
938 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000939
940 if (!intsym->gotent.offset_done) {
941 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000942 intsym->gotent.offset = got_offset;
943 got_offset += 4;
944 }
945#if defined(__arm__)
946 if (pltneeded && intsym->pltent.allocated == 0) {
947 intsym->pltent.allocated = 1;
948 intsym->pltent.offset = plt_offset;
949 plt_offset += 8;
950 intsym->pltent.inited = 0;
951 pltneeded = 0;
952 }
953#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000954 }
955 }
Eric Andersen21adca72000-12-06 18:18:26 +0000956
957#if defined(__arm__)
958 if (got_offset) {
959 struct obj_section* relsec = obj_find_section(f, ".got");
960
961 if (relsec) {
962 obj_extend_section(relsec, got_offset);
963 } else {
964 relsec = obj_create_alloced_section(f, ".got", 8, got_offset);
965 assert(relsec);
966 }
967
968 ifile->got = relsec;
Eric Andersen9f16d612000-06-12 23:11:16 +0000969 }
970
Eric Andersen21adca72000-12-06 18:18:26 +0000971 if (plt_offset)
972 ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset);
973#else
974 if (got_offset > 0 || gotneeded)
975 ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset);
976#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000977
978 return 1;
979}
980
981int arch_init_module(struct obj_file *f, struct new_module *mod)
982{
983 return 1;
984}
985
986
987/*======================================================================*/
988
989/* Standard ELF hash function. */
990inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
991{
992 unsigned long h = 0;
993 unsigned long g;
994 unsigned char ch;
995
996 while (n > 0) {
997 ch = *name++;
998 h = (h << 4) + ch;
999 if ((g = (h & 0xf0000000)) != 0) {
1000 h ^= g >> 24;
1001 h &= ~g;
1002 }
1003 n--;
1004 }
1005 return h;
1006}
1007
1008unsigned long obj_elf_hash(const char *name)
1009{
1010 return obj_elf_hash_n(name, strlen(name));
1011}
1012
1013#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1014/* Get the kernel version in the canonical integer form. */
1015
1016static int get_kernel_version(char str[STRVERSIONLEN])
1017{
1018 struct utsname uts_info;
1019 char *p, *q;
1020 int a, b, c;
1021
1022 if (uname(&uts_info) < 0)
1023 return -1;
1024 strncpy(str, uts_info.release, STRVERSIONLEN);
1025 p = uts_info.release;
1026
1027 a = strtoul(p, &p, 10);
1028 if (*p != '.')
1029 return -1;
1030 b = strtoul(p + 1, &p, 10);
1031 if (*p != '.')
1032 return -1;
1033 c = strtoul(p + 1, &q, 10);
1034 if (p + 1 == q)
1035 return -1;
1036
1037 return a << 16 | b << 8 | c;
1038}
1039
1040/* String comparison for non-co-versioned kernel and module. */
1041
1042static int ncv_strcmp(const char *a, const char *b)
1043{
1044 size_t alen = strlen(a), blen = strlen(b);
1045
1046 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1047 return strncmp(a, b, alen);
1048 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1049 return strncmp(a, b, blen);
1050 else
1051 return strcmp(a, b);
1052}
1053
1054/* String hashing for non-co-versioned kernel and module. Here
1055 we are simply forced to drop the crc from the hash. */
1056
1057static unsigned long ncv_symbol_hash(const char *str)
1058{
1059 size_t len = strlen(str);
1060 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1061 len -= 10;
1062 return obj_elf_hash_n(str, len);
1063}
1064
1065void
1066obj_set_symbol_compare(struct obj_file *f,
1067 int (*cmp) (const char *, const char *),
1068 unsigned long (*hash) (const char *))
1069{
1070 if (cmp)
1071 f->symbol_cmp = cmp;
1072 if (hash) {
1073 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1074 int i;
1075
1076 f->symbol_hash = hash;
1077
1078 memcpy(tmptab, f->symtab, sizeof(tmptab));
1079 memset(f->symtab, 0, sizeof(f->symtab));
1080
1081 for (i = 0; i < HASH_BUCKETS; ++i)
1082 for (sym = tmptab[i]; sym; sym = next) {
1083 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1084 next = sym->next;
1085 sym->next = f->symtab[h];
1086 f->symtab[h] = sym;
1087 }
1088 }
1089}
1090
1091#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1092
1093
1094struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1095 unsigned long symidx, int info,
1096 int secidx, ElfW(Addr) value,
1097 unsigned long size)
1098{
1099 struct obj_symbol *sym;
1100 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1101 int n_type = ELFW(ST_TYPE) (info);
1102 int n_binding = ELFW(ST_BIND) (info);
1103
1104 for (sym = f->symtab[hash]; sym; sym = sym->next)
1105 if (f->symbol_cmp(sym->name, name) == 0) {
1106 int o_secidx = sym->secidx;
1107 int o_info = sym->info;
1108 int o_type = ELFW(ST_TYPE) (o_info);
1109 int o_binding = ELFW(ST_BIND) (o_info);
1110
1111 /* A redefinition! Is it legal? */
1112
1113 if (secidx == SHN_UNDEF)
1114 return sym;
1115 else if (o_secidx == SHN_UNDEF)
1116 goto found;
1117 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1118 /* Cope with local and global symbols of the same name
1119 in the same object file, as might have been created
1120 by ld -r. The only reason locals are now seen at this
1121 level at all is so that we can do semi-sensible things
1122 with parameters. */
1123
1124 struct obj_symbol *nsym, **p;
1125
1126 nsym = arch_new_symbol();
1127 nsym->next = sym->next;
1128 nsym->ksymidx = -1;
1129
1130 /* Excise the old (local) symbol from the hash chain. */
1131 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1132 continue;
1133 *p = sym = nsym;
1134 goto found;
1135 } else if (n_binding == STB_LOCAL) {
1136 /* Another symbol of the same name has already been defined.
1137 Just add this to the local table. */
1138 sym = arch_new_symbol();
1139 sym->next = NULL;
1140 sym->ksymidx = -1;
1141 f->local_symtab[symidx] = sym;
1142 goto found;
1143 } else if (n_binding == STB_WEAK)
1144 return sym;
1145 else if (o_binding == STB_WEAK)
1146 goto found;
1147 /* Don't unify COMMON symbols with object types the programmer
1148 doesn't expect. */
1149 else if (secidx == SHN_COMMON
1150 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1151 return sym;
1152 else if (o_secidx == SHN_COMMON
1153 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1154 goto found;
1155 else {
1156 /* Don't report an error if the symbol is coming from
1157 the kernel or some external module. */
1158 if (secidx <= SHN_HIRESERVE)
Mark Whitleyf57c9442000-12-07 19:56:48 +00001159 error_msg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001160 return sym;
1161 }
1162 }
1163
1164 /* Completely new symbol. */
1165 sym = arch_new_symbol();
1166 sym->next = f->symtab[hash];
1167 f->symtab[hash] = sym;
1168 sym->ksymidx = -1;
1169
1170 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1171 f->local_symtab[symidx] = sym;
1172
1173 found:
1174 sym->name = name;
1175 sym->value = value;
1176 sym->size = size;
1177 sym->secidx = secidx;
1178 sym->info = info;
1179
1180 return sym;
1181}
1182
1183struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1184{
1185 struct obj_symbol *sym;
1186 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1187
1188 for (sym = f->symtab[hash]; sym; sym = sym->next)
1189 if (f->symbol_cmp(sym->name, name) == 0)
1190 return sym;
1191
1192 return NULL;
1193}
1194
1195ElfW(Addr)
1196 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1197{
1198 if (sym) {
1199 if (sym->secidx >= SHN_LORESERVE)
1200 return sym->value;
1201
1202 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1203 } else {
1204 /* As a special case, a NULL sym has value zero. */
1205 return 0;
1206 }
1207}
1208
1209struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1210{
1211 int i, n = f->header.e_shnum;
1212
1213 for (i = 0; i < n; ++i)
1214 if (strcmp(f->sections[i]->name, name) == 0)
1215 return f->sections[i];
1216
1217 return NULL;
1218}
1219
1220static int obj_load_order_prio(struct obj_section *a)
1221{
1222 unsigned long af, ac;
1223
1224 af = a->header.sh_flags;
1225
1226 ac = 0;
1227 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1228 strcmp(a->name + 5, ".init"))
1229 ac |= 32;
1230 if (af & SHF_ALLOC)
1231 ac |= 16;
1232 if (!(af & SHF_WRITE))
1233 ac |= 8;
1234 if (af & SHF_EXECINSTR)
1235 ac |= 4;
1236 if (a->header.sh_type != SHT_NOBITS)
1237 ac |= 2;
1238
1239 return ac;
1240}
1241
1242void
1243obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1244{
1245 struct obj_section **p;
1246 int prio = obj_load_order_prio(sec);
1247 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1248 if (obj_load_order_prio(*p) < prio)
1249 break;
1250 sec->load_next = *p;
1251 *p = sec;
1252}
1253
1254struct obj_section *obj_create_alloced_section(struct obj_file *f,
1255 const char *name,
1256 unsigned long align,
1257 unsigned long size)
1258{
1259 int newidx = f->header.e_shnum++;
1260 struct obj_section *sec;
1261
1262 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1263 f->sections[newidx] = sec = arch_new_section();
1264
1265 memset(sec, 0, sizeof(*sec));
1266 sec->header.sh_type = SHT_PROGBITS;
1267 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1268 sec->header.sh_size = size;
1269 sec->header.sh_addralign = align;
1270 sec->name = name;
1271 sec->idx = newidx;
1272 if (size)
1273 sec->contents = xmalloc(size);
1274
1275 obj_insert_section_load_order(f, sec);
1276
1277 return sec;
1278}
1279
1280struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1281 const char *name,
1282 unsigned long align,
1283 unsigned long size)
1284{
1285 int newidx = f->header.e_shnum++;
1286 struct obj_section *sec;
1287
1288 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1289 f->sections[newidx] = sec = arch_new_section();
1290
1291 memset(sec, 0, sizeof(*sec));
1292 sec->header.sh_type = SHT_PROGBITS;
1293 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1294 sec->header.sh_size = size;
1295 sec->header.sh_addralign = align;
1296 sec->name = name;
1297 sec->idx = newidx;
1298 if (size)
1299 sec->contents = xmalloc(size);
1300
1301 sec->load_next = f->load_order;
1302 f->load_order = sec;
1303 if (f->load_order_search_start == &f->load_order)
1304 f->load_order_search_start = &sec->load_next;
1305
1306 return sec;
1307}
1308
1309void *obj_extend_section(struct obj_section *sec, unsigned long more)
1310{
1311 unsigned long oldsize = sec->header.sh_size;
1312 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1313 return sec->contents + oldsize;
1314}
1315
1316
1317
1318/* Conditionally add the symbols from the given symbol set to the
1319 new module. */
1320
1321static int
1322add_symbols_from(
1323 struct obj_file *f,
1324 int idx, struct new_module_symbol *syms, size_t nsyms)
1325{
1326 struct new_module_symbol *s;
1327 size_t i;
1328 int used = 0;
1329
1330 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1331
1332 /* Only add symbols that are already marked external. If we
1333 override locals we may cause problems for argument initialization.
1334 We will also create a false dependency on the module. */
1335 struct obj_symbol *sym;
1336
1337 sym = obj_find_symbol(f, (char *) s->name);
1338 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1339 sym = obj_add_symbol(f, (char *) s->name, -1,
1340 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1341 idx, s->value, 0);
1342 /* Did our symbol just get installed? If so, mark the
1343 module as "used". */
1344 if (sym->secidx == idx)
1345 used = 1;
1346 }
1347 }
1348
1349 return used;
1350}
1351
1352static void add_kernel_symbols(struct obj_file *f)
1353{
1354 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001355 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001356
1357 /* Add module symbols first. */
1358
1359 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1360 if (m->nsyms
1361 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1362 m->nsyms)) m->used = 1, ++nused;
1363
1364 n_ext_modules_used = nused;
1365
1366 /* And finally the symbols from the kernel proper. */
1367
1368 if (nksyms)
1369 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1370}
1371
1372static char *get_modinfo_value(struct obj_file *f, const char *key)
1373{
1374 struct obj_section *sec;
1375 char *p, *v, *n, *ep;
1376 size_t klen = strlen(key);
1377
1378 sec = obj_find_section(f, ".modinfo");
1379 if (sec == NULL)
1380 return NULL;
1381 p = sec->contents;
1382 ep = p + sec->header.sh_size;
1383 while (p < ep) {
1384 v = strchr(p, '=');
1385 n = strchr(p, '\0');
1386 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001387 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001388 return v + 1;
1389 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001390 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001391 return n;
1392 }
1393 p = n + 1;
1394 }
1395
1396 return NULL;
1397}
1398
1399
1400/*======================================================================*/
1401/* Functions relating to module loading in pre 2.1 kernels. */
1402
1403static int
1404old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1405{
1406 while (argc > 0) {
1407 char *p, *q;
1408 struct obj_symbol *sym;
1409 int *loc;
1410
1411 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001412 if ((q = strchr(p, '=')) == NULL) {
1413 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001414 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001415 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001416 *q++ = '\0';
1417
1418 sym = obj_find_symbol(f, p);
1419
1420 /* Also check that the parameter was not resolved from the kernel. */
1421 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001422 error_msg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001423 return 0;
1424 }
1425
1426 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1427
1428 /* Do C quoting if we begin with a ". */
1429 if (*q == '"') {
1430 char *r, *str;
1431
1432 str = alloca(strlen(q));
1433 for (r = str, q++; *q != '"'; ++q, ++r) {
1434 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001435 error_msg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001436 return 0;
1437 } else if (*q == '\\')
1438 switch (*++q) {
1439 case 'a':
1440 *r = '\a';
1441 break;
1442 case 'b':
1443 *r = '\b';
1444 break;
1445 case 'e':
1446 *r = '\033';
1447 break;
1448 case 'f':
1449 *r = '\f';
1450 break;
1451 case 'n':
1452 *r = '\n';
1453 break;
1454 case 'r':
1455 *r = '\r';
1456 break;
1457 case 't':
1458 *r = '\t';
1459 break;
1460
1461 case '0':
1462 case '1':
1463 case '2':
1464 case '3':
1465 case '4':
1466 case '5':
1467 case '6':
1468 case '7':
1469 {
1470 int c = *q - '0';
1471 if (q[1] >= '0' && q[1] <= '7') {
1472 c = (c * 8) + *++q - '0';
1473 if (q[1] >= '0' && q[1] <= '7')
1474 c = (c * 8) + *++q - '0';
1475 }
1476 *r = c;
1477 }
1478 break;
1479
1480 default:
1481 *r = *q;
1482 break;
1483 } else
1484 *r = *q;
1485 }
1486 *r = '\0';
1487 obj_string_patch(f, sym->secidx, sym->value, str);
1488 } else if (*q >= '0' && *q <= '9') {
1489 do
1490 *loc++ = strtoul(q, &q, 0);
1491 while (*q++ == ',');
1492 } else {
1493 char *contents = f->sections[sym->secidx]->contents;
1494 char *loc = contents + sym->value;
1495 char *r; /* To search for commas */
1496
1497 /* Break the string with comas */
1498 while ((r = strchr(q, ',')) != (char *) NULL) {
1499 *r++ = '\0';
1500 obj_string_patch(f, sym->secidx, loc - contents, q);
1501 loc += sizeof(char *);
1502 q = r;
1503 }
1504
1505 /* last part */
1506 obj_string_patch(f, sym->secidx, loc - contents, q);
1507 }
1508
1509 argc--, argv++;
1510 }
1511
1512 return 1;
1513}
1514
1515#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1516static int old_is_module_checksummed(struct obj_file *f)
1517{
1518 return obj_find_symbol(f, "Using_Versions") != NULL;
1519}
1520/* Get the module's kernel version in the canonical integer form. */
1521
1522static int
1523old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1524{
1525 struct obj_symbol *sym;
1526 char *p, *q;
1527 int a, b, c;
1528
1529 sym = obj_find_symbol(f, "kernel_version");
1530 if (sym == NULL)
1531 return -1;
1532
1533 p = f->sections[sym->secidx]->contents + sym->value;
1534 strncpy(str, p, STRVERSIONLEN);
1535
1536 a = strtoul(p, &p, 10);
1537 if (*p != '.')
1538 return -1;
1539 b = strtoul(p + 1, &p, 10);
1540 if (*p != '.')
1541 return -1;
1542 c = strtoul(p + 1, &q, 10);
1543 if (p + 1 == q)
1544 return -1;
1545
1546 return a << 16 | b << 8 | c;
1547}
1548
1549#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1550
Eric Andersenf5d5e772001-01-24 23:34:48 +00001551#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001552
1553/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1554
Eric Andersen8c185f92000-09-22 00:38:07 +00001555static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001556{
1557 struct old_kernel_sym *ks, *k;
1558 struct new_module_symbol *s;
1559 struct external_module *mod;
1560 int nks, nms, nmod, i;
1561
1562 nks = get_kernel_syms(NULL);
1563 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001564 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001565 return 0;
1566 }
1567
1568 ks = k = xmalloc(nks * sizeof(*ks));
1569
1570 if (get_kernel_syms(ks) != nks) {
1571 perror("inconsistency with get_kernel_syms -- is someone else "
1572 "playing with modules?");
1573 free(ks);
1574 return 0;
1575 }
1576
1577 /* Collect the module information. */
1578
1579 mod = NULL;
1580 nmod = -1;
1581
1582 while (k->name[0] == '#' && k->name[1]) {
1583 struct old_kernel_sym *k2;
1584 struct new_module_symbol *s;
1585
1586 /* Find out how many symbols this module has. */
1587 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1588 continue;
1589 nms = k2 - k - 1;
1590
1591 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1592 mod[nmod].name = k->name + 1;
1593 mod[nmod].addr = k->value;
1594 mod[nmod].used = 0;
1595 mod[nmod].nsyms = nms;
1596 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1597
1598 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1599 s->name = (unsigned long) k->name;
1600 s->value = k->value;
1601 }
1602
1603 k = k2;
1604 }
1605
1606 ext_modules = mod;
1607 n_ext_modules = nmod + 1;
1608
1609 /* Now collect the symbols for the kernel proper. */
1610
1611 if (k->name[0] == '#')
1612 ++k;
1613
1614 nksyms = nms = nks - (k - ks);
1615 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1616
1617 for (i = 0; i < nms; ++i, ++s, ++k) {
1618 s->name = (unsigned long) k->name;
1619 s->value = k->value;
1620 }
1621
1622 return 1;
1623}
1624
1625/* Return the kernel symbol checksum version, or zero if not used. */
1626
1627static int old_is_kernel_checksummed(void)
1628{
1629 /* Using_Versions is the first symbol. */
1630 if (nksyms > 0
1631 && strcmp((char *) ksyms[0].name,
1632 "Using_Versions") == 0) return ksyms[0].value;
1633 else
1634 return 0;
1635}
1636
1637
1638static int old_create_mod_use_count(struct obj_file *f)
1639{
1640 struct obj_section *sec;
1641
1642 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1643 sizeof(long));
1644
1645 obj_add_symbol(f, "mod_use_count_", -1,
1646 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1647 sizeof(long));
1648
1649 return 1;
1650}
1651
1652static int
1653old_init_module(const char *m_name, struct obj_file *f,
1654 unsigned long m_size)
1655{
1656 char *image;
1657 struct old_mod_routines routines;
1658 struct old_symbol_table *symtab;
1659 int ret;
1660
1661 /* Create the symbol table */
1662 {
1663 int nsyms = 0, strsize = 0, total;
1664
1665 /* Size things first... */
1666 if (flag_export) {
1667 int i;
1668 for (i = 0; i < HASH_BUCKETS; ++i) {
1669 struct obj_symbol *sym;
1670 for (sym = f->symtab[i]; sym; sym = sym->next)
1671 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1672 && sym->secidx <= SHN_HIRESERVE)
1673 {
1674 sym->ksymidx = nsyms++;
1675 strsize += strlen(sym->name) + 1;
1676 }
1677 }
1678 }
1679
1680 total = (sizeof(struct old_symbol_table)
1681 + nsyms * sizeof(struct old_module_symbol)
1682 + n_ext_modules_used * sizeof(struct old_module_ref)
1683 + strsize);
1684 symtab = xmalloc(total);
1685 symtab->size = total;
1686 symtab->n_symbols = nsyms;
1687 symtab->n_refs = n_ext_modules_used;
1688
1689 if (flag_export && nsyms) {
1690 struct old_module_symbol *ksym;
1691 char *str;
1692 int i;
1693
1694 ksym = symtab->symbol;
1695 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1696 + n_ext_modules_used * sizeof(struct old_module_ref));
1697
1698 for (i = 0; i < HASH_BUCKETS; ++i) {
1699 struct obj_symbol *sym;
1700 for (sym = f->symtab[i]; sym; sym = sym->next)
1701 if (sym->ksymidx >= 0) {
1702 ksym->addr = obj_symbol_final_value(f, sym);
1703 ksym->name =
1704 (unsigned long) str - (unsigned long) symtab;
1705
Matt Kraai70a78552001-01-04 02:00:17 +00001706 strcpy(str, sym->name);
1707 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001708 ksym++;
1709 }
1710 }
1711 }
1712
1713 if (n_ext_modules_used) {
1714 struct old_module_ref *ref;
1715 int i;
1716
1717 ref = (struct old_module_ref *)
1718 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1719
1720 for (i = 0; i < n_ext_modules; ++i)
1721 if (ext_modules[i].used)
1722 ref++->module = ext_modules[i].addr;
1723 }
1724 }
1725
1726 /* Fill in routines. */
1727
1728 routines.init =
1729 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1730 routines.cleanup =
1731 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1732
1733 /* Whew! All of the initialization is complete. Collect the final
1734 module image and give it to the kernel. */
1735
1736 image = xmalloc(m_size);
1737 obj_create_image(f, image);
1738
1739 /* image holds the complete relocated module, accounting correctly for
1740 mod_use_count. However the old module kernel support assume that
1741 it is receiving something which does not contain mod_use_count. */
1742 ret = old_sys_init_module(m_name, image + sizeof(long),
1743 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1744 : 0), &routines, symtab);
1745 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001746 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001747
1748 free(image);
1749 free(symtab);
1750
1751 return ret == 0;
1752}
1753
1754#else
1755
1756#define old_create_mod_use_count(x) TRUE
1757#define old_init_module(x, y, z) TRUE
1758
Eric Andersenf5d5e772001-01-24 23:34:48 +00001759#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00001760
1761
1762
1763/*======================================================================*/
1764/* Functions relating to module loading after 2.1.18. */
1765
1766static int
1767new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1768{
1769 while (argc > 0) {
1770 char *p, *q, *key;
1771 struct obj_symbol *sym;
1772 char *contents, *loc;
1773 int min, max, n;
1774
1775 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001776 if ((q = strchr(p, '=')) == NULL) {
1777 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001778 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001779 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001780
1781 key = alloca(q - p + 6);
1782 memcpy(key, "parm_", 5);
1783 memcpy(key + 5, p, q - p);
1784 key[q - p + 5] = 0;
1785
1786 p = get_modinfo_value(f, key);
1787 key += 5;
1788 if (p == NULL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001789 error_msg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001790 return 0;
1791 }
1792
1793 sym = obj_find_symbol(f, key);
1794
1795 /* Also check that the parameter was not resolved from the kernel. */
1796 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001797 error_msg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001798 return 0;
1799 }
1800
1801 if (isdigit(*p)) {
1802 min = strtoul(p, &p, 10);
1803 if (*p == '-')
1804 max = strtoul(p + 1, &p, 10);
1805 else
1806 max = min;
1807 } else
1808 min = max = 1;
1809
1810 contents = f->sections[sym->secidx]->contents;
1811 loc = contents + sym->value;
1812 n = (*++q != '\0');
1813
1814 while (1) {
1815 if ((*p == 's') || (*p == 'c')) {
1816 char *str;
1817
1818 /* Do C quoting if we begin with a ", else slurp the lot. */
1819 if (*q == '"') {
1820 char *r;
1821
1822 str = alloca(strlen(q));
1823 for (r = str, q++; *q != '"'; ++q, ++r) {
1824 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001825 error_msg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001826 key);
1827 return 0;
1828 } else if (*q == '\\')
1829 switch (*++q) {
1830 case 'a':
1831 *r = '\a';
1832 break;
1833 case 'b':
1834 *r = '\b';
1835 break;
1836 case 'e':
1837 *r = '\033';
1838 break;
1839 case 'f':
1840 *r = '\f';
1841 break;
1842 case 'n':
1843 *r = '\n';
1844 break;
1845 case 'r':
1846 *r = '\r';
1847 break;
1848 case 't':
1849 *r = '\t';
1850 break;
1851
1852 case '0':
1853 case '1':
1854 case '2':
1855 case '3':
1856 case '4':
1857 case '5':
1858 case '6':
1859 case '7':
1860 {
1861 int c = *q - '0';
1862 if (q[1] >= '0' && q[1] <= '7') {
1863 c = (c * 8) + *++q - '0';
1864 if (q[1] >= '0' && q[1] <= '7')
1865 c = (c * 8) + *++q - '0';
1866 }
1867 *r = c;
1868 }
1869 break;
1870
1871 default:
1872 *r = *q;
1873 break;
1874 } else
1875 *r = *q;
1876 }
1877 *r = '\0';
1878 ++q;
1879 } else {
1880 char *r;
1881
1882 /* In this case, the string is not quoted. We will break
1883 it using the coma (like for ints). If the user wants to
1884 include comas in a string, he just has to quote it */
1885
1886 /* Search the next coma */
1887 r = strchr(q, ',');
1888
1889 /* Found ? */
1890 if (r != (char *) NULL) {
1891 /* Recopy the current field */
1892 str = alloca(r - q + 1);
1893 memcpy(str, q, r - q);
1894
1895 /* I don't know if it is usefull, as the previous case
1896 doesn't null terminate the string ??? */
1897 str[r - q] = '\0';
1898
1899 /* Keep next fields */
1900 q = r;
1901 } else {
1902 /* last string */
1903 str = q;
1904 q = "";
1905 }
1906 }
1907
1908 if (*p == 's') {
1909 /* Normal string */
1910 obj_string_patch(f, sym->secidx, loc - contents, str);
1911 loc += tgt_sizeof_char_p;
1912 } else {
1913 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001914 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001915
1916 /* Get the size of each member */
1917 /* Probably we should do that outside the loop ? */
1918 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001919 error_msg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001920 " the maximum size\n", key);
1921 return 0;
1922 }
1923 charssize = strtoul(p + 1, (char **) NULL, 10);
1924
1925 /* Check length */
1926 if (strlen(str) >= charssize) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001927 error_msg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001928 charssize - 1);
1929 return 0;
1930 }
1931
1932 /* Copy to location */
1933 strcpy((char *) loc, str);
1934 loc += charssize;
1935 }
1936 } else {
1937 long v = strtoul(q, &q, 0);
1938 switch (*p) {
1939 case 'b':
1940 *loc++ = v;
1941 break;
1942 case 'h':
1943 *(short *) loc = v;
1944 loc += tgt_sizeof_short;
1945 break;
1946 case 'i':
1947 *(int *) loc = v;
1948 loc += tgt_sizeof_int;
1949 break;
1950 case 'l':
1951 *(long *) loc = v;
1952 loc += tgt_sizeof_long;
1953 break;
1954
1955 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001956 error_msg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001957 return 0;
1958 }
1959 }
1960
1961 retry_end_of_value:
1962 switch (*q) {
1963 case '\0':
1964 goto end_of_arg;
1965
1966 case ' ':
1967 case '\t':
1968 case '\n':
1969 case '\r':
1970 ++q;
1971 goto retry_end_of_value;
1972
1973 case ',':
1974 if (++n > max) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001975 error_msg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001976 return 0;
1977 }
1978 ++q;
1979 break;
1980
1981 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001982 error_msg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001983 return 0;
1984 }
1985 }
1986
1987 end_of_arg:
1988 if (n < min) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001989 error_msg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001990 return 0;
1991 }
1992
1993 argc--, argv++;
1994 }
1995
1996 return 1;
1997}
1998
1999#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2000static int new_is_module_checksummed(struct obj_file *f)
2001{
2002 const char *p = get_modinfo_value(f, "using_checksums");
2003 if (p)
2004 return atoi(p);
2005 else
2006 return 0;
2007}
2008
2009/* Get the module's kernel version in the canonical integer form. */
2010
2011static int
2012new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2013{
2014 char *p, *q;
2015 int a, b, c;
2016
2017 p = get_modinfo_value(f, "kernel_version");
2018 if (p == NULL)
2019 return -1;
2020 strncpy(str, p, STRVERSIONLEN);
2021
2022 a = strtoul(p, &p, 10);
2023 if (*p != '.')
2024 return -1;
2025 b = strtoul(p + 1, &p, 10);
2026 if (*p != '.')
2027 return -1;
2028 c = strtoul(p + 1, &q, 10);
2029 if (p + 1 == q)
2030 return -1;
2031
2032 return a << 16 | b << 8 | c;
2033}
2034
2035#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2036
2037
Eric Andersenf5d5e772001-01-24 23:34:48 +00002038#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002039
2040/* Fetch the loaded modules, and all currently exported symbols. */
2041
2042static int new_get_kernel_symbols(void)
2043{
2044 char *module_names, *mn;
2045 struct external_module *modules, *m;
2046 struct new_module_symbol *syms, *s;
2047 size_t ret, bufsize, nmod, nsyms, i, j;
2048
2049 /* Collect the loaded modules. */
2050
2051 module_names = xmalloc(bufsize = 256);
2052 retry_modules_load:
2053 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2054 if (errno == ENOSPC) {
2055 module_names = xrealloc(module_names, bufsize = ret);
2056 goto retry_modules_load;
2057 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002058 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002059 return 0;
2060 }
2061
2062 n_ext_modules = nmod = ret;
2063 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2064 memset(modules, 0, nmod * sizeof(*modules));
2065
2066 /* Collect the modules' symbols. */
2067
2068 for (i = 0, mn = module_names, m = modules;
2069 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2070 struct new_module_info info;
2071
2072 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2073 if (errno == ENOENT) {
2074 /* The module was removed out from underneath us. */
2075 continue;
2076 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002077 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002078 return 0;
2079 }
2080
2081 syms = xmalloc(bufsize = 1024);
2082 retry_mod_sym_load:
2083 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2084 switch (errno) {
2085 case ENOSPC:
2086 syms = xrealloc(syms, bufsize = ret);
2087 goto retry_mod_sym_load;
2088 case ENOENT:
2089 /* The module was removed out from underneath us. */
2090 continue;
2091 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002092 perror_msg("query_module: QM_SYMBOLS: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002093 return 0;
2094 }
2095 }
2096 nsyms = ret;
2097
2098 m->name = mn;
2099 m->addr = info.addr;
2100 m->nsyms = nsyms;
2101 m->syms = syms;
2102
2103 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2104 s->name += (unsigned long) syms;
2105 }
2106 }
2107
2108 /* Collect the kernel's symbols. */
2109
2110 syms = xmalloc(bufsize = 16 * 1024);
2111 retry_kern_sym_load:
2112 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2113 if (errno == ENOSPC) {
2114 syms = xrealloc(syms, bufsize = ret);
2115 goto retry_kern_sym_load;
2116 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002117 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002118 return 0;
2119 }
2120 nksyms = nsyms = ret;
2121 ksyms = syms;
2122
2123 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2124 s->name += (unsigned long) syms;
2125 }
2126 return 1;
2127}
2128
2129
2130/* Return the kernel symbol checksum version, or zero if not used. */
2131
2132static int new_is_kernel_checksummed(void)
2133{
2134 struct new_module_symbol *s;
2135 size_t i;
2136
2137 /* Using_Versions is not the first symbol, but it should be in there. */
2138
2139 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2140 if (strcmp((char *) s->name, "Using_Versions") == 0)
2141 return s->value;
2142
2143 return 0;
2144}
2145
2146
2147static int new_create_this_module(struct obj_file *f, const char *m_name)
2148{
2149 struct obj_section *sec;
2150
2151 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2152 sizeof(struct new_module));
2153 memset(sec->contents, 0, sizeof(struct new_module));
2154
2155 obj_add_symbol(f, "__this_module", -1,
2156 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2157 sizeof(struct new_module));
2158
2159 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2160 m_name);
2161
2162 return 1;
2163}
2164
2165
2166static int new_create_module_ksymtab(struct obj_file *f)
2167{
2168 struct obj_section *sec;
2169 int i;
2170
2171 /* We must always add the module references. */
2172
2173 if (n_ext_modules_used) {
2174 struct new_module_ref *dep;
2175 struct obj_symbol *tm;
2176
2177 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2178 (sizeof(struct new_module_ref)
2179 * n_ext_modules_used));
2180 if (!sec)
2181 return 0;
2182
2183 tm = obj_find_symbol(f, "__this_module");
2184 dep = (struct new_module_ref *) sec->contents;
2185 for (i = 0; i < n_ext_modules; ++i)
2186 if (ext_modules[i].used) {
2187 dep->dep = ext_modules[i].addr;
2188 obj_symbol_patch(f, sec->idx,
2189 (char *) &dep->ref - sec->contents, tm);
2190 dep->next_ref = 0;
2191 ++dep;
2192 }
2193 }
2194
2195 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2196 size_t nsyms;
2197 int *loaded;
2198
2199 sec =
2200 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2201 0);
2202
2203 /* We don't want to export symbols residing in sections that
2204 aren't loaded. There are a number of these created so that
2205 we make sure certain module options don't appear twice. */
2206
2207 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2208 while (--i >= 0)
2209 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2210
2211 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2212 struct obj_symbol *sym;
2213 for (sym = f->symtab[i]; sym; sym = sym->next)
2214 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2215 && sym->secidx <= SHN_HIRESERVE
2216 && (sym->secidx >= SHN_LORESERVE
2217 || loaded[sym->secidx])) {
2218 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2219
2220 obj_symbol_patch(f, sec->idx, ofs, sym);
2221 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2222 sym->name);
2223
2224 nsyms++;
2225 }
2226 }
2227
2228 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2229 }
2230
2231 return 1;
2232}
2233
2234
2235static int
2236new_init_module(const char *m_name, struct obj_file *f,
2237 unsigned long m_size)
2238{
2239 struct new_module *module;
2240 struct obj_section *sec;
2241 void *image;
2242 int ret;
2243 tgt_long m_addr;
2244
2245 sec = obj_find_section(f, ".this");
2246 module = (struct new_module *) sec->contents;
2247 m_addr = sec->header.sh_addr;
2248
2249 module->size_of_struct = sizeof(*module);
2250 module->size = m_size;
2251 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2252
2253 sec = obj_find_section(f, "__ksymtab");
2254 if (sec && sec->header.sh_size) {
2255 module->syms = sec->header.sh_addr;
2256 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2257 }
2258
2259 if (n_ext_modules_used) {
2260 sec = obj_find_section(f, ".kmodtab");
2261 module->deps = sec->header.sh_addr;
2262 module->ndeps = n_ext_modules_used;
2263 }
2264
2265 module->init =
2266 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2267 module->cleanup =
2268 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2269
2270 sec = obj_find_section(f, "__ex_table");
2271 if (sec) {
2272 module->ex_table_start = sec->header.sh_addr;
2273 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2274 }
2275
2276 sec = obj_find_section(f, ".text.init");
2277 if (sec) {
2278 module->runsize = sec->header.sh_addr - m_addr;
2279 }
2280 sec = obj_find_section(f, ".data.init");
2281 if (sec) {
2282 if (!module->runsize ||
2283 module->runsize > sec->header.sh_addr - m_addr)
2284 module->runsize = sec->header.sh_addr - m_addr;
2285 }
2286
2287 if (!arch_init_module(f, module))
2288 return 0;
2289
2290 /* Whew! All of the initialization is complete. Collect the final
2291 module image and give it to the kernel. */
2292
2293 image = xmalloc(m_size);
2294 obj_create_image(f, image);
2295
2296 ret = new_sys_init_module(m_name, (struct new_module *) image);
2297 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002298 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002299
2300 free(image);
2301
2302 return ret == 0;
2303}
2304
2305#else
2306
2307#define new_init_module(x, y, z) TRUE
2308#define new_create_this_module(x, y) 0
2309#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002310#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002311
Eric Andersenf5d5e772001-01-24 23:34:48 +00002312#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002313
2314
2315/*======================================================================*/
2316
2317int
2318obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2319 const char *string)
2320{
2321 struct obj_string_patch *p;
2322 struct obj_section *strsec;
2323 size_t len = strlen(string) + 1;
2324 char *loc;
2325
2326 p = xmalloc(sizeof(*p));
2327 p->next = f->string_patches;
2328 p->reloc_secidx = secidx;
2329 p->reloc_offset = offset;
2330 f->string_patches = p;
2331
2332 strsec = obj_find_section(f, ".kstrtab");
2333 if (strsec == NULL) {
2334 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2335 p->string_offset = 0;
2336 loc = strsec->contents;
2337 } else {
2338 p->string_offset = strsec->header.sh_size;
2339 loc = obj_extend_section(strsec, len);
2340 }
2341 memcpy(loc, string, len);
2342
2343 return 1;
2344}
2345
2346int
2347obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2348 struct obj_symbol *sym)
2349{
2350 struct obj_symbol_patch *p;
2351
2352 p = xmalloc(sizeof(*p));
2353 p->next = f->symbol_patches;
2354 p->reloc_secidx = secidx;
2355 p->reloc_offset = offset;
2356 p->sym = sym;
2357 f->symbol_patches = p;
2358
2359 return 1;
2360}
2361
2362int obj_check_undefineds(struct obj_file *f)
2363{
2364 unsigned long i;
2365 int ret = 1;
2366
2367 for (i = 0; i < HASH_BUCKETS; ++i) {
2368 struct obj_symbol *sym;
2369 for (sym = f->symtab[i]; sym; sym = sym->next)
2370 if (sym->secidx == SHN_UNDEF) {
2371 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2372 sym->secidx = SHN_ABS;
2373 sym->value = 0;
2374 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002375 error_msg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002376 ret = 0;
2377 }
2378 }
2379 }
2380
2381 return ret;
2382}
2383
2384void obj_allocate_commons(struct obj_file *f)
2385{
2386 struct common_entry {
2387 struct common_entry *next;
2388 struct obj_symbol *sym;
2389 } *common_head = NULL;
2390
2391 unsigned long i;
2392
2393 for (i = 0; i < HASH_BUCKETS; ++i) {
2394 struct obj_symbol *sym;
2395 for (sym = f->symtab[i]; sym; sym = sym->next)
2396 if (sym->secidx == SHN_COMMON) {
2397 /* Collect all COMMON symbols and sort them by size so as to
2398 minimize space wasted by alignment requirements. */
2399 {
2400 struct common_entry **p, *n;
2401 for (p = &common_head; *p; p = &(*p)->next)
2402 if (sym->size <= (*p)->sym->size)
2403 break;
2404
2405 n = alloca(sizeof(*n));
2406 n->next = *p;
2407 n->sym = sym;
2408 *p = n;
2409 }
2410 }
2411 }
2412
2413 for (i = 1; i < f->local_symtab_size; ++i) {
2414 struct obj_symbol *sym = f->local_symtab[i];
2415 if (sym && sym->secidx == SHN_COMMON) {
2416 struct common_entry **p, *n;
2417 for (p = &common_head; *p; p = &(*p)->next)
2418 if (sym == (*p)->sym)
2419 break;
2420 else if (sym->size < (*p)->sym->size) {
2421 n = alloca(sizeof(*n));
2422 n->next = *p;
2423 n->sym = sym;
2424 *p = n;
2425 break;
2426 }
2427 }
2428 }
2429
2430 if (common_head) {
2431 /* Find the bss section. */
2432 for (i = 0; i < f->header.e_shnum; ++i)
2433 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2434 break;
2435
2436 /* If for some reason there hadn't been one, create one. */
2437 if (i == f->header.e_shnum) {
2438 struct obj_section *sec;
2439
2440 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2441 f->sections[i] = sec = arch_new_section();
2442 f->header.e_shnum = i + 1;
2443
2444 memset(sec, 0, sizeof(*sec));
2445 sec->header.sh_type = SHT_PROGBITS;
2446 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2447 sec->name = ".bss";
2448 sec->idx = i;
2449 }
2450
2451 /* Allocate the COMMONS. */
2452 {
2453 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2454 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2455 struct common_entry *c;
2456
2457 for (c = common_head; c; c = c->next) {
2458 ElfW(Addr) align = c->sym->value;
2459
2460 if (align > max_align)
2461 max_align = align;
2462 if (bss_size & (align - 1))
2463 bss_size = (bss_size | (align - 1)) + 1;
2464
2465 c->sym->secidx = i;
2466 c->sym->value = bss_size;
2467
2468 bss_size += c->sym->size;
2469 }
2470
2471 f->sections[i]->header.sh_size = bss_size;
2472 f->sections[i]->header.sh_addralign = max_align;
2473 }
2474 }
2475
2476 /* For the sake of patch relocation and parameter initialization,
2477 allocate zeroed data for NOBITS sections now. Note that after
2478 this we cannot assume NOBITS are really empty. */
2479 for (i = 0; i < f->header.e_shnum; ++i) {
2480 struct obj_section *s = f->sections[i];
2481 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002482 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002483 s->contents = memset(xmalloc(s->header.sh_size),
2484 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002485 else
2486 s->contents = NULL;
2487
Eric Andersen9f16d612000-06-12 23:11:16 +00002488 s->header.sh_type = SHT_PROGBITS;
2489 }
2490 }
2491}
2492
2493unsigned long obj_load_size(struct obj_file *f)
2494{
2495 unsigned long dot = 0;
2496 struct obj_section *sec;
2497
2498 /* Finalize the positions of the sections relative to one another. */
2499
2500 for (sec = f->load_order; sec; sec = sec->load_next) {
2501 ElfW(Addr) align;
2502
2503 align = sec->header.sh_addralign;
2504 if (align && (dot & (align - 1)))
2505 dot = (dot | (align - 1)) + 1;
2506
2507 sec->header.sh_addr = dot;
2508 dot += sec->header.sh_size;
2509 }
2510
2511 return dot;
2512}
2513
2514int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2515{
2516 int i, n = f->header.e_shnum;
2517 int ret = 1;
2518
2519 /* Finalize the addresses of the sections. */
2520
2521 f->baseaddr = base;
2522 for (i = 0; i < n; ++i)
2523 f->sections[i]->header.sh_addr += base;
2524
2525 /* And iterate over all of the relocations. */
2526
2527 for (i = 0; i < n; ++i) {
2528 struct obj_section *relsec, *symsec, *targsec, *strsec;
2529 ElfW(RelM) * rel, *relend;
2530 ElfW(Sym) * symtab;
2531 const char *strtab;
2532
2533 relsec = f->sections[i];
2534 if (relsec->header.sh_type != SHT_RELM)
2535 continue;
2536
2537 symsec = f->sections[relsec->header.sh_link];
2538 targsec = f->sections[relsec->header.sh_info];
2539 strsec = f->sections[symsec->header.sh_link];
2540
2541 rel = (ElfW(RelM) *) relsec->contents;
2542 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2543 symtab = (ElfW(Sym) *) symsec->contents;
2544 strtab = (const char *) strsec->contents;
2545
2546 for (; rel < relend; ++rel) {
2547 ElfW(Addr) value = 0;
2548 struct obj_symbol *intsym = NULL;
2549 unsigned long symndx;
2550 ElfW(Sym) * extsym = 0;
2551 const char *errmsg;
2552
2553 /* Attempt to find a value to use for this relocation. */
2554
2555 symndx = ELFW(R_SYM) (rel->r_info);
2556 if (symndx) {
2557 /* Note we've already checked for undefined symbols. */
2558
2559 extsym = &symtab[symndx];
2560 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2561 /* Local symbols we look up in the local table to be sure
2562 we get the one that is really intended. */
2563 intsym = f->local_symtab[symndx];
2564 } else {
2565 /* Others we look up in the hash table. */
2566 const char *name;
2567 if (extsym->st_name)
2568 name = strtab + extsym->st_name;
2569 else
2570 name = f->sections[extsym->st_shndx]->name;
2571 intsym = obj_find_symbol(f, name);
2572 }
2573
2574 value = obj_symbol_final_value(f, intsym);
2575 intsym->referenced = 1;
2576 }
2577#if SHT_RELM == SHT_RELA
2578#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2579 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2580 if (!extsym || !extsym->st_name ||
2581 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2582#endif
2583 value += rel->r_addend;
2584#endif
2585
2586 /* Do it! */
2587 switch (arch_apply_relocation
2588 (f, targsec, symsec, intsym, rel, value)) {
2589 case obj_reloc_ok:
2590 break;
2591
2592 case obj_reloc_overflow:
2593 errmsg = "Relocation overflow";
2594 goto bad_reloc;
2595 case obj_reloc_dangerous:
2596 errmsg = "Dangerous relocation";
2597 goto bad_reloc;
2598 case obj_reloc_unhandled:
2599 errmsg = "Unhandled relocation";
2600 bad_reloc:
2601 if (extsym) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002602 error_msg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002603 (long) ELFW(R_TYPE) (rel->r_info),
2604 strtab + extsym->st_name);
2605 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002606 error_msg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002607 (long) ELFW(R_TYPE) (rel->r_info));
2608 }
2609 ret = 0;
2610 break;
2611 }
2612 }
2613 }
2614
2615 /* Finally, take care of the patches. */
2616
2617 if (f->string_patches) {
2618 struct obj_string_patch *p;
2619 struct obj_section *strsec;
2620 ElfW(Addr) strsec_base;
2621 strsec = obj_find_section(f, ".kstrtab");
2622 strsec_base = strsec->header.sh_addr;
2623
2624 for (p = f->string_patches; p; p = p->next) {
2625 struct obj_section *targsec = f->sections[p->reloc_secidx];
2626 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2627 = strsec_base + p->string_offset;
2628 }
2629 }
2630
2631 if (f->symbol_patches) {
2632 struct obj_symbol_patch *p;
2633
2634 for (p = f->symbol_patches; p; p = p->next) {
2635 struct obj_section *targsec = f->sections[p->reloc_secidx];
2636 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2637 = obj_symbol_final_value(f, p->sym);
2638 }
2639 }
2640
2641 return ret;
2642}
2643
2644int obj_create_image(struct obj_file *f, char *image)
2645{
2646 struct obj_section *sec;
2647 ElfW(Addr) base = f->baseaddr;
2648
2649 for (sec = f->load_order; sec; sec = sec->load_next) {
2650 char *secimg;
2651
2652 if (sec->header.sh_size == 0)
2653 continue;
2654
2655 secimg = image + (sec->header.sh_addr - base);
2656
2657 /* Note that we allocated data for NOBITS sections earlier. */
2658 memcpy(secimg, sec->contents, sec->header.sh_size);
2659 }
2660
2661 return 1;
2662}
2663
2664/*======================================================================*/
2665
2666struct obj_file *obj_load(FILE * fp)
2667{
2668 struct obj_file *f;
2669 ElfW(Shdr) * section_headers;
2670 int shnum, i;
2671 char *shstrtab;
2672
2673 /* Read the file header. */
2674
2675 f = arch_new_file();
2676 memset(f, 0, sizeof(*f));
2677 f->symbol_cmp = strcmp;
2678 f->symbol_hash = obj_elf_hash;
2679 f->load_order_search_start = &f->load_order;
2680
2681 fseek(fp, 0, SEEK_SET);
2682 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002683 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002684 return NULL;
2685 }
2686
2687 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2688 || f->header.e_ident[EI_MAG1] != ELFMAG1
2689 || f->header.e_ident[EI_MAG2] != ELFMAG2
2690 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002691 error_msg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002692 return NULL;
2693 }
2694 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2695 || f->header.e_ident[EI_DATA] != ELFDATAM
2696 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2697 || !MATCH_MACHINE(f->header.e_machine)) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002698 error_msg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002699 return NULL;
2700 }
2701 if (f->header.e_type != ET_REL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002702 error_msg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002703 return NULL;
2704 }
2705
2706 /* Read the section headers. */
2707
2708 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002709 error_msg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002710 (unsigned long) f->header.e_shentsize,
2711 (unsigned long) sizeof(ElfW(Shdr)));
2712 return NULL;
2713 }
2714
2715 shnum = f->header.e_shnum;
2716 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2717 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2718
2719 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2720 fseek(fp, f->header.e_shoff, SEEK_SET);
2721 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002722 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002723 return NULL;
2724 }
2725
2726 /* Read the section data. */
2727
2728 for (i = 0; i < shnum; ++i) {
2729 struct obj_section *sec;
2730
2731 f->sections[i] = sec = arch_new_section();
2732 memset(sec, 0, sizeof(*sec));
2733
2734 sec->header = section_headers[i];
2735 sec->idx = i;
2736
2737 switch (sec->header.sh_type) {
2738 case SHT_NULL:
2739 case SHT_NOTE:
2740 case SHT_NOBITS:
2741 /* ignore */
2742 break;
2743
2744 case SHT_PROGBITS:
2745 case SHT_SYMTAB:
2746 case SHT_STRTAB:
2747 case SHT_RELM:
2748 if (sec->header.sh_size > 0) {
2749 sec->contents = xmalloc(sec->header.sh_size);
2750 fseek(fp, sec->header.sh_offset, SEEK_SET);
2751 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002752 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002753 return NULL;
2754 }
2755 } else {
2756 sec->contents = NULL;
2757 }
2758 break;
2759
2760#if SHT_RELM == SHT_REL
2761 case SHT_RELA:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002762 error_msg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002763 return NULL;
2764#else
2765 case SHT_REL:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002766 error_msg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002767 return NULL;
2768#endif
2769
2770 default:
2771 if (sec->header.sh_type >= SHT_LOPROC) {
2772 /* Assume processor specific section types are debug
2773 info and can safely be ignored. If this is ever not
2774 the case (Hello MIPS?), don't put ifdefs here but
2775 create an arch_load_proc_section(). */
2776 break;
2777 }
2778
Mark Whitleyf57c9442000-12-07 19:56:48 +00002779 error_msg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002780 (long) sec->header.sh_type);
2781 return NULL;
2782 }
2783 }
2784
2785 /* Do what sort of interpretation as needed by each section. */
2786
2787 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2788
2789 for (i = 0; i < shnum; ++i) {
2790 struct obj_section *sec = f->sections[i];
2791 sec->name = shstrtab + sec->header.sh_name;
2792 }
2793
2794 for (i = 0; i < shnum; ++i) {
2795 struct obj_section *sec = f->sections[i];
2796
2797 if (sec->header.sh_flags & SHF_ALLOC)
2798 obj_insert_section_load_order(f, sec);
2799
2800 switch (sec->header.sh_type) {
2801 case SHT_SYMTAB:
2802 {
2803 unsigned long nsym, j;
2804 char *strtab;
2805 ElfW(Sym) * sym;
2806
2807 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002808 error_msg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002809 (unsigned long) sec->header.sh_entsize,
2810 (unsigned long) sizeof(ElfW(Sym)));
2811 return NULL;
2812 }
2813
2814 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2815 strtab = f->sections[sec->header.sh_link]->contents;
2816 sym = (ElfW(Sym) *) sec->contents;
2817
2818 /* Allocate space for a table of local symbols. */
2819 j = f->local_symtab_size = sec->header.sh_info;
2820 f->local_symtab = xmalloc(j *=
2821 sizeof(struct obj_symbol *));
2822 memset(f->local_symtab, 0, j);
2823
2824 /* Insert all symbols into the hash table. */
2825 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2826 const char *name;
2827 if (sym->st_name)
2828 name = strtab + sym->st_name;
2829 else
2830 name = f->sections[sym->st_shndx]->name;
2831
2832 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2833 sym->st_value, sym->st_size);
2834 }
2835 }
2836 break;
2837
2838 case SHT_RELM:
2839 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002840 error_msg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002841 (unsigned long) sec->header.sh_entsize,
2842 (unsigned long) sizeof(ElfW(RelM)));
2843 return NULL;
2844 }
2845 break;
2846 }
2847 }
2848
2849 return f;
2850}
2851
2852static void hide_special_symbols(struct obj_file *f)
2853{
2854 static const char *const specials[] = {
2855 "cleanup_module",
2856 "init_module",
2857 "kernel_version",
2858 NULL
2859 };
2860
2861 struct obj_symbol *sym;
2862 const char *const *p;
2863
2864 for (p = specials; *p; ++p)
2865 if ((sym = obj_find_symbol(f, *p)) != NULL)
2866 sym->info =
2867 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2868}
2869
2870
2871
2872extern int insmod_main( int argc, char **argv)
2873{
Eric Andersena18aaf12001-01-24 19:07:09 +00002874 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00002875 int k_crcs;
2876 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002877 int len;
2878 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002879 unsigned long m_size;
2880 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002881 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002882 struct obj_file *f;
2883 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00002884 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00002885 int m_has_modinfo;
2886#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2887 int k_version;
2888 char k_strversion[STRVERSIONLEN];
2889 char m_strversion[STRVERSIONLEN];
2890 int m_version;
2891 int m_crcs;
2892#endif
2893
Erik Andersene49d5ec2000-02-08 19:58:47 +00002894 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00002895 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00002896 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002897 case 'f': /* force loading */
2898 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002899 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002900 case 'k': /* module loaded by kerneld, auto-cleanable */
2901 flag_autoclean = 1;
2902 break;
2903 case 'v': /* verbose output */
2904 flag_verbose = 1;
2905 break;
2906 case 'x': /* do not export externs */
2907 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002908 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00002909 case 'o': /* name the output module */
2910 strncpy(m_name, optarg, BUFSIZ);
2911 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00002912 case 'L': /* Stub warning */
2913 /* This is needed for compatibility with modprobe.
2914 * In theory, this does locking, but we don't do
2915 * that. So be careful and plan your life around not
2916 * loading the same module 50 times concurrently. */
2917 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002918 default:
2919 usage(insmod_usage);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002920 }
Erik Andersend387d011999-12-21 02:55:11 +00002921 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002922
2923 if (argv[optind] == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002924 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002925 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002926
Erik Andersene49d5ec2000-02-08 19:58:47 +00002927 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00002928 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002929 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00002931 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00002932 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002933 len = strlen(tmp);
2934
2935 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2936 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00002937 strncpy(m_fullName, tmp, len);
Eric Andersen114ad9c2001-01-26 01:52:14 +00002938 if (*m_name == '\0') {
2939 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00002940 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00002941 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00002942
2943 /* Get a filedesc for the module */
Eric Andersena18aaf12001-01-24 19:07:09 +00002944 if ((fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002945 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00002946 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002947 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002948 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002949 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002950 || ((fp = fopen(m_filename, "r")) == NULL))
2951 {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002952 error_msg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00002953 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002954 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002955 } else
Mark Whitleyf57c9442000-12-07 19:56:48 +00002956 error_msg_and_die("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002957 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00002958 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00002959
2960
Matt Kraaia9819b22000-12-22 01:48:07 +00002961 if ((f = obj_load(fp)) == NULL)
2962 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00002963
Eric Andersen9f16d612000-06-12 23:11:16 +00002964 if (get_modinfo_value(f, "kernel_version") == NULL)
2965 m_has_modinfo = 0;
2966 else
2967 m_has_modinfo = 1;
2968
2969#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2970 /* Version correspondence? */
2971
2972 k_version = get_kernel_version(k_strversion);
2973 if (m_has_modinfo) {
2974 m_version = new_get_module_version(f, m_strversion);
2975 } else {
2976 m_version = old_get_module_version(f, m_strversion);
2977 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002978 error_msg("couldn't find the kernel version the module was "
Matt Kraaid537a952000-07-14 01:51:25 +00002979 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002980 goto out;
2981 }
2982 }
2983
2984 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2985 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002986 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002987 "\t%s was compiled for kernel version %s\n"
2988 "\twhile this kernel is version %s\n",
2989 m_filename, m_strversion, k_strversion);
2990 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002991 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002992 "\t%s was compiled for kernel version %s\n"
2993 "\twhile this kernel is version %s.\n",
2994 m_filename, m_strversion, k_strversion);
2995 goto out;
2996 }
2997 }
2998 k_crcs = 0;
2999#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3000
3001 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3002
3003 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003004#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003005 if (!new_get_kernel_symbols())
3006 goto out;
3007 k_crcs = new_is_kernel_checksummed();
3008#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003009 error_msg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003010 goto out;
3011#endif
3012 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003013#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003014 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 goto out;
3016 k_crcs = old_is_kernel_checksummed();
3017#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003018 error_msg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003019 goto out;
3020#endif
3021 }
3022
3023#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3024 if (m_has_modinfo)
3025 m_crcs = new_is_module_checksummed(f);
3026 else
3027 m_crcs = old_is_module_checksummed(f);
3028
3029 if (m_crcs != k_crcs)
3030 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3031#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3032
Erik Andersene49d5ec2000-02-08 19:58:47 +00003033 /* Let the module know about the kernel symbols. */
3034 add_kernel_symbols(f);
3035
Eric Andersen9f16d612000-06-12 23:11:16 +00003036 /* Allocate common symbols, symbol tables, and string tables. */
3037
3038 if (k_new_syscalls
3039 ? !new_create_this_module(f, m_name)
3040 : !old_create_mod_use_count(f))
3041 {
3042 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003043 }
3044
Eric Andersen9f16d612000-06-12 23:11:16 +00003045 if (!obj_check_undefineds(f)) {
3046 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003047 }
3048 obj_allocate_commons(f);
3049
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003050 /* done with the module name, on to the optional var=value arguments */
3051 ++optind;
3052
Eric Andersen9f16d612000-06-12 23:11:16 +00003053 if (optind < argc) {
3054 if (m_has_modinfo
3055 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3056 : !old_process_module_arguments(f, argc - optind, argv + optind))
3057 {
3058 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003059 }
3060 }
3061
Eric Andersen9f16d612000-06-12 23:11:16 +00003062 arch_create_got(f);
3063 hide_special_symbols(f);
3064
3065 if (k_new_syscalls)
3066 new_create_module_ksymtab(f);
3067
Erik Andersene49d5ec2000-02-08 19:58:47 +00003068 /* Find current size of the module */
3069 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003070
3071
Erik Andersene49d5ec2000-02-08 19:58:47 +00003072 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003073 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003074 case EEXIST:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003075 error_msg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003076 goto out;
3077 case ENOMEM:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003078 error_msg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00003079 m_size);
3080 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003081 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003082 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003083 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003084 }
Erik Andersend387d011999-12-21 02:55:11 +00003085
Eric Andersen9f16d612000-06-12 23:11:16 +00003086 if (!obj_relocate(f, m_addr)) {
3087 delete_module(m_name);
3088 goto out;
3089 }
Erik Andersend387d011999-12-21 02:55:11 +00003090
Eric Andersen9f16d612000-06-12 23:11:16 +00003091 if (k_new_syscalls
3092 ? !new_init_module(m_name, f, m_size)
3093 : !old_init_module(m_name, f, m_size))
3094 {
3095 delete_module(m_name);
3096 goto out;
3097 }
3098
Matt Kraai3e856ce2000-12-01 02:55:13 +00003099 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003100
3101out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003102 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003103 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003104}