blob: c51ee4f322ec42e776b0734cacec7e19c210174d [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
4 *
Erik Andersen61677fe2000-04-13 01:18:56 +00005 * Copyright (C) 1999,2000 by Lineo, inc.
Eric Andersen9f16d612000-06-12 23:11:16 +00006 * Written by Erik Andersen <andersen@lineo.com>
7 * and Ron Alder <alder@lineo.com>
8 *
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 Andersen999bf722000-07-09 06:59:58 +000049#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000050#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000051
52//----------------------------------------------------------------------------
53//--------modutils module.h, lines 45-242
54//----------------------------------------------------------------------------
55
56/* Definitions for the Linux module syscall interface.
57 Copyright 1996, 1997 Linux International.
58
59 Contributed by Richard Henderson <rth@tamu.edu>
60
61 This file is part of the Linux modutils.
62
63 This program is free software; you can redistribute it and/or modify it
64 under the terms of the GNU General Public License as published by the
65 Free Software Foundation; either version 2 of the License, or (at your
66 option) any later version.
67
68 This program is distributed in the hope that it will be useful, but
69 WITHOUT ANY WARRANTY; without even the implied warranty of
70 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
71 General Public License for more details.
72
73 You should have received a copy of the GNU General Public License
74 along with this program; if not, write to the Free Software Foundation,
75 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
76
77
78#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +000079static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +000080
Eric Andersen155c89b2001-01-25 04:11:06 +000081#ident "$Id: insmod.c,v 1.40 2001/01/25 04:11:06 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +000082
83/* This file contains the structures used by the 2.0 and 2.1 kernels.
84 We do not use the kernel headers directly because we do not wish
85 to be dependant on a particular kernel version to compile insmod. */
86
87
88/*======================================================================*/
89/* The structures used by Linux 2.0. */
90
91/* The symbol format used by get_kernel_syms(2). */
92struct old_kernel_sym
93{
94 unsigned long value;
95 char name[60];
96};
97
98struct old_module_ref
99{
100 unsigned long module; /* kernel addresses */
101 unsigned long next;
102};
103
104struct old_module_symbol
105{
106 unsigned long addr;
107 unsigned long name;
108};
109
110struct old_symbol_table
111{
112 int size; /* total, including string table!!! */
113 int n_symbols;
114 int n_refs;
115 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
116 struct old_module_ref ref[0]; /* actual size defined by n_refs */
117};
118
119struct old_mod_routines
120{
121 unsigned long init;
122 unsigned long cleanup;
123};
124
125struct old_module
126{
127 unsigned long next;
128 unsigned long ref; /* the list of modules that refer to me */
129 unsigned long symtab;
130 unsigned long name;
131 int size; /* size of module in pages */
132 unsigned long addr; /* address of module */
133 int state;
134 unsigned long cleanup; /* cleanup routine */
135};
136
137/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000138static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000139
140int get_kernel_syms(struct old_kernel_sym *);
141int old_sys_init_module(const char *name, char *code, unsigned codesize,
142 struct old_mod_routines *, struct old_symbol_table *);
143
144/*======================================================================*/
145/* For sizeof() which are related to the module platform and not to the
146 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
147
148#define tgt_sizeof_char sizeof(char)
149#define tgt_sizeof_short sizeof(short)
150#define tgt_sizeof_int sizeof(int)
151#define tgt_sizeof_long sizeof(long)
152#define tgt_sizeof_char_p sizeof(char *)
153#define tgt_sizeof_void_p sizeof(void *)
154#define tgt_long long
155
156#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
157#undef tgt_sizeof_long
158#undef tgt_sizeof_char_p
159#undef tgt_sizeof_void_p
160#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000161static const int tgt_sizeof_long = 8;
162static const int tgt_sizeof_char_p = 8;
163static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000164#define tgt_long long long
165#endif
166
167/*======================================================================*/
168/* The structures used in Linux 2.1. */
169
170/* Note: new_module_symbol does not use tgt_long intentionally */
171struct new_module_symbol
172{
173 unsigned long value;
174 unsigned long name;
175};
176
177struct new_module_persist;
178
179struct new_module_ref
180{
181 unsigned tgt_long dep; /* kernel addresses */
182 unsigned tgt_long ref;
183 unsigned tgt_long next_ref;
184};
185
186struct new_module
187{
188 unsigned tgt_long size_of_struct; /* == sizeof(module) */
189 unsigned tgt_long next;
190 unsigned tgt_long name;
191 unsigned tgt_long size;
192
193 tgt_long usecount;
194 unsigned tgt_long flags; /* AUTOCLEAN et al */
195
196 unsigned nsyms;
197 unsigned ndeps;
198
199 unsigned tgt_long syms;
200 unsigned tgt_long deps;
201 unsigned tgt_long refs;
202 unsigned tgt_long init;
203 unsigned tgt_long cleanup;
204 unsigned tgt_long ex_table_start;
205 unsigned tgt_long ex_table_end;
206#ifdef __alpha__
207 unsigned tgt_long gp;
208#endif
209 /* Everything after here is extension. */
210 unsigned tgt_long persist_start;
211 unsigned tgt_long persist_end;
212 unsigned tgt_long can_unload;
213 unsigned tgt_long runsize;
214};
215
216struct new_module_info
217{
218 unsigned long addr;
219 unsigned long size;
220 unsigned long flags;
221 long usecount;
222};
223
224/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000225static const int NEW_MOD_RUNNING = 1;
226static const int NEW_MOD_DELETED = 2;
227static const int NEW_MOD_AUTOCLEAN = 4;
228static const int NEW_MOD_VISITED = 8;
229static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000230
231int new_sys_init_module(const char *name, const struct new_module *);
232int query_module(const char *name, int which, void *buf, size_t bufsize,
233 size_t *ret);
234
235/* Values for query_module's which. */
236
Mark Whitley59ab0252001-01-23 22:30:04 +0000237static const int QM_MODULES = 1;
238static const int QM_DEPS = 2;
239static const int QM_REFS = 3;
240static const int QM_SYMBOLS = 4;
241static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000242
243/*======================================================================*/
244/* The system calls unchanged between 2.0 and 2.1. */
245
246unsigned long create_module(const char *, size_t);
247int delete_module(const char *);
248
249
250#endif /* module.h */
251
252//----------------------------------------------------------------------------
253//--------end of modutils module.h
254//----------------------------------------------------------------------------
255
256
257
258//----------------------------------------------------------------------------
259//--------modutils obj.h, lines 253-462
260//----------------------------------------------------------------------------
261
262/* Elf object file loading and relocation routines.
263 Copyright 1996, 1997 Linux International.
264
265 Contributed by Richard Henderson <rth@tamu.edu>
266
267 This file is part of the Linux modutils.
268
269 This program is free software; you can redistribute it and/or modify it
270 under the terms of the GNU General Public License as published by the
271 Free Software Foundation; either version 2 of the License, or (at your
272 option) any later version.
273
274 This program is distributed in the hope that it will be useful, but
275 WITHOUT ANY WARRANTY; without even the implied warranty of
276 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
277 General Public License for more details.
278
279 You should have received a copy of the GNU General Public License
280 along with this program; if not, write to the Free Software Foundation,
281 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
282
283
284#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000285static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000286
Eric Andersen155c89b2001-01-25 04:11:06 +0000287#ident "$Id: insmod.c,v 1.40 2001/01/25 04:11:06 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000288
289/* The relocatable object is manipulated using elfin types. */
290
291#include <stdio.h>
292#include <elf.h>
293
294
295/* Machine-specific elf macros for i386 et al. */
296
Eric Andersenfe4208f2000-09-24 03:44:29 +0000297/* the SH changes have only been tested on the SH4 in =little endian= mode */
298/* I'm not sure about big endian, so let's warn: */
299
300#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
301#error insmod.c may require changes for use on big endian SH4/SH3
302#endif
303
304/* it may or may not work on the SH1/SH2... So let's error on those
305 also */
306#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
307#error insmod.c may require changes for non-SH3/SH4 use
308#endif
309
Eric Andersen9f16d612000-06-12 23:11:16 +0000310#define ELFCLASSM ELFCLASS32
311#define ELFDATAM ELFDATA2LSB
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313
Eric Andersenfe4208f2000-09-24 03:44:29 +0000314
315#if defined(__sh__)
316
317#define MATCH_MACHINE(x) (x == EM_SH)
318#define SHT_RELM SHT_RELA
319#define Elf32_RelM Elf32_Rela
320
Eric Andersen21adca72000-12-06 18:18:26 +0000321#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000322
Eric Andersen21adca72000-12-06 18:18:26 +0000323#define MATCH_MACHINE(x) (x == EM_ARM)
324#define SHT_RELM SHT_REL
325#define Elf32_RelM Elf32_Rel
326
327#elif defined(__i386__)
328
329/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000330/* this is the previous behavior, but it does result in
331 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000332#ifndef EM_486
333#define MATCH_MACHINE(x) (x == EM_386)
334#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000335#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000336#endif
337
Eric Andersen9f16d612000-06-12 23:11:16 +0000338#define SHT_RELM SHT_REL
339#define Elf32_RelM Elf32_Rel
340
Eric Andersen21adca72000-12-06 18:18:26 +0000341#else
342#error insmod.c no platform specified
Eric Andersenfe4208f2000-09-24 03:44:29 +0000343#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000344
345#ifndef ElfW
346# if ELFCLASSM == ELFCLASS32
347# define ElfW(x) Elf32_ ## x
348# define ELFW(x) ELF32_ ## x
349# else
350# define ElfW(x) Elf64_ ## x
351# define ELFW(x) ELF64_ ## x
352# endif
353#endif
354
355/* For some reason this is missing from libc5. */
356#ifndef ELF32_ST_INFO
357# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
358#endif
359
360#ifndef ELF64_ST_INFO
361# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
362#endif
363
364struct obj_string_patch;
365struct obj_symbol_patch;
366
367struct obj_section
368{
369 ElfW(Shdr) header;
370 const char *name;
371 char *contents;
372 struct obj_section *load_next;
373 int idx;
374};
375
376struct obj_symbol
377{
378 struct obj_symbol *next; /* hash table link */
379 const char *name;
380 unsigned long value;
381 unsigned long size;
382 int secidx; /* the defining section index/module */
383 int info;
384 int ksymidx; /* for export to the kernel symtab */
385 int referenced; /* actually used in the link */
386};
387
388/* Hardcode the hash table size. We shouldn't be needing so many
389 symbols that we begin to degrade performance, and we get a big win
390 by giving the compiler a constant divisor. */
391
392#define HASH_BUCKETS 521
393
394struct obj_file
395{
396 ElfW(Ehdr) header;
397 ElfW(Addr) baseaddr;
398 struct obj_section **sections;
399 struct obj_section *load_order;
400 struct obj_section **load_order_search_start;
401 struct obj_string_patch *string_patches;
402 struct obj_symbol_patch *symbol_patches;
403 int (*symbol_cmp)(const char *, const char *);
404 unsigned long (*symbol_hash)(const char *);
405 unsigned long local_symtab_size;
406 struct obj_symbol **local_symtab;
407 struct obj_symbol *symtab[HASH_BUCKETS];
408};
409
410enum obj_reloc
411{
412 obj_reloc_ok,
413 obj_reloc_overflow,
414 obj_reloc_dangerous,
415 obj_reloc_unhandled
416};
417
418struct obj_string_patch
419{
420 struct obj_string_patch *next;
421 int reloc_secidx;
422 ElfW(Addr) reloc_offset;
423 ElfW(Addr) string_offset;
424};
425
426struct obj_symbol_patch
427{
428 struct obj_symbol_patch *next;
429 int reloc_secidx;
430 ElfW(Addr) reloc_offset;
431 struct obj_symbol *sym;
432};
433
434
435/* Generic object manipulation routines. */
436
437unsigned long obj_elf_hash(const char *);
438
439unsigned long obj_elf_hash_n(const char *, unsigned long len);
440
441struct obj_symbol *obj_add_symbol (struct obj_file *f, const char *name,
442 unsigned long symidx, int info, int secidx,
443 ElfW(Addr) value, unsigned long size);
444
445struct obj_symbol *obj_find_symbol (struct obj_file *f,
446 const char *name);
447
448ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
449 struct obj_symbol *sym);
450
451void obj_set_symbol_compare(struct obj_file *f,
452 int (*cmp)(const char *, const char *),
453 unsigned long (*hash)(const char *));
454
455struct obj_section *obj_find_section (struct obj_file *f,
456 const char *name);
457
458void obj_insert_section_load_order (struct obj_file *f,
459 struct obj_section *sec);
460
461struct obj_section *obj_create_alloced_section (struct obj_file *f,
462 const char *name,
463 unsigned long align,
464 unsigned long size);
465
466struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
467 const char *name,
468 unsigned long align,
469 unsigned long size);
470
471void *obj_extend_section (struct obj_section *sec, unsigned long more);
472
473int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
474 const char *string);
475
476int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
477 struct obj_symbol *sym);
478
479int obj_check_undefineds(struct obj_file *f);
480
481void obj_allocate_commons(struct obj_file *f);
482
483unsigned long obj_load_size (struct obj_file *f);
484
485int obj_relocate (struct obj_file *f, ElfW(Addr) base);
486
487struct obj_file *obj_load(FILE *f);
488
489int obj_create_image (struct obj_file *f, char *image);
490
491/* Architecture specific manipulation routines. */
492
493struct obj_file *arch_new_file (void);
494
495struct obj_section *arch_new_section (void);
496
497struct obj_symbol *arch_new_symbol (void);
498
499enum obj_reloc arch_apply_relocation (struct obj_file *f,
500 struct obj_section *targsec,
501 struct obj_section *symsec,
502 struct obj_symbol *sym,
503 ElfW(RelM) *rel, ElfW(Addr) value);
504
505int arch_create_got (struct obj_file *f);
506
507struct new_module;
508int arch_init_module (struct obj_file *f, struct new_module *);
509
510#endif /* obj.h */
511//----------------------------------------------------------------------------
512//--------end of modutils obj.h
513//----------------------------------------------------------------------------
514
515
516
517
Erik Andersen02104321999-12-17 18:57:34 +0000518
Erik Andersend387d011999-12-21 02:55:11 +0000519#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000520static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000521
Eric Andersen9f16d612000-06-12 23:11:16 +0000522/*======================================================================*/
523
524int flag_force_load = 0;
525int flag_autoclean = 0;
526int flag_verbose = 0;
527int flag_export = 1;
528
529
530/*======================================================================*/
531
Eric Andersenfe4208f2000-09-24 03:44:29 +0000532/* previously, these were named i386_* but since we could be
533 compiling for the sh, I've renamed them to the more general
534 arch_* These structures are the same between the x86 and SH,
535 and we can't support anything else right now anyway. In the
536 future maybe they should be #if defined'd */
537
Eric Andersen21adca72000-12-06 18:18:26 +0000538/* Done ;-) */
539
540#if defined(__arm__)
541struct arm_plt_entry
542{
543 int offset;
544 int allocated:1;
545 int inited:1; /* has been set up */
546};
547#endif
548
Eric Andersenfe4208f2000-09-24 03:44:29 +0000549struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000550 int offset;
551 unsigned offset_done:1;
552 unsigned reloc_done:1;
553};
554
Eric Andersenfe4208f2000-09-24 03:44:29 +0000555struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000556 struct obj_file root;
Eric Andersen21adca72000-12-06 18:18:26 +0000557#if defined(__arm__)
558 struct obj_section *plt;
559#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000560 struct obj_section *got;
561};
562
Eric Andersenfe4208f2000-09-24 03:44:29 +0000563struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000564 struct obj_symbol root;
Eric Andersen21adca72000-12-06 18:18:26 +0000565#if defined(__arm__)
566 struct arm_plt_entry pltent;
567#endif
Eric Andersenfe4208f2000-09-24 03:44:29 +0000568 struct arch_got_entry gotent;
Eric Andersen9f16d612000-06-12 23:11:16 +0000569};
570
571
Eric Andersen9f16d612000-06-12 23:11:16 +0000572struct external_module {
573 const char *name;
574 ElfW(Addr) addr;
575 int used;
576 size_t nsyms;
577 struct new_module_symbol *syms;
578};
579
580struct new_module_symbol *ksyms;
581size_t nksyms;
582
583struct external_module *ext_modules;
584int n_ext_modules;
585int n_ext_modules_used;
586
Erik Andersend387d011999-12-21 02:55:11 +0000587
588
Erik Andersen02104321999-12-17 18:57:34 +0000589/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000590#define __NR_new_sys_init_module __NR_init_module
591_syscall2(int, new_sys_init_module, const char *, name,
592 const struct new_module *, info)
593#define __NR_old_sys_init_module __NR_init_module
594_syscall5(int, old_sys_init_module, const char *, name, char *, code,
595 unsigned, codesize, struct old_mod_routines *, routines,
596 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000597#ifndef BB_RMMOD
598_syscall1(int, delete_module, const char *, name)
599#else
600extern int delete_module(const char *);
601#endif
602
Eric Andersenfe4208f2000-09-24 03:44:29 +0000603/* This is kind of troublesome. See, we don't actually support
604 the m68k or the arm the same way we support i386 and (now)
605 sh. In doing my SH patch, I just assumed that whatever works
606 for i386 also works for m68k and arm since currently insmod.c
607 does nothing special for them. If this isn't true, the below
608 line is rather misleading IMHO, and someone should either
609 change it or add more proper architecture-dependent support
610 for these boys.
611
612 -- Bryan Rittmeyer <bryan@ixiacom.com> */
613
Eric Andersenf5d5e772001-01-24 23:34:48 +0000614#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen21adca72000-12-06 18:18:26 +0000615_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
616#endif
617
Erik Andersen02104321999-12-17 18:57:34 +0000618#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
619/* Jump through hoops to fixup error return codes */
620#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000621static inline _syscall2(long, _create_module, const char *, name, size_t,
622 size)
Erik Andersen02104321999-12-17 18:57:34 +0000623unsigned long create_module(const char *name, size_t size)
624{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000625 long ret = _create_module(name, size);
626
627 if (ret == -1 && errno > 125) {
628 ret = -errno;
629 errno = 0;
630 }
631 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000632}
633#else
634_syscall2(unsigned long, create_module, const char *, name, size_t, size)
635#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000636static char m_filename[BUFSIZ + 1] = "\0";
637static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000638
Eric Andersen9f16d612000-06-12 23:11:16 +0000639/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000640
Eric Andersen9f16d612000-06-12 23:11:16 +0000641
642static int findNamedModule(const char *fileName, struct stat *statbuf,
643 void *userDate)
644{
645 char *fullName = (char *) userDate;
646
647
648 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000649 return (FALSE);
650 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000651 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000652
653 if (tmp == NULL)
654 tmp = (char *) fileName;
655 else
656 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000657 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000658 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000659 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000660 return (FALSE);
661 }
Erik Andersend387d011999-12-21 02:55:11 +0000662 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000663 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000664}
665
Erik Andersen02104321999-12-17 18:57:34 +0000666
Eric Andersen9f16d612000-06-12 23:11:16 +0000667/*======================================================================*/
668
669struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000670{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000671 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000672 f = xmalloc(sizeof(*f));
673 f->got = NULL;
674 return &f->root;
675}
676
677struct obj_section *arch_new_section(void)
678{
679 return xmalloc(sizeof(struct obj_section));
680}
681
682struct obj_symbol *arch_new_symbol(void)
683{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000684 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000685 sym = xmalloc(sizeof(*sym));
686 memset(&sym->gotent, 0, sizeof(sym->gotent));
687 return &sym->root;
688}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000689
Eric Andersen9f16d612000-06-12 23:11:16 +0000690enum obj_reloc
691arch_apply_relocation(struct obj_file *f,
692 struct obj_section *targsec,
693 struct obj_section *symsec,
694 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000695 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000696{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000697 struct arch_file *ifile = (struct arch_file *) f;
698 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000699
Eric Andersen21adca72000-12-06 18:18:26 +0000700 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
701 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
702 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
703#if defined(__arm__)
704 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
705
706 struct arm_plt_entry *pe;
707 unsigned long *ip;
708#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000709
710 enum obj_reloc ret = obj_reloc_ok;
711
712 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000713
714/* even though these constants seem to be the same for
715 the i386 and the sh, we "#if define" them for clarity
716 and in case that ever changes */
717#if defined(__sh__)
718 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000719#elif defined(__arm__)
720 case R_ARM_NONE:
721#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000722 case R_386_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000723#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000724 break;
725
Eric Andersenfe4208f2000-09-24 03:44:29 +0000726#if defined(__sh__)
727 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000728#elif defined(__arm__)
729 case R_ARM_ABS32:
730#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000731 case R_386_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000732#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000733 *loc += v;
734 break;
735
Eric Andersen21adca72000-12-06 18:18:26 +0000736#if defined(__arm__)
737#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000738 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000739 *loc += v - dot;
740 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000741#elif defined(__i386__)
742 case R_386_PLT32:
743 case R_386_PC32:
744 *loc += v - dot;
745 break;
746#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000747
Eric Andersenfe4208f2000-09-24 03:44:29 +0000748#if defined(__sh__)
749 case R_SH_PLT32:
750 *loc = v - dot;
751 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000752#elif defined(__arm__)
753 case R_ARM_PC24:
754 case R_ARM_PLT32:
755 /* find the plt entry and initialize it if necessary */
756 assert(isym != NULL);
757 pe = (struct arm_plt_entry*) &isym->pltent;
758 if (! pe->inited) {
759 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
760 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
761 ip[1] = v; /* sym@ */
762 pe->inited = 1;
763 }
764
765 /* relative distance to target */
766 v -= dot;
767 /* if the target is too far away.... */
768 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
769 /* go via the plt */
770 v = plt + pe->offset - dot;
771 }
772 if (v & 3)
773 ret = obj_reloc_dangerous;
774
775 /* Convert to words. */
776 v >>= 2;
777
778 /* merge the offset into the instruction. */
779 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
780 break;
781#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000782#endif
783
784
Eric Andersen21adca72000-12-06 18:18:26 +0000785#if defined(__arm__)
786#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000787 case R_SH_GLOB_DAT:
788 case R_SH_JMP_SLOT:
789 *loc = v;
790 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000791#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000792 case R_386_GLOB_DAT:
793 case R_386_JMP_SLOT:
794 *loc = v;
795 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000796#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000797
Eric Andersen21adca72000-12-06 18:18:26 +0000798#if defined(__arm__)
799#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000800 case R_SH_RELATIVE:
801 *loc += f->baseaddr + rel->r_addend;
802 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000803#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000804 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000805 *loc += f->baseaddr;
806 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000807#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000808
Eric Andersenfe4208f2000-09-24 03:44:29 +0000809#if defined(__sh__)
810 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +0000811#elif defined(__arm__)
812 case R_ARM_GOTPC:
813#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000814 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000815#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000816 assert(got != 0);
817#if defined(__sh__)
818 *loc += got - dot + rel->r_addend;;
819#elif defined(__i386__) || defined(__arm__)
820 *loc += got - dot;
821#endif
822 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000823
Eric Andersenfe4208f2000-09-24 03:44:29 +0000824#if defined(__sh__)
825 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000826#elif defined(__arm__)
827 case R_ARM_GOT32:
828#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000829 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000830#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +0000832 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 if (!isym->gotent.reloc_done) {
834 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000835 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +0000836 }
Eric Andersen21adca72000-12-06 18:18:26 +0000837 /* make the reloc with_respect_to_.got */
838#if defined(__sh__)
839 *loc += isym->gotent.offset + rel->r_addend;
840#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000841 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000842#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000843 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000844
Eric Andersen21adca72000-12-06 18:18:26 +0000845 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +0000846#if defined(__sh__)
847 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +0000848#elif defined(__arm__)
849 case R_ARM_GOTOFF:
850#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000851 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000852#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000853 assert(got != 0);
854 *loc += v - got;
855 break;
856
857 default:
Eric Andersen21125542000-12-13 16:41:29 +0000858 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +0000859 ret = obj_reloc_unhandled;
860 break;
861 }
862
863 return ret;
864}
865
866int arch_create_got(struct obj_file *f)
867{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000868 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen21adca72000-12-06 18:18:26 +0000869 int i, got_offset = 0, gotneeded = 0;
870#if defined(__arm__)
871 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000872#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000873 struct obj_section *relsec, *symsec, *strsec;
874 ElfW(RelM) *rel, *relend;
875 ElfW(Sym) *symtab, *extsym;
876 const char *strtab, *name;
877 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000878
Eric Andersen21adca72000-12-06 18:18:26 +0000879 for (i = 0; i < f->header.e_shnum; ++i) {
880 relsec = f->sections[i];
881 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +0000882 continue;
883
Eric Andersen21adca72000-12-06 18:18:26 +0000884 symsec = f->sections[relsec->header.sh_link];
885 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +0000886
Eric Andersen21adca72000-12-06 18:18:26 +0000887 rel = (ElfW(RelM) *) relsec->contents;
888 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
889 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +0000890 strtab = (const char *) strsec->contents;
891
892 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +0000893 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +0000894
895 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +0000896#if defined(__arm__)
897 case R_ARM_GOT32:
898#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000899 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000900#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000901 case R_386_GOT32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000902#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000903 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000904
905#if defined(__arm__)
906 case R_ARM_PC24:
907 case R_ARM_PLT32:
908 pltneeded = 1;
909 break;
910
911 case R_ARM_GOTPC:
912 case R_ARM_GOTOFF:
913 gotneeded = 1;
914 if (got_offset == 0)
915 got_offset = 4;
916#elif defined(__sh__)
917 case R_SH_GOTPC:
918 case R_SH_GOTOFF:
919 gotneeded = 1;
920#elif defined(__i386__)
921 case R_386_GOTPC:
922 case R_386_GOTOFF:
923 gotneeded = 1;
924#endif
925
926 default:
927 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +0000928 }
929
Eric Andersen21adca72000-12-06 18:18:26 +0000930 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +0000931 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +0000932 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +0000933 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +0000934 }
935 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000936
937 if (!intsym->gotent.offset_done) {
938 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000939 intsym->gotent.offset = got_offset;
940 got_offset += 4;
941 }
942#if defined(__arm__)
943 if (pltneeded && intsym->pltent.allocated == 0) {
944 intsym->pltent.allocated = 1;
945 intsym->pltent.offset = plt_offset;
946 plt_offset += 8;
947 intsym->pltent.inited = 0;
948 pltneeded = 0;
949 }
950#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000951 }
952 }
Eric Andersen21adca72000-12-06 18:18:26 +0000953
954#if defined(__arm__)
955 if (got_offset) {
956 struct obj_section* relsec = obj_find_section(f, ".got");
957
958 if (relsec) {
959 obj_extend_section(relsec, got_offset);
960 } else {
961 relsec = obj_create_alloced_section(f, ".got", 8, got_offset);
962 assert(relsec);
963 }
964
965 ifile->got = relsec;
Eric Andersen9f16d612000-06-12 23:11:16 +0000966 }
967
Eric Andersen21adca72000-12-06 18:18:26 +0000968 if (plt_offset)
969 ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset);
970#else
971 if (got_offset > 0 || gotneeded)
972 ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset);
973#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000974
975 return 1;
976}
977
978int arch_init_module(struct obj_file *f, struct new_module *mod)
979{
980 return 1;
981}
982
983
984/*======================================================================*/
985
986/* Standard ELF hash function. */
987inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
988{
989 unsigned long h = 0;
990 unsigned long g;
991 unsigned char ch;
992
993 while (n > 0) {
994 ch = *name++;
995 h = (h << 4) + ch;
996 if ((g = (h & 0xf0000000)) != 0) {
997 h ^= g >> 24;
998 h &= ~g;
999 }
1000 n--;
1001 }
1002 return h;
1003}
1004
1005unsigned long obj_elf_hash(const char *name)
1006{
1007 return obj_elf_hash_n(name, strlen(name));
1008}
1009
1010#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1011/* Get the kernel version in the canonical integer form. */
1012
1013static int get_kernel_version(char str[STRVERSIONLEN])
1014{
1015 struct utsname uts_info;
1016 char *p, *q;
1017 int a, b, c;
1018
1019 if (uname(&uts_info) < 0)
1020 return -1;
1021 strncpy(str, uts_info.release, STRVERSIONLEN);
1022 p = uts_info.release;
1023
1024 a = strtoul(p, &p, 10);
1025 if (*p != '.')
1026 return -1;
1027 b = strtoul(p + 1, &p, 10);
1028 if (*p != '.')
1029 return -1;
1030 c = strtoul(p + 1, &q, 10);
1031 if (p + 1 == q)
1032 return -1;
1033
1034 return a << 16 | b << 8 | c;
1035}
1036
1037/* String comparison for non-co-versioned kernel and module. */
1038
1039static int ncv_strcmp(const char *a, const char *b)
1040{
1041 size_t alen = strlen(a), blen = strlen(b);
1042
1043 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1044 return strncmp(a, b, alen);
1045 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1046 return strncmp(a, b, blen);
1047 else
1048 return strcmp(a, b);
1049}
1050
1051/* String hashing for non-co-versioned kernel and module. Here
1052 we are simply forced to drop the crc from the hash. */
1053
1054static unsigned long ncv_symbol_hash(const char *str)
1055{
1056 size_t len = strlen(str);
1057 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1058 len -= 10;
1059 return obj_elf_hash_n(str, len);
1060}
1061
1062void
1063obj_set_symbol_compare(struct obj_file *f,
1064 int (*cmp) (const char *, const char *),
1065 unsigned long (*hash) (const char *))
1066{
1067 if (cmp)
1068 f->symbol_cmp = cmp;
1069 if (hash) {
1070 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1071 int i;
1072
1073 f->symbol_hash = hash;
1074
1075 memcpy(tmptab, f->symtab, sizeof(tmptab));
1076 memset(f->symtab, 0, sizeof(f->symtab));
1077
1078 for (i = 0; i < HASH_BUCKETS; ++i)
1079 for (sym = tmptab[i]; sym; sym = next) {
1080 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1081 next = sym->next;
1082 sym->next = f->symtab[h];
1083 f->symtab[h] = sym;
1084 }
1085 }
1086}
1087
1088#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1089
1090
1091struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1092 unsigned long symidx, int info,
1093 int secidx, ElfW(Addr) value,
1094 unsigned long size)
1095{
1096 struct obj_symbol *sym;
1097 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1098 int n_type = ELFW(ST_TYPE) (info);
1099 int n_binding = ELFW(ST_BIND) (info);
1100
1101 for (sym = f->symtab[hash]; sym; sym = sym->next)
1102 if (f->symbol_cmp(sym->name, name) == 0) {
1103 int o_secidx = sym->secidx;
1104 int o_info = sym->info;
1105 int o_type = ELFW(ST_TYPE) (o_info);
1106 int o_binding = ELFW(ST_BIND) (o_info);
1107
1108 /* A redefinition! Is it legal? */
1109
1110 if (secidx == SHN_UNDEF)
1111 return sym;
1112 else if (o_secidx == SHN_UNDEF)
1113 goto found;
1114 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1115 /* Cope with local and global symbols of the same name
1116 in the same object file, as might have been created
1117 by ld -r. The only reason locals are now seen at this
1118 level at all is so that we can do semi-sensible things
1119 with parameters. */
1120
1121 struct obj_symbol *nsym, **p;
1122
1123 nsym = arch_new_symbol();
1124 nsym->next = sym->next;
1125 nsym->ksymidx = -1;
1126
1127 /* Excise the old (local) symbol from the hash chain. */
1128 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1129 continue;
1130 *p = sym = nsym;
1131 goto found;
1132 } else if (n_binding == STB_LOCAL) {
1133 /* Another symbol of the same name has already been defined.
1134 Just add this to the local table. */
1135 sym = arch_new_symbol();
1136 sym->next = NULL;
1137 sym->ksymidx = -1;
1138 f->local_symtab[symidx] = sym;
1139 goto found;
1140 } else if (n_binding == STB_WEAK)
1141 return sym;
1142 else if (o_binding == STB_WEAK)
1143 goto found;
1144 /* Don't unify COMMON symbols with object types the programmer
1145 doesn't expect. */
1146 else if (secidx == SHN_COMMON
1147 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1148 return sym;
1149 else if (o_secidx == SHN_COMMON
1150 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1151 goto found;
1152 else {
1153 /* Don't report an error if the symbol is coming from
1154 the kernel or some external module. */
1155 if (secidx <= SHN_HIRESERVE)
Mark Whitleyf57c9442000-12-07 19:56:48 +00001156 error_msg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001157 return sym;
1158 }
1159 }
1160
1161 /* Completely new symbol. */
1162 sym = arch_new_symbol();
1163 sym->next = f->symtab[hash];
1164 f->symtab[hash] = sym;
1165 sym->ksymidx = -1;
1166
1167 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1168 f->local_symtab[symidx] = sym;
1169
1170 found:
1171 sym->name = name;
1172 sym->value = value;
1173 sym->size = size;
1174 sym->secidx = secidx;
1175 sym->info = info;
1176
1177 return sym;
1178}
1179
1180struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1181{
1182 struct obj_symbol *sym;
1183 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1184
1185 for (sym = f->symtab[hash]; sym; sym = sym->next)
1186 if (f->symbol_cmp(sym->name, name) == 0)
1187 return sym;
1188
1189 return NULL;
1190}
1191
1192ElfW(Addr)
1193 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1194{
1195 if (sym) {
1196 if (sym->secidx >= SHN_LORESERVE)
1197 return sym->value;
1198
1199 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1200 } else {
1201 /* As a special case, a NULL sym has value zero. */
1202 return 0;
1203 }
1204}
1205
1206struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1207{
1208 int i, n = f->header.e_shnum;
1209
1210 for (i = 0; i < n; ++i)
1211 if (strcmp(f->sections[i]->name, name) == 0)
1212 return f->sections[i];
1213
1214 return NULL;
1215}
1216
1217static int obj_load_order_prio(struct obj_section *a)
1218{
1219 unsigned long af, ac;
1220
1221 af = a->header.sh_flags;
1222
1223 ac = 0;
1224 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1225 strcmp(a->name + 5, ".init"))
1226 ac |= 32;
1227 if (af & SHF_ALLOC)
1228 ac |= 16;
1229 if (!(af & SHF_WRITE))
1230 ac |= 8;
1231 if (af & SHF_EXECINSTR)
1232 ac |= 4;
1233 if (a->header.sh_type != SHT_NOBITS)
1234 ac |= 2;
1235
1236 return ac;
1237}
1238
1239void
1240obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1241{
1242 struct obj_section **p;
1243 int prio = obj_load_order_prio(sec);
1244 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1245 if (obj_load_order_prio(*p) < prio)
1246 break;
1247 sec->load_next = *p;
1248 *p = sec;
1249}
1250
1251struct obj_section *obj_create_alloced_section(struct obj_file *f,
1252 const char *name,
1253 unsigned long align,
1254 unsigned long size)
1255{
1256 int newidx = f->header.e_shnum++;
1257 struct obj_section *sec;
1258
1259 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1260 f->sections[newidx] = sec = arch_new_section();
1261
1262 memset(sec, 0, sizeof(*sec));
1263 sec->header.sh_type = SHT_PROGBITS;
1264 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1265 sec->header.sh_size = size;
1266 sec->header.sh_addralign = align;
1267 sec->name = name;
1268 sec->idx = newidx;
1269 if (size)
1270 sec->contents = xmalloc(size);
1271
1272 obj_insert_section_load_order(f, sec);
1273
1274 return sec;
1275}
1276
1277struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1278 const char *name,
1279 unsigned long align,
1280 unsigned long size)
1281{
1282 int newidx = f->header.e_shnum++;
1283 struct obj_section *sec;
1284
1285 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1286 f->sections[newidx] = sec = arch_new_section();
1287
1288 memset(sec, 0, sizeof(*sec));
1289 sec->header.sh_type = SHT_PROGBITS;
1290 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1291 sec->header.sh_size = size;
1292 sec->header.sh_addralign = align;
1293 sec->name = name;
1294 sec->idx = newidx;
1295 if (size)
1296 sec->contents = xmalloc(size);
1297
1298 sec->load_next = f->load_order;
1299 f->load_order = sec;
1300 if (f->load_order_search_start == &f->load_order)
1301 f->load_order_search_start = &sec->load_next;
1302
1303 return sec;
1304}
1305
1306void *obj_extend_section(struct obj_section *sec, unsigned long more)
1307{
1308 unsigned long oldsize = sec->header.sh_size;
1309 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1310 return sec->contents + oldsize;
1311}
1312
1313
1314
1315/* Conditionally add the symbols from the given symbol set to the
1316 new module. */
1317
1318static int
1319add_symbols_from(
1320 struct obj_file *f,
1321 int idx, struct new_module_symbol *syms, size_t nsyms)
1322{
1323 struct new_module_symbol *s;
1324 size_t i;
1325 int used = 0;
1326
1327 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1328
1329 /* Only add symbols that are already marked external. If we
1330 override locals we may cause problems for argument initialization.
1331 We will also create a false dependency on the module. */
1332 struct obj_symbol *sym;
1333
1334 sym = obj_find_symbol(f, (char *) s->name);
1335 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1336 sym = obj_add_symbol(f, (char *) s->name, -1,
1337 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1338 idx, s->value, 0);
1339 /* Did our symbol just get installed? If so, mark the
1340 module as "used". */
1341 if (sym->secidx == idx)
1342 used = 1;
1343 }
1344 }
1345
1346 return used;
1347}
1348
1349static void add_kernel_symbols(struct obj_file *f)
1350{
1351 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001352 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001353
1354 /* Add module symbols first. */
1355
1356 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1357 if (m->nsyms
1358 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1359 m->nsyms)) m->used = 1, ++nused;
1360
1361 n_ext_modules_used = nused;
1362
1363 /* And finally the symbols from the kernel proper. */
1364
1365 if (nksyms)
1366 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1367}
1368
1369static char *get_modinfo_value(struct obj_file *f, const char *key)
1370{
1371 struct obj_section *sec;
1372 char *p, *v, *n, *ep;
1373 size_t klen = strlen(key);
1374
1375 sec = obj_find_section(f, ".modinfo");
1376 if (sec == NULL)
1377 return NULL;
1378 p = sec->contents;
1379 ep = p + sec->header.sh_size;
1380 while (p < ep) {
1381 v = strchr(p, '=');
1382 n = strchr(p, '\0');
1383 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001384 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001385 return v + 1;
1386 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001387 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001388 return n;
1389 }
1390 p = n + 1;
1391 }
1392
1393 return NULL;
1394}
1395
1396
1397/*======================================================================*/
1398/* Functions relating to module loading in pre 2.1 kernels. */
1399
1400static int
1401old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1402{
1403 while (argc > 0) {
1404 char *p, *q;
1405 struct obj_symbol *sym;
1406 int *loc;
1407
1408 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001409 if ((q = strchr(p, '=')) == NULL) {
1410 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001411 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001412 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001413 *q++ = '\0';
1414
1415 sym = obj_find_symbol(f, p);
1416
1417 /* Also check that the parameter was not resolved from the kernel. */
1418 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001419 error_msg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001420 return 0;
1421 }
1422
1423 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1424
1425 /* Do C quoting if we begin with a ". */
1426 if (*q == '"') {
1427 char *r, *str;
1428
1429 str = alloca(strlen(q));
1430 for (r = str, q++; *q != '"'; ++q, ++r) {
1431 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001432 error_msg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001433 return 0;
1434 } else if (*q == '\\')
1435 switch (*++q) {
1436 case 'a':
1437 *r = '\a';
1438 break;
1439 case 'b':
1440 *r = '\b';
1441 break;
1442 case 'e':
1443 *r = '\033';
1444 break;
1445 case 'f':
1446 *r = '\f';
1447 break;
1448 case 'n':
1449 *r = '\n';
1450 break;
1451 case 'r':
1452 *r = '\r';
1453 break;
1454 case 't':
1455 *r = '\t';
1456 break;
1457
1458 case '0':
1459 case '1':
1460 case '2':
1461 case '3':
1462 case '4':
1463 case '5':
1464 case '6':
1465 case '7':
1466 {
1467 int c = *q - '0';
1468 if (q[1] >= '0' && q[1] <= '7') {
1469 c = (c * 8) + *++q - '0';
1470 if (q[1] >= '0' && q[1] <= '7')
1471 c = (c * 8) + *++q - '0';
1472 }
1473 *r = c;
1474 }
1475 break;
1476
1477 default:
1478 *r = *q;
1479 break;
1480 } else
1481 *r = *q;
1482 }
1483 *r = '\0';
1484 obj_string_patch(f, sym->secidx, sym->value, str);
1485 } else if (*q >= '0' && *q <= '9') {
1486 do
1487 *loc++ = strtoul(q, &q, 0);
1488 while (*q++ == ',');
1489 } else {
1490 char *contents = f->sections[sym->secidx]->contents;
1491 char *loc = contents + sym->value;
1492 char *r; /* To search for commas */
1493
1494 /* Break the string with comas */
1495 while ((r = strchr(q, ',')) != (char *) NULL) {
1496 *r++ = '\0';
1497 obj_string_patch(f, sym->secidx, loc - contents, q);
1498 loc += sizeof(char *);
1499 q = r;
1500 }
1501
1502 /* last part */
1503 obj_string_patch(f, sym->secidx, loc - contents, q);
1504 }
1505
1506 argc--, argv++;
1507 }
1508
1509 return 1;
1510}
1511
1512#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1513static int old_is_module_checksummed(struct obj_file *f)
1514{
1515 return obj_find_symbol(f, "Using_Versions") != NULL;
1516}
1517/* Get the module's kernel version in the canonical integer form. */
1518
1519static int
1520old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1521{
1522 struct obj_symbol *sym;
1523 char *p, *q;
1524 int a, b, c;
1525
1526 sym = obj_find_symbol(f, "kernel_version");
1527 if (sym == NULL)
1528 return -1;
1529
1530 p = f->sections[sym->secidx]->contents + sym->value;
1531 strncpy(str, p, STRVERSIONLEN);
1532
1533 a = strtoul(p, &p, 10);
1534 if (*p != '.')
1535 return -1;
1536 b = strtoul(p + 1, &p, 10);
1537 if (*p != '.')
1538 return -1;
1539 c = strtoul(p + 1, &q, 10);
1540 if (p + 1 == q)
1541 return -1;
1542
1543 return a << 16 | b << 8 | c;
1544}
1545
1546#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1547
Eric Andersenf5d5e772001-01-24 23:34:48 +00001548#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001549
1550/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1551
Eric Andersen8c185f92000-09-22 00:38:07 +00001552static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001553{
1554 struct old_kernel_sym *ks, *k;
1555 struct new_module_symbol *s;
1556 struct external_module *mod;
1557 int nks, nms, nmod, i;
1558
1559 nks = get_kernel_syms(NULL);
1560 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001561 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001562 return 0;
1563 }
1564
1565 ks = k = xmalloc(nks * sizeof(*ks));
1566
1567 if (get_kernel_syms(ks) != nks) {
1568 perror("inconsistency with get_kernel_syms -- is someone else "
1569 "playing with modules?");
1570 free(ks);
1571 return 0;
1572 }
1573
1574 /* Collect the module information. */
1575
1576 mod = NULL;
1577 nmod = -1;
1578
1579 while (k->name[0] == '#' && k->name[1]) {
1580 struct old_kernel_sym *k2;
1581 struct new_module_symbol *s;
1582
1583 /* Find out how many symbols this module has. */
1584 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1585 continue;
1586 nms = k2 - k - 1;
1587
1588 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1589 mod[nmod].name = k->name + 1;
1590 mod[nmod].addr = k->value;
1591 mod[nmod].used = 0;
1592 mod[nmod].nsyms = nms;
1593 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1594
1595 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1596 s->name = (unsigned long) k->name;
1597 s->value = k->value;
1598 }
1599
1600 k = k2;
1601 }
1602
1603 ext_modules = mod;
1604 n_ext_modules = nmod + 1;
1605
1606 /* Now collect the symbols for the kernel proper. */
1607
1608 if (k->name[0] == '#')
1609 ++k;
1610
1611 nksyms = nms = nks - (k - ks);
1612 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1613
1614 for (i = 0; i < nms; ++i, ++s, ++k) {
1615 s->name = (unsigned long) k->name;
1616 s->value = k->value;
1617 }
1618
1619 return 1;
1620}
1621
1622/* Return the kernel symbol checksum version, or zero if not used. */
1623
1624static int old_is_kernel_checksummed(void)
1625{
1626 /* Using_Versions is the first symbol. */
1627 if (nksyms > 0
1628 && strcmp((char *) ksyms[0].name,
1629 "Using_Versions") == 0) return ksyms[0].value;
1630 else
1631 return 0;
1632}
1633
1634
1635static int old_create_mod_use_count(struct obj_file *f)
1636{
1637 struct obj_section *sec;
1638
1639 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1640 sizeof(long));
1641
1642 obj_add_symbol(f, "mod_use_count_", -1,
1643 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1644 sizeof(long));
1645
1646 return 1;
1647}
1648
1649static int
1650old_init_module(const char *m_name, struct obj_file *f,
1651 unsigned long m_size)
1652{
1653 char *image;
1654 struct old_mod_routines routines;
1655 struct old_symbol_table *symtab;
1656 int ret;
1657
1658 /* Create the symbol table */
1659 {
1660 int nsyms = 0, strsize = 0, total;
1661
1662 /* Size things first... */
1663 if (flag_export) {
1664 int i;
1665 for (i = 0; i < HASH_BUCKETS; ++i) {
1666 struct obj_symbol *sym;
1667 for (sym = f->symtab[i]; sym; sym = sym->next)
1668 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1669 && sym->secidx <= SHN_HIRESERVE)
1670 {
1671 sym->ksymidx = nsyms++;
1672 strsize += strlen(sym->name) + 1;
1673 }
1674 }
1675 }
1676
1677 total = (sizeof(struct old_symbol_table)
1678 + nsyms * sizeof(struct old_module_symbol)
1679 + n_ext_modules_used * sizeof(struct old_module_ref)
1680 + strsize);
1681 symtab = xmalloc(total);
1682 symtab->size = total;
1683 symtab->n_symbols = nsyms;
1684 symtab->n_refs = n_ext_modules_used;
1685
1686 if (flag_export && nsyms) {
1687 struct old_module_symbol *ksym;
1688 char *str;
1689 int i;
1690
1691 ksym = symtab->symbol;
1692 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1693 + n_ext_modules_used * sizeof(struct old_module_ref));
1694
1695 for (i = 0; i < HASH_BUCKETS; ++i) {
1696 struct obj_symbol *sym;
1697 for (sym = f->symtab[i]; sym; sym = sym->next)
1698 if (sym->ksymidx >= 0) {
1699 ksym->addr = obj_symbol_final_value(f, sym);
1700 ksym->name =
1701 (unsigned long) str - (unsigned long) symtab;
1702
Matt Kraai70a78552001-01-04 02:00:17 +00001703 strcpy(str, sym->name);
1704 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001705 ksym++;
1706 }
1707 }
1708 }
1709
1710 if (n_ext_modules_used) {
1711 struct old_module_ref *ref;
1712 int i;
1713
1714 ref = (struct old_module_ref *)
1715 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1716
1717 for (i = 0; i < n_ext_modules; ++i)
1718 if (ext_modules[i].used)
1719 ref++->module = ext_modules[i].addr;
1720 }
1721 }
1722
1723 /* Fill in routines. */
1724
1725 routines.init =
1726 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1727 routines.cleanup =
1728 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1729
1730 /* Whew! All of the initialization is complete. Collect the final
1731 module image and give it to the kernel. */
1732
1733 image = xmalloc(m_size);
1734 obj_create_image(f, image);
1735
1736 /* image holds the complete relocated module, accounting correctly for
1737 mod_use_count. However the old module kernel support assume that
1738 it is receiving something which does not contain mod_use_count. */
1739 ret = old_sys_init_module(m_name, image + sizeof(long),
1740 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1741 : 0), &routines, symtab);
1742 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001743 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001744
1745 free(image);
1746 free(symtab);
1747
1748 return ret == 0;
1749}
1750
1751#else
1752
1753#define old_create_mod_use_count(x) TRUE
1754#define old_init_module(x, y, z) TRUE
1755
Eric Andersenf5d5e772001-01-24 23:34:48 +00001756#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00001757
1758
1759
1760/*======================================================================*/
1761/* Functions relating to module loading after 2.1.18. */
1762
1763static int
1764new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1765{
1766 while (argc > 0) {
1767 char *p, *q, *key;
1768 struct obj_symbol *sym;
1769 char *contents, *loc;
1770 int min, max, n;
1771
1772 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001773 if ((q = strchr(p, '=')) == NULL) {
1774 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001775 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001776 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001777
1778 key = alloca(q - p + 6);
1779 memcpy(key, "parm_", 5);
1780 memcpy(key + 5, p, q - p);
1781 key[q - p + 5] = 0;
1782
1783 p = get_modinfo_value(f, key);
1784 key += 5;
1785 if (p == NULL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001786 error_msg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001787 return 0;
1788 }
1789
1790 sym = obj_find_symbol(f, key);
1791
1792 /* Also check that the parameter was not resolved from the kernel. */
1793 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001794 error_msg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001795 return 0;
1796 }
1797
1798 if (isdigit(*p)) {
1799 min = strtoul(p, &p, 10);
1800 if (*p == '-')
1801 max = strtoul(p + 1, &p, 10);
1802 else
1803 max = min;
1804 } else
1805 min = max = 1;
1806
1807 contents = f->sections[sym->secidx]->contents;
1808 loc = contents + sym->value;
1809 n = (*++q != '\0');
1810
1811 while (1) {
1812 if ((*p == 's') || (*p == 'c')) {
1813 char *str;
1814
1815 /* Do C quoting if we begin with a ", else slurp the lot. */
1816 if (*q == '"') {
1817 char *r;
1818
1819 str = alloca(strlen(q));
1820 for (r = str, q++; *q != '"'; ++q, ++r) {
1821 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001822 error_msg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001823 key);
1824 return 0;
1825 } else if (*q == '\\')
1826 switch (*++q) {
1827 case 'a':
1828 *r = '\a';
1829 break;
1830 case 'b':
1831 *r = '\b';
1832 break;
1833 case 'e':
1834 *r = '\033';
1835 break;
1836 case 'f':
1837 *r = '\f';
1838 break;
1839 case 'n':
1840 *r = '\n';
1841 break;
1842 case 'r':
1843 *r = '\r';
1844 break;
1845 case 't':
1846 *r = '\t';
1847 break;
1848
1849 case '0':
1850 case '1':
1851 case '2':
1852 case '3':
1853 case '4':
1854 case '5':
1855 case '6':
1856 case '7':
1857 {
1858 int c = *q - '0';
1859 if (q[1] >= '0' && q[1] <= '7') {
1860 c = (c * 8) + *++q - '0';
1861 if (q[1] >= '0' && q[1] <= '7')
1862 c = (c * 8) + *++q - '0';
1863 }
1864 *r = c;
1865 }
1866 break;
1867
1868 default:
1869 *r = *q;
1870 break;
1871 } else
1872 *r = *q;
1873 }
1874 *r = '\0';
1875 ++q;
1876 } else {
1877 char *r;
1878
1879 /* In this case, the string is not quoted. We will break
1880 it using the coma (like for ints). If the user wants to
1881 include comas in a string, he just has to quote it */
1882
1883 /* Search the next coma */
1884 r = strchr(q, ',');
1885
1886 /* Found ? */
1887 if (r != (char *) NULL) {
1888 /* Recopy the current field */
1889 str = alloca(r - q + 1);
1890 memcpy(str, q, r - q);
1891
1892 /* I don't know if it is usefull, as the previous case
1893 doesn't null terminate the string ??? */
1894 str[r - q] = '\0';
1895
1896 /* Keep next fields */
1897 q = r;
1898 } else {
1899 /* last string */
1900 str = q;
1901 q = "";
1902 }
1903 }
1904
1905 if (*p == 's') {
1906 /* Normal string */
1907 obj_string_patch(f, sym->secidx, loc - contents, str);
1908 loc += tgt_sizeof_char_p;
1909 } else {
1910 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001911 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001912
1913 /* Get the size of each member */
1914 /* Probably we should do that outside the loop ? */
1915 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001916 error_msg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001917 " the maximum size\n", key);
1918 return 0;
1919 }
1920 charssize = strtoul(p + 1, (char **) NULL, 10);
1921
1922 /* Check length */
1923 if (strlen(str) >= charssize) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001924 error_msg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001925 charssize - 1);
1926 return 0;
1927 }
1928
1929 /* Copy to location */
1930 strcpy((char *) loc, str);
1931 loc += charssize;
1932 }
1933 } else {
1934 long v = strtoul(q, &q, 0);
1935 switch (*p) {
1936 case 'b':
1937 *loc++ = v;
1938 break;
1939 case 'h':
1940 *(short *) loc = v;
1941 loc += tgt_sizeof_short;
1942 break;
1943 case 'i':
1944 *(int *) loc = v;
1945 loc += tgt_sizeof_int;
1946 break;
1947 case 'l':
1948 *(long *) loc = v;
1949 loc += tgt_sizeof_long;
1950 break;
1951
1952 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001953 error_msg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001954 return 0;
1955 }
1956 }
1957
1958 retry_end_of_value:
1959 switch (*q) {
1960 case '\0':
1961 goto end_of_arg;
1962
1963 case ' ':
1964 case '\t':
1965 case '\n':
1966 case '\r':
1967 ++q;
1968 goto retry_end_of_value;
1969
1970 case ',':
1971 if (++n > max) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001972 error_msg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001973 return 0;
1974 }
1975 ++q;
1976 break;
1977
1978 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001979 error_msg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001980 return 0;
1981 }
1982 }
1983
1984 end_of_arg:
1985 if (n < min) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001986 error_msg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001987 return 0;
1988 }
1989
1990 argc--, argv++;
1991 }
1992
1993 return 1;
1994}
1995
1996#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1997static int new_is_module_checksummed(struct obj_file *f)
1998{
1999 const char *p = get_modinfo_value(f, "using_checksums");
2000 if (p)
2001 return atoi(p);
2002 else
2003 return 0;
2004}
2005
2006/* Get the module's kernel version in the canonical integer form. */
2007
2008static int
2009new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2010{
2011 char *p, *q;
2012 int a, b, c;
2013
2014 p = get_modinfo_value(f, "kernel_version");
2015 if (p == NULL)
2016 return -1;
2017 strncpy(str, p, STRVERSIONLEN);
2018
2019 a = strtoul(p, &p, 10);
2020 if (*p != '.')
2021 return -1;
2022 b = strtoul(p + 1, &p, 10);
2023 if (*p != '.')
2024 return -1;
2025 c = strtoul(p + 1, &q, 10);
2026 if (p + 1 == q)
2027 return -1;
2028
2029 return a << 16 | b << 8 | c;
2030}
2031
2032#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2033
2034
Eric Andersenf5d5e772001-01-24 23:34:48 +00002035#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002036
2037/* Fetch the loaded modules, and all currently exported symbols. */
2038
2039static int new_get_kernel_symbols(void)
2040{
2041 char *module_names, *mn;
2042 struct external_module *modules, *m;
2043 struct new_module_symbol *syms, *s;
2044 size_t ret, bufsize, nmod, nsyms, i, j;
2045
2046 /* Collect the loaded modules. */
2047
2048 module_names = xmalloc(bufsize = 256);
2049 retry_modules_load:
2050 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2051 if (errno == ENOSPC) {
2052 module_names = xrealloc(module_names, bufsize = ret);
2053 goto retry_modules_load;
2054 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002055 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002056 return 0;
2057 }
2058
2059 n_ext_modules = nmod = ret;
2060 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2061 memset(modules, 0, nmod * sizeof(*modules));
2062
2063 /* Collect the modules' symbols. */
2064
2065 for (i = 0, mn = module_names, m = modules;
2066 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2067 struct new_module_info info;
2068
2069 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2070 if (errno == ENOENT) {
2071 /* The module was removed out from underneath us. */
2072 continue;
2073 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002074 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002075 return 0;
2076 }
2077
2078 syms = xmalloc(bufsize = 1024);
2079 retry_mod_sym_load:
2080 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2081 switch (errno) {
2082 case ENOSPC:
2083 syms = xrealloc(syms, bufsize = ret);
2084 goto retry_mod_sym_load;
2085 case ENOENT:
2086 /* The module was removed out from underneath us. */
2087 continue;
2088 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002089 perror_msg("query_module: QM_SYMBOLS: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002090 return 0;
2091 }
2092 }
2093 nsyms = ret;
2094
2095 m->name = mn;
2096 m->addr = info.addr;
2097 m->nsyms = nsyms;
2098 m->syms = syms;
2099
2100 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2101 s->name += (unsigned long) syms;
2102 }
2103 }
2104
2105 /* Collect the kernel's symbols. */
2106
2107 syms = xmalloc(bufsize = 16 * 1024);
2108 retry_kern_sym_load:
2109 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2110 if (errno == ENOSPC) {
2111 syms = xrealloc(syms, bufsize = ret);
2112 goto retry_kern_sym_load;
2113 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002114 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002115 return 0;
2116 }
2117 nksyms = nsyms = ret;
2118 ksyms = syms;
2119
2120 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2121 s->name += (unsigned long) syms;
2122 }
2123 return 1;
2124}
2125
2126
2127/* Return the kernel symbol checksum version, or zero if not used. */
2128
2129static int new_is_kernel_checksummed(void)
2130{
2131 struct new_module_symbol *s;
2132 size_t i;
2133
2134 /* Using_Versions is not the first symbol, but it should be in there. */
2135
2136 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2137 if (strcmp((char *) s->name, "Using_Versions") == 0)
2138 return s->value;
2139
2140 return 0;
2141}
2142
2143
2144static int new_create_this_module(struct obj_file *f, const char *m_name)
2145{
2146 struct obj_section *sec;
2147
2148 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2149 sizeof(struct new_module));
2150 memset(sec->contents, 0, sizeof(struct new_module));
2151
2152 obj_add_symbol(f, "__this_module", -1,
2153 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2154 sizeof(struct new_module));
2155
2156 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2157 m_name);
2158
2159 return 1;
2160}
2161
2162
2163static int new_create_module_ksymtab(struct obj_file *f)
2164{
2165 struct obj_section *sec;
2166 int i;
2167
2168 /* We must always add the module references. */
2169
2170 if (n_ext_modules_used) {
2171 struct new_module_ref *dep;
2172 struct obj_symbol *tm;
2173
2174 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2175 (sizeof(struct new_module_ref)
2176 * n_ext_modules_used));
2177 if (!sec)
2178 return 0;
2179
2180 tm = obj_find_symbol(f, "__this_module");
2181 dep = (struct new_module_ref *) sec->contents;
2182 for (i = 0; i < n_ext_modules; ++i)
2183 if (ext_modules[i].used) {
2184 dep->dep = ext_modules[i].addr;
2185 obj_symbol_patch(f, sec->idx,
2186 (char *) &dep->ref - sec->contents, tm);
2187 dep->next_ref = 0;
2188 ++dep;
2189 }
2190 }
2191
2192 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2193 size_t nsyms;
2194 int *loaded;
2195
2196 sec =
2197 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2198 0);
2199
2200 /* We don't want to export symbols residing in sections that
2201 aren't loaded. There are a number of these created so that
2202 we make sure certain module options don't appear twice. */
2203
2204 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2205 while (--i >= 0)
2206 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2207
2208 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2209 struct obj_symbol *sym;
2210 for (sym = f->symtab[i]; sym; sym = sym->next)
2211 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2212 && sym->secidx <= SHN_HIRESERVE
2213 && (sym->secidx >= SHN_LORESERVE
2214 || loaded[sym->secidx])) {
2215 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2216
2217 obj_symbol_patch(f, sec->idx, ofs, sym);
2218 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2219 sym->name);
2220
2221 nsyms++;
2222 }
2223 }
2224
2225 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2226 }
2227
2228 return 1;
2229}
2230
2231
2232static int
2233new_init_module(const char *m_name, struct obj_file *f,
2234 unsigned long m_size)
2235{
2236 struct new_module *module;
2237 struct obj_section *sec;
2238 void *image;
2239 int ret;
2240 tgt_long m_addr;
2241
2242 sec = obj_find_section(f, ".this");
2243 module = (struct new_module *) sec->contents;
2244 m_addr = sec->header.sh_addr;
2245
2246 module->size_of_struct = sizeof(*module);
2247 module->size = m_size;
2248 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2249
2250 sec = obj_find_section(f, "__ksymtab");
2251 if (sec && sec->header.sh_size) {
2252 module->syms = sec->header.sh_addr;
2253 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2254 }
2255
2256 if (n_ext_modules_used) {
2257 sec = obj_find_section(f, ".kmodtab");
2258 module->deps = sec->header.sh_addr;
2259 module->ndeps = n_ext_modules_used;
2260 }
2261
2262 module->init =
2263 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2264 module->cleanup =
2265 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2266
2267 sec = obj_find_section(f, "__ex_table");
2268 if (sec) {
2269 module->ex_table_start = sec->header.sh_addr;
2270 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2271 }
2272
2273 sec = obj_find_section(f, ".text.init");
2274 if (sec) {
2275 module->runsize = sec->header.sh_addr - m_addr;
2276 }
2277 sec = obj_find_section(f, ".data.init");
2278 if (sec) {
2279 if (!module->runsize ||
2280 module->runsize > sec->header.sh_addr - m_addr)
2281 module->runsize = sec->header.sh_addr - m_addr;
2282 }
2283
2284 if (!arch_init_module(f, module))
2285 return 0;
2286
2287 /* Whew! All of the initialization is complete. Collect the final
2288 module image and give it to the kernel. */
2289
2290 image = xmalloc(m_size);
2291 obj_create_image(f, image);
2292
2293 ret = new_sys_init_module(m_name, (struct new_module *) image);
2294 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002295 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002296
2297 free(image);
2298
2299 return ret == 0;
2300}
2301
2302#else
2303
2304#define new_init_module(x, y, z) TRUE
2305#define new_create_this_module(x, y) 0
2306#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002307#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002308
Eric Andersenf5d5e772001-01-24 23:34:48 +00002309#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002310
2311
2312/*======================================================================*/
2313
2314int
2315obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2316 const char *string)
2317{
2318 struct obj_string_patch *p;
2319 struct obj_section *strsec;
2320 size_t len = strlen(string) + 1;
2321 char *loc;
2322
2323 p = xmalloc(sizeof(*p));
2324 p->next = f->string_patches;
2325 p->reloc_secidx = secidx;
2326 p->reloc_offset = offset;
2327 f->string_patches = p;
2328
2329 strsec = obj_find_section(f, ".kstrtab");
2330 if (strsec == NULL) {
2331 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2332 p->string_offset = 0;
2333 loc = strsec->contents;
2334 } else {
2335 p->string_offset = strsec->header.sh_size;
2336 loc = obj_extend_section(strsec, len);
2337 }
2338 memcpy(loc, string, len);
2339
2340 return 1;
2341}
2342
2343int
2344obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2345 struct obj_symbol *sym)
2346{
2347 struct obj_symbol_patch *p;
2348
2349 p = xmalloc(sizeof(*p));
2350 p->next = f->symbol_patches;
2351 p->reloc_secidx = secidx;
2352 p->reloc_offset = offset;
2353 p->sym = sym;
2354 f->symbol_patches = p;
2355
2356 return 1;
2357}
2358
2359int obj_check_undefineds(struct obj_file *f)
2360{
2361 unsigned long i;
2362 int ret = 1;
2363
2364 for (i = 0; i < HASH_BUCKETS; ++i) {
2365 struct obj_symbol *sym;
2366 for (sym = f->symtab[i]; sym; sym = sym->next)
2367 if (sym->secidx == SHN_UNDEF) {
2368 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2369 sym->secidx = SHN_ABS;
2370 sym->value = 0;
2371 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002372 error_msg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002373 ret = 0;
2374 }
2375 }
2376 }
2377
2378 return ret;
2379}
2380
2381void obj_allocate_commons(struct obj_file *f)
2382{
2383 struct common_entry {
2384 struct common_entry *next;
2385 struct obj_symbol *sym;
2386 } *common_head = NULL;
2387
2388 unsigned long i;
2389
2390 for (i = 0; i < HASH_BUCKETS; ++i) {
2391 struct obj_symbol *sym;
2392 for (sym = f->symtab[i]; sym; sym = sym->next)
2393 if (sym->secidx == SHN_COMMON) {
2394 /* Collect all COMMON symbols and sort them by size so as to
2395 minimize space wasted by alignment requirements. */
2396 {
2397 struct common_entry **p, *n;
2398 for (p = &common_head; *p; p = &(*p)->next)
2399 if (sym->size <= (*p)->sym->size)
2400 break;
2401
2402 n = alloca(sizeof(*n));
2403 n->next = *p;
2404 n->sym = sym;
2405 *p = n;
2406 }
2407 }
2408 }
2409
2410 for (i = 1; i < f->local_symtab_size; ++i) {
2411 struct obj_symbol *sym = f->local_symtab[i];
2412 if (sym && sym->secidx == SHN_COMMON) {
2413 struct common_entry **p, *n;
2414 for (p = &common_head; *p; p = &(*p)->next)
2415 if (sym == (*p)->sym)
2416 break;
2417 else if (sym->size < (*p)->sym->size) {
2418 n = alloca(sizeof(*n));
2419 n->next = *p;
2420 n->sym = sym;
2421 *p = n;
2422 break;
2423 }
2424 }
2425 }
2426
2427 if (common_head) {
2428 /* Find the bss section. */
2429 for (i = 0; i < f->header.e_shnum; ++i)
2430 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2431 break;
2432
2433 /* If for some reason there hadn't been one, create one. */
2434 if (i == f->header.e_shnum) {
2435 struct obj_section *sec;
2436
2437 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2438 f->sections[i] = sec = arch_new_section();
2439 f->header.e_shnum = i + 1;
2440
2441 memset(sec, 0, sizeof(*sec));
2442 sec->header.sh_type = SHT_PROGBITS;
2443 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2444 sec->name = ".bss";
2445 sec->idx = i;
2446 }
2447
2448 /* Allocate the COMMONS. */
2449 {
2450 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2451 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2452 struct common_entry *c;
2453
2454 for (c = common_head; c; c = c->next) {
2455 ElfW(Addr) align = c->sym->value;
2456
2457 if (align > max_align)
2458 max_align = align;
2459 if (bss_size & (align - 1))
2460 bss_size = (bss_size | (align - 1)) + 1;
2461
2462 c->sym->secidx = i;
2463 c->sym->value = bss_size;
2464
2465 bss_size += c->sym->size;
2466 }
2467
2468 f->sections[i]->header.sh_size = bss_size;
2469 f->sections[i]->header.sh_addralign = max_align;
2470 }
2471 }
2472
2473 /* For the sake of patch relocation and parameter initialization,
2474 allocate zeroed data for NOBITS sections now. Note that after
2475 this we cannot assume NOBITS are really empty. */
2476 for (i = 0; i < f->header.e_shnum; ++i) {
2477 struct obj_section *s = f->sections[i];
2478 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002479 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002480 s->contents = memset(xmalloc(s->header.sh_size),
2481 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002482 else
2483 s->contents = NULL;
2484
Eric Andersen9f16d612000-06-12 23:11:16 +00002485 s->header.sh_type = SHT_PROGBITS;
2486 }
2487 }
2488}
2489
2490unsigned long obj_load_size(struct obj_file *f)
2491{
2492 unsigned long dot = 0;
2493 struct obj_section *sec;
2494
2495 /* Finalize the positions of the sections relative to one another. */
2496
2497 for (sec = f->load_order; sec; sec = sec->load_next) {
2498 ElfW(Addr) align;
2499
2500 align = sec->header.sh_addralign;
2501 if (align && (dot & (align - 1)))
2502 dot = (dot | (align - 1)) + 1;
2503
2504 sec->header.sh_addr = dot;
2505 dot += sec->header.sh_size;
2506 }
2507
2508 return dot;
2509}
2510
2511int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2512{
2513 int i, n = f->header.e_shnum;
2514 int ret = 1;
2515
2516 /* Finalize the addresses of the sections. */
2517
2518 f->baseaddr = base;
2519 for (i = 0; i < n; ++i)
2520 f->sections[i]->header.sh_addr += base;
2521
2522 /* And iterate over all of the relocations. */
2523
2524 for (i = 0; i < n; ++i) {
2525 struct obj_section *relsec, *symsec, *targsec, *strsec;
2526 ElfW(RelM) * rel, *relend;
2527 ElfW(Sym) * symtab;
2528 const char *strtab;
2529
2530 relsec = f->sections[i];
2531 if (relsec->header.sh_type != SHT_RELM)
2532 continue;
2533
2534 symsec = f->sections[relsec->header.sh_link];
2535 targsec = f->sections[relsec->header.sh_info];
2536 strsec = f->sections[symsec->header.sh_link];
2537
2538 rel = (ElfW(RelM) *) relsec->contents;
2539 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2540 symtab = (ElfW(Sym) *) symsec->contents;
2541 strtab = (const char *) strsec->contents;
2542
2543 for (; rel < relend; ++rel) {
2544 ElfW(Addr) value = 0;
2545 struct obj_symbol *intsym = NULL;
2546 unsigned long symndx;
2547 ElfW(Sym) * extsym = 0;
2548 const char *errmsg;
2549
2550 /* Attempt to find a value to use for this relocation. */
2551
2552 symndx = ELFW(R_SYM) (rel->r_info);
2553 if (symndx) {
2554 /* Note we've already checked for undefined symbols. */
2555
2556 extsym = &symtab[symndx];
2557 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2558 /* Local symbols we look up in the local table to be sure
2559 we get the one that is really intended. */
2560 intsym = f->local_symtab[symndx];
2561 } else {
2562 /* Others we look up in the hash table. */
2563 const char *name;
2564 if (extsym->st_name)
2565 name = strtab + extsym->st_name;
2566 else
2567 name = f->sections[extsym->st_shndx]->name;
2568 intsym = obj_find_symbol(f, name);
2569 }
2570
2571 value = obj_symbol_final_value(f, intsym);
2572 intsym->referenced = 1;
2573 }
2574#if SHT_RELM == SHT_RELA
2575#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2576 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2577 if (!extsym || !extsym->st_name ||
2578 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2579#endif
2580 value += rel->r_addend;
2581#endif
2582
2583 /* Do it! */
2584 switch (arch_apply_relocation
2585 (f, targsec, symsec, intsym, rel, value)) {
2586 case obj_reloc_ok:
2587 break;
2588
2589 case obj_reloc_overflow:
2590 errmsg = "Relocation overflow";
2591 goto bad_reloc;
2592 case obj_reloc_dangerous:
2593 errmsg = "Dangerous relocation";
2594 goto bad_reloc;
2595 case obj_reloc_unhandled:
2596 errmsg = "Unhandled relocation";
2597 bad_reloc:
2598 if (extsym) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002599 error_msg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002600 (long) ELFW(R_TYPE) (rel->r_info),
2601 strtab + extsym->st_name);
2602 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002603 error_msg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002604 (long) ELFW(R_TYPE) (rel->r_info));
2605 }
2606 ret = 0;
2607 break;
2608 }
2609 }
2610 }
2611
2612 /* Finally, take care of the patches. */
2613
2614 if (f->string_patches) {
2615 struct obj_string_patch *p;
2616 struct obj_section *strsec;
2617 ElfW(Addr) strsec_base;
2618 strsec = obj_find_section(f, ".kstrtab");
2619 strsec_base = strsec->header.sh_addr;
2620
2621 for (p = f->string_patches; p; p = p->next) {
2622 struct obj_section *targsec = f->sections[p->reloc_secidx];
2623 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2624 = strsec_base + p->string_offset;
2625 }
2626 }
2627
2628 if (f->symbol_patches) {
2629 struct obj_symbol_patch *p;
2630
2631 for (p = f->symbol_patches; p; p = p->next) {
2632 struct obj_section *targsec = f->sections[p->reloc_secidx];
2633 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2634 = obj_symbol_final_value(f, p->sym);
2635 }
2636 }
2637
2638 return ret;
2639}
2640
2641int obj_create_image(struct obj_file *f, char *image)
2642{
2643 struct obj_section *sec;
2644 ElfW(Addr) base = f->baseaddr;
2645
2646 for (sec = f->load_order; sec; sec = sec->load_next) {
2647 char *secimg;
2648
2649 if (sec->header.sh_size == 0)
2650 continue;
2651
2652 secimg = image + (sec->header.sh_addr - base);
2653
2654 /* Note that we allocated data for NOBITS sections earlier. */
2655 memcpy(secimg, sec->contents, sec->header.sh_size);
2656 }
2657
2658 return 1;
2659}
2660
2661/*======================================================================*/
2662
2663struct obj_file *obj_load(FILE * fp)
2664{
2665 struct obj_file *f;
2666 ElfW(Shdr) * section_headers;
2667 int shnum, i;
2668 char *shstrtab;
2669
2670 /* Read the file header. */
2671
2672 f = arch_new_file();
2673 memset(f, 0, sizeof(*f));
2674 f->symbol_cmp = strcmp;
2675 f->symbol_hash = obj_elf_hash;
2676 f->load_order_search_start = &f->load_order;
2677
2678 fseek(fp, 0, SEEK_SET);
2679 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002680 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002681 return NULL;
2682 }
2683
2684 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2685 || f->header.e_ident[EI_MAG1] != ELFMAG1
2686 || f->header.e_ident[EI_MAG2] != ELFMAG2
2687 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002688 error_msg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002689 return NULL;
2690 }
2691 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2692 || f->header.e_ident[EI_DATA] != ELFDATAM
2693 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2694 || !MATCH_MACHINE(f->header.e_machine)) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002695 error_msg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002696 return NULL;
2697 }
2698 if (f->header.e_type != ET_REL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002699 error_msg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002700 return NULL;
2701 }
2702
2703 /* Read the section headers. */
2704
2705 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002706 error_msg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002707 (unsigned long) f->header.e_shentsize,
2708 (unsigned long) sizeof(ElfW(Shdr)));
2709 return NULL;
2710 }
2711
2712 shnum = f->header.e_shnum;
2713 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2714 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2715
2716 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2717 fseek(fp, f->header.e_shoff, SEEK_SET);
2718 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002719 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002720 return NULL;
2721 }
2722
2723 /* Read the section data. */
2724
2725 for (i = 0; i < shnum; ++i) {
2726 struct obj_section *sec;
2727
2728 f->sections[i] = sec = arch_new_section();
2729 memset(sec, 0, sizeof(*sec));
2730
2731 sec->header = section_headers[i];
2732 sec->idx = i;
2733
2734 switch (sec->header.sh_type) {
2735 case SHT_NULL:
2736 case SHT_NOTE:
2737 case SHT_NOBITS:
2738 /* ignore */
2739 break;
2740
2741 case SHT_PROGBITS:
2742 case SHT_SYMTAB:
2743 case SHT_STRTAB:
2744 case SHT_RELM:
2745 if (sec->header.sh_size > 0) {
2746 sec->contents = xmalloc(sec->header.sh_size);
2747 fseek(fp, sec->header.sh_offset, SEEK_SET);
2748 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002749 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002750 return NULL;
2751 }
2752 } else {
2753 sec->contents = NULL;
2754 }
2755 break;
2756
2757#if SHT_RELM == SHT_REL
2758 case SHT_RELA:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002759 error_msg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002760 return NULL;
2761#else
2762 case SHT_REL:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002763 error_msg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002764 return NULL;
2765#endif
2766
2767 default:
2768 if (sec->header.sh_type >= SHT_LOPROC) {
2769 /* Assume processor specific section types are debug
2770 info and can safely be ignored. If this is ever not
2771 the case (Hello MIPS?), don't put ifdefs here but
2772 create an arch_load_proc_section(). */
2773 break;
2774 }
2775
Mark Whitleyf57c9442000-12-07 19:56:48 +00002776 error_msg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002777 (long) sec->header.sh_type);
2778 return NULL;
2779 }
2780 }
2781
2782 /* Do what sort of interpretation as needed by each section. */
2783
2784 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2785
2786 for (i = 0; i < shnum; ++i) {
2787 struct obj_section *sec = f->sections[i];
2788 sec->name = shstrtab + sec->header.sh_name;
2789 }
2790
2791 for (i = 0; i < shnum; ++i) {
2792 struct obj_section *sec = f->sections[i];
2793
2794 if (sec->header.sh_flags & SHF_ALLOC)
2795 obj_insert_section_load_order(f, sec);
2796
2797 switch (sec->header.sh_type) {
2798 case SHT_SYMTAB:
2799 {
2800 unsigned long nsym, j;
2801 char *strtab;
2802 ElfW(Sym) * sym;
2803
2804 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002805 error_msg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002806 (unsigned long) sec->header.sh_entsize,
2807 (unsigned long) sizeof(ElfW(Sym)));
2808 return NULL;
2809 }
2810
2811 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2812 strtab = f->sections[sec->header.sh_link]->contents;
2813 sym = (ElfW(Sym) *) sec->contents;
2814
2815 /* Allocate space for a table of local symbols. */
2816 j = f->local_symtab_size = sec->header.sh_info;
2817 f->local_symtab = xmalloc(j *=
2818 sizeof(struct obj_symbol *));
2819 memset(f->local_symtab, 0, j);
2820
2821 /* Insert all symbols into the hash table. */
2822 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2823 const char *name;
2824 if (sym->st_name)
2825 name = strtab + sym->st_name;
2826 else
2827 name = f->sections[sym->st_shndx]->name;
2828
2829 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2830 sym->st_value, sym->st_size);
2831 }
2832 }
2833 break;
2834
2835 case SHT_RELM:
2836 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002837 error_msg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002838 (unsigned long) sec->header.sh_entsize,
2839 (unsigned long) sizeof(ElfW(RelM)));
2840 return NULL;
2841 }
2842 break;
2843 }
2844 }
2845
2846 return f;
2847}
2848
2849static void hide_special_symbols(struct obj_file *f)
2850{
2851 static const char *const specials[] = {
2852 "cleanup_module",
2853 "init_module",
2854 "kernel_version",
2855 NULL
2856 };
2857
2858 struct obj_symbol *sym;
2859 const char *const *p;
2860
2861 for (p = specials; *p; ++p)
2862 if ((sym = obj_find_symbol(f, *p)) != NULL)
2863 sym->info =
2864 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2865}
2866
2867
2868
2869extern int insmod_main( int argc, char **argv)
2870{
Eric Andersena18aaf12001-01-24 19:07:09 +00002871 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00002872 int k_crcs;
2873 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002874 int len;
2875 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002876 unsigned long m_size;
2877 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002878 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002879 struct obj_file *f;
2880 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00002881 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00002882 int m_has_modinfo;
2883#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2884 int k_version;
2885 char k_strversion[STRVERSIONLEN];
2886 char m_strversion[STRVERSIONLEN];
2887 int m_version;
2888 int m_crcs;
2889#endif
2890
Erik Andersene49d5ec2000-02-08 19:58:47 +00002891 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00002892 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00002893 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002894 case 'f': /* force loading */
2895 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002896 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002897 case 'k': /* module loaded by kerneld, auto-cleanable */
2898 flag_autoclean = 1;
2899 break;
2900 case 'v': /* verbose output */
2901 flag_verbose = 1;
2902 break;
2903 case 'x': /* do not export externs */
2904 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002905 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00002906 case 'o': /* name the output module */
2907 strncpy(m_name, optarg, BUFSIZ);
2908 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00002909 case 'L': /* Stub warning */
2910 /* This is needed for compatibility with modprobe.
2911 * In theory, this does locking, but we don't do
2912 * that. So be careful and plan your life around not
2913 * loading the same module 50 times concurrently. */
2914 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002915 default:
2916 usage(insmod_usage);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002917 }
Erik Andersend387d011999-12-21 02:55:11 +00002918 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002919
2920 if (argv[optind] == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002921 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002922 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002923
Erik Andersene49d5ec2000-02-08 19:58:47 +00002924 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00002925 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002926 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002927 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00002928 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00002929 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002930 len = strlen(tmp);
2931
2932 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2933 len -= 2;
Eric Andersen155c89b2001-01-25 04:11:06 +00002934 strncpy(m_fullName, tmp, len);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002935 strcat(m_fullName, ".o");
Eric Andersen155c89b2001-01-25 04:11:06 +00002936 if (m_name == NULL) {
2937 memcpy(m_name, tmp, len);
2938 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002939
2940 /* Get a filedesc for the module */
Eric Andersena18aaf12001-01-24 19:07:09 +00002941 if ((fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002942 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00002943 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002944 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002945 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002946 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002947 || ((fp = fopen(m_filename, "r")) == NULL))
2948 {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002949 error_msg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00002950 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002951 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002952 } else
Mark Whitleyf57c9442000-12-07 19:56:48 +00002953 error_msg_and_die("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002954 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00002955 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00002956
2957
Matt Kraaia9819b22000-12-22 01:48:07 +00002958 if ((f = obj_load(fp)) == NULL)
2959 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00002960
Eric Andersen9f16d612000-06-12 23:11:16 +00002961 if (get_modinfo_value(f, "kernel_version") == NULL)
2962 m_has_modinfo = 0;
2963 else
2964 m_has_modinfo = 1;
2965
2966#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2967 /* Version correspondence? */
2968
2969 k_version = get_kernel_version(k_strversion);
2970 if (m_has_modinfo) {
2971 m_version = new_get_module_version(f, m_strversion);
2972 } else {
2973 m_version = old_get_module_version(f, m_strversion);
2974 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002975 error_msg("couldn't find the kernel version the module was "
Matt Kraaid537a952000-07-14 01:51:25 +00002976 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002977 goto out;
2978 }
2979 }
2980
2981 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2982 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002983 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002984 "\t%s was compiled for kernel version %s\n"
2985 "\twhile this kernel is version %s\n",
2986 m_filename, m_strversion, k_strversion);
2987 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002988 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002989 "\t%s was compiled for kernel version %s\n"
2990 "\twhile this kernel is version %s.\n",
2991 m_filename, m_strversion, k_strversion);
2992 goto out;
2993 }
2994 }
2995 k_crcs = 0;
2996#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2997
2998 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2999
3000 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003001#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003002 if (!new_get_kernel_symbols())
3003 goto out;
3004 k_crcs = new_is_kernel_checksummed();
3005#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003006 error_msg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003007 goto out;
3008#endif
3009 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003010#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003011 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003012 goto out;
3013 k_crcs = old_is_kernel_checksummed();
3014#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003015 error_msg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003016 goto out;
3017#endif
3018 }
3019
3020#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3021 if (m_has_modinfo)
3022 m_crcs = new_is_module_checksummed(f);
3023 else
3024 m_crcs = old_is_module_checksummed(f);
3025
3026 if (m_crcs != k_crcs)
3027 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3028#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3029
Erik Andersene49d5ec2000-02-08 19:58:47 +00003030 /* Let the module know about the kernel symbols. */
3031 add_kernel_symbols(f);
3032
Eric Andersen9f16d612000-06-12 23:11:16 +00003033 /* Allocate common symbols, symbol tables, and string tables. */
3034
3035 if (k_new_syscalls
3036 ? !new_create_this_module(f, m_name)
3037 : !old_create_mod_use_count(f))
3038 {
3039 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003040 }
3041
Eric Andersen9f16d612000-06-12 23:11:16 +00003042 if (!obj_check_undefineds(f)) {
3043 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003044 }
3045 obj_allocate_commons(f);
3046
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003047 /* done with the module name, on to the optional var=value arguments */
3048 ++optind;
3049
Eric Andersen9f16d612000-06-12 23:11:16 +00003050 if (optind < argc) {
3051 if (m_has_modinfo
3052 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3053 : !old_process_module_arguments(f, argc - optind, argv + optind))
3054 {
3055 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003056 }
3057 }
3058
Eric Andersen9f16d612000-06-12 23:11:16 +00003059 arch_create_got(f);
3060 hide_special_symbols(f);
3061
3062 if (k_new_syscalls)
3063 new_create_module_ksymtab(f);
3064
Erik Andersene49d5ec2000-02-08 19:58:47 +00003065 /* Find current size of the module */
3066 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003067
3068
Erik Andersene49d5ec2000-02-08 19:58:47 +00003069 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003070 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003071 case EEXIST:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003072 error_msg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003073 goto out;
3074 case ENOMEM:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003075 error_msg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00003076 m_size);
3077 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003078 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003079 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003080 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003081 }
Erik Andersend387d011999-12-21 02:55:11 +00003082
Eric Andersen9f16d612000-06-12 23:11:16 +00003083 if (!obj_relocate(f, m_addr)) {
3084 delete_module(m_name);
3085 goto out;
3086 }
Erik Andersend387d011999-12-21 02:55:11 +00003087
Eric Andersen9f16d612000-06-12 23:11:16 +00003088 if (k_new_syscalls
3089 ? !new_init_module(m_name, f, m_size)
3090 : !old_init_module(m_name, f, m_size))
3091 {
3092 delete_module(m_name);
3093 goto out;
3094 }
3095
Matt Kraai3e856ce2000-12-01 02:55:13 +00003096 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003097
3098out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003099 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003100 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003101}