blob: 1a63ecb2ac0cb7a2bf417a65ec8cbe31eeb47ca3 [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
Eric Andersen2835efe2001-07-25 16:58:58 +00004 *
5 * This version of insmod supports x86, ARM, SH3/4, powerpc, m68k,
6 * and MIPS.
7 *
Erik Andersen02104321999-12-17 18:57:34 +00008 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00009 * Copyright (C) 1999,2000,2001 by Lineo, inc.
Eric Andersen9f16d612000-06-12 23:11:16 +000010 * Written by Erik Andersen <andersen@lineo.com>
11 * and Ron Alder <alder@lineo.com>
12 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000013 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000014 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
15 *
16 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
17 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
18 * very minor changes required to also work with StrongArm and presumably
19 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000020 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000021 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
22 * PowerPC specific code stolen from modutils-2.3.16,
23 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
24 * I've only tested the code on mpc8xx platforms in big-endian mode.
25 * Did some cleanup and added BB_USE_xxx_ENTRIES...
26 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000027 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
28 * based on modutils-2.4.2
29 * MIPS specific support for Elf loading and relocation.
30 * Copyright 1996, 1997 Linux International.
31 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
32 *
Eric Andersen9f16d612000-06-12 23:11:16 +000033 * Based almost entirely on the Linux modutils-2.3.11 implementation.
34 * Copyright 1996, 1997 Linux International.
35 * New implementation contributed by Richard Henderson <rth@tamu.edu>
36 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
37 * Restructured (and partly rewritten) by:
38 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000039 *
40 * This program is free software; you can redistribute it and/or modify
41 * it under the terms of the GNU General Public License as published by
42 * the Free Software Foundation; either version 2 of the License, or
43 * (at your option) any later version.
44 *
45 * This program is distributed in the hope that it will be useful,
46 * but WITHOUT ANY WARRANTY; without even the implied warranty of
47 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
48 * General Public License for more details.
49 *
50 * You should have received a copy of the GNU General Public License
51 * along with this program; if not, write to the Free Software
52 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
53 *
54 */
55
Erik Andersen02104321999-12-17 18:57:34 +000056#include <stdlib.h>
57#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000058#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000059#include <errno.h>
60#include <unistd.h>
61#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000062#include <ctype.h>
63#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000064#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000065#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000066#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000067#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000068
Eric Andersen64c8b172001-04-05 07:33:10 +000069#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
70# define new_sys_init_module init_module
71#else
72# define old_sys_init_module init_module
73#endif
74
Eric Andersen8ae319a2001-05-21 16:09:18 +000075#ifdef BB_FEATURE_INSMOD_LOADINKMEM
76#define LOADBITS 0
77#else
78#define LOADBITS 1
79#endif
80
Eric Andersen90fe7fe2001-02-20 20:47:08 +000081#if defined(__powerpc__)
82#define BB_USE_PLT_ENTRIES
83#define BB_PLT_ENTRY_SIZE 16
84#endif
85
86#if defined(__arm__)
87#define BB_USE_PLT_ENTRIES
88#define BB_PLT_ENTRY_SIZE 8
89#define BB_USE_GOT_ENTRIES
90#define BB_GOT_ENTRY_SIZE 8
91#endif
92
93#if defined(__sh__)
94#define BB_USE_GOT_ENTRIES
95#define BB_GOT_ENTRY_SIZE 4
96#endif
97
98#if defined(__i386__)
99#define BB_USE_GOT_ENTRIES
100#define BB_GOT_ENTRY_SIZE 4
101#endif
102
Eric Andersen2bf658d2001-02-24 20:01:53 +0000103#if defined(__mips__)
104// neither used
105#endif
106
Eric Andersen9f16d612000-06-12 23:11:16 +0000107//----------------------------------------------------------------------------
108//--------modutils module.h, lines 45-242
109//----------------------------------------------------------------------------
110
111/* Definitions for the Linux module syscall interface.
112 Copyright 1996, 1997 Linux International.
113
114 Contributed by Richard Henderson <rth@tamu.edu>
115
116 This file is part of the Linux modutils.
117
118 This program is free software; you can redistribute it and/or modify it
119 under the terms of the GNU General Public License as published by the
120 Free Software Foundation; either version 2 of the License, or (at your
121 option) any later version.
122
123 This program is distributed in the hope that it will be useful, but
124 WITHOUT ANY WARRANTY; without even the implied warranty of
125 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
126 General Public License for more details.
127
128 You should have received a copy of the GNU General Public License
129 along with this program; if not, write to the Free Software Foundation,
130 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
131
132
133#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000134static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000135
Eric Andersenf672c9e2001-07-31 22:51:49 +0000136#ident "$Id: insmod.c,v 1.70 2001/07/31 22:51:49 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000137
138/* This file contains the structures used by the 2.0 and 2.1 kernels.
139 We do not use the kernel headers directly because we do not wish
140 to be dependant on a particular kernel version to compile insmod. */
141
142
143/*======================================================================*/
144/* The structures used by Linux 2.0. */
145
146/* The symbol format used by get_kernel_syms(2). */
147struct old_kernel_sym
148{
149 unsigned long value;
150 char name[60];
151};
152
153struct old_module_ref
154{
155 unsigned long module; /* kernel addresses */
156 unsigned long next;
157};
158
159struct old_module_symbol
160{
161 unsigned long addr;
162 unsigned long name;
163};
164
165struct old_symbol_table
166{
167 int size; /* total, including string table!!! */
168 int n_symbols;
169 int n_refs;
170 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
171 struct old_module_ref ref[0]; /* actual size defined by n_refs */
172};
173
174struct old_mod_routines
175{
176 unsigned long init;
177 unsigned long cleanup;
178};
179
180struct old_module
181{
182 unsigned long next;
183 unsigned long ref; /* the list of modules that refer to me */
184 unsigned long symtab;
185 unsigned long name;
186 int size; /* size of module in pages */
187 unsigned long addr; /* address of module */
188 int state;
189 unsigned long cleanup; /* cleanup routine */
190};
191
192/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000193static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000194
195int get_kernel_syms(struct old_kernel_sym *);
196int old_sys_init_module(const char *name, char *code, unsigned codesize,
197 struct old_mod_routines *, struct old_symbol_table *);
198
199/*======================================================================*/
200/* For sizeof() which are related to the module platform and not to the
201 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
202
203#define tgt_sizeof_char sizeof(char)
204#define tgt_sizeof_short sizeof(short)
205#define tgt_sizeof_int sizeof(int)
206#define tgt_sizeof_long sizeof(long)
207#define tgt_sizeof_char_p sizeof(char *)
208#define tgt_sizeof_void_p sizeof(void *)
209#define tgt_long long
210
211#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
212#undef tgt_sizeof_long
213#undef tgt_sizeof_char_p
214#undef tgt_sizeof_void_p
215#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000216static const int tgt_sizeof_long = 8;
217static const int tgt_sizeof_char_p = 8;
218static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000219#define tgt_long long long
220#endif
221
222/*======================================================================*/
223/* The structures used in Linux 2.1. */
224
225/* Note: new_module_symbol does not use tgt_long intentionally */
226struct new_module_symbol
227{
228 unsigned long value;
229 unsigned long name;
230};
231
232struct new_module_persist;
233
234struct new_module_ref
235{
236 unsigned tgt_long dep; /* kernel addresses */
237 unsigned tgt_long ref;
238 unsigned tgt_long next_ref;
239};
240
241struct new_module
242{
243 unsigned tgt_long size_of_struct; /* == sizeof(module) */
244 unsigned tgt_long next;
245 unsigned tgt_long name;
246 unsigned tgt_long size;
247
248 tgt_long usecount;
249 unsigned tgt_long flags; /* AUTOCLEAN et al */
250
251 unsigned nsyms;
252 unsigned ndeps;
253
254 unsigned tgt_long syms;
255 unsigned tgt_long deps;
256 unsigned tgt_long refs;
257 unsigned tgt_long init;
258 unsigned tgt_long cleanup;
259 unsigned tgt_long ex_table_start;
260 unsigned tgt_long ex_table_end;
261#ifdef __alpha__
262 unsigned tgt_long gp;
263#endif
264 /* Everything after here is extension. */
265 unsigned tgt_long persist_start;
266 unsigned tgt_long persist_end;
267 unsigned tgt_long can_unload;
268 unsigned tgt_long runsize;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000269#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
270 const char *kallsyms_start; /* All symbols for kernel debugging */
271 const char *kallsyms_end;
272 const char *archdata_start; /* arch specific data for module */
273 const char *archdata_end;
274 const char *kernel_data; /* Reserved for kernel internal use */
275#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000276};
277
Eric Andersen8ae319a2001-05-21 16:09:18 +0000278#define ARCHDATA_SEC_NAME "__archdata"
279#define KALLSYMS_SEC_NAME "__kallsyms"
280
281
Eric Andersen9f16d612000-06-12 23:11:16 +0000282struct new_module_info
283{
284 unsigned long addr;
285 unsigned long size;
286 unsigned long flags;
287 long usecount;
288};
289
290/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000291static const int NEW_MOD_RUNNING = 1;
292static const int NEW_MOD_DELETED = 2;
293static const int NEW_MOD_AUTOCLEAN = 4;
294static const int NEW_MOD_VISITED = 8;
295static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000296
Eric Andersen64c8b172001-04-05 07:33:10 +0000297int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000298int query_module(const char *name, int which, void *buf, size_t bufsize,
299 size_t *ret);
300
301/* Values for query_module's which. */
302
Mark Whitley59ab0252001-01-23 22:30:04 +0000303static const int QM_MODULES = 1;
304static const int QM_DEPS = 2;
305static const int QM_REFS = 3;
306static const int QM_SYMBOLS = 4;
307static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000308
309/*======================================================================*/
310/* The system calls unchanged between 2.0 and 2.1. */
311
312unsigned long create_module(const char *, size_t);
313int delete_module(const char *);
314
315
316#endif /* module.h */
317
318//----------------------------------------------------------------------------
319//--------end of modutils module.h
320//----------------------------------------------------------------------------
321
322
323
324//----------------------------------------------------------------------------
325//--------modutils obj.h, lines 253-462
326//----------------------------------------------------------------------------
327
328/* Elf object file loading and relocation routines.
329 Copyright 1996, 1997 Linux International.
330
331 Contributed by Richard Henderson <rth@tamu.edu>
332
333 This file is part of the Linux modutils.
334
335 This program is free software; you can redistribute it and/or modify it
336 under the terms of the GNU General Public License as published by the
337 Free Software Foundation; either version 2 of the License, or (at your
338 option) any later version.
339
340 This program is distributed in the hope that it will be useful, but
341 WITHOUT ANY WARRANTY; without even the implied warranty of
342 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
343 General Public License for more details.
344
345 You should have received a copy of the GNU General Public License
346 along with this program; if not, write to the Free Software Foundation,
347 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
348
349
350#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000351static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000352
Eric Andersenf672c9e2001-07-31 22:51:49 +0000353#ident "$Id: insmod.c,v 1.70 2001/07/31 22:51:49 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000354
355/* The relocatable object is manipulated using elfin types. */
356
357#include <stdio.h>
358#include <elf.h>
359
360
361/* Machine-specific elf macros for i386 et al. */
362
Eric Andersenfe4208f2000-09-24 03:44:29 +0000363/* the SH changes have only been tested on the SH4 in =little endian= mode */
364/* I'm not sure about big endian, so let's warn: */
365
366#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
367#error insmod.c may require changes for use on big endian SH4/SH3
368#endif
369
370/* it may or may not work on the SH1/SH2... So let's error on those
371 also */
372#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
373#error insmod.c may require changes for non-SH3/SH4 use
374#endif
375
Eric Andersen9f16d612000-06-12 23:11:16 +0000376#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000377
Eric Andersenb4a26e62001-06-19 15:00:52 +0000378#if (defined(__mc68000__))
Eric Andersen8ae319a2001-05-21 16:09:18 +0000379#define ELFDATAM ELFDATA2MSB
Eric Andersen8ae319a2001-05-21 16:09:18 +0000380#endif
381
382
383
Eric Andersenfe4208f2000-09-24 03:44:29 +0000384#if defined(__sh__)
385
386#define MATCH_MACHINE(x) (x == EM_SH)
387#define SHT_RELM SHT_RELA
388#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000389#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000390
Eric Andersen21adca72000-12-06 18:18:26 +0000391#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000392
Eric Andersen21adca72000-12-06 18:18:26 +0000393#define MATCH_MACHINE(x) (x == EM_ARM)
394#define SHT_RELM SHT_REL
395#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000396#define ELFDATAM ELFDATA2LSB
397
398#elif defined(__powerpc__)
399
400#define MATCH_MACHINE(x) (x == EM_PPC)
401#define SHT_RELM SHT_RELA
402#define Elf32_RelM Elf32_Rela
Eric Andersen5a9d4412001-05-24 14:16:28 +0000403#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000404
Eric Andersen2bf658d2001-02-24 20:01:53 +0000405#elif defined(__mips__)
406
Eric Andersen82bb8a22001-03-22 19:01:16 +0000407/* Account for ELF spec changes. */
408#ifndef EM_MIPS_RS3_LE
409#ifdef EM_MIPS_RS4_BE
410#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
411#else
412#define EM_MIPS_RS3_LE 10
413#endif
414#endif /* !EM_MIPS_RS3_LE */
415
Eric Andersen2bf658d2001-02-24 20:01:53 +0000416#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
417#define SHT_RELM SHT_REL
418#define Elf32_RelM Elf32_Rel
419#ifdef __MIPSEB__
420#define ELFDATAM ELFDATA2MSB
421#endif
422#ifdef __MIPSEL__
423#define ELFDATAM ELFDATA2LSB
424#endif
425
Eric Andersen21adca72000-12-06 18:18:26 +0000426#elif defined(__i386__)
427
428/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000429/* this is the previous behavior, but it does result in
430 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000431#ifndef EM_486
432#define MATCH_MACHINE(x) (x == EM_386)
433#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000434#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000435#endif
436
Eric Andersen9f16d612000-06-12 23:11:16 +0000437#define SHT_RELM SHT_REL
438#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000439#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersenb4a26e62001-06-19 15:00:52 +0000441#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000442
443#define MATCH_MACHINE(x) (x == EM_68K)
444#define SHT_RELM SHT_RELA
445#define Elf32_RelM Elf32_Rela
446
Eric Andersen21adca72000-12-06 18:18:26 +0000447#else
Eric Andersend5cad142001-01-26 02:23:57 +0000448#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000449#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000450
451#ifndef ElfW
452# if ELFCLASSM == ELFCLASS32
453# define ElfW(x) Elf32_ ## x
454# define ELFW(x) ELF32_ ## x
455# else
456# define ElfW(x) Elf64_ ## x
457# define ELFW(x) ELF64_ ## x
458# endif
459#endif
460
461/* For some reason this is missing from libc5. */
462#ifndef ELF32_ST_INFO
463# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
464#endif
465
466#ifndef ELF64_ST_INFO
467# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
468#endif
469
470struct obj_string_patch;
471struct obj_symbol_patch;
472
473struct obj_section
474{
475 ElfW(Shdr) header;
476 const char *name;
477 char *contents;
478 struct obj_section *load_next;
479 int idx;
480};
481
482struct obj_symbol
483{
484 struct obj_symbol *next; /* hash table link */
485 const char *name;
486 unsigned long value;
487 unsigned long size;
488 int secidx; /* the defining section index/module */
489 int info;
490 int ksymidx; /* for export to the kernel symtab */
491 int referenced; /* actually used in the link */
492};
493
494/* Hardcode the hash table size. We shouldn't be needing so many
495 symbols that we begin to degrade performance, and we get a big win
496 by giving the compiler a constant divisor. */
497
498#define HASH_BUCKETS 521
499
500struct obj_file
501{
502 ElfW(Ehdr) header;
503 ElfW(Addr) baseaddr;
504 struct obj_section **sections;
505 struct obj_section *load_order;
506 struct obj_section **load_order_search_start;
507 struct obj_string_patch *string_patches;
508 struct obj_symbol_patch *symbol_patches;
509 int (*symbol_cmp)(const char *, const char *);
510 unsigned long (*symbol_hash)(const char *);
511 unsigned long local_symtab_size;
512 struct obj_symbol **local_symtab;
513 struct obj_symbol *symtab[HASH_BUCKETS];
514};
515
516enum obj_reloc
517{
518 obj_reloc_ok,
519 obj_reloc_overflow,
520 obj_reloc_dangerous,
521 obj_reloc_unhandled
522};
523
524struct obj_string_patch
525{
526 struct obj_string_patch *next;
527 int reloc_secidx;
528 ElfW(Addr) reloc_offset;
529 ElfW(Addr) string_offset;
530};
531
532struct obj_symbol_patch
533{
534 struct obj_symbol_patch *next;
535 int reloc_secidx;
536 ElfW(Addr) reloc_offset;
537 struct obj_symbol *sym;
538};
539
540
541/* Generic object manipulation routines. */
542
Eric Andersen044228d2001-07-17 01:12:36 +0000543static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000544
Eric Andersen044228d2001-07-17 01:12:36 +0000545static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000546
Eric Andersen044228d2001-07-17 01:12:36 +0000547static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000548 const char *name);
549
Eric Andersen044228d2001-07-17 01:12:36 +0000550static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000551 struct obj_symbol *sym);
552
Eric Andersenf672c9e2001-07-31 22:51:49 +0000553#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000554static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000555 int (*cmp)(const char *, const char *),
556 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000557#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000558
Eric Andersen044228d2001-07-17 01:12:36 +0000559static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000560 const char *name);
561
Eric Andersen044228d2001-07-17 01:12:36 +0000562static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000563 struct obj_section *sec);
564
Eric Andersen044228d2001-07-17 01:12:36 +0000565static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000566 const char *name,
567 unsigned long align,
568 unsigned long size);
569
Eric Andersen044228d2001-07-17 01:12:36 +0000570static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000571 const char *name,
572 unsigned long align,
573 unsigned long size);
574
Eric Andersen044228d2001-07-17 01:12:36 +0000575static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000576
Eric Andersen044228d2001-07-17 01:12:36 +0000577static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000578 const char *string);
579
Eric Andersen044228d2001-07-17 01:12:36 +0000580static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000581 struct obj_symbol *sym);
582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000584
Eric Andersen044228d2001-07-17 01:12:36 +0000585static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000586
Eric Andersen044228d2001-07-17 01:12:36 +0000587static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000588
Eric Andersen044228d2001-07-17 01:12:36 +0000589static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000590
Eric Andersen044228d2001-07-17 01:12:36 +0000591static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000592
Eric Andersen044228d2001-07-17 01:12:36 +0000593static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000594
595/* Architecture specific manipulation routines. */
596
Eric Andersen044228d2001-07-17 01:12:36 +0000597static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000602
Eric Andersen044228d2001-07-17 01:12:36 +0000603static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000604 struct obj_section *targsec,
605 struct obj_section *symsec,
606 struct obj_symbol *sym,
607 ElfW(RelM) *rel, ElfW(Addr) value);
608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static int arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000612
613#endif /* obj.h */
614//----------------------------------------------------------------------------
615//--------end of modutils obj.h
616//----------------------------------------------------------------------------
617
618
619
620
Erik Andersen02104321999-12-17 18:57:34 +0000621
Erik Andersend387d011999-12-21 02:55:11 +0000622#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000623static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000624
Eric Andersen9f16d612000-06-12 23:11:16 +0000625/*======================================================================*/
626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static int flag_force_load = 0;
628static int flag_autoclean = 0;
629static int flag_verbose = 0;
630static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000631
632
633/*======================================================================*/
634
Eric Andersenfe4208f2000-09-24 03:44:29 +0000635/* previously, these were named i386_* but since we could be
636 compiling for the sh, I've renamed them to the more general
637 arch_* These structures are the same between the x86 and SH,
638 and we can't support anything else right now anyway. In the
639 future maybe they should be #if defined'd */
640
Eric Andersen21adca72000-12-06 18:18:26 +0000641/* Done ;-) */
642
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000643
644
645#if defined(BB_USE_PLT_ENTRIES)
646struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000647{
648 int offset;
649 int allocated:1;
650 int inited:1; /* has been set up */
651};
652#endif
653
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000654#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000655struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 int offset;
657 unsigned offset_done:1;
658 unsigned reloc_done:1;
659};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000660#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen2bf658d2001-02-24 20:01:53 +0000662#if defined(__mips__)
663struct mips_hi16
664{
665 struct mips_hi16 *next;
666 Elf32_Addr *addr;
667 Elf32_Addr value;
668};
669#endif
670
Eric Andersenfe4208f2000-09-24 03:44:29 +0000671struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000672 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000673#if defined(BB_USE_PLT_ENTRIES)
674 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000675#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000676#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000677 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000678#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000679#if defined(__mips__)
680 struct mips_hi16 *mips_hi16_list;
681#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000682};
683
Eric Andersenfe4208f2000-09-24 03:44:29 +0000684struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000685 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000686#if defined(BB_USE_PLT_ENTRIES)
687 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000688#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000689#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000690 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000691#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000692};
693
694
Eric Andersen9f16d612000-06-12 23:11:16 +0000695struct external_module {
696 const char *name;
697 ElfW(Addr) addr;
698 int used;
699 size_t nsyms;
700 struct new_module_symbol *syms;
701};
702
Eric Andersen044228d2001-07-17 01:12:36 +0000703static struct new_module_symbol *ksyms;
704static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000705
Eric Andersen044228d2001-07-17 01:12:36 +0000706static struct external_module *ext_modules;
707static int n_ext_modules;
708static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000709extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000710
Eric Andersen14d35432001-05-14 17:07:32 +0000711static char m_filename[FILENAME_MAX + 1];
712static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000713
Eric Andersenfe4208f2000-09-24 03:44:29 +0000714
Erik Andersen02104321999-12-17 18:57:34 +0000715
Eric Andersen9f16d612000-06-12 23:11:16 +0000716/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000717
Eric Andersen9f16d612000-06-12 23:11:16 +0000718
Eric Andersen14d35432001-05-14 17:07:32 +0000719static int check_module_name_match(const char *filename, struct stat *statbuf,
720 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000721{
Eric Andersen14d35432001-05-14 17:07:32 +0000722 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000723
Eric Andersen14d35432001-05-14 17:07:32 +0000724 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000725 return (FALSE);
726 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000727 char *tmp, *tmp1 = strdup(filename);
728 tmp = get_last_path_component(tmp1);
729 if (strcmp(tmp, fullname) == 0) {
730 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000731 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000732 safe_strncpy(m_filename, filename, sizeof(m_filename));
733 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000734 }
Eric Andersen14d35432001-05-14 17:07:32 +0000735 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000736 }
Eric Andersen14d35432001-05-14 17:07:32 +0000737 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000738}
739
Erik Andersen02104321999-12-17 18:57:34 +0000740
Eric Andersen9f16d612000-06-12 23:11:16 +0000741/*======================================================================*/
742
Eric Andersen044228d2001-07-17 01:12:36 +0000743static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000744{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000745 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000747
748#if defined(BB_USE_PLT_ENTRIES)
749 f->plt = NULL;
750#endif
751#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000752 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000753#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000754#if defined(__mips__)
755 f->mips_hi16_list = NULL;
756#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000757
Eric Andersen9f16d612000-06-12 23:11:16 +0000758 return &f->root;
759}
760
Eric Andersen044228d2001-07-17 01:12:36 +0000761static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000762{
763 return xmalloc(sizeof(struct obj_section));
764}
765
Eric Andersen044228d2001-07-17 01:12:36 +0000766static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000767{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000768 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000769 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000770
771#if defined(BB_USE_PLT_ENTRIES)
772 memset(&sym->pltent, 0, sizeof(sym->pltent));
773#endif
774#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000775 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000776#endif
777
Eric Andersen9f16d612000-06-12 23:11:16 +0000778 return &sym->root;
779}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000780
Eric Andersen044228d2001-07-17 01:12:36 +0000781static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000782arch_apply_relocation(struct obj_file *f,
783 struct obj_section *targsec,
784 struct obj_section *symsec,
785 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000786 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000787{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000788 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000789#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000791#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000792
Eric Andersen21adca72000-12-06 18:18:26 +0000793 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
794 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000795#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000796 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000797#endif
798#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000799 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000800 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000801 unsigned long *ip;
802#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000803 enum obj_reloc ret = obj_reloc_ok;
804
805 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000806
807/* even though these constants seem to be the same for
808 the i386 and the sh, we "#if define" them for clarity
809 and in case that ever changes */
810#if defined(__sh__)
811 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000812#elif defined(__arm__)
813 case R_ARM_NONE:
814#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000815 case R_386_NONE:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000816#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000817 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000818#elif defined(__powerpc__)
819 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000820#elif defined(__mips__)
821 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000822#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000823 break;
824
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825#if defined(__sh__)
826 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000827#elif defined(__arm__)
828 case R_ARM_ABS32:
829#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830 case R_386_32:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000831#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000832 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833#elif defined(__powerpc__)
834 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000835#elif defined(__mips__)
836 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000837#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000838 *loc += v;
839 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000840#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000841 case R_68K_8:
842 if (v > 0xff)
843 ret = obj_reloc_overflow;
844 *(char *)loc = v;
845 break;
846 case R_68K_16:
847 if (v > 0xffff)
848 ret = obj_reloc_overflow;
849 *(short *)loc = v;
850 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000851#endif /* __mc68000__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000852
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000853#if defined(__powerpc__)
854 case R_PPC_ADDR16_HA:
855 *(unsigned short *)loc = (v + 0x8000) >> 16;
856 break;
857
858 case R_PPC_ADDR16_HI:
859 *(unsigned short *)loc = v >> 16;
860 break;
861
862 case R_PPC_ADDR16_LO:
863 *(unsigned short *)loc = v;
864 break;
865#endif
866
Eric Andersen2bf658d2001-02-24 20:01:53 +0000867#if defined(__mips__)
868 case R_MIPS_26:
869 if (v % 4)
870 ret = obj_reloc_dangerous;
871 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
872 ret = obj_reloc_overflow;
873 *loc =
874 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
875 0x03ffffff);
876 break;
877
878 case R_MIPS_HI16:
879 {
880 struct mips_hi16 *n;
881
882 /* We cannot relocate this one now because we don't know the value
883 of the carry we need to add. Save the information, and let LO16
884 do the actual relocation. */
885 n = (struct mips_hi16 *) xmalloc(sizeof *n);
886 n->addr = loc;
887 n->value = v;
888 n->next = ifile->mips_hi16_list;
889 ifile->mips_hi16_list = n;
890 break;
891 }
892
893 case R_MIPS_LO16:
894 {
895 unsigned long insnlo = *loc;
896 Elf32_Addr val, vallo;
897
898 /* Sign extend the addend we extract from the lo insn. */
899 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
900
901 if (ifile->mips_hi16_list != NULL) {
902 struct mips_hi16 *l;
903
904 l = ifile->mips_hi16_list;
905 while (l != NULL) {
906 struct mips_hi16 *next;
907 unsigned long insn;
908
909 /* The value for the HI16 had best be the same. */
910 assert(v == l->value);
911
912 /* Do the HI16 relocation. Note that we actually don't
913 need to know anything about the LO16 itself, except where
914 to find the low 16 bits of the addend needed by the LO16. */
915 insn = *l->addr;
916 val =
917 ((insn & 0xffff) << 16) +
918 vallo;
919 val += v;
920
921 /* Account for the sign extension that will happen in the
922 low bits. */
923 val =
924 ((val >> 16) +
925 ((val & 0x8000) !=
926 0)) & 0xffff;
927
928 insn = (insn & ~0xffff) | val;
929 *l->addr = insn;
930
931 next = l->next;
932 free(l);
933 l = next;
934 }
935
936 ifile->mips_hi16_list = NULL;
937 }
938
939 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
940 val = v + vallo;
941 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
942 *loc = insnlo;
943 break;
944 }
945#endif
946
Eric Andersen21adca72000-12-06 18:18:26 +0000947#if defined(__arm__)
948#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000949 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000950 *loc += v - dot;
951 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000952#elif defined(__i386__)
953 case R_386_PLT32:
954 case R_386_PC32:
955 *loc += v - dot;
956 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000957#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000958 case R_68K_PC8:
959 v -= dot;
960 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
961 ret = obj_reloc_overflow;
962 *(char *)loc = v;
963 break;
964 case R_68K_PC16:
965 v -= dot;
966 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
967 ret = obj_reloc_overflow;
968 *(short *)loc = v;
969 break;
970 case R_68K_PC32:
971 *(int *)loc = v - dot;
972 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000973#elif defined(__powerpc__)
974 case R_PPC_REL32:
975 *loc = v - dot;
976 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000977#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000978
Eric Andersenfe4208f2000-09-24 03:44:29 +0000979#if defined(__sh__)
980 case R_SH_PLT32:
981 *loc = v - dot;
982 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000983#elif defined(__i386__)
984#endif
985
986#if defined(BB_USE_PLT_ENTRIES)
987
988#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000989 case R_ARM_PC24:
990 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000991#endif
992#if defined(__powerpc__)
993 case R_PPC_REL24:
994#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000995 /* find the plt entry and initialize it if necessary */
996 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000997
998 pe = (struct arch_plt_entry*) &isym->pltent;
999
Eric Andersen21adca72000-12-06 18:18:26 +00001000 if (! pe->inited) {
1001 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001002
1003 /* generate some machine code */
1004
1005#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001006 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1007 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001008#endif
1009#if defined(__powerpc__)
1010 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1011 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1012 ip[2] = 0x7d6903a6; /* mtctr r11 */
1013 ip[3] = 0x4e800420; /* bctr */
1014#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001015 pe->inited = 1;
1016 }
1017
1018 /* relative distance to target */
1019 v -= dot;
1020 /* if the target is too far away.... */
1021 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1022 /* go via the plt */
1023 v = plt + pe->offset - dot;
1024 }
1025 if (v & 3)
1026 ret = obj_reloc_dangerous;
1027
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001028 /* merge the offset into the instruction. */
1029#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001030 /* Convert to words. */
1031 v >>= 2;
1032
Eric Andersen21adca72000-12-06 18:18:26 +00001033 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001034#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001035#if defined(__powerpc__)
1036 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1037#endif
1038 break;
1039#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001040
Eric Andersen21adca72000-12-06 18:18:26 +00001041#if defined(__arm__)
1042#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001043 case R_SH_GLOB_DAT:
1044 case R_SH_JMP_SLOT:
1045 *loc = v;
1046 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001047#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001048 case R_386_GLOB_DAT:
1049 case R_386_JMP_SLOT:
1050 *loc = v;
1051 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001052#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001053 case R_68K_GLOB_DAT:
1054 case R_68K_JMP_SLOT:
1055 *loc = v;
1056 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001058
Eric Andersen21adca72000-12-06 18:18:26 +00001059#if defined(__arm__)
1060#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001061 case R_SH_RELATIVE:
1062 *loc += f->baseaddr + rel->r_addend;
1063 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001064#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001065 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001066 *loc += f->baseaddr;
1067 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001068#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001069 case R_68K_RELATIVE:
1070 *(int *)loc += f->baseaddr;
1071 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001072#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001073
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001074#if defined(BB_USE_GOT_ENTRIES)
1075
Eric Andersen8ae319a2001-05-21 16:09:18 +00001076#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001077#if defined(__sh__)
1078 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001079#elif defined(__arm__)
1080 case R_ARM_GOTPC:
1081#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001082 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001083#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001084 assert(got != 0);
1085#if defined(__sh__)
1086 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001087#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001088 *loc += got - dot;
1089#endif
1090 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001091#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001092
Eric Andersenfe4208f2000-09-24 03:44:29 +00001093#if defined(__sh__)
1094 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001095#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001096 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001097#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001098 case R_386_GOT32:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001099#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001100 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001101#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001102 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001103 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001104 if (!isym->gotent.reloc_done) {
1105 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001106 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001107 }
Eric Andersen21adca72000-12-06 18:18:26 +00001108 /* make the reloc with_respect_to_.got */
1109#if defined(__sh__)
1110 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001111#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001112 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001113#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001114 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001115
Eric Andersen21adca72000-12-06 18:18:26 +00001116 /* address relative to the got */
Eric Andersenb4a26e62001-06-19 15:00:52 +00001117#if !defined(__mc68000__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001118#if defined(__sh__)
1119 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001120#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001121 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001122#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001123 case R_386_GOTOFF:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001124#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001125 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001126#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001127 assert(got != 0);
1128 *loc += v - got;
1129 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001130#endif // __mc68000__
Eric Andersen9f16d612000-06-12 23:11:16 +00001131
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001132#endif /* BB_USE_GOT_ENTRIES */
1133
Eric Andersen9f16d612000-06-12 23:11:16 +00001134 default:
Eric Andersen21125542000-12-13 16:41:29 +00001135 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001136 ret = obj_reloc_unhandled;
1137 break;
1138 }
1139
1140 return ret;
1141}
1142
Eric Andersen044228d2001-07-17 01:12:36 +00001143static int arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001144{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001145#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001146 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001147 int i;
1148#if defined(BB_USE_GOT_ENTRIES)
1149 int got_offset = 0, gotneeded = 0;
1150#endif
1151#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001152 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001153#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001154 struct obj_section *relsec, *symsec, *strsec;
1155 ElfW(RelM) *rel, *relend;
1156 ElfW(Sym) *symtab, *extsym;
1157 const char *strtab, *name;
1158 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001159
Eric Andersen21adca72000-12-06 18:18:26 +00001160 for (i = 0; i < f->header.e_shnum; ++i) {
1161 relsec = f->sections[i];
1162 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001163 continue;
1164
Eric Andersen21adca72000-12-06 18:18:26 +00001165 symsec = f->sections[relsec->header.sh_link];
1166 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001167
Eric Andersen21adca72000-12-06 18:18:26 +00001168 rel = (ElfW(RelM) *) relsec->contents;
1169 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1170 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001171 strtab = (const char *) strsec->contents;
1172
1173 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001174 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001175
1176 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001177#if defined(__arm__)
1178 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001179 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001180#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001181 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001182 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001183#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001184 case R_386_GOT32:
1185 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001186#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001187 case R_68K_GOT32:
1188 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001189#endif
1190
1191#if defined(__powerpc__)
1192 case R_PPC_REL24:
1193 pltneeded = 1;
1194 break;
1195#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001196
1197#if defined(__arm__)
1198 case R_ARM_PC24:
1199 case R_ARM_PLT32:
1200 pltneeded = 1;
1201 break;
1202
1203 case R_ARM_GOTPC:
1204 case R_ARM_GOTOFF:
1205 gotneeded = 1;
1206 if (got_offset == 0)
1207 got_offset = 4;
1208#elif defined(__sh__)
1209 case R_SH_GOTPC:
1210 case R_SH_GOTOFF:
1211 gotneeded = 1;
1212#elif defined(__i386__)
1213 case R_386_GOTPC:
1214 case R_386_GOTOFF:
1215 gotneeded = 1;
1216#endif
1217
1218 default:
1219 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001220 }
1221
Eric Andersen21adca72000-12-06 18:18:26 +00001222 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001223 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001224 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001225 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001226 }
1227 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001228#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001229 if (!intsym->gotent.offset_done) {
1230 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001231 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001232 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001233 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001234#endif
1235#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001236 if (pltneeded && intsym->pltent.allocated == 0) {
1237 intsym->pltent.allocated = 1;
1238 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001239 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001240 intsym->pltent.inited = 0;
1241 pltneeded = 0;
1242 }
1243#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001244 }
1245 }
Eric Andersen21adca72000-12-06 18:18:26 +00001246
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001247#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001248 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001249 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001250
Eric Andersene76c3b02001-04-05 03:14:39 +00001251 if (myrelsec) {
1252 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001253 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001254 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001255 BB_GOT_ENTRY_SIZE,
1256 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001257 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001258 }
1259
Eric Andersene76c3b02001-04-05 03:14:39 +00001260 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001261 }
Eric Andersen21adca72000-12-06 18:18:26 +00001262#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001263
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001264#if defined(BB_USE_PLT_ENTRIES)
1265 if (plt_offset)
1266 ifile->plt = obj_create_alloced_section(f, ".plt",
1267 BB_PLT_ENTRY_SIZE,
1268 plt_offset);
1269#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001270#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001271 return 1;
1272}
1273
Eric Andersen044228d2001-07-17 01:12:36 +00001274static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001275{
1276 return 1;
1277}
1278
1279
1280/*======================================================================*/
1281
1282/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001283static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001284{
1285 unsigned long h = 0;
1286 unsigned long g;
1287 unsigned char ch;
1288
1289 while (n > 0) {
1290 ch = *name++;
1291 h = (h << 4) + ch;
1292 if ((g = (h & 0xf0000000)) != 0) {
1293 h ^= g >> 24;
1294 h &= ~g;
1295 }
1296 n--;
1297 }
1298 return h;
1299}
1300
Eric Andersen044228d2001-07-17 01:12:36 +00001301static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001302{
1303 return obj_elf_hash_n(name, strlen(name));
1304}
1305
1306#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1307/* Get the kernel version in the canonical integer form. */
1308
1309static int get_kernel_version(char str[STRVERSIONLEN])
1310{
1311 struct utsname uts_info;
Eric Andersen044228d2001-07-17 01:12:36 +00001312 int kv;
Eric Andersen9f16d612000-06-12 23:11:16 +00001313
1314 if (uname(&uts_info) < 0)
1315 return -1;
1316 strncpy(str, uts_info.release, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00001317
Eric Andersen044228d2001-07-17 01:12:36 +00001318 kv = get_kernel_revision();
1319 if(kv==0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001320 return -1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001321}
1322
1323/* String comparison for non-co-versioned kernel and module. */
1324
1325static int ncv_strcmp(const char *a, const char *b)
1326{
1327 size_t alen = strlen(a), blen = strlen(b);
1328
1329 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1330 return strncmp(a, b, alen);
1331 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1332 return strncmp(a, b, blen);
1333 else
1334 return strcmp(a, b);
1335}
1336
1337/* String hashing for non-co-versioned kernel and module. Here
1338 we are simply forced to drop the crc from the hash. */
1339
1340static unsigned long ncv_symbol_hash(const char *str)
1341{
1342 size_t len = strlen(str);
1343 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1344 len -= 10;
1345 return obj_elf_hash_n(str, len);
1346}
1347
Eric Andersen044228d2001-07-17 01:12:36 +00001348static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001349obj_set_symbol_compare(struct obj_file *f,
1350 int (*cmp) (const char *, const char *),
1351 unsigned long (*hash) (const char *))
1352{
1353 if (cmp)
1354 f->symbol_cmp = cmp;
1355 if (hash) {
1356 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1357 int i;
1358
1359 f->symbol_hash = hash;
1360
1361 memcpy(tmptab, f->symtab, sizeof(tmptab));
1362 memset(f->symtab, 0, sizeof(f->symtab));
1363
1364 for (i = 0; i < HASH_BUCKETS; ++i)
1365 for (sym = tmptab[i]; sym; sym = next) {
1366 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1367 next = sym->next;
1368 sym->next = f->symtab[h];
1369 f->symtab[h] = sym;
1370 }
1371 }
1372}
1373
1374#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1375
Eric Andersen044228d2001-07-17 01:12:36 +00001376static struct obj_symbol *
1377obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001378 unsigned long symidx, int info,
1379 int secidx, ElfW(Addr) value,
1380 unsigned long size)
1381{
1382 struct obj_symbol *sym;
1383 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1384 int n_type = ELFW(ST_TYPE) (info);
1385 int n_binding = ELFW(ST_BIND) (info);
1386
1387 for (sym = f->symtab[hash]; sym; sym = sym->next)
1388 if (f->symbol_cmp(sym->name, name) == 0) {
1389 int o_secidx = sym->secidx;
1390 int o_info = sym->info;
1391 int o_type = ELFW(ST_TYPE) (o_info);
1392 int o_binding = ELFW(ST_BIND) (o_info);
1393
1394 /* A redefinition! Is it legal? */
1395
1396 if (secidx == SHN_UNDEF)
1397 return sym;
1398 else if (o_secidx == SHN_UNDEF)
1399 goto found;
1400 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1401 /* Cope with local and global symbols of the same name
1402 in the same object file, as might have been created
1403 by ld -r. The only reason locals are now seen at this
1404 level at all is so that we can do semi-sensible things
1405 with parameters. */
1406
1407 struct obj_symbol *nsym, **p;
1408
1409 nsym = arch_new_symbol();
1410 nsym->next = sym->next;
1411 nsym->ksymidx = -1;
1412
1413 /* Excise the old (local) symbol from the hash chain. */
1414 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1415 continue;
1416 *p = sym = nsym;
1417 goto found;
1418 } else if (n_binding == STB_LOCAL) {
1419 /* Another symbol of the same name has already been defined.
1420 Just add this to the local table. */
1421 sym = arch_new_symbol();
1422 sym->next = NULL;
1423 sym->ksymidx = -1;
1424 f->local_symtab[symidx] = sym;
1425 goto found;
1426 } else if (n_binding == STB_WEAK)
1427 return sym;
1428 else if (o_binding == STB_WEAK)
1429 goto found;
1430 /* Don't unify COMMON symbols with object types the programmer
1431 doesn't expect. */
1432 else if (secidx == SHN_COMMON
1433 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1434 return sym;
1435 else if (o_secidx == SHN_COMMON
1436 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1437 goto found;
1438 else {
1439 /* Don't report an error if the symbol is coming from
1440 the kernel or some external module. */
1441 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001442 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001443 return sym;
1444 }
1445 }
1446
1447 /* Completely new symbol. */
1448 sym = arch_new_symbol();
1449 sym->next = f->symtab[hash];
1450 f->symtab[hash] = sym;
1451 sym->ksymidx = -1;
1452
Eric Andersen66ca9482001-06-28 21:36:06 +00001453 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1454 if (symidx >= f->local_symtab_size)
1455 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1456 name, (long) symidx, (long) f->local_symtab_size);
1457 else
1458 f->local_symtab[symidx] = sym;
1459 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001460
1461 found:
1462 sym->name = name;
1463 sym->value = value;
1464 sym->size = size;
1465 sym->secidx = secidx;
1466 sym->info = info;
1467
1468 return sym;
1469}
1470
Eric Andersen044228d2001-07-17 01:12:36 +00001471static struct obj_symbol *
1472obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001473{
1474 struct obj_symbol *sym;
1475 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1476
1477 for (sym = f->symtab[hash]; sym; sym = sym->next)
1478 if (f->symbol_cmp(sym->name, name) == 0)
1479 return sym;
1480
1481 return NULL;
1482}
1483
Eric Andersen044228d2001-07-17 01:12:36 +00001484static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001485 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1486{
1487 if (sym) {
1488 if (sym->secidx >= SHN_LORESERVE)
1489 return sym->value;
1490
1491 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1492 } else {
1493 /* As a special case, a NULL sym has value zero. */
1494 return 0;
1495 }
1496}
1497
Eric Andersen044228d2001-07-17 01:12:36 +00001498static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001499{
1500 int i, n = f->header.e_shnum;
1501
1502 for (i = 0; i < n; ++i)
1503 if (strcmp(f->sections[i]->name, name) == 0)
1504 return f->sections[i];
1505
1506 return NULL;
1507}
1508
1509static int obj_load_order_prio(struct obj_section *a)
1510{
1511 unsigned long af, ac;
1512
1513 af = a->header.sh_flags;
1514
1515 ac = 0;
1516 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1517 strcmp(a->name + 5, ".init"))
1518 ac |= 32;
1519 if (af & SHF_ALLOC)
1520 ac |= 16;
1521 if (!(af & SHF_WRITE))
1522 ac |= 8;
1523 if (af & SHF_EXECINSTR)
1524 ac |= 4;
1525 if (a->header.sh_type != SHT_NOBITS)
1526 ac |= 2;
1527
1528 return ac;
1529}
1530
Eric Andersen044228d2001-07-17 01:12:36 +00001531static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001532obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1533{
1534 struct obj_section **p;
1535 int prio = obj_load_order_prio(sec);
1536 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1537 if (obj_load_order_prio(*p) < prio)
1538 break;
1539 sec->load_next = *p;
1540 *p = sec;
1541}
1542
Eric Andersen044228d2001-07-17 01:12:36 +00001543static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001544 const char *name,
1545 unsigned long align,
1546 unsigned long size)
1547{
1548 int newidx = f->header.e_shnum++;
1549 struct obj_section *sec;
1550
1551 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1552 f->sections[newidx] = sec = arch_new_section();
1553
1554 memset(sec, 0, sizeof(*sec));
1555 sec->header.sh_type = SHT_PROGBITS;
1556 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1557 sec->header.sh_size = size;
1558 sec->header.sh_addralign = align;
1559 sec->name = name;
1560 sec->idx = newidx;
1561 if (size)
1562 sec->contents = xmalloc(size);
1563
1564 obj_insert_section_load_order(f, sec);
1565
1566 return sec;
1567}
1568
Eric Andersen044228d2001-07-17 01:12:36 +00001569static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001570 const char *name,
1571 unsigned long align,
1572 unsigned long size)
1573{
1574 int newidx = f->header.e_shnum++;
1575 struct obj_section *sec;
1576
1577 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1578 f->sections[newidx] = sec = arch_new_section();
1579
1580 memset(sec, 0, sizeof(*sec));
1581 sec->header.sh_type = SHT_PROGBITS;
1582 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1583 sec->header.sh_size = size;
1584 sec->header.sh_addralign = align;
1585 sec->name = name;
1586 sec->idx = newidx;
1587 if (size)
1588 sec->contents = xmalloc(size);
1589
1590 sec->load_next = f->load_order;
1591 f->load_order = sec;
1592 if (f->load_order_search_start == &f->load_order)
1593 f->load_order_search_start = &sec->load_next;
1594
1595 return sec;
1596}
1597
Eric Andersen044228d2001-07-17 01:12:36 +00001598static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001599{
1600 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001601 if (more) {
1602 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1603 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001604 return sec->contents + oldsize;
1605}
1606
1607
Eric Andersen9f16d612000-06-12 23:11:16 +00001608/* Conditionally add the symbols from the given symbol set to the
1609 new module. */
1610
1611static int
1612add_symbols_from(
1613 struct obj_file *f,
1614 int idx, struct new_module_symbol *syms, size_t nsyms)
1615{
1616 struct new_module_symbol *s;
1617 size_t i;
1618 int used = 0;
1619
1620 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1621
1622 /* Only add symbols that are already marked external. If we
1623 override locals we may cause problems for argument initialization.
1624 We will also create a false dependency on the module. */
1625 struct obj_symbol *sym;
1626
1627 sym = obj_find_symbol(f, (char *) s->name);
1628 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1629 sym = obj_add_symbol(f, (char *) s->name, -1,
1630 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1631 idx, s->value, 0);
1632 /* Did our symbol just get installed? If so, mark the
1633 module as "used". */
1634 if (sym->secidx == idx)
1635 used = 1;
1636 }
1637 }
1638
1639 return used;
1640}
1641
1642static void add_kernel_symbols(struct obj_file *f)
1643{
1644 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001645 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001646
1647 /* Add module symbols first. */
1648
1649 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1650 if (m->nsyms
1651 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1652 m->nsyms)) m->used = 1, ++nused;
1653
1654 n_ext_modules_used = nused;
1655
1656 /* And finally the symbols from the kernel proper. */
1657
1658 if (nksyms)
1659 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1660}
1661
1662static char *get_modinfo_value(struct obj_file *f, const char *key)
1663{
1664 struct obj_section *sec;
1665 char *p, *v, *n, *ep;
1666 size_t klen = strlen(key);
1667
1668 sec = obj_find_section(f, ".modinfo");
1669 if (sec == NULL)
1670 return NULL;
1671 p = sec->contents;
1672 ep = p + sec->header.sh_size;
1673 while (p < ep) {
1674 v = strchr(p, '=');
1675 n = strchr(p, '\0');
1676 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001677 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001678 return v + 1;
1679 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001680 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001681 return n;
1682 }
1683 p = n + 1;
1684 }
1685
1686 return NULL;
1687}
1688
1689
1690/*======================================================================*/
1691/* Functions relating to module loading in pre 2.1 kernels. */
1692
1693static int
1694old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1695{
1696 while (argc > 0) {
1697 char *p, *q;
1698 struct obj_symbol *sym;
1699 int *loc;
1700
1701 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001702 if ((q = strchr(p, '=')) == NULL) {
1703 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001704 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001705 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001706 *q++ = '\0';
1707
1708 sym = obj_find_symbol(f, p);
1709
1710 /* Also check that the parameter was not resolved from the kernel. */
1711 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001712 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001713 return 0;
1714 }
1715
1716 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1717
1718 /* Do C quoting if we begin with a ". */
1719 if (*q == '"') {
1720 char *r, *str;
1721
1722 str = alloca(strlen(q));
1723 for (r = str, q++; *q != '"'; ++q, ++r) {
1724 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001725 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001726 return 0;
1727 } else if (*q == '\\')
1728 switch (*++q) {
1729 case 'a':
1730 *r = '\a';
1731 break;
1732 case 'b':
1733 *r = '\b';
1734 break;
1735 case 'e':
1736 *r = '\033';
1737 break;
1738 case 'f':
1739 *r = '\f';
1740 break;
1741 case 'n':
1742 *r = '\n';
1743 break;
1744 case 'r':
1745 *r = '\r';
1746 break;
1747 case 't':
1748 *r = '\t';
1749 break;
1750
1751 case '0':
1752 case '1':
1753 case '2':
1754 case '3':
1755 case '4':
1756 case '5':
1757 case '6':
1758 case '7':
1759 {
1760 int c = *q - '0';
1761 if (q[1] >= '0' && q[1] <= '7') {
1762 c = (c * 8) + *++q - '0';
1763 if (q[1] >= '0' && q[1] <= '7')
1764 c = (c * 8) + *++q - '0';
1765 }
1766 *r = c;
1767 }
1768 break;
1769
1770 default:
1771 *r = *q;
1772 break;
1773 } else
1774 *r = *q;
1775 }
1776 *r = '\0';
1777 obj_string_patch(f, sym->secidx, sym->value, str);
1778 } else if (*q >= '0' && *q <= '9') {
1779 do
1780 *loc++ = strtoul(q, &q, 0);
1781 while (*q++ == ',');
1782 } else {
1783 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001784 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001785 char *r; /* To search for commas */
1786
1787 /* Break the string with comas */
1788 while ((r = strchr(q, ',')) != (char *) NULL) {
1789 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001790 obj_string_patch(f, sym->secidx, myloc - contents, q);
1791 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001792 q = r;
1793 }
1794
1795 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001796 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001797 }
1798
1799 argc--, argv++;
1800 }
1801
1802 return 1;
1803}
1804
1805#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1806static int old_is_module_checksummed(struct obj_file *f)
1807{
1808 return obj_find_symbol(f, "Using_Versions") != NULL;
1809}
1810/* Get the module's kernel version in the canonical integer form. */
1811
1812static int
1813old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1814{
1815 struct obj_symbol *sym;
1816 char *p, *q;
1817 int a, b, c;
1818
1819 sym = obj_find_symbol(f, "kernel_version");
1820 if (sym == NULL)
1821 return -1;
1822
1823 p = f->sections[sym->secidx]->contents + sym->value;
1824 strncpy(str, p, STRVERSIONLEN);
1825
1826 a = strtoul(p, &p, 10);
1827 if (*p != '.')
1828 return -1;
1829 b = strtoul(p + 1, &p, 10);
1830 if (*p != '.')
1831 return -1;
1832 c = strtoul(p + 1, &q, 10);
1833 if (p + 1 == q)
1834 return -1;
1835
1836 return a << 16 | b << 8 | c;
1837}
1838
1839#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1840
Eric Andersenf5d5e772001-01-24 23:34:48 +00001841#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001842
1843/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1844
Eric Andersen8c185f92000-09-22 00:38:07 +00001845static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001846{
1847 struct old_kernel_sym *ks, *k;
1848 struct new_module_symbol *s;
1849 struct external_module *mod;
1850 int nks, nms, nmod, i;
1851
1852 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001853 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001854 if (nks)
1855 perror_msg("get_kernel_syms: %s", m_name);
1856 else
1857 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001858 return 0;
1859 }
1860
1861 ks = k = xmalloc(nks * sizeof(*ks));
1862
1863 if (get_kernel_syms(ks) != nks) {
1864 perror("inconsistency with get_kernel_syms -- is someone else "
1865 "playing with modules?");
1866 free(ks);
1867 return 0;
1868 }
1869
1870 /* Collect the module information. */
1871
1872 mod = NULL;
1873 nmod = -1;
1874
1875 while (k->name[0] == '#' && k->name[1]) {
1876 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001877
1878 /* Find out how many symbols this module has. */
1879 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1880 continue;
1881 nms = k2 - k - 1;
1882
1883 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1884 mod[nmod].name = k->name + 1;
1885 mod[nmod].addr = k->value;
1886 mod[nmod].used = 0;
1887 mod[nmod].nsyms = nms;
1888 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1889
1890 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1891 s->name = (unsigned long) k->name;
1892 s->value = k->value;
1893 }
1894
1895 k = k2;
1896 }
1897
1898 ext_modules = mod;
1899 n_ext_modules = nmod + 1;
1900
1901 /* Now collect the symbols for the kernel proper. */
1902
1903 if (k->name[0] == '#')
1904 ++k;
1905
1906 nksyms = nms = nks - (k - ks);
1907 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1908
1909 for (i = 0; i < nms; ++i, ++s, ++k) {
1910 s->name = (unsigned long) k->name;
1911 s->value = k->value;
1912 }
1913
1914 return 1;
1915}
1916
1917/* Return the kernel symbol checksum version, or zero if not used. */
1918
1919static int old_is_kernel_checksummed(void)
1920{
1921 /* Using_Versions is the first symbol. */
1922 if (nksyms > 0
1923 && strcmp((char *) ksyms[0].name,
1924 "Using_Versions") == 0) return ksyms[0].value;
1925 else
1926 return 0;
1927}
1928
1929
1930static int old_create_mod_use_count(struct obj_file *f)
1931{
1932 struct obj_section *sec;
1933
1934 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1935 sizeof(long));
1936
1937 obj_add_symbol(f, "mod_use_count_", -1,
1938 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1939 sizeof(long));
1940
1941 return 1;
1942}
1943
1944static int
1945old_init_module(const char *m_name, struct obj_file *f,
1946 unsigned long m_size)
1947{
1948 char *image;
1949 struct old_mod_routines routines;
1950 struct old_symbol_table *symtab;
1951 int ret;
1952
1953 /* Create the symbol table */
1954 {
1955 int nsyms = 0, strsize = 0, total;
1956
1957 /* Size things first... */
1958 if (flag_export) {
1959 int i;
1960 for (i = 0; i < HASH_BUCKETS; ++i) {
1961 struct obj_symbol *sym;
1962 for (sym = f->symtab[i]; sym; sym = sym->next)
1963 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1964 && sym->secidx <= SHN_HIRESERVE)
1965 {
1966 sym->ksymidx = nsyms++;
1967 strsize += strlen(sym->name) + 1;
1968 }
1969 }
1970 }
1971
1972 total = (sizeof(struct old_symbol_table)
1973 + nsyms * sizeof(struct old_module_symbol)
1974 + n_ext_modules_used * sizeof(struct old_module_ref)
1975 + strsize);
1976 symtab = xmalloc(total);
1977 symtab->size = total;
1978 symtab->n_symbols = nsyms;
1979 symtab->n_refs = n_ext_modules_used;
1980
1981 if (flag_export && nsyms) {
1982 struct old_module_symbol *ksym;
1983 char *str;
1984 int i;
1985
1986 ksym = symtab->symbol;
1987 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1988 + n_ext_modules_used * sizeof(struct old_module_ref));
1989
1990 for (i = 0; i < HASH_BUCKETS; ++i) {
1991 struct obj_symbol *sym;
1992 for (sym = f->symtab[i]; sym; sym = sym->next)
1993 if (sym->ksymidx >= 0) {
1994 ksym->addr = obj_symbol_final_value(f, sym);
1995 ksym->name =
1996 (unsigned long) str - (unsigned long) symtab;
1997
Matt Kraai70a78552001-01-04 02:00:17 +00001998 strcpy(str, sym->name);
1999 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002000 ksym++;
2001 }
2002 }
2003 }
2004
2005 if (n_ext_modules_used) {
2006 struct old_module_ref *ref;
2007 int i;
2008
2009 ref = (struct old_module_ref *)
2010 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2011
2012 for (i = 0; i < n_ext_modules; ++i)
2013 if (ext_modules[i].used)
2014 ref++->module = ext_modules[i].addr;
2015 }
2016 }
2017
2018 /* Fill in routines. */
2019
2020 routines.init =
2021 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2022 routines.cleanup =
2023 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2024
2025 /* Whew! All of the initialization is complete. Collect the final
2026 module image and give it to the kernel. */
2027
2028 image = xmalloc(m_size);
2029 obj_create_image(f, image);
2030
2031 /* image holds the complete relocated module, accounting correctly for
2032 mod_use_count. However the old module kernel support assume that
2033 it is receiving something which does not contain mod_use_count. */
2034 ret = old_sys_init_module(m_name, image + sizeof(long),
2035 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2036 : 0), &routines, symtab);
2037 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002038 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002039
2040 free(image);
2041 free(symtab);
2042
2043 return ret == 0;
2044}
2045
2046#else
2047
2048#define old_create_mod_use_count(x) TRUE
2049#define old_init_module(x, y, z) TRUE
2050
Eric Andersenf5d5e772001-01-24 23:34:48 +00002051#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002052
2053
2054
2055/*======================================================================*/
2056/* Functions relating to module loading after 2.1.18. */
2057
2058static int
2059new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2060{
2061 while (argc > 0) {
2062 char *p, *q, *key;
2063 struct obj_symbol *sym;
2064 char *contents, *loc;
2065 int min, max, n;
2066
2067 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002068 if ((q = strchr(p, '=')) == NULL) {
2069 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002070 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002071 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002072
2073 key = alloca(q - p + 6);
2074 memcpy(key, "parm_", 5);
2075 memcpy(key + 5, p, q - p);
2076 key[q - p + 5] = 0;
2077
2078 p = get_modinfo_value(f, key);
2079 key += 5;
2080 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002081 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002082 return 0;
2083 }
2084
2085 sym = obj_find_symbol(f, key);
2086
2087 /* Also check that the parameter was not resolved from the kernel. */
2088 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002089 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002090 return 0;
2091 }
2092
2093 if (isdigit(*p)) {
2094 min = strtoul(p, &p, 10);
2095 if (*p == '-')
2096 max = strtoul(p + 1, &p, 10);
2097 else
2098 max = min;
2099 } else
2100 min = max = 1;
2101
2102 contents = f->sections[sym->secidx]->contents;
2103 loc = contents + sym->value;
2104 n = (*++q != '\0');
2105
2106 while (1) {
2107 if ((*p == 's') || (*p == 'c')) {
2108 char *str;
2109
2110 /* Do C quoting if we begin with a ", else slurp the lot. */
2111 if (*q == '"') {
2112 char *r;
2113
2114 str = alloca(strlen(q));
2115 for (r = str, q++; *q != '"'; ++q, ++r) {
2116 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002117 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002118 key);
2119 return 0;
2120 } else if (*q == '\\')
2121 switch (*++q) {
2122 case 'a':
2123 *r = '\a';
2124 break;
2125 case 'b':
2126 *r = '\b';
2127 break;
2128 case 'e':
2129 *r = '\033';
2130 break;
2131 case 'f':
2132 *r = '\f';
2133 break;
2134 case 'n':
2135 *r = '\n';
2136 break;
2137 case 'r':
2138 *r = '\r';
2139 break;
2140 case 't':
2141 *r = '\t';
2142 break;
2143
2144 case '0':
2145 case '1':
2146 case '2':
2147 case '3':
2148 case '4':
2149 case '5':
2150 case '6':
2151 case '7':
2152 {
2153 int c = *q - '0';
2154 if (q[1] >= '0' && q[1] <= '7') {
2155 c = (c * 8) + *++q - '0';
2156 if (q[1] >= '0' && q[1] <= '7')
2157 c = (c * 8) + *++q - '0';
2158 }
2159 *r = c;
2160 }
2161 break;
2162
2163 default:
2164 *r = *q;
2165 break;
2166 } else
2167 *r = *q;
2168 }
2169 *r = '\0';
2170 ++q;
2171 } else {
2172 char *r;
2173
2174 /* In this case, the string is not quoted. We will break
2175 it using the coma (like for ints). If the user wants to
2176 include comas in a string, he just has to quote it */
2177
2178 /* Search the next coma */
2179 r = strchr(q, ',');
2180
2181 /* Found ? */
2182 if (r != (char *) NULL) {
2183 /* Recopy the current field */
2184 str = alloca(r - q + 1);
2185 memcpy(str, q, r - q);
2186
2187 /* I don't know if it is usefull, as the previous case
2188 doesn't null terminate the string ??? */
2189 str[r - q] = '\0';
2190
2191 /* Keep next fields */
2192 q = r;
2193 } else {
2194 /* last string */
2195 str = q;
2196 q = "";
2197 }
2198 }
2199
2200 if (*p == 's') {
2201 /* Normal string */
2202 obj_string_patch(f, sym->secidx, loc - contents, str);
2203 loc += tgt_sizeof_char_p;
2204 } else {
2205 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002206 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002207
2208 /* Get the size of each member */
2209 /* Probably we should do that outside the loop ? */
2210 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002211 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002212 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002213 return 0;
2214 }
2215 charssize = strtoul(p + 1, (char **) NULL, 10);
2216
2217 /* Check length */
2218 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002219 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002220 charssize - 1);
2221 return 0;
2222 }
2223
2224 /* Copy to location */
2225 strcpy((char *) loc, str);
2226 loc += charssize;
2227 }
2228 } else {
2229 long v = strtoul(q, &q, 0);
2230 switch (*p) {
2231 case 'b':
2232 *loc++ = v;
2233 break;
2234 case 'h':
2235 *(short *) loc = v;
2236 loc += tgt_sizeof_short;
2237 break;
2238 case 'i':
2239 *(int *) loc = v;
2240 loc += tgt_sizeof_int;
2241 break;
2242 case 'l':
2243 *(long *) loc = v;
2244 loc += tgt_sizeof_long;
2245 break;
2246
2247 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002248 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002249 return 0;
2250 }
2251 }
2252
2253 retry_end_of_value:
2254 switch (*q) {
2255 case '\0':
2256 goto end_of_arg;
2257
2258 case ' ':
2259 case '\t':
2260 case '\n':
2261 case '\r':
2262 ++q;
2263 goto retry_end_of_value;
2264
2265 case ',':
2266 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002267 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002268 return 0;
2269 }
2270 ++q;
2271 break;
2272
2273 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002274 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002275 return 0;
2276 }
2277 }
2278
2279 end_of_arg:
2280 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002281 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002282 return 0;
2283 }
2284
2285 argc--, argv++;
2286 }
2287
2288 return 1;
2289}
2290
2291#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2292static int new_is_module_checksummed(struct obj_file *f)
2293{
2294 const char *p = get_modinfo_value(f, "using_checksums");
2295 if (p)
2296 return atoi(p);
2297 else
2298 return 0;
2299}
2300
2301/* Get the module's kernel version in the canonical integer form. */
2302
2303static int
2304new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2305{
2306 char *p, *q;
2307 int a, b, c;
2308
2309 p = get_modinfo_value(f, "kernel_version");
2310 if (p == NULL)
2311 return -1;
2312 strncpy(str, p, STRVERSIONLEN);
2313
2314 a = strtoul(p, &p, 10);
2315 if (*p != '.')
2316 return -1;
2317 b = strtoul(p + 1, &p, 10);
2318 if (*p != '.')
2319 return -1;
2320 c = strtoul(p + 1, &q, 10);
2321 if (p + 1 == q)
2322 return -1;
2323
2324 return a << 16 | b << 8 | c;
2325}
2326
2327#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2328
2329
Eric Andersenf5d5e772001-01-24 23:34:48 +00002330#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002331
2332/* Fetch the loaded modules, and all currently exported symbols. */
2333
2334static int new_get_kernel_symbols(void)
2335{
2336 char *module_names, *mn;
2337 struct external_module *modules, *m;
2338 struct new_module_symbol *syms, *s;
2339 size_t ret, bufsize, nmod, nsyms, i, j;
2340
2341 /* Collect the loaded modules. */
2342
2343 module_names = xmalloc(bufsize = 256);
2344 retry_modules_load:
2345 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002346 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002347 module_names = xrealloc(module_names, bufsize = ret);
2348 goto retry_modules_load;
2349 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002350 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002351 return 0;
2352 }
2353
2354 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002355
2356 /* Collect the modules' symbols. */
2357
Mark Whitley94fd4802001-03-12 23:08:34 +00002358 if (nmod){
2359 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2360 memset(modules, 0, nmod * sizeof(*modules));
2361 for (i = 0, mn = module_names, m = modules;
2362 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2363 struct new_module_info info;
2364
2365 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2366 if (errno == ENOENT) {
2367 /* The module was removed out from underneath us. */
2368 continue;
2369 }
2370 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002371 return 0;
2372 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002373
2374 syms = xmalloc(bufsize = 1024);
2375 retry_mod_sym_load:
2376 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2377 switch (errno) {
2378 case ENOSPC:
2379 syms = xrealloc(syms, bufsize = ret);
2380 goto retry_mod_sym_load;
2381 case ENOENT:
2382 /* The module was removed out from underneath us. */
2383 continue;
2384 default:
2385 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2386 return 0;
2387 }
2388 }
2389 nsyms = ret;
2390
2391 m->name = mn;
2392 m->addr = info.addr;
2393 m->nsyms = nsyms;
2394 m->syms = syms;
2395
2396 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2397 s->name += (unsigned long) syms;
2398 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 }
2400 }
2401
2402 /* Collect the kernel's symbols. */
2403
2404 syms = xmalloc(bufsize = 16 * 1024);
2405 retry_kern_sym_load:
2406 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002407 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002408 syms = xrealloc(syms, bufsize = ret);
2409 goto retry_kern_sym_load;
2410 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002411 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002412 return 0;
2413 }
2414 nksyms = nsyms = ret;
2415 ksyms = syms;
2416
2417 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2418 s->name += (unsigned long) syms;
2419 }
2420 return 1;
2421}
2422
2423
2424/* Return the kernel symbol checksum version, or zero if not used. */
2425
2426static int new_is_kernel_checksummed(void)
2427{
2428 struct new_module_symbol *s;
2429 size_t i;
2430
2431 /* Using_Versions is not the first symbol, but it should be in there. */
2432
2433 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2434 if (strcmp((char *) s->name, "Using_Versions") == 0)
2435 return s->value;
2436
2437 return 0;
2438}
2439
2440
2441static int new_create_this_module(struct obj_file *f, const char *m_name)
2442{
2443 struct obj_section *sec;
2444
2445 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2446 sizeof(struct new_module));
2447 memset(sec->contents, 0, sizeof(struct new_module));
2448
2449 obj_add_symbol(f, "__this_module", -1,
2450 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2451 sizeof(struct new_module));
2452
2453 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2454 m_name);
2455
2456 return 1;
2457}
2458
2459
2460static int new_create_module_ksymtab(struct obj_file *f)
2461{
2462 struct obj_section *sec;
2463 int i;
2464
2465 /* We must always add the module references. */
2466
2467 if (n_ext_modules_used) {
2468 struct new_module_ref *dep;
2469 struct obj_symbol *tm;
2470
2471 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2472 (sizeof(struct new_module_ref)
2473 * n_ext_modules_used));
2474 if (!sec)
2475 return 0;
2476
2477 tm = obj_find_symbol(f, "__this_module");
2478 dep = (struct new_module_ref *) sec->contents;
2479 for (i = 0; i < n_ext_modules; ++i)
2480 if (ext_modules[i].used) {
2481 dep->dep = ext_modules[i].addr;
2482 obj_symbol_patch(f, sec->idx,
2483 (char *) &dep->ref - sec->contents, tm);
2484 dep->next_ref = 0;
2485 ++dep;
2486 }
2487 }
2488
2489 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2490 size_t nsyms;
2491 int *loaded;
2492
2493 sec =
2494 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2495 0);
2496
2497 /* We don't want to export symbols residing in sections that
2498 aren't loaded. There are a number of these created so that
2499 we make sure certain module options don't appear twice. */
2500
2501 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2502 while (--i >= 0)
2503 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2504
2505 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2506 struct obj_symbol *sym;
2507 for (sym = f->symtab[i]; sym; sym = sym->next)
2508 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2509 && sym->secidx <= SHN_HIRESERVE
2510 && (sym->secidx >= SHN_LORESERVE
2511 || loaded[sym->secidx])) {
2512 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2513
2514 obj_symbol_patch(f, sec->idx, ofs, sym);
2515 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2516 sym->name);
2517
2518 nsyms++;
2519 }
2520 }
2521
2522 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2523 }
2524
2525 return 1;
2526}
2527
2528
2529static int
2530new_init_module(const char *m_name, struct obj_file *f,
2531 unsigned long m_size)
2532{
2533 struct new_module *module;
2534 struct obj_section *sec;
2535 void *image;
2536 int ret;
2537 tgt_long m_addr;
2538
2539 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002540 if (!sec || !sec->contents) {
2541 perror_msg_and_die("corrupt module %s?",m_name);
2542 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002543 module = (struct new_module *) sec->contents;
2544 m_addr = sec->header.sh_addr;
2545
2546 module->size_of_struct = sizeof(*module);
2547 module->size = m_size;
2548 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2549
2550 sec = obj_find_section(f, "__ksymtab");
2551 if (sec && sec->header.sh_size) {
2552 module->syms = sec->header.sh_addr;
2553 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2554 }
2555
2556 if (n_ext_modules_used) {
2557 sec = obj_find_section(f, ".kmodtab");
2558 module->deps = sec->header.sh_addr;
2559 module->ndeps = n_ext_modules_used;
2560 }
2561
2562 module->init =
2563 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2564 module->cleanup =
2565 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2566
2567 sec = obj_find_section(f, "__ex_table");
2568 if (sec) {
2569 module->ex_table_start = sec->header.sh_addr;
2570 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2571 }
2572
2573 sec = obj_find_section(f, ".text.init");
2574 if (sec) {
2575 module->runsize = sec->header.sh_addr - m_addr;
2576 }
2577 sec = obj_find_section(f, ".data.init");
2578 if (sec) {
2579 if (!module->runsize ||
2580 module->runsize > sec->header.sh_addr - m_addr)
2581 module->runsize = sec->header.sh_addr - m_addr;
2582 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002583 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2584 if (sec && sec->header.sh_size) {
2585 module->archdata_start = (void*)sec->header.sh_addr;
2586 module->archdata_end = module->archdata_start + sec->header.sh_size;
2587 }
2588 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2589 if (sec && sec->header.sh_size) {
2590 module->kallsyms_start = (void*)sec->header.sh_addr;
2591 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2592 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002593
2594 if (!arch_init_module(f, module))
2595 return 0;
2596
2597 /* Whew! All of the initialization is complete. Collect the final
2598 module image and give it to the kernel. */
2599
2600 image = xmalloc(m_size);
2601 obj_create_image(f, image);
2602
Eric Andersen64c8b172001-04-05 07:33:10 +00002603 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002604 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002605 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002606
2607 free(image);
2608
2609 return ret == 0;
2610}
2611
2612#else
2613
2614#define new_init_module(x, y, z) TRUE
2615#define new_create_this_module(x, y) 0
2616#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002617#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002618
Eric Andersenf5d5e772001-01-24 23:34:48 +00002619#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002620
2621
2622/*======================================================================*/
2623
Eric Andersen044228d2001-07-17 01:12:36 +00002624static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002625obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2626 const char *string)
2627{
2628 struct obj_string_patch *p;
2629 struct obj_section *strsec;
2630 size_t len = strlen(string) + 1;
2631 char *loc;
2632
2633 p = xmalloc(sizeof(*p));
2634 p->next = f->string_patches;
2635 p->reloc_secidx = secidx;
2636 p->reloc_offset = offset;
2637 f->string_patches = p;
2638
2639 strsec = obj_find_section(f, ".kstrtab");
2640 if (strsec == NULL) {
2641 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2642 p->string_offset = 0;
2643 loc = strsec->contents;
2644 } else {
2645 p->string_offset = strsec->header.sh_size;
2646 loc = obj_extend_section(strsec, len);
2647 }
2648 memcpy(loc, string, len);
2649
2650 return 1;
2651}
2652
Eric Andersen044228d2001-07-17 01:12:36 +00002653static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002654obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2655 struct obj_symbol *sym)
2656{
2657 struct obj_symbol_patch *p;
2658
2659 p = xmalloc(sizeof(*p));
2660 p->next = f->symbol_patches;
2661 p->reloc_secidx = secidx;
2662 p->reloc_offset = offset;
2663 p->sym = sym;
2664 f->symbol_patches = p;
2665
2666 return 1;
2667}
2668
Eric Andersen044228d2001-07-17 01:12:36 +00002669static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002670{
2671 unsigned long i;
2672 int ret = 1;
2673
2674 for (i = 0; i < HASH_BUCKETS; ++i) {
2675 struct obj_symbol *sym;
2676 for (sym = f->symtab[i]; sym; sym = sym->next)
2677 if (sym->secidx == SHN_UNDEF) {
2678 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2679 sym->secidx = SHN_ABS;
2680 sym->value = 0;
2681 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002682 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002683 ret = 0;
2684 }
2685 }
2686 }
2687
2688 return ret;
2689}
2690
Eric Andersen044228d2001-07-17 01:12:36 +00002691static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002692{
2693 struct common_entry {
2694 struct common_entry *next;
2695 struct obj_symbol *sym;
2696 } *common_head = NULL;
2697
2698 unsigned long i;
2699
2700 for (i = 0; i < HASH_BUCKETS; ++i) {
2701 struct obj_symbol *sym;
2702 for (sym = f->symtab[i]; sym; sym = sym->next)
2703 if (sym->secidx == SHN_COMMON) {
2704 /* Collect all COMMON symbols and sort them by size so as to
2705 minimize space wasted by alignment requirements. */
2706 {
2707 struct common_entry **p, *n;
2708 for (p = &common_head; *p; p = &(*p)->next)
2709 if (sym->size <= (*p)->sym->size)
2710 break;
2711
2712 n = alloca(sizeof(*n));
2713 n->next = *p;
2714 n->sym = sym;
2715 *p = n;
2716 }
2717 }
2718 }
2719
2720 for (i = 1; i < f->local_symtab_size; ++i) {
2721 struct obj_symbol *sym = f->local_symtab[i];
2722 if (sym && sym->secidx == SHN_COMMON) {
2723 struct common_entry **p, *n;
2724 for (p = &common_head; *p; p = &(*p)->next)
2725 if (sym == (*p)->sym)
2726 break;
2727 else if (sym->size < (*p)->sym->size) {
2728 n = alloca(sizeof(*n));
2729 n->next = *p;
2730 n->sym = sym;
2731 *p = n;
2732 break;
2733 }
2734 }
2735 }
2736
2737 if (common_head) {
2738 /* Find the bss section. */
2739 for (i = 0; i < f->header.e_shnum; ++i)
2740 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2741 break;
2742
2743 /* If for some reason there hadn't been one, create one. */
2744 if (i == f->header.e_shnum) {
2745 struct obj_section *sec;
2746
2747 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2748 f->sections[i] = sec = arch_new_section();
2749 f->header.e_shnum = i + 1;
2750
2751 memset(sec, 0, sizeof(*sec));
2752 sec->header.sh_type = SHT_PROGBITS;
2753 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2754 sec->name = ".bss";
2755 sec->idx = i;
2756 }
2757
2758 /* Allocate the COMMONS. */
2759 {
2760 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2761 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2762 struct common_entry *c;
2763
2764 for (c = common_head; c; c = c->next) {
2765 ElfW(Addr) align = c->sym->value;
2766
2767 if (align > max_align)
2768 max_align = align;
2769 if (bss_size & (align - 1))
2770 bss_size = (bss_size | (align - 1)) + 1;
2771
2772 c->sym->secidx = i;
2773 c->sym->value = bss_size;
2774
2775 bss_size += c->sym->size;
2776 }
2777
2778 f->sections[i]->header.sh_size = bss_size;
2779 f->sections[i]->header.sh_addralign = max_align;
2780 }
2781 }
2782
2783 /* For the sake of patch relocation and parameter initialization,
2784 allocate zeroed data for NOBITS sections now. Note that after
2785 this we cannot assume NOBITS are really empty. */
2786 for (i = 0; i < f->header.e_shnum; ++i) {
2787 struct obj_section *s = f->sections[i];
2788 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002789 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002790 s->contents = memset(xmalloc(s->header.sh_size),
2791 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002792 else
2793 s->contents = NULL;
2794
Eric Andersen9f16d612000-06-12 23:11:16 +00002795 s->header.sh_type = SHT_PROGBITS;
2796 }
2797 }
2798}
2799
Eric Andersen044228d2001-07-17 01:12:36 +00002800static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002801{
2802 unsigned long dot = 0;
2803 struct obj_section *sec;
2804
2805 /* Finalize the positions of the sections relative to one another. */
2806
2807 for (sec = f->load_order; sec; sec = sec->load_next) {
2808 ElfW(Addr) align;
2809
2810 align = sec->header.sh_addralign;
2811 if (align && (dot & (align - 1)))
2812 dot = (dot | (align - 1)) + 1;
2813
2814 sec->header.sh_addr = dot;
2815 dot += sec->header.sh_size;
2816 }
2817
2818 return dot;
2819}
2820
Eric Andersen044228d2001-07-17 01:12:36 +00002821static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002822{
2823 int i, n = f->header.e_shnum;
2824 int ret = 1;
2825
2826 /* Finalize the addresses of the sections. */
2827
2828 f->baseaddr = base;
2829 for (i = 0; i < n; ++i)
2830 f->sections[i]->header.sh_addr += base;
2831
2832 /* And iterate over all of the relocations. */
2833
2834 for (i = 0; i < n; ++i) {
2835 struct obj_section *relsec, *symsec, *targsec, *strsec;
2836 ElfW(RelM) * rel, *relend;
2837 ElfW(Sym) * symtab;
2838 const char *strtab;
2839
2840 relsec = f->sections[i];
2841 if (relsec->header.sh_type != SHT_RELM)
2842 continue;
2843
2844 symsec = f->sections[relsec->header.sh_link];
2845 targsec = f->sections[relsec->header.sh_info];
2846 strsec = f->sections[symsec->header.sh_link];
2847
2848 rel = (ElfW(RelM) *) relsec->contents;
2849 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2850 symtab = (ElfW(Sym) *) symsec->contents;
2851 strtab = (const char *) strsec->contents;
2852
2853 for (; rel < relend; ++rel) {
2854 ElfW(Addr) value = 0;
2855 struct obj_symbol *intsym = NULL;
2856 unsigned long symndx;
2857 ElfW(Sym) * extsym = 0;
2858 const char *errmsg;
2859
2860 /* Attempt to find a value to use for this relocation. */
2861
2862 symndx = ELFW(R_SYM) (rel->r_info);
2863 if (symndx) {
2864 /* Note we've already checked for undefined symbols. */
2865
2866 extsym = &symtab[symndx];
2867 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2868 /* Local symbols we look up in the local table to be sure
2869 we get the one that is really intended. */
2870 intsym = f->local_symtab[symndx];
2871 } else {
2872 /* Others we look up in the hash table. */
2873 const char *name;
2874 if (extsym->st_name)
2875 name = strtab + extsym->st_name;
2876 else
2877 name = f->sections[extsym->st_shndx]->name;
2878 intsym = obj_find_symbol(f, name);
2879 }
2880
2881 value = obj_symbol_final_value(f, intsym);
2882 intsym->referenced = 1;
2883 }
2884#if SHT_RELM == SHT_RELA
2885#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2886 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2887 if (!extsym || !extsym->st_name ||
2888 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2889#endif
2890 value += rel->r_addend;
2891#endif
2892
2893 /* Do it! */
2894 switch (arch_apply_relocation
2895 (f, targsec, symsec, intsym, rel, value)) {
2896 case obj_reloc_ok:
2897 break;
2898
2899 case obj_reloc_overflow:
2900 errmsg = "Relocation overflow";
2901 goto bad_reloc;
2902 case obj_reloc_dangerous:
2903 errmsg = "Dangerous relocation";
2904 goto bad_reloc;
2905 case obj_reloc_unhandled:
2906 errmsg = "Unhandled relocation";
2907 bad_reloc:
2908 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002909 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002910 (long) ELFW(R_TYPE) (rel->r_info),
2911 strtab + extsym->st_name);
2912 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002913 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002914 (long) ELFW(R_TYPE) (rel->r_info));
2915 }
2916 ret = 0;
2917 break;
2918 }
2919 }
2920 }
2921
2922 /* Finally, take care of the patches. */
2923
2924 if (f->string_patches) {
2925 struct obj_string_patch *p;
2926 struct obj_section *strsec;
2927 ElfW(Addr) strsec_base;
2928 strsec = obj_find_section(f, ".kstrtab");
2929 strsec_base = strsec->header.sh_addr;
2930
2931 for (p = f->string_patches; p; p = p->next) {
2932 struct obj_section *targsec = f->sections[p->reloc_secidx];
2933 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2934 = strsec_base + p->string_offset;
2935 }
2936 }
2937
2938 if (f->symbol_patches) {
2939 struct obj_symbol_patch *p;
2940
2941 for (p = f->symbol_patches; p; p = p->next) {
2942 struct obj_section *targsec = f->sections[p->reloc_secidx];
2943 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2944 = obj_symbol_final_value(f, p->sym);
2945 }
2946 }
2947
2948 return ret;
2949}
2950
Eric Andersen044228d2001-07-17 01:12:36 +00002951static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002952{
2953 struct obj_section *sec;
2954 ElfW(Addr) base = f->baseaddr;
2955
2956 for (sec = f->load_order; sec; sec = sec->load_next) {
2957 char *secimg;
2958
Eric Andersen2bf658d2001-02-24 20:01:53 +00002959 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002960 continue;
2961
2962 secimg = image + (sec->header.sh_addr - base);
2963
2964 /* Note that we allocated data for NOBITS sections earlier. */
2965 memcpy(secimg, sec->contents, sec->header.sh_size);
2966 }
2967
2968 return 1;
2969}
2970
2971/*======================================================================*/
2972
Eric Andersen044228d2001-07-17 01:12:36 +00002973static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002974{
2975 struct obj_file *f;
2976 ElfW(Shdr) * section_headers;
2977 int shnum, i;
2978 char *shstrtab;
2979
2980 /* Read the file header. */
2981
2982 f = arch_new_file();
2983 memset(f, 0, sizeof(*f));
2984 f->symbol_cmp = strcmp;
2985 f->symbol_hash = obj_elf_hash;
2986 f->load_order_search_start = &f->load_order;
2987
2988 fseek(fp, 0, SEEK_SET);
2989 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002990 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002991 return NULL;
2992 }
2993
2994 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2995 || f->header.e_ident[EI_MAG1] != ELFMAG1
2996 || f->header.e_ident[EI_MAG2] != ELFMAG2
2997 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002998 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002999 return NULL;
3000 }
3001 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3002 || f->header.e_ident[EI_DATA] != ELFDATAM
3003 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3004 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003005 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003006 return NULL;
3007 }
3008 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003009 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003010 return NULL;
3011 }
3012
3013 /* Read the section headers. */
3014
3015 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003016 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003017 (unsigned long) f->header.e_shentsize,
3018 (unsigned long) sizeof(ElfW(Shdr)));
3019 return NULL;
3020 }
3021
3022 shnum = f->header.e_shnum;
3023 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3024 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3025
3026 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3027 fseek(fp, f->header.e_shoff, SEEK_SET);
3028 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003029 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003030 return NULL;
3031 }
3032
3033 /* Read the section data. */
3034
3035 for (i = 0; i < shnum; ++i) {
3036 struct obj_section *sec;
3037
3038 f->sections[i] = sec = arch_new_section();
3039 memset(sec, 0, sizeof(*sec));
3040
3041 sec->header = section_headers[i];
3042 sec->idx = i;
3043
Eric Andersen2bf658d2001-02-24 20:01:53 +00003044 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003045 case SHT_NULL:
3046 case SHT_NOTE:
3047 case SHT_NOBITS:
3048 /* ignore */
3049 break;
3050
3051 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003052#if LOADBITS
3053 if (!loadprogbits) {
3054 sec->contents = NULL;
3055 break;
3056 }
3057#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003058 case SHT_SYMTAB:
3059 case SHT_STRTAB:
3060 case SHT_RELM:
3061 if (sec->header.sh_size > 0) {
3062 sec->contents = xmalloc(sec->header.sh_size);
3063 fseek(fp, sec->header.sh_offset, SEEK_SET);
3064 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003065 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003066 return NULL;
3067 }
3068 } else {
3069 sec->contents = NULL;
3070 }
3071 break;
3072
3073#if SHT_RELM == SHT_REL
3074 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003075 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003076 return NULL;
3077#else
3078 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003079 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003080 return NULL;
3081#endif
3082
3083 default:
3084 if (sec->header.sh_type >= SHT_LOPROC) {
3085 /* Assume processor specific section types are debug
3086 info and can safely be ignored. If this is ever not
3087 the case (Hello MIPS?), don't put ifdefs here but
3088 create an arch_load_proc_section(). */
3089 break;
3090 }
3091
Matt Kraaidd19c692001-01-31 19:00:21 +00003092 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003093 (long) sec->header.sh_type);
3094 return NULL;
3095 }
3096 }
3097
3098 /* Do what sort of interpretation as needed by each section. */
3099
3100 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3101
3102 for (i = 0; i < shnum; ++i) {
3103 struct obj_section *sec = f->sections[i];
3104 sec->name = shstrtab + sec->header.sh_name;
3105 }
3106
3107 for (i = 0; i < shnum; ++i) {
3108 struct obj_section *sec = f->sections[i];
3109
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003110 /* .modinfo should be contents only but gcc has no attribute for that.
3111 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3112 */
3113 if (strcmp(sec->name, ".modinfo") == 0)
3114 sec->header.sh_flags &= ~SHF_ALLOC;
3115
Eric Andersen9f16d612000-06-12 23:11:16 +00003116 if (sec->header.sh_flags & SHF_ALLOC)
3117 obj_insert_section_load_order(f, sec);
3118
3119 switch (sec->header.sh_type) {
3120 case SHT_SYMTAB:
3121 {
3122 unsigned long nsym, j;
3123 char *strtab;
3124 ElfW(Sym) * sym;
3125
3126 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003127 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003128 (unsigned long) sec->header.sh_entsize,
3129 (unsigned long) sizeof(ElfW(Sym)));
3130 return NULL;
3131 }
3132
3133 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3134 strtab = f->sections[sec->header.sh_link]->contents;
3135 sym = (ElfW(Sym) *) sec->contents;
3136
3137 /* Allocate space for a table of local symbols. */
3138 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003139 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003140
3141 /* Insert all symbols into the hash table. */
3142 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3143 const char *name;
3144 if (sym->st_name)
3145 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003146 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003147 name = f->sections[sym->st_shndx]->name;
3148
3149 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3150 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003151 }
3152 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003153 break;
3154
3155 case SHT_RELM:
3156 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003157 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003158 (unsigned long) sec->header.sh_entsize,
3159 (unsigned long) sizeof(ElfW(RelM)));
3160 return NULL;
3161 }
3162 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003163 /* XXX Relocation code from modutils-2.3.19 is not here.
3164 * Why? That's about 20 lines of code from obj/obj_load.c,
3165 * which gets done in a second pass through the sections.
3166 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003167 }
3168 }
3169
3170 return f;
3171}
3172
Eric Andersen8ae319a2001-05-21 16:09:18 +00003173#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3174/*
3175 * load the unloaded sections directly into the memory allocated by
3176 * kernel for the module
3177 */
3178
Eric Andersen044228d2001-07-17 01:12:36 +00003179static int obj_load_progbits(FILE * fp, struct obj_file* f)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003180{
3181 char* imagebase = (char*) f->imagebase;
3182 ElfW(Addr) base = f->baseaddr;
3183 struct obj_section* sec;
3184
3185 for (sec = f->load_order; sec; sec = sec->load_next) {
3186
3187 /* section already loaded? */
3188 if (sec->contents != NULL)
3189 continue;
3190
3191 if (sec->header.sh_size == 0)
3192 continue;
3193
3194 sec->contents = imagebase + (sec->header.sh_addr - base);
3195 fseek(fp, sec->header.sh_offset, SEEK_SET);
3196 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3197 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3198 return 0;
3199 }
3200
3201 }
3202 return 1;
3203}
3204#endif
3205
Eric Andersen9f16d612000-06-12 23:11:16 +00003206static void hide_special_symbols(struct obj_file *f)
3207{
3208 static const char *const specials[] = {
3209 "cleanup_module",
3210 "init_module",
3211 "kernel_version",
3212 NULL
3213 };
3214
3215 struct obj_symbol *sym;
3216 const char *const *p;
3217
3218 for (p = specials; *p; ++p)
3219 if ((sym = obj_find_symbol(f, *p)) != NULL)
3220 sym->info =
3221 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3222}
3223
3224
3225
3226extern int insmod_main( int argc, char **argv)
3227{
Eric Andersena18aaf12001-01-24 19:07:09 +00003228 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003229 int k_crcs;
3230 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003231 int len;
3232 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003233 unsigned long m_size;
3234 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003235 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003236 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003237 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003238 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003239 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003240 int m_has_modinfo;
3241#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3242 int k_version;
3243 char k_strversion[STRVERSIONLEN];
3244 char m_strversion[STRVERSIONLEN];
3245 int m_version;
3246 int m_crcs;
3247#endif
3248
Erik Andersene49d5ec2000-02-08 19:58:47 +00003249 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003250 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003251 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003252 case 'f': /* force loading */
3253 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003254 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003255 case 'k': /* module loaded by kerneld, auto-cleanable */
3256 flag_autoclean = 1;
3257 break;
3258 case 'v': /* verbose output */
3259 flag_verbose = 1;
3260 break;
3261 case 'x': /* do not export externs */
3262 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003263 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003264 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003265 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003266 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003267 case 'L': /* Stub warning */
3268 /* This is needed for compatibility with modprobe.
3269 * In theory, this does locking, but we don't do
3270 * that. So be careful and plan your life around not
3271 * loading the same module 50 times concurrently. */
3272 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003273 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003274 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003275 }
Erik Andersend387d011999-12-21 02:55:11 +00003276 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003277
3278 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003279 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003280 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003281
Erik Andersene49d5ec2000-02-08 19:58:47 +00003282 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003283 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003284 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003285 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003286 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003287 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003288 len = strlen(tmp);
3289
3290 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3291 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003292 memcpy(m_fullName, tmp, len);
3293 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003294 if (*m_name == '\0') {
3295 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003296 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003297 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003298
Eric Andersen14d35432001-05-14 17:07:32 +00003299 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003300 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3301 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003302 struct utsname myuname;
3303
3304 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3305 * but do not error out yet if we fail to find it... */
3306 if (uname(&myuname) == 0) {
3307 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003308 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003309 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3310 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003311 /* Jump through hoops in case /lib/modules/`uname -r`
3312 * is a symlink. We do not want recursive_action to
3313 * follow symlinks, but we do want to follow the
3314 * /lib/modules/`uname -r` dir, So resolve it ourselves
3315 * if it is a link... */
3316 if (realpath (module_dir, real_module_dir) == NULL)
3317 strcpy(real_module_dir, module_dir);
3318 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003319 check_module_name_match, 0, m_fullName);
3320 }
3321
3322 /* Check if we have found anything yet */
3323 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003324 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003325 char module_dir[FILENAME_MAX];
3326 if (realpath (_PATH_MODULES, module_dir) == NULL)
3327 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003328 /* No module found under /lib/modules/`uname -r`, this
3329 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003330 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003331 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003332 {
Eric Andersen14d35432001-05-14 17:07:32 +00003333 if (m_filename[0] == '\0'
3334 || ((fp = fopen(m_filename, "r")) == NULL))
3335 {
3336 error_msg("%s: no module by that name found", m_fullName);
3337 return EXIT_FAILURE;
3338 }
3339 } else
3340 error_msg_and_die("%s: no module by that name found", m_fullName);
3341 }
3342 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003343 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003344
Eric Andersen14d35432001-05-14 17:07:32 +00003345 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003346
Eric Andersen8ae319a2001-05-21 16:09:18 +00003347 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003348 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003349
Eric Andersen9f16d612000-06-12 23:11:16 +00003350 if (get_modinfo_value(f, "kernel_version") == NULL)
3351 m_has_modinfo = 0;
3352 else
3353 m_has_modinfo = 1;
3354
3355#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3356 /* Version correspondence? */
3357
3358 k_version = get_kernel_version(k_strversion);
3359 if (m_has_modinfo) {
3360 m_version = new_get_module_version(f, m_strversion);
3361 } else {
3362 m_version = old_get_module_version(f, m_strversion);
3363 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003364 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003365 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003366 goto out;
3367 }
3368 }
3369
3370 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3371 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003372 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003373 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003374 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003375 m_filename, m_strversion, k_strversion);
3376 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003377 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003379 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 m_filename, m_strversion, k_strversion);
3381 goto out;
3382 }
3383 }
3384 k_crcs = 0;
3385#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3386
3387 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3388
3389 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003390#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003391 if (!new_get_kernel_symbols())
3392 goto out;
3393 k_crcs = new_is_kernel_checksummed();
3394#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003395 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 goto out;
3397#endif
3398 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003399#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003400 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003401 goto out;
3402 k_crcs = old_is_kernel_checksummed();
3403#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003404 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003405 goto out;
3406#endif
3407 }
3408
3409#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3410 if (m_has_modinfo)
3411 m_crcs = new_is_module_checksummed(f);
3412 else
3413 m_crcs = old_is_module_checksummed(f);
3414
3415 if (m_crcs != k_crcs)
3416 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3417#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3418
Erik Andersene49d5ec2000-02-08 19:58:47 +00003419 /* Let the module know about the kernel symbols. */
3420 add_kernel_symbols(f);
3421
Eric Andersen9f16d612000-06-12 23:11:16 +00003422 /* Allocate common symbols, symbol tables, and string tables. */
3423
3424 if (k_new_syscalls
3425 ? !new_create_this_module(f, m_name)
3426 : !old_create_mod_use_count(f))
3427 {
3428 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003429 }
3430
Eric Andersen9f16d612000-06-12 23:11:16 +00003431 if (!obj_check_undefineds(f)) {
3432 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003433 }
3434 obj_allocate_commons(f);
3435
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003436 /* done with the module name, on to the optional var=value arguments */
3437 ++optind;
3438
Eric Andersen9f16d612000-06-12 23:11:16 +00003439 if (optind < argc) {
3440 if (m_has_modinfo
3441 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3442 : !old_process_module_arguments(f, argc - optind, argv + optind))
3443 {
3444 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003445 }
3446 }
3447
Eric Andersen9f16d612000-06-12 23:11:16 +00003448 arch_create_got(f);
3449 hide_special_symbols(f);
3450
3451 if (k_new_syscalls)
3452 new_create_module_ksymtab(f);
3453
Erik Andersene49d5ec2000-02-08 19:58:47 +00003454 /* Find current size of the module */
3455 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003456
3457
Erik Andersene49d5ec2000-02-08 19:58:47 +00003458 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003459 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003460 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003461 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003462 goto out;
3463 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003464 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003465 m_size);
3466 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003467 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003468 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003469 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003470 }
Erik Andersend387d011999-12-21 02:55:11 +00003471
Eric Andersen8ae319a2001-05-21 16:09:18 +00003472#if !LOADBITS
3473 /*
3474 * the PROGBITS section was not loaded by the obj_load
3475 * now we can load them directly into the kernel memory
3476 */
3477 // f->imagebase = (char*) m_addr;
3478 f->imagebase = (ElfW(Addr)) m_addr;
3479 if (!obj_load_progbits(fp, f)) {
3480 delete_module(m_name);
3481 goto out;
3482 }
3483#endif
3484
Eric Andersen9f16d612000-06-12 23:11:16 +00003485 if (!obj_relocate(f, m_addr)) {
3486 delete_module(m_name);
3487 goto out;
3488 }
Erik Andersend387d011999-12-21 02:55:11 +00003489
Eric Andersen9f16d612000-06-12 23:11:16 +00003490 if (k_new_syscalls
3491 ? !new_init_module(m_name, f, m_size)
3492 : !old_init_module(m_name, f, m_size))
3493 {
3494 delete_module(m_name);
3495 goto out;
3496 }
3497
Matt Kraai3e856ce2000-12-01 02:55:13 +00003498 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003499
3500out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003501 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003502 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003503}