blob: a134fea873d6f6216718e24be7cd4114921c50c5 [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 Andersena18aaf12001-01-24 19:07:09 +000081#ident "$Id: insmod.c,v 1.37 2001/01/24 19:07:09 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 Andersena18aaf12001-01-24 19:07:09 +0000287#ident "$Id: insmod.c,v 1.37 2001/01/24 19:07:09 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#if !defined(BB_FEATURE_INSMOD_NEW_KERNEL) && !defined(BB_FEATURE_INSMOD_OLD_KERNEL)
523#error "Must have ether BB_FEATURE_INSMOD_NEW_KERNEL or BB_FEATURE_INSMOD_OLD_KERNEL defined"
524#endif
525
526/*======================================================================*/
527
528int flag_force_load = 0;
529int flag_autoclean = 0;
530int flag_verbose = 0;
531int flag_export = 1;
532
533
534/*======================================================================*/
535
Eric Andersenfe4208f2000-09-24 03:44:29 +0000536/* previously, these were named i386_* but since we could be
537 compiling for the sh, I've renamed them to the more general
538 arch_* These structures are the same between the x86 and SH,
539 and we can't support anything else right now anyway. In the
540 future maybe they should be #if defined'd */
541
Eric Andersen21adca72000-12-06 18:18:26 +0000542/* Done ;-) */
543
544#if defined(__arm__)
545struct arm_plt_entry
546{
547 int offset;
548 int allocated:1;
549 int inited:1; /* has been set up */
550};
551#endif
552
Eric Andersenfe4208f2000-09-24 03:44:29 +0000553struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000554 int offset;
555 unsigned offset_done:1;
556 unsigned reloc_done:1;
557};
558
Eric Andersenfe4208f2000-09-24 03:44:29 +0000559struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000560 struct obj_file root;
Eric Andersen21adca72000-12-06 18:18:26 +0000561#if defined(__arm__)
562 struct obj_section *plt;
563#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000564 struct obj_section *got;
565};
566
Eric Andersenfe4208f2000-09-24 03:44:29 +0000567struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000568 struct obj_symbol root;
Eric Andersen21adca72000-12-06 18:18:26 +0000569#if defined(__arm__)
570 struct arm_plt_entry pltent;
571#endif
Eric Andersenfe4208f2000-09-24 03:44:29 +0000572 struct arch_got_entry gotent;
Eric Andersen9f16d612000-06-12 23:11:16 +0000573};
574
575
Eric Andersen9f16d612000-06-12 23:11:16 +0000576struct external_module {
577 const char *name;
578 ElfW(Addr) addr;
579 int used;
580 size_t nsyms;
581 struct new_module_symbol *syms;
582};
583
584struct new_module_symbol *ksyms;
585size_t nksyms;
586
587struct external_module *ext_modules;
588int n_ext_modules;
589int n_ext_modules_used;
590
Erik Andersend387d011999-12-21 02:55:11 +0000591
592
Erik Andersen02104321999-12-17 18:57:34 +0000593/* Some firendly syscalls to cheer everyone's day... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000594#define __NR_new_sys_init_module __NR_init_module
595_syscall2(int, new_sys_init_module, const char *, name,
596 const struct new_module *, info)
597#define __NR_old_sys_init_module __NR_init_module
598_syscall5(int, old_sys_init_module, const char *, name, char *, code,
599 unsigned, codesize, struct old_mod_routines *, routines,
600 struct old_symbol_table *, symtab)
Erik Andersen02104321999-12-17 18:57:34 +0000601#ifndef BB_RMMOD
602_syscall1(int, delete_module, const char *, name)
603#else
604extern int delete_module(const char *);
605#endif
606
Eric Andersenfe4208f2000-09-24 03:44:29 +0000607/* This is kind of troublesome. See, we don't actually support
608 the m68k or the arm the same way we support i386 and (now)
609 sh. In doing my SH patch, I just assumed that whatever works
610 for i386 also works for m68k and arm since currently insmod.c
611 does nothing special for them. If this isn't true, the below
612 line is rather misleading IMHO, and someone should either
613 change it or add more proper architecture-dependent support
614 for these boys.
615
616 -- Bryan Rittmeyer <bryan@ixiacom.com> */
617
Eric Andersen21adca72000-12-06 18:18:26 +0000618#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
619_syscall1(int, get_kernel_syms, struct old_kernel_sym *, ks)
620#endif
621
Erik Andersen02104321999-12-17 18:57:34 +0000622#if defined(__i386__) || defined(__m68k__) || defined(__arm__)
623/* Jump through hoops to fixup error return codes */
624#define __NR__create_module __NR_create_module
Erik Andersene49d5ec2000-02-08 19:58:47 +0000625static inline _syscall2(long, _create_module, const char *, name, size_t,
626 size)
Erik Andersen02104321999-12-17 18:57:34 +0000627unsigned long create_module(const char *name, size_t size)
628{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000629 long ret = _create_module(name, size);
630
631 if (ret == -1 && errno > 125) {
632 ret = -errno;
633 errno = 0;
634 }
635 return ret;
Erik Andersen02104321999-12-17 18:57:34 +0000636}
637#else
638_syscall2(unsigned long, create_module, const char *, name, size_t, size)
639#endif
Erik Andersen4f3f7572000-04-28 00:18:56 +0000640static char m_filename[BUFSIZ + 1] = "\0";
641static char m_fullName[BUFSIZ + 1] = "\0";
Erik Andersen02104321999-12-17 18:57:34 +0000642
Eric Andersen9f16d612000-06-12 23:11:16 +0000643/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000644
Eric Andersen9f16d612000-06-12 23:11:16 +0000645
646static int findNamedModule(const char *fileName, struct stat *statbuf,
647 void *userDate)
648{
649 char *fullName = (char *) userDate;
650
651
652 if (fullName[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000653 return (FALSE);
654 else {
Eric Andersen21adca72000-12-06 18:18:26 +0000655 char *tmp = strrchr((char *) fileName, '/');
Erik Andersene49d5ec2000-02-08 19:58:47 +0000656
657 if (tmp == NULL)
658 tmp = (char *) fileName;
659 else
660 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +0000661 if (check_wildcard_match(tmp, fullName) == TRUE) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000662 /* Stop searching if we find a match */
Eric Andersen089d12d2000-08-22 05:18:30 +0000663 memcpy(m_filename, fileName, strlen(fileName)+1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000664 return (FALSE);
665 }
Erik Andersend387d011999-12-21 02:55:11 +0000666 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000667 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000668}
669
Erik Andersen02104321999-12-17 18:57:34 +0000670
Eric Andersen9f16d612000-06-12 23:11:16 +0000671/*======================================================================*/
672
673struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000674{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000675 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000676 f = xmalloc(sizeof(*f));
677 f->got = NULL;
678 return &f->root;
679}
680
681struct obj_section *arch_new_section(void)
682{
683 return xmalloc(sizeof(struct obj_section));
684}
685
686struct obj_symbol *arch_new_symbol(void)
687{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000688 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000689 sym = xmalloc(sizeof(*sym));
690 memset(&sym->gotent, 0, sizeof(sym->gotent));
691 return &sym->root;
692}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000693
Eric Andersen9f16d612000-06-12 23:11:16 +0000694enum obj_reloc
695arch_apply_relocation(struct obj_file *f,
696 struct obj_section *targsec,
697 struct obj_section *symsec,
698 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000699 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000700{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000701 struct arch_file *ifile = (struct arch_file *) f;
702 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000703
Eric Andersen21adca72000-12-06 18:18:26 +0000704 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
705 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
706 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
707#if defined(__arm__)
708 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
709
710 struct arm_plt_entry *pe;
711 unsigned long *ip;
712#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000713
714 enum obj_reloc ret = obj_reloc_ok;
715
716 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000717
718/* even though these constants seem to be the same for
719 the i386 and the sh, we "#if define" them for clarity
720 and in case that ever changes */
721#if defined(__sh__)
722 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000723#elif defined(__arm__)
724 case R_ARM_NONE:
725#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000726 case R_386_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000727#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000728 break;
729
Eric Andersenfe4208f2000-09-24 03:44:29 +0000730#if defined(__sh__)
731 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000732#elif defined(__arm__)
733 case R_ARM_ABS32:
734#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000735 case R_386_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000736#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000737 *loc += v;
738 break;
739
Eric Andersen21adca72000-12-06 18:18:26 +0000740#if defined(__arm__)
741#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000742 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000743 *loc += v - dot;
744 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000745#elif defined(__i386__)
746 case R_386_PLT32:
747 case R_386_PC32:
748 *loc += v - dot;
749 break;
750#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000751
Eric Andersenfe4208f2000-09-24 03:44:29 +0000752#if defined(__sh__)
753 case R_SH_PLT32:
754 *loc = v - dot;
755 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000756#elif defined(__arm__)
757 case R_ARM_PC24:
758 case R_ARM_PLT32:
759 /* find the plt entry and initialize it if necessary */
760 assert(isym != NULL);
761 pe = (struct arm_plt_entry*) &isym->pltent;
762 if (! pe->inited) {
763 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
764 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
765 ip[1] = v; /* sym@ */
766 pe->inited = 1;
767 }
768
769 /* relative distance to target */
770 v -= dot;
771 /* if the target is too far away.... */
772 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
773 /* go via the plt */
774 v = plt + pe->offset - dot;
775 }
776 if (v & 3)
777 ret = obj_reloc_dangerous;
778
779 /* Convert to words. */
780 v >>= 2;
781
782 /* merge the offset into the instruction. */
783 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
784 break;
785#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000786#endif
787
788
Eric Andersen21adca72000-12-06 18:18:26 +0000789#if defined(__arm__)
790#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000791 case R_SH_GLOB_DAT:
792 case R_SH_JMP_SLOT:
793 *loc = v;
794 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000795#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000796 case R_386_GLOB_DAT:
797 case R_386_JMP_SLOT:
798 *loc = v;
799 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000800#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000801
Eric Andersen21adca72000-12-06 18:18:26 +0000802#if defined(__arm__)
803#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000804 case R_SH_RELATIVE:
805 *loc += f->baseaddr + rel->r_addend;
806 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000807#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000808 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000809 *loc += f->baseaddr;
810 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000811#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000812
Eric Andersenfe4208f2000-09-24 03:44:29 +0000813#if defined(__sh__)
814 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +0000815#elif defined(__arm__)
816 case R_ARM_GOTPC:
817#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000818 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000819#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000820 assert(got != 0);
821#if defined(__sh__)
822 *loc += got - dot + rel->r_addend;;
823#elif defined(__i386__) || defined(__arm__)
824 *loc += got - dot;
825#endif
826 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000827
Eric Andersenfe4208f2000-09-24 03:44:29 +0000828#if defined(__sh__)
829 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000830#elif defined(__arm__)
831 case R_ARM_GOT32:
832#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 case R_386_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000834#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000835 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +0000836 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +0000837 if (!isym->gotent.reloc_done) {
838 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000839 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +0000840 }
Eric Andersen21adca72000-12-06 18:18:26 +0000841 /* make the reloc with_respect_to_.got */
842#if defined(__sh__)
843 *loc += isym->gotent.offset + rel->r_addend;
844#elif defined(__i386__) || defined(__arm__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000846#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000847 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000848
Eric Andersen21adca72000-12-06 18:18:26 +0000849 /* address relative to the got */
Eric Andersenfe4208f2000-09-24 03:44:29 +0000850#if defined(__sh__)
851 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +0000852#elif defined(__arm__)
853 case R_ARM_GOTOFF:
854#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000855 case R_386_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000856#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000857 assert(got != 0);
858 *loc += v - got;
859 break;
860
861 default:
Eric Andersen21125542000-12-13 16:41:29 +0000862 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +0000863 ret = obj_reloc_unhandled;
864 break;
865 }
866
867 return ret;
868}
869
870int arch_create_got(struct obj_file *f)
871{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000872 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen21adca72000-12-06 18:18:26 +0000873 int i, got_offset = 0, gotneeded = 0;
874#if defined(__arm__)
875 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +0000876#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000877 struct obj_section *relsec, *symsec, *strsec;
878 ElfW(RelM) *rel, *relend;
879 ElfW(Sym) *symtab, *extsym;
880 const char *strtab, *name;
881 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000882
Eric Andersen21adca72000-12-06 18:18:26 +0000883 for (i = 0; i < f->header.e_shnum; ++i) {
884 relsec = f->sections[i];
885 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +0000886 continue;
887
Eric Andersen21adca72000-12-06 18:18:26 +0000888 symsec = f->sections[relsec->header.sh_link];
889 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +0000890
Eric Andersen21adca72000-12-06 18:18:26 +0000891 rel = (ElfW(RelM) *) relsec->contents;
892 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
893 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +0000894 strtab = (const char *) strsec->contents;
895
896 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +0000897 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +0000898
899 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +0000900#if defined(__arm__)
901 case R_ARM_GOT32:
902#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000903 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +0000904#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000905 case R_386_GOT32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000906#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000907 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000908
909#if defined(__arm__)
910 case R_ARM_PC24:
911 case R_ARM_PLT32:
912 pltneeded = 1;
913 break;
914
915 case R_ARM_GOTPC:
916 case R_ARM_GOTOFF:
917 gotneeded = 1;
918 if (got_offset == 0)
919 got_offset = 4;
920#elif defined(__sh__)
921 case R_SH_GOTPC:
922 case R_SH_GOTOFF:
923 gotneeded = 1;
924#elif defined(__i386__)
925 case R_386_GOTPC:
926 case R_386_GOTOFF:
927 gotneeded = 1;
928#endif
929
930 default:
931 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +0000932 }
933
Eric Andersen21adca72000-12-06 18:18:26 +0000934 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +0000935 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +0000936 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +0000937 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +0000938 }
939 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen9f16d612000-06-12 23:11:16 +0000940
941 if (!intsym->gotent.offset_done) {
942 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000943 intsym->gotent.offset = got_offset;
944 got_offset += 4;
945 }
946#if defined(__arm__)
947 if (pltneeded && intsym->pltent.allocated == 0) {
948 intsym->pltent.allocated = 1;
949 intsym->pltent.offset = plt_offset;
950 plt_offset += 8;
951 intsym->pltent.inited = 0;
952 pltneeded = 0;
953 }
954#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000955 }
956 }
Eric Andersen21adca72000-12-06 18:18:26 +0000957
958#if defined(__arm__)
959 if (got_offset) {
960 struct obj_section* relsec = obj_find_section(f, ".got");
961
962 if (relsec) {
963 obj_extend_section(relsec, got_offset);
964 } else {
965 relsec = obj_create_alloced_section(f, ".got", 8, got_offset);
966 assert(relsec);
967 }
968
969 ifile->got = relsec;
Eric Andersen9f16d612000-06-12 23:11:16 +0000970 }
971
Eric Andersen21adca72000-12-06 18:18:26 +0000972 if (plt_offset)
973 ifile->plt = obj_create_alloced_section(f, ".plt", 8, plt_offset);
974#else
975 if (got_offset > 0 || gotneeded)
976 ifile->got = obj_create_alloced_section(f, ".got", 4, got_offset);
977#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000978
979 return 1;
980}
981
982int arch_init_module(struct obj_file *f, struct new_module *mod)
983{
984 return 1;
985}
986
987
988/*======================================================================*/
989
990/* Standard ELF hash function. */
991inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
992{
993 unsigned long h = 0;
994 unsigned long g;
995 unsigned char ch;
996
997 while (n > 0) {
998 ch = *name++;
999 h = (h << 4) + ch;
1000 if ((g = (h & 0xf0000000)) != 0) {
1001 h ^= g >> 24;
1002 h &= ~g;
1003 }
1004 n--;
1005 }
1006 return h;
1007}
1008
1009unsigned long obj_elf_hash(const char *name)
1010{
1011 return obj_elf_hash_n(name, strlen(name));
1012}
1013
1014#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1015/* Get the kernel version in the canonical integer form. */
1016
1017static int get_kernel_version(char str[STRVERSIONLEN])
1018{
1019 struct utsname uts_info;
1020 char *p, *q;
1021 int a, b, c;
1022
1023 if (uname(&uts_info) < 0)
1024 return -1;
1025 strncpy(str, uts_info.release, STRVERSIONLEN);
1026 p = uts_info.release;
1027
1028 a = strtoul(p, &p, 10);
1029 if (*p != '.')
1030 return -1;
1031 b = strtoul(p + 1, &p, 10);
1032 if (*p != '.')
1033 return -1;
1034 c = strtoul(p + 1, &q, 10);
1035 if (p + 1 == q)
1036 return -1;
1037
1038 return a << 16 | b << 8 | c;
1039}
1040
1041/* String comparison for non-co-versioned kernel and module. */
1042
1043static int ncv_strcmp(const char *a, const char *b)
1044{
1045 size_t alen = strlen(a), blen = strlen(b);
1046
1047 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1048 return strncmp(a, b, alen);
1049 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1050 return strncmp(a, b, blen);
1051 else
1052 return strcmp(a, b);
1053}
1054
1055/* String hashing for non-co-versioned kernel and module. Here
1056 we are simply forced to drop the crc from the hash. */
1057
1058static unsigned long ncv_symbol_hash(const char *str)
1059{
1060 size_t len = strlen(str);
1061 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1062 len -= 10;
1063 return obj_elf_hash_n(str, len);
1064}
1065
1066void
1067obj_set_symbol_compare(struct obj_file *f,
1068 int (*cmp) (const char *, const char *),
1069 unsigned long (*hash) (const char *))
1070{
1071 if (cmp)
1072 f->symbol_cmp = cmp;
1073 if (hash) {
1074 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1075 int i;
1076
1077 f->symbol_hash = hash;
1078
1079 memcpy(tmptab, f->symtab, sizeof(tmptab));
1080 memset(f->symtab, 0, sizeof(f->symtab));
1081
1082 for (i = 0; i < HASH_BUCKETS; ++i)
1083 for (sym = tmptab[i]; sym; sym = next) {
1084 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1085 next = sym->next;
1086 sym->next = f->symtab[h];
1087 f->symtab[h] = sym;
1088 }
1089 }
1090}
1091
1092#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1093
1094
1095struct obj_symbol *obj_add_symbol(struct obj_file *f, const char *name,
1096 unsigned long symidx, int info,
1097 int secidx, ElfW(Addr) value,
1098 unsigned long size)
1099{
1100 struct obj_symbol *sym;
1101 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1102 int n_type = ELFW(ST_TYPE) (info);
1103 int n_binding = ELFW(ST_BIND) (info);
1104
1105 for (sym = f->symtab[hash]; sym; sym = sym->next)
1106 if (f->symbol_cmp(sym->name, name) == 0) {
1107 int o_secidx = sym->secidx;
1108 int o_info = sym->info;
1109 int o_type = ELFW(ST_TYPE) (o_info);
1110 int o_binding = ELFW(ST_BIND) (o_info);
1111
1112 /* A redefinition! Is it legal? */
1113
1114 if (secidx == SHN_UNDEF)
1115 return sym;
1116 else if (o_secidx == SHN_UNDEF)
1117 goto found;
1118 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1119 /* Cope with local and global symbols of the same name
1120 in the same object file, as might have been created
1121 by ld -r. The only reason locals are now seen at this
1122 level at all is so that we can do semi-sensible things
1123 with parameters. */
1124
1125 struct obj_symbol *nsym, **p;
1126
1127 nsym = arch_new_symbol();
1128 nsym->next = sym->next;
1129 nsym->ksymidx = -1;
1130
1131 /* Excise the old (local) symbol from the hash chain. */
1132 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1133 continue;
1134 *p = sym = nsym;
1135 goto found;
1136 } else if (n_binding == STB_LOCAL) {
1137 /* Another symbol of the same name has already been defined.
1138 Just add this to the local table. */
1139 sym = arch_new_symbol();
1140 sym->next = NULL;
1141 sym->ksymidx = -1;
1142 f->local_symtab[symidx] = sym;
1143 goto found;
1144 } else if (n_binding == STB_WEAK)
1145 return sym;
1146 else if (o_binding == STB_WEAK)
1147 goto found;
1148 /* Don't unify COMMON symbols with object types the programmer
1149 doesn't expect. */
1150 else if (secidx == SHN_COMMON
1151 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1152 return sym;
1153 else if (o_secidx == SHN_COMMON
1154 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1155 goto found;
1156 else {
1157 /* Don't report an error if the symbol is coming from
1158 the kernel or some external module. */
1159 if (secidx <= SHN_HIRESERVE)
Mark Whitleyf57c9442000-12-07 19:56:48 +00001160 error_msg("%s multiply defined\n", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001161 return sym;
1162 }
1163 }
1164
1165 /* Completely new symbol. */
1166 sym = arch_new_symbol();
1167 sym->next = f->symtab[hash];
1168 f->symtab[hash] = sym;
1169 sym->ksymidx = -1;
1170
1171 if (ELFW(ST_BIND) (info) == STB_LOCAL)
1172 f->local_symtab[symidx] = sym;
1173
1174 found:
1175 sym->name = name;
1176 sym->value = value;
1177 sym->size = size;
1178 sym->secidx = secidx;
1179 sym->info = info;
1180
1181 return sym;
1182}
1183
1184struct obj_symbol *obj_find_symbol(struct obj_file *f, const char *name)
1185{
1186 struct obj_symbol *sym;
1187 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1188
1189 for (sym = f->symtab[hash]; sym; sym = sym->next)
1190 if (f->symbol_cmp(sym->name, name) == 0)
1191 return sym;
1192
1193 return NULL;
1194}
1195
1196ElfW(Addr)
1197 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1198{
1199 if (sym) {
1200 if (sym->secidx >= SHN_LORESERVE)
1201 return sym->value;
1202
1203 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1204 } else {
1205 /* As a special case, a NULL sym has value zero. */
1206 return 0;
1207 }
1208}
1209
1210struct obj_section *obj_find_section(struct obj_file *f, const char *name)
1211{
1212 int i, n = f->header.e_shnum;
1213
1214 for (i = 0; i < n; ++i)
1215 if (strcmp(f->sections[i]->name, name) == 0)
1216 return f->sections[i];
1217
1218 return NULL;
1219}
1220
1221static int obj_load_order_prio(struct obj_section *a)
1222{
1223 unsigned long af, ac;
1224
1225 af = a->header.sh_flags;
1226
1227 ac = 0;
1228 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1229 strcmp(a->name + 5, ".init"))
1230 ac |= 32;
1231 if (af & SHF_ALLOC)
1232 ac |= 16;
1233 if (!(af & SHF_WRITE))
1234 ac |= 8;
1235 if (af & SHF_EXECINSTR)
1236 ac |= 4;
1237 if (a->header.sh_type != SHT_NOBITS)
1238 ac |= 2;
1239
1240 return ac;
1241}
1242
1243void
1244obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1245{
1246 struct obj_section **p;
1247 int prio = obj_load_order_prio(sec);
1248 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1249 if (obj_load_order_prio(*p) < prio)
1250 break;
1251 sec->load_next = *p;
1252 *p = sec;
1253}
1254
1255struct obj_section *obj_create_alloced_section(struct obj_file *f,
1256 const char *name,
1257 unsigned long align,
1258 unsigned long size)
1259{
1260 int newidx = f->header.e_shnum++;
1261 struct obj_section *sec;
1262
1263 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1264 f->sections[newidx] = sec = arch_new_section();
1265
1266 memset(sec, 0, sizeof(*sec));
1267 sec->header.sh_type = SHT_PROGBITS;
1268 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1269 sec->header.sh_size = size;
1270 sec->header.sh_addralign = align;
1271 sec->name = name;
1272 sec->idx = newidx;
1273 if (size)
1274 sec->contents = xmalloc(size);
1275
1276 obj_insert_section_load_order(f, sec);
1277
1278 return sec;
1279}
1280
1281struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
1282 const char *name,
1283 unsigned long align,
1284 unsigned long size)
1285{
1286 int newidx = f->header.e_shnum++;
1287 struct obj_section *sec;
1288
1289 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1290 f->sections[newidx] = sec = arch_new_section();
1291
1292 memset(sec, 0, sizeof(*sec));
1293 sec->header.sh_type = SHT_PROGBITS;
1294 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1295 sec->header.sh_size = size;
1296 sec->header.sh_addralign = align;
1297 sec->name = name;
1298 sec->idx = newidx;
1299 if (size)
1300 sec->contents = xmalloc(size);
1301
1302 sec->load_next = f->load_order;
1303 f->load_order = sec;
1304 if (f->load_order_search_start == &f->load_order)
1305 f->load_order_search_start = &sec->load_next;
1306
1307 return sec;
1308}
1309
1310void *obj_extend_section(struct obj_section *sec, unsigned long more)
1311{
1312 unsigned long oldsize = sec->header.sh_size;
1313 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1314 return sec->contents + oldsize;
1315}
1316
1317
1318
1319/* Conditionally add the symbols from the given symbol set to the
1320 new module. */
1321
1322static int
1323add_symbols_from(
1324 struct obj_file *f,
1325 int idx, struct new_module_symbol *syms, size_t nsyms)
1326{
1327 struct new_module_symbol *s;
1328 size_t i;
1329 int used = 0;
1330
1331 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1332
1333 /* Only add symbols that are already marked external. If we
1334 override locals we may cause problems for argument initialization.
1335 We will also create a false dependency on the module. */
1336 struct obj_symbol *sym;
1337
1338 sym = obj_find_symbol(f, (char *) s->name);
1339 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1340 sym = obj_add_symbol(f, (char *) s->name, -1,
1341 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1342 idx, s->value, 0);
1343 /* Did our symbol just get installed? If so, mark the
1344 module as "used". */
1345 if (sym->secidx == idx)
1346 used = 1;
1347 }
1348 }
1349
1350 return used;
1351}
1352
1353static void add_kernel_symbols(struct obj_file *f)
1354{
1355 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001356 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001357
1358 /* Add module symbols first. */
1359
1360 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1361 if (m->nsyms
1362 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1363 m->nsyms)) m->used = 1, ++nused;
1364
1365 n_ext_modules_used = nused;
1366
1367 /* And finally the symbols from the kernel proper. */
1368
1369 if (nksyms)
1370 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1371}
1372
1373static char *get_modinfo_value(struct obj_file *f, const char *key)
1374{
1375 struct obj_section *sec;
1376 char *p, *v, *n, *ep;
1377 size_t klen = strlen(key);
1378
1379 sec = obj_find_section(f, ".modinfo");
1380 if (sec == NULL)
1381 return NULL;
1382 p = sec->contents;
1383 ep = p + sec->header.sh_size;
1384 while (p < ep) {
1385 v = strchr(p, '=');
1386 n = strchr(p, '\0');
1387 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001388 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001389 return v + 1;
1390 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001391 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001392 return n;
1393 }
1394 p = n + 1;
1395 }
1396
1397 return NULL;
1398}
1399
1400
1401/*======================================================================*/
1402/* Functions relating to module loading in pre 2.1 kernels. */
1403
1404static int
1405old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1406{
1407 while (argc > 0) {
1408 char *p, *q;
1409 struct obj_symbol *sym;
1410 int *loc;
1411
1412 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001413 if ((q = strchr(p, '=')) == NULL) {
1414 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001415 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001416 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001417 *q++ = '\0';
1418
1419 sym = obj_find_symbol(f, p);
1420
1421 /* Also check that the parameter was not resolved from the kernel. */
1422 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001423 error_msg("symbol for parameter %s not found\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001424 return 0;
1425 }
1426
1427 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1428
1429 /* Do C quoting if we begin with a ". */
1430 if (*q == '"') {
1431 char *r, *str;
1432
1433 str = alloca(strlen(q));
1434 for (r = str, q++; *q != '"'; ++q, ++r) {
1435 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001436 error_msg("improperly terminated string argument for %s\n", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001437 return 0;
1438 } else if (*q == '\\')
1439 switch (*++q) {
1440 case 'a':
1441 *r = '\a';
1442 break;
1443 case 'b':
1444 *r = '\b';
1445 break;
1446 case 'e':
1447 *r = '\033';
1448 break;
1449 case 'f':
1450 *r = '\f';
1451 break;
1452 case 'n':
1453 *r = '\n';
1454 break;
1455 case 'r':
1456 *r = '\r';
1457 break;
1458 case 't':
1459 *r = '\t';
1460 break;
1461
1462 case '0':
1463 case '1':
1464 case '2':
1465 case '3':
1466 case '4':
1467 case '5':
1468 case '6':
1469 case '7':
1470 {
1471 int c = *q - '0';
1472 if (q[1] >= '0' && q[1] <= '7') {
1473 c = (c * 8) + *++q - '0';
1474 if (q[1] >= '0' && q[1] <= '7')
1475 c = (c * 8) + *++q - '0';
1476 }
1477 *r = c;
1478 }
1479 break;
1480
1481 default:
1482 *r = *q;
1483 break;
1484 } else
1485 *r = *q;
1486 }
1487 *r = '\0';
1488 obj_string_patch(f, sym->secidx, sym->value, str);
1489 } else if (*q >= '0' && *q <= '9') {
1490 do
1491 *loc++ = strtoul(q, &q, 0);
1492 while (*q++ == ',');
1493 } else {
1494 char *contents = f->sections[sym->secidx]->contents;
1495 char *loc = contents + sym->value;
1496 char *r; /* To search for commas */
1497
1498 /* Break the string with comas */
1499 while ((r = strchr(q, ',')) != (char *) NULL) {
1500 *r++ = '\0';
1501 obj_string_patch(f, sym->secidx, loc - contents, q);
1502 loc += sizeof(char *);
1503 q = r;
1504 }
1505
1506 /* last part */
1507 obj_string_patch(f, sym->secidx, loc - contents, q);
1508 }
1509
1510 argc--, argv++;
1511 }
1512
1513 return 1;
1514}
1515
1516#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1517static int old_is_module_checksummed(struct obj_file *f)
1518{
1519 return obj_find_symbol(f, "Using_Versions") != NULL;
1520}
1521/* Get the module's kernel version in the canonical integer form. */
1522
1523static int
1524old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1525{
1526 struct obj_symbol *sym;
1527 char *p, *q;
1528 int a, b, c;
1529
1530 sym = obj_find_symbol(f, "kernel_version");
1531 if (sym == NULL)
1532 return -1;
1533
1534 p = f->sections[sym->secidx]->contents + sym->value;
1535 strncpy(str, p, STRVERSIONLEN);
1536
1537 a = strtoul(p, &p, 10);
1538 if (*p != '.')
1539 return -1;
1540 b = strtoul(p + 1, &p, 10);
1541 if (*p != '.')
1542 return -1;
1543 c = strtoul(p + 1, &q, 10);
1544 if (p + 1 == q)
1545 return -1;
1546
1547 return a << 16 | b << 8 | c;
1548}
1549
1550#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1551
1552#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
1553
1554/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1555
Eric Andersen8c185f92000-09-22 00:38:07 +00001556static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001557{
1558 struct old_kernel_sym *ks, *k;
1559 struct new_module_symbol *s;
1560 struct external_module *mod;
1561 int nks, nms, nmod, i;
1562
1563 nks = get_kernel_syms(NULL);
1564 if (nks < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001565 perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001566 return 0;
1567 }
1568
1569 ks = k = xmalloc(nks * sizeof(*ks));
1570
1571 if (get_kernel_syms(ks) != nks) {
1572 perror("inconsistency with get_kernel_syms -- is someone else "
1573 "playing with modules?");
1574 free(ks);
1575 return 0;
1576 }
1577
1578 /* Collect the module information. */
1579
1580 mod = NULL;
1581 nmod = -1;
1582
1583 while (k->name[0] == '#' && k->name[1]) {
1584 struct old_kernel_sym *k2;
1585 struct new_module_symbol *s;
1586
1587 /* Find out how many symbols this module has. */
1588 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1589 continue;
1590 nms = k2 - k - 1;
1591
1592 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1593 mod[nmod].name = k->name + 1;
1594 mod[nmod].addr = k->value;
1595 mod[nmod].used = 0;
1596 mod[nmod].nsyms = nms;
1597 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1598
1599 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1600 s->name = (unsigned long) k->name;
1601 s->value = k->value;
1602 }
1603
1604 k = k2;
1605 }
1606
1607 ext_modules = mod;
1608 n_ext_modules = nmod + 1;
1609
1610 /* Now collect the symbols for the kernel proper. */
1611
1612 if (k->name[0] == '#')
1613 ++k;
1614
1615 nksyms = nms = nks - (k - ks);
1616 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1617
1618 for (i = 0; i < nms; ++i, ++s, ++k) {
1619 s->name = (unsigned long) k->name;
1620 s->value = k->value;
1621 }
1622
1623 return 1;
1624}
1625
1626/* Return the kernel symbol checksum version, or zero if not used. */
1627
1628static int old_is_kernel_checksummed(void)
1629{
1630 /* Using_Versions is the first symbol. */
1631 if (nksyms > 0
1632 && strcmp((char *) ksyms[0].name,
1633 "Using_Versions") == 0) return ksyms[0].value;
1634 else
1635 return 0;
1636}
1637
1638
1639static int old_create_mod_use_count(struct obj_file *f)
1640{
1641 struct obj_section *sec;
1642
1643 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1644 sizeof(long));
1645
1646 obj_add_symbol(f, "mod_use_count_", -1,
1647 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1648 sizeof(long));
1649
1650 return 1;
1651}
1652
1653static int
1654old_init_module(const char *m_name, struct obj_file *f,
1655 unsigned long m_size)
1656{
1657 char *image;
1658 struct old_mod_routines routines;
1659 struct old_symbol_table *symtab;
1660 int ret;
1661
1662 /* Create the symbol table */
1663 {
1664 int nsyms = 0, strsize = 0, total;
1665
1666 /* Size things first... */
1667 if (flag_export) {
1668 int i;
1669 for (i = 0; i < HASH_BUCKETS; ++i) {
1670 struct obj_symbol *sym;
1671 for (sym = f->symtab[i]; sym; sym = sym->next)
1672 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1673 && sym->secidx <= SHN_HIRESERVE)
1674 {
1675 sym->ksymidx = nsyms++;
1676 strsize += strlen(sym->name) + 1;
1677 }
1678 }
1679 }
1680
1681 total = (sizeof(struct old_symbol_table)
1682 + nsyms * sizeof(struct old_module_symbol)
1683 + n_ext_modules_used * sizeof(struct old_module_ref)
1684 + strsize);
1685 symtab = xmalloc(total);
1686 symtab->size = total;
1687 symtab->n_symbols = nsyms;
1688 symtab->n_refs = n_ext_modules_used;
1689
1690 if (flag_export && nsyms) {
1691 struct old_module_symbol *ksym;
1692 char *str;
1693 int i;
1694
1695 ksym = symtab->symbol;
1696 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1697 + n_ext_modules_used * sizeof(struct old_module_ref));
1698
1699 for (i = 0; i < HASH_BUCKETS; ++i) {
1700 struct obj_symbol *sym;
1701 for (sym = f->symtab[i]; sym; sym = sym->next)
1702 if (sym->ksymidx >= 0) {
1703 ksym->addr = obj_symbol_final_value(f, sym);
1704 ksym->name =
1705 (unsigned long) str - (unsigned long) symtab;
1706
Matt Kraai70a78552001-01-04 02:00:17 +00001707 strcpy(str, sym->name);
1708 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001709 ksym++;
1710 }
1711 }
1712 }
1713
1714 if (n_ext_modules_used) {
1715 struct old_module_ref *ref;
1716 int i;
1717
1718 ref = (struct old_module_ref *)
1719 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1720
1721 for (i = 0; i < n_ext_modules; ++i)
1722 if (ext_modules[i].used)
1723 ref++->module = ext_modules[i].addr;
1724 }
1725 }
1726
1727 /* Fill in routines. */
1728
1729 routines.init =
1730 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
1731 routines.cleanup =
1732 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
1733
1734 /* Whew! All of the initialization is complete. Collect the final
1735 module image and give it to the kernel. */
1736
1737 image = xmalloc(m_size);
1738 obj_create_image(f, image);
1739
1740 /* image holds the complete relocated module, accounting correctly for
1741 mod_use_count. However the old module kernel support assume that
1742 it is receiving something which does not contain mod_use_count. */
1743 ret = old_sys_init_module(m_name, image + sizeof(long),
1744 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
1745 : 0), &routines, symtab);
1746 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00001747 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001748
1749 free(image);
1750 free(symtab);
1751
1752 return ret == 0;
1753}
1754
1755#else
1756
1757#define old_create_mod_use_count(x) TRUE
1758#define old_init_module(x, y, z) TRUE
1759
1760#endif /* BB_FEATURE_INSMOD_OLD_KERNEL */
1761
1762
1763
1764/*======================================================================*/
1765/* Functions relating to module loading after 2.1.18. */
1766
1767static int
1768new_process_module_arguments(struct obj_file *f, int argc, char **argv)
1769{
1770 while (argc > 0) {
1771 char *p, *q, *key;
1772 struct obj_symbol *sym;
1773 char *contents, *loc;
1774 int min, max, n;
1775
1776 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001777 if ((q = strchr(p, '=')) == NULL) {
1778 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001779 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001780 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001781
1782 key = alloca(q - p + 6);
1783 memcpy(key, "parm_", 5);
1784 memcpy(key + 5, p, q - p);
1785 key[q - p + 5] = 0;
1786
1787 p = get_modinfo_value(f, key);
1788 key += 5;
1789 if (p == NULL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001790 error_msg("invalid parameter %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001791 return 0;
1792 }
1793
1794 sym = obj_find_symbol(f, key);
1795
1796 /* Also check that the parameter was not resolved from the kernel. */
1797 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001798 error_msg("symbol for parameter %s not found\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001799 return 0;
1800 }
1801
1802 if (isdigit(*p)) {
1803 min = strtoul(p, &p, 10);
1804 if (*p == '-')
1805 max = strtoul(p + 1, &p, 10);
1806 else
1807 max = min;
1808 } else
1809 min = max = 1;
1810
1811 contents = f->sections[sym->secidx]->contents;
1812 loc = contents + sym->value;
1813 n = (*++q != '\0');
1814
1815 while (1) {
1816 if ((*p == 's') || (*p == 'c')) {
1817 char *str;
1818
1819 /* Do C quoting if we begin with a ", else slurp the lot. */
1820 if (*q == '"') {
1821 char *r;
1822
1823 str = alloca(strlen(q));
1824 for (r = str, q++; *q != '"'; ++q, ++r) {
1825 if (*q == '\0') {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001826 error_msg("improperly terminated string argument for %s\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00001827 key);
1828 return 0;
1829 } else if (*q == '\\')
1830 switch (*++q) {
1831 case 'a':
1832 *r = '\a';
1833 break;
1834 case 'b':
1835 *r = '\b';
1836 break;
1837 case 'e':
1838 *r = '\033';
1839 break;
1840 case 'f':
1841 *r = '\f';
1842 break;
1843 case 'n':
1844 *r = '\n';
1845 break;
1846 case 'r':
1847 *r = '\r';
1848 break;
1849 case 't':
1850 *r = '\t';
1851 break;
1852
1853 case '0':
1854 case '1':
1855 case '2':
1856 case '3':
1857 case '4':
1858 case '5':
1859 case '6':
1860 case '7':
1861 {
1862 int c = *q - '0';
1863 if (q[1] >= '0' && q[1] <= '7') {
1864 c = (c * 8) + *++q - '0';
1865 if (q[1] >= '0' && q[1] <= '7')
1866 c = (c * 8) + *++q - '0';
1867 }
1868 *r = c;
1869 }
1870 break;
1871
1872 default:
1873 *r = *q;
1874 break;
1875 } else
1876 *r = *q;
1877 }
1878 *r = '\0';
1879 ++q;
1880 } else {
1881 char *r;
1882
1883 /* In this case, the string is not quoted. We will break
1884 it using the coma (like for ints). If the user wants to
1885 include comas in a string, he just has to quote it */
1886
1887 /* Search the next coma */
1888 r = strchr(q, ',');
1889
1890 /* Found ? */
1891 if (r != (char *) NULL) {
1892 /* Recopy the current field */
1893 str = alloca(r - q + 1);
1894 memcpy(str, q, r - q);
1895
1896 /* I don't know if it is usefull, as the previous case
1897 doesn't null terminate the string ??? */
1898 str[r - q] = '\0';
1899
1900 /* Keep next fields */
1901 q = r;
1902 } else {
1903 /* last string */
1904 str = q;
1905 q = "";
1906 }
1907 }
1908
1909 if (*p == 's') {
1910 /* Normal string */
1911 obj_string_patch(f, sym->secidx, loc - contents, str);
1912 loc += tgt_sizeof_char_p;
1913 } else {
1914 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00001915 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00001916
1917 /* Get the size of each member */
1918 /* Probably we should do that outside the loop ? */
1919 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001920 error_msg("parameter type 'c' for %s must be followed by"
Eric Andersen9f16d612000-06-12 23:11:16 +00001921 " the maximum size\n", key);
1922 return 0;
1923 }
1924 charssize = strtoul(p + 1, (char **) NULL, 10);
1925
1926 /* Check length */
1927 if (strlen(str) >= charssize) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001928 error_msg("string too long for %s (max %ld)\n", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00001929 charssize - 1);
1930 return 0;
1931 }
1932
1933 /* Copy to location */
1934 strcpy((char *) loc, str);
1935 loc += charssize;
1936 }
1937 } else {
1938 long v = strtoul(q, &q, 0);
1939 switch (*p) {
1940 case 'b':
1941 *loc++ = v;
1942 break;
1943 case 'h':
1944 *(short *) loc = v;
1945 loc += tgt_sizeof_short;
1946 break;
1947 case 'i':
1948 *(int *) loc = v;
1949 loc += tgt_sizeof_int;
1950 break;
1951 case 'l':
1952 *(long *) loc = v;
1953 loc += tgt_sizeof_long;
1954 break;
1955
1956 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001957 error_msg("unknown parameter type '%c' for %s\n", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001958 return 0;
1959 }
1960 }
1961
1962 retry_end_of_value:
1963 switch (*q) {
1964 case '\0':
1965 goto end_of_arg;
1966
1967 case ' ':
1968 case '\t':
1969 case '\n':
1970 case '\r':
1971 ++q;
1972 goto retry_end_of_value;
1973
1974 case ',':
1975 if (++n > max) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001976 error_msg("too many values for %s (max %d)\n", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00001977 return 0;
1978 }
1979 ++q;
1980 break;
1981
1982 default:
Mark Whitleyf57c9442000-12-07 19:56:48 +00001983 error_msg("invalid argument syntax for %s\n", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00001984 return 0;
1985 }
1986 }
1987
1988 end_of_arg:
1989 if (n < min) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00001990 error_msg("too few values for %s (min %d)\n", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00001991 return 0;
1992 }
1993
1994 argc--, argv++;
1995 }
1996
1997 return 1;
1998}
1999
2000#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2001static int new_is_module_checksummed(struct obj_file *f)
2002{
2003 const char *p = get_modinfo_value(f, "using_checksums");
2004 if (p)
2005 return atoi(p);
2006 else
2007 return 0;
2008}
2009
2010/* Get the module's kernel version in the canonical integer form. */
2011
2012static int
2013new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2014{
2015 char *p, *q;
2016 int a, b, c;
2017
2018 p = get_modinfo_value(f, "kernel_version");
2019 if (p == NULL)
2020 return -1;
2021 strncpy(str, p, STRVERSIONLEN);
2022
2023 a = strtoul(p, &p, 10);
2024 if (*p != '.')
2025 return -1;
2026 b = strtoul(p + 1, &p, 10);
2027 if (*p != '.')
2028 return -1;
2029 c = strtoul(p + 1, &q, 10);
2030 if (p + 1 == q)
2031 return -1;
2032
2033 return a << 16 | b << 8 | c;
2034}
2035
2036#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2037
2038
2039#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
2040
2041/* Fetch the loaded modules, and all currently exported symbols. */
2042
2043static int new_get_kernel_symbols(void)
2044{
2045 char *module_names, *mn;
2046 struct external_module *modules, *m;
2047 struct new_module_symbol *syms, *s;
2048 size_t ret, bufsize, nmod, nsyms, i, j;
2049
2050 /* Collect the loaded modules. */
2051
2052 module_names = xmalloc(bufsize = 256);
2053 retry_modules_load:
2054 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
2055 if (errno == ENOSPC) {
2056 module_names = xrealloc(module_names, bufsize = ret);
2057 goto retry_modules_load;
2058 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002059 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002060 return 0;
2061 }
2062
2063 n_ext_modules = nmod = ret;
2064 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2065 memset(modules, 0, nmod * sizeof(*modules));
2066
2067 /* Collect the modules' symbols. */
2068
2069 for (i = 0, mn = module_names, m = modules;
2070 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2071 struct new_module_info info;
2072
2073 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2074 if (errno == ENOENT) {
2075 /* The module was removed out from underneath us. */
2076 continue;
2077 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002078 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002079 return 0;
2080 }
2081
2082 syms = xmalloc(bufsize = 1024);
2083 retry_mod_sym_load:
2084 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2085 switch (errno) {
2086 case ENOSPC:
2087 syms = xrealloc(syms, bufsize = ret);
2088 goto retry_mod_sym_load;
2089 case ENOENT:
2090 /* The module was removed out from underneath us. */
2091 continue;
2092 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002093 perror_msg("query_module: QM_SYMBOLS: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002094 return 0;
2095 }
2096 }
2097 nsyms = ret;
2098
2099 m->name = mn;
2100 m->addr = info.addr;
2101 m->nsyms = nsyms;
2102 m->syms = syms;
2103
2104 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2105 s->name += (unsigned long) syms;
2106 }
2107 }
2108
2109 /* Collect the kernel's symbols. */
2110
2111 syms = xmalloc(bufsize = 16 * 1024);
2112 retry_kern_sym_load:
2113 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
2114 if (errno == ENOSPC) {
2115 syms = xrealloc(syms, bufsize = ret);
2116 goto retry_kern_sym_load;
2117 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002118 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002119 return 0;
2120 }
2121 nksyms = nsyms = ret;
2122 ksyms = syms;
2123
2124 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2125 s->name += (unsigned long) syms;
2126 }
2127 return 1;
2128}
2129
2130
2131/* Return the kernel symbol checksum version, or zero if not used. */
2132
2133static int new_is_kernel_checksummed(void)
2134{
2135 struct new_module_symbol *s;
2136 size_t i;
2137
2138 /* Using_Versions is not the first symbol, but it should be in there. */
2139
2140 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2141 if (strcmp((char *) s->name, "Using_Versions") == 0)
2142 return s->value;
2143
2144 return 0;
2145}
2146
2147
2148static int new_create_this_module(struct obj_file *f, const char *m_name)
2149{
2150 struct obj_section *sec;
2151
2152 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2153 sizeof(struct new_module));
2154 memset(sec->contents, 0, sizeof(struct new_module));
2155
2156 obj_add_symbol(f, "__this_module", -1,
2157 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2158 sizeof(struct new_module));
2159
2160 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2161 m_name);
2162
2163 return 1;
2164}
2165
2166
2167static int new_create_module_ksymtab(struct obj_file *f)
2168{
2169 struct obj_section *sec;
2170 int i;
2171
2172 /* We must always add the module references. */
2173
2174 if (n_ext_modules_used) {
2175 struct new_module_ref *dep;
2176 struct obj_symbol *tm;
2177
2178 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2179 (sizeof(struct new_module_ref)
2180 * n_ext_modules_used));
2181 if (!sec)
2182 return 0;
2183
2184 tm = obj_find_symbol(f, "__this_module");
2185 dep = (struct new_module_ref *) sec->contents;
2186 for (i = 0; i < n_ext_modules; ++i)
2187 if (ext_modules[i].used) {
2188 dep->dep = ext_modules[i].addr;
2189 obj_symbol_patch(f, sec->idx,
2190 (char *) &dep->ref - sec->contents, tm);
2191 dep->next_ref = 0;
2192 ++dep;
2193 }
2194 }
2195
2196 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2197 size_t nsyms;
2198 int *loaded;
2199
2200 sec =
2201 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2202 0);
2203
2204 /* We don't want to export symbols residing in sections that
2205 aren't loaded. There are a number of these created so that
2206 we make sure certain module options don't appear twice. */
2207
2208 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2209 while (--i >= 0)
2210 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2211
2212 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2213 struct obj_symbol *sym;
2214 for (sym = f->symtab[i]; sym; sym = sym->next)
2215 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2216 && sym->secidx <= SHN_HIRESERVE
2217 && (sym->secidx >= SHN_LORESERVE
2218 || loaded[sym->secidx])) {
2219 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2220
2221 obj_symbol_patch(f, sec->idx, ofs, sym);
2222 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2223 sym->name);
2224
2225 nsyms++;
2226 }
2227 }
2228
2229 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2230 }
2231
2232 return 1;
2233}
2234
2235
2236static int
2237new_init_module(const char *m_name, struct obj_file *f,
2238 unsigned long m_size)
2239{
2240 struct new_module *module;
2241 struct obj_section *sec;
2242 void *image;
2243 int ret;
2244 tgt_long m_addr;
2245
2246 sec = obj_find_section(f, ".this");
2247 module = (struct new_module *) sec->contents;
2248 m_addr = sec->header.sh_addr;
2249
2250 module->size_of_struct = sizeof(*module);
2251 module->size = m_size;
2252 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2253
2254 sec = obj_find_section(f, "__ksymtab");
2255 if (sec && sec->header.sh_size) {
2256 module->syms = sec->header.sh_addr;
2257 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2258 }
2259
2260 if (n_ext_modules_used) {
2261 sec = obj_find_section(f, ".kmodtab");
2262 module->deps = sec->header.sh_addr;
2263 module->ndeps = n_ext_modules_used;
2264 }
2265
2266 module->init =
2267 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2268 module->cleanup =
2269 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2270
2271 sec = obj_find_section(f, "__ex_table");
2272 if (sec) {
2273 module->ex_table_start = sec->header.sh_addr;
2274 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2275 }
2276
2277 sec = obj_find_section(f, ".text.init");
2278 if (sec) {
2279 module->runsize = sec->header.sh_addr - m_addr;
2280 }
2281 sec = obj_find_section(f, ".data.init");
2282 if (sec) {
2283 if (!module->runsize ||
2284 module->runsize > sec->header.sh_addr - m_addr)
2285 module->runsize = sec->header.sh_addr - m_addr;
2286 }
2287
2288 if (!arch_init_module(f, module))
2289 return 0;
2290
2291 /* Whew! All of the initialization is complete. Collect the final
2292 module image and give it to the kernel. */
2293
2294 image = xmalloc(m_size);
2295 obj_create_image(f, image);
2296
2297 ret = new_sys_init_module(m_name, (struct new_module *) image);
2298 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002299 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002300
2301 free(image);
2302
2303 return ret == 0;
2304}
2305
2306#else
2307
2308#define new_init_module(x, y, z) TRUE
2309#define new_create_this_module(x, y) 0
2310#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002311#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002312
Eric Andersen21adca72000-12-06 18:18:26 +00002313#endif /* BB_FEATURE_INSMOD_NEW_KERNEL */
Eric Andersen9f16d612000-06-12 23:11:16 +00002314
2315
2316/*======================================================================*/
2317
2318int
2319obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2320 const char *string)
2321{
2322 struct obj_string_patch *p;
2323 struct obj_section *strsec;
2324 size_t len = strlen(string) + 1;
2325 char *loc;
2326
2327 p = xmalloc(sizeof(*p));
2328 p->next = f->string_patches;
2329 p->reloc_secidx = secidx;
2330 p->reloc_offset = offset;
2331 f->string_patches = p;
2332
2333 strsec = obj_find_section(f, ".kstrtab");
2334 if (strsec == NULL) {
2335 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2336 p->string_offset = 0;
2337 loc = strsec->contents;
2338 } else {
2339 p->string_offset = strsec->header.sh_size;
2340 loc = obj_extend_section(strsec, len);
2341 }
2342 memcpy(loc, string, len);
2343
2344 return 1;
2345}
2346
2347int
2348obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2349 struct obj_symbol *sym)
2350{
2351 struct obj_symbol_patch *p;
2352
2353 p = xmalloc(sizeof(*p));
2354 p->next = f->symbol_patches;
2355 p->reloc_secidx = secidx;
2356 p->reloc_offset = offset;
2357 p->sym = sym;
2358 f->symbol_patches = p;
2359
2360 return 1;
2361}
2362
2363int obj_check_undefineds(struct obj_file *f)
2364{
2365 unsigned long i;
2366 int ret = 1;
2367
2368 for (i = 0; i < HASH_BUCKETS; ++i) {
2369 struct obj_symbol *sym;
2370 for (sym = f->symtab[i]; sym; sym = sym->next)
2371 if (sym->secidx == SHN_UNDEF) {
2372 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2373 sym->secidx = SHN_ABS;
2374 sym->value = 0;
2375 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002376 error_msg("unresolved symbol %s\n", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002377 ret = 0;
2378 }
2379 }
2380 }
2381
2382 return ret;
2383}
2384
2385void obj_allocate_commons(struct obj_file *f)
2386{
2387 struct common_entry {
2388 struct common_entry *next;
2389 struct obj_symbol *sym;
2390 } *common_head = NULL;
2391
2392 unsigned long i;
2393
2394 for (i = 0; i < HASH_BUCKETS; ++i) {
2395 struct obj_symbol *sym;
2396 for (sym = f->symtab[i]; sym; sym = sym->next)
2397 if (sym->secidx == SHN_COMMON) {
2398 /* Collect all COMMON symbols and sort them by size so as to
2399 minimize space wasted by alignment requirements. */
2400 {
2401 struct common_entry **p, *n;
2402 for (p = &common_head; *p; p = &(*p)->next)
2403 if (sym->size <= (*p)->sym->size)
2404 break;
2405
2406 n = alloca(sizeof(*n));
2407 n->next = *p;
2408 n->sym = sym;
2409 *p = n;
2410 }
2411 }
2412 }
2413
2414 for (i = 1; i < f->local_symtab_size; ++i) {
2415 struct obj_symbol *sym = f->local_symtab[i];
2416 if (sym && sym->secidx == SHN_COMMON) {
2417 struct common_entry **p, *n;
2418 for (p = &common_head; *p; p = &(*p)->next)
2419 if (sym == (*p)->sym)
2420 break;
2421 else if (sym->size < (*p)->sym->size) {
2422 n = alloca(sizeof(*n));
2423 n->next = *p;
2424 n->sym = sym;
2425 *p = n;
2426 break;
2427 }
2428 }
2429 }
2430
2431 if (common_head) {
2432 /* Find the bss section. */
2433 for (i = 0; i < f->header.e_shnum; ++i)
2434 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2435 break;
2436
2437 /* If for some reason there hadn't been one, create one. */
2438 if (i == f->header.e_shnum) {
2439 struct obj_section *sec;
2440
2441 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2442 f->sections[i] = sec = arch_new_section();
2443 f->header.e_shnum = i + 1;
2444
2445 memset(sec, 0, sizeof(*sec));
2446 sec->header.sh_type = SHT_PROGBITS;
2447 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2448 sec->name = ".bss";
2449 sec->idx = i;
2450 }
2451
2452 /* Allocate the COMMONS. */
2453 {
2454 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2455 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2456 struct common_entry *c;
2457
2458 for (c = common_head; c; c = c->next) {
2459 ElfW(Addr) align = c->sym->value;
2460
2461 if (align > max_align)
2462 max_align = align;
2463 if (bss_size & (align - 1))
2464 bss_size = (bss_size | (align - 1)) + 1;
2465
2466 c->sym->secidx = i;
2467 c->sym->value = bss_size;
2468
2469 bss_size += c->sym->size;
2470 }
2471
2472 f->sections[i]->header.sh_size = bss_size;
2473 f->sections[i]->header.sh_addralign = max_align;
2474 }
2475 }
2476
2477 /* For the sake of patch relocation and parameter initialization,
2478 allocate zeroed data for NOBITS sections now. Note that after
2479 this we cannot assume NOBITS are really empty. */
2480 for (i = 0; i < f->header.e_shnum; ++i) {
2481 struct obj_section *s = f->sections[i];
2482 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002483 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002484 s->contents = memset(xmalloc(s->header.sh_size),
2485 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002486 else
2487 s->contents = NULL;
2488
Eric Andersen9f16d612000-06-12 23:11:16 +00002489 s->header.sh_type = SHT_PROGBITS;
2490 }
2491 }
2492}
2493
2494unsigned long obj_load_size(struct obj_file *f)
2495{
2496 unsigned long dot = 0;
2497 struct obj_section *sec;
2498
2499 /* Finalize the positions of the sections relative to one another. */
2500
2501 for (sec = f->load_order; sec; sec = sec->load_next) {
2502 ElfW(Addr) align;
2503
2504 align = sec->header.sh_addralign;
2505 if (align && (dot & (align - 1)))
2506 dot = (dot | (align - 1)) + 1;
2507
2508 sec->header.sh_addr = dot;
2509 dot += sec->header.sh_size;
2510 }
2511
2512 return dot;
2513}
2514
2515int obj_relocate(struct obj_file *f, ElfW(Addr) base)
2516{
2517 int i, n = f->header.e_shnum;
2518 int ret = 1;
2519
2520 /* Finalize the addresses of the sections. */
2521
2522 f->baseaddr = base;
2523 for (i = 0; i < n; ++i)
2524 f->sections[i]->header.sh_addr += base;
2525
2526 /* And iterate over all of the relocations. */
2527
2528 for (i = 0; i < n; ++i) {
2529 struct obj_section *relsec, *symsec, *targsec, *strsec;
2530 ElfW(RelM) * rel, *relend;
2531 ElfW(Sym) * symtab;
2532 const char *strtab;
2533
2534 relsec = f->sections[i];
2535 if (relsec->header.sh_type != SHT_RELM)
2536 continue;
2537
2538 symsec = f->sections[relsec->header.sh_link];
2539 targsec = f->sections[relsec->header.sh_info];
2540 strsec = f->sections[symsec->header.sh_link];
2541
2542 rel = (ElfW(RelM) *) relsec->contents;
2543 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2544 symtab = (ElfW(Sym) *) symsec->contents;
2545 strtab = (const char *) strsec->contents;
2546
2547 for (; rel < relend; ++rel) {
2548 ElfW(Addr) value = 0;
2549 struct obj_symbol *intsym = NULL;
2550 unsigned long symndx;
2551 ElfW(Sym) * extsym = 0;
2552 const char *errmsg;
2553
2554 /* Attempt to find a value to use for this relocation. */
2555
2556 symndx = ELFW(R_SYM) (rel->r_info);
2557 if (symndx) {
2558 /* Note we've already checked for undefined symbols. */
2559
2560 extsym = &symtab[symndx];
2561 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2562 /* Local symbols we look up in the local table to be sure
2563 we get the one that is really intended. */
2564 intsym = f->local_symtab[symndx];
2565 } else {
2566 /* Others we look up in the hash table. */
2567 const char *name;
2568 if (extsym->st_name)
2569 name = strtab + extsym->st_name;
2570 else
2571 name = f->sections[extsym->st_shndx]->name;
2572 intsym = obj_find_symbol(f, name);
2573 }
2574
2575 value = obj_symbol_final_value(f, intsym);
2576 intsym->referenced = 1;
2577 }
2578#if SHT_RELM == SHT_RELA
2579#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2580 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2581 if (!extsym || !extsym->st_name ||
2582 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2583#endif
2584 value += rel->r_addend;
2585#endif
2586
2587 /* Do it! */
2588 switch (arch_apply_relocation
2589 (f, targsec, symsec, intsym, rel, value)) {
2590 case obj_reloc_ok:
2591 break;
2592
2593 case obj_reloc_overflow:
2594 errmsg = "Relocation overflow";
2595 goto bad_reloc;
2596 case obj_reloc_dangerous:
2597 errmsg = "Dangerous relocation";
2598 goto bad_reloc;
2599 case obj_reloc_unhandled:
2600 errmsg = "Unhandled relocation";
2601 bad_reloc:
2602 if (extsym) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002603 error_msg("%s of type %ld for %s\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002604 (long) ELFW(R_TYPE) (rel->r_info),
2605 strtab + extsym->st_name);
2606 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002607 error_msg("%s of type %ld\n", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002608 (long) ELFW(R_TYPE) (rel->r_info));
2609 }
2610 ret = 0;
2611 break;
2612 }
2613 }
2614 }
2615
2616 /* Finally, take care of the patches. */
2617
2618 if (f->string_patches) {
2619 struct obj_string_patch *p;
2620 struct obj_section *strsec;
2621 ElfW(Addr) strsec_base;
2622 strsec = obj_find_section(f, ".kstrtab");
2623 strsec_base = strsec->header.sh_addr;
2624
2625 for (p = f->string_patches; p; p = p->next) {
2626 struct obj_section *targsec = f->sections[p->reloc_secidx];
2627 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2628 = strsec_base + p->string_offset;
2629 }
2630 }
2631
2632 if (f->symbol_patches) {
2633 struct obj_symbol_patch *p;
2634
2635 for (p = f->symbol_patches; p; p = p->next) {
2636 struct obj_section *targsec = f->sections[p->reloc_secidx];
2637 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2638 = obj_symbol_final_value(f, p->sym);
2639 }
2640 }
2641
2642 return ret;
2643}
2644
2645int obj_create_image(struct obj_file *f, char *image)
2646{
2647 struct obj_section *sec;
2648 ElfW(Addr) base = f->baseaddr;
2649
2650 for (sec = f->load_order; sec; sec = sec->load_next) {
2651 char *secimg;
2652
2653 if (sec->header.sh_size == 0)
2654 continue;
2655
2656 secimg = image + (sec->header.sh_addr - base);
2657
2658 /* Note that we allocated data for NOBITS sections earlier. */
2659 memcpy(secimg, sec->contents, sec->header.sh_size);
2660 }
2661
2662 return 1;
2663}
2664
2665/*======================================================================*/
2666
2667struct obj_file *obj_load(FILE * fp)
2668{
2669 struct obj_file *f;
2670 ElfW(Shdr) * section_headers;
2671 int shnum, i;
2672 char *shstrtab;
2673
2674 /* Read the file header. */
2675
2676 f = arch_new_file();
2677 memset(f, 0, sizeof(*f));
2678 f->symbol_cmp = strcmp;
2679 f->symbol_hash = obj_elf_hash;
2680 f->load_order_search_start = &f->load_order;
2681
2682 fseek(fp, 0, SEEK_SET);
2683 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002684 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002685 return NULL;
2686 }
2687
2688 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2689 || f->header.e_ident[EI_MAG1] != ELFMAG1
2690 || f->header.e_ident[EI_MAG2] != ELFMAG2
2691 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002692 error_msg("not an ELF file\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 return NULL;
2694 }
2695 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2696 || f->header.e_ident[EI_DATA] != ELFDATAM
2697 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2698 || !MATCH_MACHINE(f->header.e_machine)) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002699 error_msg("ELF file not for this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002700 return NULL;
2701 }
2702 if (f->header.e_type != ET_REL) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002703 error_msg("ELF file not a relocatable object\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002704 return NULL;
2705 }
2706
2707 /* Read the section headers. */
2708
2709 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002710 error_msg("section header size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002711 (unsigned long) f->header.e_shentsize,
2712 (unsigned long) sizeof(ElfW(Shdr)));
2713 return NULL;
2714 }
2715
2716 shnum = f->header.e_shnum;
2717 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
2718 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
2719
2720 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
2721 fseek(fp, f->header.e_shoff, SEEK_SET);
2722 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002723 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00002724 return NULL;
2725 }
2726
2727 /* Read the section data. */
2728
2729 for (i = 0; i < shnum; ++i) {
2730 struct obj_section *sec;
2731
2732 f->sections[i] = sec = arch_new_section();
2733 memset(sec, 0, sizeof(*sec));
2734
2735 sec->header = section_headers[i];
2736 sec->idx = i;
2737
2738 switch (sec->header.sh_type) {
2739 case SHT_NULL:
2740 case SHT_NOTE:
2741 case SHT_NOBITS:
2742 /* ignore */
2743 break;
2744
2745 case SHT_PROGBITS:
2746 case SHT_SYMTAB:
2747 case SHT_STRTAB:
2748 case SHT_RELM:
2749 if (sec->header.sh_size > 0) {
2750 sec->contents = xmalloc(sec->header.sh_size);
2751 fseek(fp, sec->header.sh_offset, SEEK_SET);
2752 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002753 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00002754 return NULL;
2755 }
2756 } else {
2757 sec->contents = NULL;
2758 }
2759 break;
2760
2761#if SHT_RELM == SHT_REL
2762 case SHT_RELA:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002763 error_msg("RELA relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002764 return NULL;
2765#else
2766 case SHT_REL:
Mark Whitleyf57c9442000-12-07 19:56:48 +00002767 error_msg("REL relocations not supported on this architecture\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002768 return NULL;
2769#endif
2770
2771 default:
2772 if (sec->header.sh_type >= SHT_LOPROC) {
2773 /* Assume processor specific section types are debug
2774 info and can safely be ignored. If this is ever not
2775 the case (Hello MIPS?), don't put ifdefs here but
2776 create an arch_load_proc_section(). */
2777 break;
2778 }
2779
Mark Whitleyf57c9442000-12-07 19:56:48 +00002780 error_msg("can't handle sections of type %ld\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002781 (long) sec->header.sh_type);
2782 return NULL;
2783 }
2784 }
2785
2786 /* Do what sort of interpretation as needed by each section. */
2787
2788 shstrtab = f->sections[f->header.e_shstrndx]->contents;
2789
2790 for (i = 0; i < shnum; ++i) {
2791 struct obj_section *sec = f->sections[i];
2792 sec->name = shstrtab + sec->header.sh_name;
2793 }
2794
2795 for (i = 0; i < shnum; ++i) {
2796 struct obj_section *sec = f->sections[i];
2797
2798 if (sec->header.sh_flags & SHF_ALLOC)
2799 obj_insert_section_load_order(f, sec);
2800
2801 switch (sec->header.sh_type) {
2802 case SHT_SYMTAB:
2803 {
2804 unsigned long nsym, j;
2805 char *strtab;
2806 ElfW(Sym) * sym;
2807
2808 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002809 error_msg("symbol size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002810 (unsigned long) sec->header.sh_entsize,
2811 (unsigned long) sizeof(ElfW(Sym)));
2812 return NULL;
2813 }
2814
2815 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
2816 strtab = f->sections[sec->header.sh_link]->contents;
2817 sym = (ElfW(Sym) *) sec->contents;
2818
2819 /* Allocate space for a table of local symbols. */
2820 j = f->local_symtab_size = sec->header.sh_info;
2821 f->local_symtab = xmalloc(j *=
2822 sizeof(struct obj_symbol *));
2823 memset(f->local_symtab, 0, j);
2824
2825 /* Insert all symbols into the hash table. */
2826 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
2827 const char *name;
2828 if (sym->st_name)
2829 name = strtab + sym->st_name;
2830 else
2831 name = f->sections[sym->st_shndx]->name;
2832
2833 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
2834 sym->st_value, sym->st_size);
2835 }
2836 }
2837 break;
2838
2839 case SHT_RELM:
2840 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002841 error_msg("relocation entry size mismatch: %lu != %lu\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00002842 (unsigned long) sec->header.sh_entsize,
2843 (unsigned long) sizeof(ElfW(RelM)));
2844 return NULL;
2845 }
2846 break;
2847 }
2848 }
2849
2850 return f;
2851}
2852
2853static void hide_special_symbols(struct obj_file *f)
2854{
2855 static const char *const specials[] = {
2856 "cleanup_module",
2857 "init_module",
2858 "kernel_version",
2859 NULL
2860 };
2861
2862 struct obj_symbol *sym;
2863 const char *const *p;
2864
2865 for (p = specials; *p; ++p)
2866 if ((sym = obj_find_symbol(f, *p)) != NULL)
2867 sym->info =
2868 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
2869}
2870
2871
2872
2873extern int insmod_main( int argc, char **argv)
2874{
Eric Andersena18aaf12001-01-24 19:07:09 +00002875 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00002876 int k_crcs;
2877 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002878 int len;
2879 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002880 unsigned long m_size;
2881 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002882 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00002883 struct obj_file *f;
2884 char m_name[BUFSIZ + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00002885 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00002886 int m_has_modinfo;
2887#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2888 int k_version;
2889 char k_strversion[STRVERSIONLEN];
2890 char m_strversion[STRVERSIONLEN];
2891 int m_version;
2892 int m_crcs;
2893#endif
2894
Erik Andersene49d5ec2000-02-08 19:58:47 +00002895 /* Parse any options */
Eric Andersena18aaf12001-01-24 19:07:09 +00002896 while ((opt = getopt(argc, argv, "fkvxL")) > 0) {
2897 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002898 case 'f': /* force loading */
2899 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002900 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002901 case 'k': /* module loaded by kerneld, auto-cleanable */
2902 flag_autoclean = 1;
2903 break;
2904 case 'v': /* verbose output */
2905 flag_verbose = 1;
2906 break;
2907 case 'x': /* do not export externs */
2908 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002909 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00002910 case 'L': /* Stub warning */
2911 /* This is needed for compatibility with modprobe.
2912 * In theory, this does locking, but we don't do
2913 * that. So be careful and plan your life around not
2914 * loading the same module 50 times concurrently. */
2915 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002916 default:
2917 usage(insmod_usage);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002918 }
Erik Andersend387d011999-12-21 02:55:11 +00002919 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002920
2921 if (argv[optind] == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002922 usage(insmod_usage);
Eric Andersen9f16d612000-06-12 23:11:16 +00002923 }
Eric Andersena18aaf12001-01-24 19:07:09 +00002924
Erik Andersene49d5ec2000-02-08 19:58:47 +00002925 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00002926 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002927 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002928 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00002929 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00002931 len = strlen(tmp);
2932
2933 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
2934 len -= 2;
2935 memcpy(m_name, tmp, len);
2936 strcpy(m_fullName, m_name);
2937 strcat(m_fullName, ".o");
2938
2939 /* Get a filedesc for the module */
Eric Andersena18aaf12001-01-24 19:07:09 +00002940 if ((fp = fopen(argv[optind], "r")) == NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002941 /* Hmpf. Could not open it. Search through _PATH_MODULES to find a module named m_name */
Mark Whitleyf57c9442000-12-07 19:56:48 +00002942 if (recursive_action(_PATH_MODULES, TRUE, FALSE, FALSE,
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002943 findNamedModule, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002944 {
Erik Andersene49d5ec2000-02-08 19:58:47 +00002945 if (m_filename[0] == '\0'
Eric Andersen9f16d612000-06-12 23:11:16 +00002946 || ((fp = fopen(m_filename, "r")) == NULL))
2947 {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002948 error_msg("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Matt Kraai3e856ce2000-12-01 02:55:13 +00002949 return EXIT_FAILURE;
Erik Andersene49d5ec2000-02-08 19:58:47 +00002950 }
Matt Kraai0f8f7b82000-08-01 18:16:56 +00002951 } else
Mark Whitleyf57c9442000-12-07 19:56:48 +00002952 error_msg_and_die("No module named '%s' found in '%s'\n", m_fullName, _PATH_MODULES);
Erik Andersene49d5ec2000-02-08 19:58:47 +00002953 } else
Eric Andersena18aaf12001-01-24 19:07:09 +00002954 memcpy(m_filename, argv[optind], strlen(argv[optind]));
Erik Andersend387d011999-12-21 02:55:11 +00002955
2956
Matt Kraaia9819b22000-12-22 01:48:07 +00002957 if ((f = obj_load(fp)) == NULL)
2958 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00002959
Eric Andersen9f16d612000-06-12 23:11:16 +00002960 if (get_modinfo_value(f, "kernel_version") == NULL)
2961 m_has_modinfo = 0;
2962 else
2963 m_has_modinfo = 1;
2964
2965#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2966 /* Version correspondence? */
2967
2968 k_version = get_kernel_version(k_strversion);
2969 if (m_has_modinfo) {
2970 m_version = new_get_module_version(f, m_strversion);
2971 } else {
2972 m_version = old_get_module_version(f, m_strversion);
2973 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002974 error_msg("couldn't find the kernel version the module was "
Matt Kraaid537a952000-07-14 01:51:25 +00002975 "compiled for\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00002976 goto out;
2977 }
2978 }
2979
2980 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
2981 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002982 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002983 "\t%s was compiled for kernel version %s\n"
2984 "\twhile this kernel is version %s\n",
2985 m_filename, m_strversion, k_strversion);
2986 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002987 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00002988 "\t%s was compiled for kernel version %s\n"
2989 "\twhile this kernel is version %s.\n",
2990 m_filename, m_strversion, k_strversion);
2991 goto out;
2992 }
2993 }
2994 k_crcs = 0;
2995#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2996
2997 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
2998
2999 if (k_new_syscalls) {
3000#ifdef BB_FEATURE_INSMOD_NEW_KERNEL
3001 if (!new_get_kernel_symbols())
3002 goto out;
3003 k_crcs = new_is_kernel_checksummed();
3004#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003005 error_msg("Not configured to support new kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003006 goto out;
3007#endif
3008 } else {
3009#ifdef BB_FEATURE_INSMOD_OLD_KERNEL
Eric Andersen8c185f92000-09-22 00:38:07 +00003010 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003011 goto out;
3012 k_crcs = old_is_kernel_checksummed();
3013#else
Mark Whitleyf57c9442000-12-07 19:56:48 +00003014 error_msg("Not configured to support old kernels\n");
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 goto out;
3016#endif
3017 }
3018
3019#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3020 if (m_has_modinfo)
3021 m_crcs = new_is_module_checksummed(f);
3022 else
3023 m_crcs = old_is_module_checksummed(f);
3024
3025 if (m_crcs != k_crcs)
3026 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3027#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3028
Erik Andersene49d5ec2000-02-08 19:58:47 +00003029 /* Let the module know about the kernel symbols. */
3030 add_kernel_symbols(f);
3031
Eric Andersen9f16d612000-06-12 23:11:16 +00003032 /* Allocate common symbols, symbol tables, and string tables. */
3033
3034 if (k_new_syscalls
3035 ? !new_create_this_module(f, m_name)
3036 : !old_create_mod_use_count(f))
3037 {
3038 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003039 }
3040
Eric Andersen9f16d612000-06-12 23:11:16 +00003041 if (!obj_check_undefineds(f)) {
3042 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003043 }
3044 obj_allocate_commons(f);
3045
Eric Andersen9f16d612000-06-12 23:11:16 +00003046 if (optind < argc) {
3047 if (m_has_modinfo
3048 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3049 : !old_process_module_arguments(f, argc - optind, argv + optind))
3050 {
3051 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003052 }
3053 }
3054
Eric Andersen9f16d612000-06-12 23:11:16 +00003055 arch_create_got(f);
3056 hide_special_symbols(f);
3057
3058 if (k_new_syscalls)
3059 new_create_module_ksymtab(f);
3060
Erik Andersene49d5ec2000-02-08 19:58:47 +00003061 /* Find current size of the module */
3062 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003063
3064
Erik Andersene49d5ec2000-02-08 19:58:47 +00003065 errno = 0;
3066 m_addr = create_module(m_name, m_size);
3067 switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003068 case 0:
3069 break;
3070 case EEXIST:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003071 error_msg("A module named %s already exists\n", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003072 goto out;
3073 case ENOMEM:
Mark Whitleyf57c9442000-12-07 19:56:48 +00003074 error_msg("Can't allocate kernel memory for module; needed %lu bytes\n",
Eric Andersen9f16d612000-06-12 23:11:16 +00003075 m_size);
3076 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003077 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003078 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003079 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003080 }
Erik Andersend387d011999-12-21 02:55:11 +00003081
Eric Andersen9f16d612000-06-12 23:11:16 +00003082 if (!obj_relocate(f, m_addr)) {
3083 delete_module(m_name);
3084 goto out;
3085 }
Erik Andersend387d011999-12-21 02:55:11 +00003086
Eric Andersen9f16d612000-06-12 23:11:16 +00003087 if (k_new_syscalls
3088 ? !new_init_module(m_name, f, m_size)
3089 : !old_init_module(m_name, f, m_size))
3090 {
3091 delete_module(m_name);
3092 goto out;
3093 }
3094
Matt Kraai3e856ce2000-12-01 02:55:13 +00003095 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003096
3097out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003098 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003099 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003100}