blob: 6e1ffad366cf86d2bb7a88b19085b13c361c8abb [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 Andersen2835efe2001-07-25 16:58:58 +0000136#ident "$Id: insmod.c,v 1.69 2001/07/25 16:58:58 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 Andersen2835efe2001-07-25 16:58:58 +0000353#ident "$Id: insmod.c,v 1.69 2001/07/25 16:58:58 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 Andersen044228d2001-07-17 01:12:36 +0000553static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000554 int (*cmp)(const char *, const char *),
555 unsigned long (*hash)(const char *));
556
Eric Andersen044228d2001-07-17 01:12:36 +0000557static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000558 const char *name);
559
Eric Andersen044228d2001-07-17 01:12:36 +0000560static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000561 struct obj_section *sec);
562
Eric Andersen044228d2001-07-17 01:12:36 +0000563static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000564 const char *name,
565 unsigned long align,
566 unsigned long size);
567
Eric Andersen044228d2001-07-17 01:12:36 +0000568static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000569 const char *name,
570 unsigned long align,
571 unsigned long size);
572
Eric Andersen044228d2001-07-17 01:12:36 +0000573static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000574
Eric Andersen044228d2001-07-17 01:12:36 +0000575static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000576 const char *string);
577
Eric Andersen044228d2001-07-17 01:12:36 +0000578static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000579 struct obj_symbol *sym);
580
Eric Andersen044228d2001-07-17 01:12:36 +0000581static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000584
Eric Andersen044228d2001-07-17 01:12:36 +0000585static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000586
Eric Andersen044228d2001-07-17 01:12:36 +0000587static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000588
Eric Andersen044228d2001-07-17 01:12:36 +0000589static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000590
Eric Andersen044228d2001-07-17 01:12:36 +0000591static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000592
593/* Architecture specific manipulation routines. */
594
Eric Andersen044228d2001-07-17 01:12:36 +0000595static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000596
Eric Andersen044228d2001-07-17 01:12:36 +0000597static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000602 struct obj_section *targsec,
603 struct obj_section *symsec,
604 struct obj_symbol *sym,
605 ElfW(RelM) *rel, ElfW(Addr) value);
606
Eric Andersen044228d2001-07-17 01:12:36 +0000607static int arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
611#endif /* obj.h */
612//----------------------------------------------------------------------------
613//--------end of modutils obj.h
614//----------------------------------------------------------------------------
615
616
617
618
Erik Andersen02104321999-12-17 18:57:34 +0000619
Erik Andersend387d011999-12-21 02:55:11 +0000620#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000621static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000622
Eric Andersen9f16d612000-06-12 23:11:16 +0000623/*======================================================================*/
624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static int flag_force_load = 0;
626static int flag_autoclean = 0;
627static int flag_verbose = 0;
628static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000629
630
631/*======================================================================*/
632
Eric Andersenfe4208f2000-09-24 03:44:29 +0000633/* previously, these were named i386_* but since we could be
634 compiling for the sh, I've renamed them to the more general
635 arch_* These structures are the same between the x86 and SH,
636 and we can't support anything else right now anyway. In the
637 future maybe they should be #if defined'd */
638
Eric Andersen21adca72000-12-06 18:18:26 +0000639/* Done ;-) */
640
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000641
642
643#if defined(BB_USE_PLT_ENTRIES)
644struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000645{
646 int offset;
647 int allocated:1;
648 int inited:1; /* has been set up */
649};
650#endif
651
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000652#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000653struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000654 int offset;
655 unsigned offset_done:1;
656 unsigned reloc_done:1;
657};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000658#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen2bf658d2001-02-24 20:01:53 +0000660#if defined(__mips__)
661struct mips_hi16
662{
663 struct mips_hi16 *next;
664 Elf32_Addr *addr;
665 Elf32_Addr value;
666};
667#endif
668
Eric Andersenfe4208f2000-09-24 03:44:29 +0000669struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000670 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000671#if defined(BB_USE_PLT_ENTRIES)
672 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000673#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000674#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000675 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000676#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000677#if defined(__mips__)
678 struct mips_hi16 *mips_hi16_list;
679#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000680};
681
Eric Andersenfe4208f2000-09-24 03:44:29 +0000682struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000683 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000684#if defined(BB_USE_PLT_ENTRIES)
685 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000686#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000687#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000688 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000689#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000690};
691
692
Eric Andersen9f16d612000-06-12 23:11:16 +0000693struct external_module {
694 const char *name;
695 ElfW(Addr) addr;
696 int used;
697 size_t nsyms;
698 struct new_module_symbol *syms;
699};
700
Eric Andersen044228d2001-07-17 01:12:36 +0000701static struct new_module_symbol *ksyms;
702static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000703
Eric Andersen044228d2001-07-17 01:12:36 +0000704static struct external_module *ext_modules;
705static int n_ext_modules;
706static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000707extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000708
Eric Andersen14d35432001-05-14 17:07:32 +0000709static char m_filename[FILENAME_MAX + 1];
710static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000711
Eric Andersenfe4208f2000-09-24 03:44:29 +0000712
Erik Andersen02104321999-12-17 18:57:34 +0000713
Eric Andersen9f16d612000-06-12 23:11:16 +0000714/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000715
Eric Andersen9f16d612000-06-12 23:11:16 +0000716
Eric Andersen14d35432001-05-14 17:07:32 +0000717static int check_module_name_match(const char *filename, struct stat *statbuf,
718 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000719{
Eric Andersen14d35432001-05-14 17:07:32 +0000720 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000721
Eric Andersen14d35432001-05-14 17:07:32 +0000722 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000723 return (FALSE);
724 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000725 char *tmp, *tmp1 = strdup(filename);
726 tmp = get_last_path_component(tmp1);
727 if (strcmp(tmp, fullname) == 0) {
728 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000729 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000730 safe_strncpy(m_filename, filename, sizeof(m_filename));
731 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000732 }
Eric Andersen14d35432001-05-14 17:07:32 +0000733 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000734 }
Eric Andersen14d35432001-05-14 17:07:32 +0000735 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000736}
737
Erik Andersen02104321999-12-17 18:57:34 +0000738
Eric Andersen9f16d612000-06-12 23:11:16 +0000739/*======================================================================*/
740
Eric Andersen044228d2001-07-17 01:12:36 +0000741static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000742{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000743 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000744 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000745
746#if defined(BB_USE_PLT_ENTRIES)
747 f->plt = NULL;
748#endif
749#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000750 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000751#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000752#if defined(__mips__)
753 f->mips_hi16_list = NULL;
754#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755
Eric Andersen9f16d612000-06-12 23:11:16 +0000756 return &f->root;
757}
758
Eric Andersen044228d2001-07-17 01:12:36 +0000759static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000760{
761 return xmalloc(sizeof(struct obj_section));
762}
763
Eric Andersen044228d2001-07-17 01:12:36 +0000764static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000765{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000766 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000767 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000768
769#if defined(BB_USE_PLT_ENTRIES)
770 memset(&sym->pltent, 0, sizeof(sym->pltent));
771#endif
772#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000773 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000774#endif
775
Eric Andersen9f16d612000-06-12 23:11:16 +0000776 return &sym->root;
777}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000778
Eric Andersen044228d2001-07-17 01:12:36 +0000779static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000780arch_apply_relocation(struct obj_file *f,
781 struct obj_section *targsec,
782 struct obj_section *symsec,
783 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000784 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000785{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000786 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000787#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000788 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000789#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000790
Eric Andersen21adca72000-12-06 18:18:26 +0000791 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
792 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000793#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000794 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000795#endif
796#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000797 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000798 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000799 unsigned long *ip;
800#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000801 enum obj_reloc ret = obj_reloc_ok;
802
803 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000804
805/* even though these constants seem to be the same for
806 the i386 and the sh, we "#if define" them for clarity
807 and in case that ever changes */
808#if defined(__sh__)
809 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000810#elif defined(__arm__)
811 case R_ARM_NONE:
812#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000813 case R_386_NONE:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000814#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000815 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816#elif defined(__powerpc__)
817 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000818#elif defined(__mips__)
819 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000820#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000821 break;
822
Eric Andersenfe4208f2000-09-24 03:44:29 +0000823#if defined(__sh__)
824 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000825#elif defined(__arm__)
826 case R_ARM_ABS32:
827#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828 case R_386_32:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000829#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000830 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831#elif defined(__powerpc__)
832 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000833#elif defined(__mips__)
834 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000835#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000836 *loc += v;
837 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000838#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000839 case R_68K_8:
840 if (v > 0xff)
841 ret = obj_reloc_overflow;
842 *(char *)loc = v;
843 break;
844 case R_68K_16:
845 if (v > 0xffff)
846 ret = obj_reloc_overflow;
847 *(short *)loc = v;
848 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000849#endif /* __mc68000__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000850
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000851#if defined(__powerpc__)
852 case R_PPC_ADDR16_HA:
853 *(unsigned short *)loc = (v + 0x8000) >> 16;
854 break;
855
856 case R_PPC_ADDR16_HI:
857 *(unsigned short *)loc = v >> 16;
858 break;
859
860 case R_PPC_ADDR16_LO:
861 *(unsigned short *)loc = v;
862 break;
863#endif
864
Eric Andersen2bf658d2001-02-24 20:01:53 +0000865#if defined(__mips__)
866 case R_MIPS_26:
867 if (v % 4)
868 ret = obj_reloc_dangerous;
869 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
870 ret = obj_reloc_overflow;
871 *loc =
872 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
873 0x03ffffff);
874 break;
875
876 case R_MIPS_HI16:
877 {
878 struct mips_hi16 *n;
879
880 /* We cannot relocate this one now because we don't know the value
881 of the carry we need to add. Save the information, and let LO16
882 do the actual relocation. */
883 n = (struct mips_hi16 *) xmalloc(sizeof *n);
884 n->addr = loc;
885 n->value = v;
886 n->next = ifile->mips_hi16_list;
887 ifile->mips_hi16_list = n;
888 break;
889 }
890
891 case R_MIPS_LO16:
892 {
893 unsigned long insnlo = *loc;
894 Elf32_Addr val, vallo;
895
896 /* Sign extend the addend we extract from the lo insn. */
897 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
898
899 if (ifile->mips_hi16_list != NULL) {
900 struct mips_hi16 *l;
901
902 l = ifile->mips_hi16_list;
903 while (l != NULL) {
904 struct mips_hi16 *next;
905 unsigned long insn;
906
907 /* The value for the HI16 had best be the same. */
908 assert(v == l->value);
909
910 /* Do the HI16 relocation. Note that we actually don't
911 need to know anything about the LO16 itself, except where
912 to find the low 16 bits of the addend needed by the LO16. */
913 insn = *l->addr;
914 val =
915 ((insn & 0xffff) << 16) +
916 vallo;
917 val += v;
918
919 /* Account for the sign extension that will happen in the
920 low bits. */
921 val =
922 ((val >> 16) +
923 ((val & 0x8000) !=
924 0)) & 0xffff;
925
926 insn = (insn & ~0xffff) | val;
927 *l->addr = insn;
928
929 next = l->next;
930 free(l);
931 l = next;
932 }
933
934 ifile->mips_hi16_list = NULL;
935 }
936
937 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
938 val = v + vallo;
939 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
940 *loc = insnlo;
941 break;
942 }
943#endif
944
Eric Andersen21adca72000-12-06 18:18:26 +0000945#if defined(__arm__)
946#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000947 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000948 *loc += v - dot;
949 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000950#elif defined(__i386__)
951 case R_386_PLT32:
952 case R_386_PC32:
953 *loc += v - dot;
954 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000955#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000956 case R_68K_PC8:
957 v -= dot;
958 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
959 ret = obj_reloc_overflow;
960 *(char *)loc = v;
961 break;
962 case R_68K_PC16:
963 v -= dot;
964 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
965 ret = obj_reloc_overflow;
966 *(short *)loc = v;
967 break;
968 case R_68K_PC32:
969 *(int *)loc = v - dot;
970 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000971#elif defined(__powerpc__)
972 case R_PPC_REL32:
973 *loc = v - dot;
974 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000975#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000976
Eric Andersenfe4208f2000-09-24 03:44:29 +0000977#if defined(__sh__)
978 case R_SH_PLT32:
979 *loc = v - dot;
980 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000981#elif defined(__i386__)
982#endif
983
984#if defined(BB_USE_PLT_ENTRIES)
985
986#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000987 case R_ARM_PC24:
988 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000989#endif
990#if defined(__powerpc__)
991 case R_PPC_REL24:
992#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000993 /* find the plt entry and initialize it if necessary */
994 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000995
996 pe = (struct arch_plt_entry*) &isym->pltent;
997
Eric Andersen21adca72000-12-06 18:18:26 +0000998 if (! pe->inited) {
999 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001000
1001 /* generate some machine code */
1002
1003#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001004 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1005 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001006#endif
1007#if defined(__powerpc__)
1008 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1009 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1010 ip[2] = 0x7d6903a6; /* mtctr r11 */
1011 ip[3] = 0x4e800420; /* bctr */
1012#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001013 pe->inited = 1;
1014 }
1015
1016 /* relative distance to target */
1017 v -= dot;
1018 /* if the target is too far away.... */
1019 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1020 /* go via the plt */
1021 v = plt + pe->offset - dot;
1022 }
1023 if (v & 3)
1024 ret = obj_reloc_dangerous;
1025
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001026 /* merge the offset into the instruction. */
1027#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001028 /* Convert to words. */
1029 v >>= 2;
1030
Eric Andersen21adca72000-12-06 18:18:26 +00001031 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001032#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001033#if defined(__powerpc__)
1034 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1035#endif
1036 break;
1037#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001038
Eric Andersen21adca72000-12-06 18:18:26 +00001039#if defined(__arm__)
1040#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001041 case R_SH_GLOB_DAT:
1042 case R_SH_JMP_SLOT:
1043 *loc = v;
1044 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001045#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001046 case R_386_GLOB_DAT:
1047 case R_386_JMP_SLOT:
1048 *loc = v;
1049 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001050#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001051 case R_68K_GLOB_DAT:
1052 case R_68K_JMP_SLOT:
1053 *loc = v;
1054 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001055#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001056
Eric Andersen21adca72000-12-06 18:18:26 +00001057#if defined(__arm__)
1058#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001059 case R_SH_RELATIVE:
1060 *loc += f->baseaddr + rel->r_addend;
1061 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001062#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001063 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001064 *loc += f->baseaddr;
1065 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001066#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001067 case R_68K_RELATIVE:
1068 *(int *)loc += f->baseaddr;
1069 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001070#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001071
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001072#if defined(BB_USE_GOT_ENTRIES)
1073
Eric Andersen8ae319a2001-05-21 16:09:18 +00001074#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001075#if defined(__sh__)
1076 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001077#elif defined(__arm__)
1078 case R_ARM_GOTPC:
1079#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001080 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001081#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001082 assert(got != 0);
1083#if defined(__sh__)
1084 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001085#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001086 *loc += got - dot;
1087#endif
1088 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001089#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001090
Eric Andersenfe4208f2000-09-24 03:44:29 +00001091#if defined(__sh__)
1092 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001093#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001094 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001095#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001096 case R_386_GOT32:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001097#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001098 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001099#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001100 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001101 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001102 if (!isym->gotent.reloc_done) {
1103 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001104 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001105 }
Eric Andersen21adca72000-12-06 18:18:26 +00001106 /* make the reloc with_respect_to_.got */
1107#if defined(__sh__)
1108 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001109#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001110 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001111#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001112 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001113
Eric Andersen21adca72000-12-06 18:18:26 +00001114 /* address relative to the got */
Eric Andersenb4a26e62001-06-19 15:00:52 +00001115#if !defined(__mc68000__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001116#if defined(__sh__)
1117 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001118#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001119 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001120#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001121 case R_386_GOTOFF:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001122#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001123 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001124#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001125 assert(got != 0);
1126 *loc += v - got;
1127 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001128#endif // __mc68000__
Eric Andersen9f16d612000-06-12 23:11:16 +00001129
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001130#endif /* BB_USE_GOT_ENTRIES */
1131
Eric Andersen9f16d612000-06-12 23:11:16 +00001132 default:
Eric Andersen21125542000-12-13 16:41:29 +00001133 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001134 ret = obj_reloc_unhandled;
1135 break;
1136 }
1137
1138 return ret;
1139}
1140
Eric Andersen044228d2001-07-17 01:12:36 +00001141static int arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001142{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001143#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001144 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001145 int i;
1146#if defined(BB_USE_GOT_ENTRIES)
1147 int got_offset = 0, gotneeded = 0;
1148#endif
1149#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001150 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001151#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001152 struct obj_section *relsec, *symsec, *strsec;
1153 ElfW(RelM) *rel, *relend;
1154 ElfW(Sym) *symtab, *extsym;
1155 const char *strtab, *name;
1156 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001157
Eric Andersen21adca72000-12-06 18:18:26 +00001158 for (i = 0; i < f->header.e_shnum; ++i) {
1159 relsec = f->sections[i];
1160 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001161 continue;
1162
Eric Andersen21adca72000-12-06 18:18:26 +00001163 symsec = f->sections[relsec->header.sh_link];
1164 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001165
Eric Andersen21adca72000-12-06 18:18:26 +00001166 rel = (ElfW(RelM) *) relsec->contents;
1167 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1168 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001169 strtab = (const char *) strsec->contents;
1170
1171 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001172 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001173
1174 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001175#if defined(__arm__)
1176 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001177 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001178#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001179 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001180 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001181#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001182 case R_386_GOT32:
1183 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001184#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001185 case R_68K_GOT32:
1186 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001187#endif
1188
1189#if defined(__powerpc__)
1190 case R_PPC_REL24:
1191 pltneeded = 1;
1192 break;
1193#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001194
1195#if defined(__arm__)
1196 case R_ARM_PC24:
1197 case R_ARM_PLT32:
1198 pltneeded = 1;
1199 break;
1200
1201 case R_ARM_GOTPC:
1202 case R_ARM_GOTOFF:
1203 gotneeded = 1;
1204 if (got_offset == 0)
1205 got_offset = 4;
1206#elif defined(__sh__)
1207 case R_SH_GOTPC:
1208 case R_SH_GOTOFF:
1209 gotneeded = 1;
1210#elif defined(__i386__)
1211 case R_386_GOTPC:
1212 case R_386_GOTOFF:
1213 gotneeded = 1;
1214#endif
1215
1216 default:
1217 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001218 }
1219
Eric Andersen21adca72000-12-06 18:18:26 +00001220 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001221 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001222 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001223 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001224 }
1225 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001226#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001227 if (!intsym->gotent.offset_done) {
1228 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001229 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001230 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001231 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001232#endif
1233#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001234 if (pltneeded && intsym->pltent.allocated == 0) {
1235 intsym->pltent.allocated = 1;
1236 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001237 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001238 intsym->pltent.inited = 0;
1239 pltneeded = 0;
1240 }
1241#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001242 }
1243 }
Eric Andersen21adca72000-12-06 18:18:26 +00001244
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001245#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001246 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001247 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001248
Eric Andersene76c3b02001-04-05 03:14:39 +00001249 if (myrelsec) {
1250 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001251 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001252 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001253 BB_GOT_ENTRY_SIZE,
1254 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001255 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001256 }
1257
Eric Andersene76c3b02001-04-05 03:14:39 +00001258 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001259 }
Eric Andersen21adca72000-12-06 18:18:26 +00001260#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001261
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001262#if defined(BB_USE_PLT_ENTRIES)
1263 if (plt_offset)
1264 ifile->plt = obj_create_alloced_section(f, ".plt",
1265 BB_PLT_ENTRY_SIZE,
1266 plt_offset);
1267#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001268#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001269 return 1;
1270}
1271
Eric Andersen044228d2001-07-17 01:12:36 +00001272static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001273{
1274 return 1;
1275}
1276
1277
1278/*======================================================================*/
1279
1280/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001281static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001282{
1283 unsigned long h = 0;
1284 unsigned long g;
1285 unsigned char ch;
1286
1287 while (n > 0) {
1288 ch = *name++;
1289 h = (h << 4) + ch;
1290 if ((g = (h & 0xf0000000)) != 0) {
1291 h ^= g >> 24;
1292 h &= ~g;
1293 }
1294 n--;
1295 }
1296 return h;
1297}
1298
Eric Andersen044228d2001-07-17 01:12:36 +00001299static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001300{
1301 return obj_elf_hash_n(name, strlen(name));
1302}
1303
1304#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1305/* Get the kernel version in the canonical integer form. */
1306
1307static int get_kernel_version(char str[STRVERSIONLEN])
1308{
1309 struct utsname uts_info;
Eric Andersen044228d2001-07-17 01:12:36 +00001310 int kv;
Eric Andersen9f16d612000-06-12 23:11:16 +00001311
1312 if (uname(&uts_info) < 0)
1313 return -1;
1314 strncpy(str, uts_info.release, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00001315
Eric Andersen044228d2001-07-17 01:12:36 +00001316 kv = get_kernel_revision();
1317 if(kv==0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001318 return -1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001319}
1320
1321/* String comparison for non-co-versioned kernel and module. */
1322
1323static int ncv_strcmp(const char *a, const char *b)
1324{
1325 size_t alen = strlen(a), blen = strlen(b);
1326
1327 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1328 return strncmp(a, b, alen);
1329 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1330 return strncmp(a, b, blen);
1331 else
1332 return strcmp(a, b);
1333}
1334
1335/* String hashing for non-co-versioned kernel and module. Here
1336 we are simply forced to drop the crc from the hash. */
1337
1338static unsigned long ncv_symbol_hash(const char *str)
1339{
1340 size_t len = strlen(str);
1341 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1342 len -= 10;
1343 return obj_elf_hash_n(str, len);
1344}
1345
Eric Andersen044228d2001-07-17 01:12:36 +00001346static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001347obj_set_symbol_compare(struct obj_file *f,
1348 int (*cmp) (const char *, const char *),
1349 unsigned long (*hash) (const char *))
1350{
1351 if (cmp)
1352 f->symbol_cmp = cmp;
1353 if (hash) {
1354 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1355 int i;
1356
1357 f->symbol_hash = hash;
1358
1359 memcpy(tmptab, f->symtab, sizeof(tmptab));
1360 memset(f->symtab, 0, sizeof(f->symtab));
1361
1362 for (i = 0; i < HASH_BUCKETS; ++i)
1363 for (sym = tmptab[i]; sym; sym = next) {
1364 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1365 next = sym->next;
1366 sym->next = f->symtab[h];
1367 f->symtab[h] = sym;
1368 }
1369 }
1370}
1371
1372#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1373
Eric Andersen044228d2001-07-17 01:12:36 +00001374static struct obj_symbol *
1375obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001376 unsigned long symidx, int info,
1377 int secidx, ElfW(Addr) value,
1378 unsigned long size)
1379{
1380 struct obj_symbol *sym;
1381 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1382 int n_type = ELFW(ST_TYPE) (info);
1383 int n_binding = ELFW(ST_BIND) (info);
1384
1385 for (sym = f->symtab[hash]; sym; sym = sym->next)
1386 if (f->symbol_cmp(sym->name, name) == 0) {
1387 int o_secidx = sym->secidx;
1388 int o_info = sym->info;
1389 int o_type = ELFW(ST_TYPE) (o_info);
1390 int o_binding = ELFW(ST_BIND) (o_info);
1391
1392 /* A redefinition! Is it legal? */
1393
1394 if (secidx == SHN_UNDEF)
1395 return sym;
1396 else if (o_secidx == SHN_UNDEF)
1397 goto found;
1398 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1399 /* Cope with local and global symbols of the same name
1400 in the same object file, as might have been created
1401 by ld -r. The only reason locals are now seen at this
1402 level at all is so that we can do semi-sensible things
1403 with parameters. */
1404
1405 struct obj_symbol *nsym, **p;
1406
1407 nsym = arch_new_symbol();
1408 nsym->next = sym->next;
1409 nsym->ksymidx = -1;
1410
1411 /* Excise the old (local) symbol from the hash chain. */
1412 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1413 continue;
1414 *p = sym = nsym;
1415 goto found;
1416 } else if (n_binding == STB_LOCAL) {
1417 /* Another symbol of the same name has already been defined.
1418 Just add this to the local table. */
1419 sym = arch_new_symbol();
1420 sym->next = NULL;
1421 sym->ksymidx = -1;
1422 f->local_symtab[symidx] = sym;
1423 goto found;
1424 } else if (n_binding == STB_WEAK)
1425 return sym;
1426 else if (o_binding == STB_WEAK)
1427 goto found;
1428 /* Don't unify COMMON symbols with object types the programmer
1429 doesn't expect. */
1430 else if (secidx == SHN_COMMON
1431 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1432 return sym;
1433 else if (o_secidx == SHN_COMMON
1434 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1435 goto found;
1436 else {
1437 /* Don't report an error if the symbol is coming from
1438 the kernel or some external module. */
1439 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001440 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001441 return sym;
1442 }
1443 }
1444
1445 /* Completely new symbol. */
1446 sym = arch_new_symbol();
1447 sym->next = f->symtab[hash];
1448 f->symtab[hash] = sym;
1449 sym->ksymidx = -1;
1450
Eric Andersen66ca9482001-06-28 21:36:06 +00001451 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1452 if (symidx >= f->local_symtab_size)
1453 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1454 name, (long) symidx, (long) f->local_symtab_size);
1455 else
1456 f->local_symtab[symidx] = sym;
1457 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001458
1459 found:
1460 sym->name = name;
1461 sym->value = value;
1462 sym->size = size;
1463 sym->secidx = secidx;
1464 sym->info = info;
1465
1466 return sym;
1467}
1468
Eric Andersen044228d2001-07-17 01:12:36 +00001469static struct obj_symbol *
1470obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001471{
1472 struct obj_symbol *sym;
1473 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1474
1475 for (sym = f->symtab[hash]; sym; sym = sym->next)
1476 if (f->symbol_cmp(sym->name, name) == 0)
1477 return sym;
1478
1479 return NULL;
1480}
1481
Eric Andersen044228d2001-07-17 01:12:36 +00001482static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001483 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1484{
1485 if (sym) {
1486 if (sym->secidx >= SHN_LORESERVE)
1487 return sym->value;
1488
1489 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1490 } else {
1491 /* As a special case, a NULL sym has value zero. */
1492 return 0;
1493 }
1494}
1495
Eric Andersen044228d2001-07-17 01:12:36 +00001496static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001497{
1498 int i, n = f->header.e_shnum;
1499
1500 for (i = 0; i < n; ++i)
1501 if (strcmp(f->sections[i]->name, name) == 0)
1502 return f->sections[i];
1503
1504 return NULL;
1505}
1506
1507static int obj_load_order_prio(struct obj_section *a)
1508{
1509 unsigned long af, ac;
1510
1511 af = a->header.sh_flags;
1512
1513 ac = 0;
1514 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1515 strcmp(a->name + 5, ".init"))
1516 ac |= 32;
1517 if (af & SHF_ALLOC)
1518 ac |= 16;
1519 if (!(af & SHF_WRITE))
1520 ac |= 8;
1521 if (af & SHF_EXECINSTR)
1522 ac |= 4;
1523 if (a->header.sh_type != SHT_NOBITS)
1524 ac |= 2;
1525
1526 return ac;
1527}
1528
Eric Andersen044228d2001-07-17 01:12:36 +00001529static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001530obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1531{
1532 struct obj_section **p;
1533 int prio = obj_load_order_prio(sec);
1534 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1535 if (obj_load_order_prio(*p) < prio)
1536 break;
1537 sec->load_next = *p;
1538 *p = sec;
1539}
1540
Eric Andersen044228d2001-07-17 01:12:36 +00001541static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001542 const char *name,
1543 unsigned long align,
1544 unsigned long size)
1545{
1546 int newidx = f->header.e_shnum++;
1547 struct obj_section *sec;
1548
1549 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1550 f->sections[newidx] = sec = arch_new_section();
1551
1552 memset(sec, 0, sizeof(*sec));
1553 sec->header.sh_type = SHT_PROGBITS;
1554 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1555 sec->header.sh_size = size;
1556 sec->header.sh_addralign = align;
1557 sec->name = name;
1558 sec->idx = newidx;
1559 if (size)
1560 sec->contents = xmalloc(size);
1561
1562 obj_insert_section_load_order(f, sec);
1563
1564 return sec;
1565}
1566
Eric Andersen044228d2001-07-17 01:12:36 +00001567static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001568 const char *name,
1569 unsigned long align,
1570 unsigned long size)
1571{
1572 int newidx = f->header.e_shnum++;
1573 struct obj_section *sec;
1574
1575 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1576 f->sections[newidx] = sec = arch_new_section();
1577
1578 memset(sec, 0, sizeof(*sec));
1579 sec->header.sh_type = SHT_PROGBITS;
1580 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1581 sec->header.sh_size = size;
1582 sec->header.sh_addralign = align;
1583 sec->name = name;
1584 sec->idx = newidx;
1585 if (size)
1586 sec->contents = xmalloc(size);
1587
1588 sec->load_next = f->load_order;
1589 f->load_order = sec;
1590 if (f->load_order_search_start == &f->load_order)
1591 f->load_order_search_start = &sec->load_next;
1592
1593 return sec;
1594}
1595
Eric Andersen044228d2001-07-17 01:12:36 +00001596static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001597{
1598 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001599 if (more) {
1600 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1601 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001602 return sec->contents + oldsize;
1603}
1604
1605
Eric Andersen9f16d612000-06-12 23:11:16 +00001606/* Conditionally add the symbols from the given symbol set to the
1607 new module. */
1608
1609static int
1610add_symbols_from(
1611 struct obj_file *f,
1612 int idx, struct new_module_symbol *syms, size_t nsyms)
1613{
1614 struct new_module_symbol *s;
1615 size_t i;
1616 int used = 0;
1617
1618 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1619
1620 /* Only add symbols that are already marked external. If we
1621 override locals we may cause problems for argument initialization.
1622 We will also create a false dependency on the module. */
1623 struct obj_symbol *sym;
1624
1625 sym = obj_find_symbol(f, (char *) s->name);
1626 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1627 sym = obj_add_symbol(f, (char *) s->name, -1,
1628 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1629 idx, s->value, 0);
1630 /* Did our symbol just get installed? If so, mark the
1631 module as "used". */
1632 if (sym->secidx == idx)
1633 used = 1;
1634 }
1635 }
1636
1637 return used;
1638}
1639
1640static void add_kernel_symbols(struct obj_file *f)
1641{
1642 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001643 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001644
1645 /* Add module symbols first. */
1646
1647 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1648 if (m->nsyms
1649 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1650 m->nsyms)) m->used = 1, ++nused;
1651
1652 n_ext_modules_used = nused;
1653
1654 /* And finally the symbols from the kernel proper. */
1655
1656 if (nksyms)
1657 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1658}
1659
1660static char *get_modinfo_value(struct obj_file *f, const char *key)
1661{
1662 struct obj_section *sec;
1663 char *p, *v, *n, *ep;
1664 size_t klen = strlen(key);
1665
1666 sec = obj_find_section(f, ".modinfo");
1667 if (sec == NULL)
1668 return NULL;
1669 p = sec->contents;
1670 ep = p + sec->header.sh_size;
1671 while (p < ep) {
1672 v = strchr(p, '=');
1673 n = strchr(p, '\0');
1674 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001675 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001676 return v + 1;
1677 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001678 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001679 return n;
1680 }
1681 p = n + 1;
1682 }
1683
1684 return NULL;
1685}
1686
1687
1688/*======================================================================*/
1689/* Functions relating to module loading in pre 2.1 kernels. */
1690
1691static int
1692old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1693{
1694 while (argc > 0) {
1695 char *p, *q;
1696 struct obj_symbol *sym;
1697 int *loc;
1698
1699 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001700 if ((q = strchr(p, '=')) == NULL) {
1701 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001702 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001703 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001704 *q++ = '\0';
1705
1706 sym = obj_find_symbol(f, p);
1707
1708 /* Also check that the parameter was not resolved from the kernel. */
1709 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001710 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001711 return 0;
1712 }
1713
1714 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1715
1716 /* Do C quoting if we begin with a ". */
1717 if (*q == '"') {
1718 char *r, *str;
1719
1720 str = alloca(strlen(q));
1721 for (r = str, q++; *q != '"'; ++q, ++r) {
1722 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001723 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001724 return 0;
1725 } else if (*q == '\\')
1726 switch (*++q) {
1727 case 'a':
1728 *r = '\a';
1729 break;
1730 case 'b':
1731 *r = '\b';
1732 break;
1733 case 'e':
1734 *r = '\033';
1735 break;
1736 case 'f':
1737 *r = '\f';
1738 break;
1739 case 'n':
1740 *r = '\n';
1741 break;
1742 case 'r':
1743 *r = '\r';
1744 break;
1745 case 't':
1746 *r = '\t';
1747 break;
1748
1749 case '0':
1750 case '1':
1751 case '2':
1752 case '3':
1753 case '4':
1754 case '5':
1755 case '6':
1756 case '7':
1757 {
1758 int c = *q - '0';
1759 if (q[1] >= '0' && q[1] <= '7') {
1760 c = (c * 8) + *++q - '0';
1761 if (q[1] >= '0' && q[1] <= '7')
1762 c = (c * 8) + *++q - '0';
1763 }
1764 *r = c;
1765 }
1766 break;
1767
1768 default:
1769 *r = *q;
1770 break;
1771 } else
1772 *r = *q;
1773 }
1774 *r = '\0';
1775 obj_string_patch(f, sym->secidx, sym->value, str);
1776 } else if (*q >= '0' && *q <= '9') {
1777 do
1778 *loc++ = strtoul(q, &q, 0);
1779 while (*q++ == ',');
1780 } else {
1781 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001782 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001783 char *r; /* To search for commas */
1784
1785 /* Break the string with comas */
1786 while ((r = strchr(q, ',')) != (char *) NULL) {
1787 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001788 obj_string_patch(f, sym->secidx, myloc - contents, q);
1789 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001790 q = r;
1791 }
1792
1793 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001794 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001795 }
1796
1797 argc--, argv++;
1798 }
1799
1800 return 1;
1801}
1802
1803#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1804static int old_is_module_checksummed(struct obj_file *f)
1805{
1806 return obj_find_symbol(f, "Using_Versions") != NULL;
1807}
1808/* Get the module's kernel version in the canonical integer form. */
1809
1810static int
1811old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1812{
1813 struct obj_symbol *sym;
1814 char *p, *q;
1815 int a, b, c;
1816
1817 sym = obj_find_symbol(f, "kernel_version");
1818 if (sym == NULL)
1819 return -1;
1820
1821 p = f->sections[sym->secidx]->contents + sym->value;
1822 strncpy(str, p, STRVERSIONLEN);
1823
1824 a = strtoul(p, &p, 10);
1825 if (*p != '.')
1826 return -1;
1827 b = strtoul(p + 1, &p, 10);
1828 if (*p != '.')
1829 return -1;
1830 c = strtoul(p + 1, &q, 10);
1831 if (p + 1 == q)
1832 return -1;
1833
1834 return a << 16 | b << 8 | c;
1835}
1836
1837#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1838
Eric Andersenf5d5e772001-01-24 23:34:48 +00001839#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001840
1841/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1842
Eric Andersen8c185f92000-09-22 00:38:07 +00001843static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001844{
1845 struct old_kernel_sym *ks, *k;
1846 struct new_module_symbol *s;
1847 struct external_module *mod;
1848 int nks, nms, nmod, i;
1849
1850 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001851 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001852 if (nks)
1853 perror_msg("get_kernel_syms: %s", m_name);
1854 else
1855 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001856 return 0;
1857 }
1858
1859 ks = k = xmalloc(nks * sizeof(*ks));
1860
1861 if (get_kernel_syms(ks) != nks) {
1862 perror("inconsistency with get_kernel_syms -- is someone else "
1863 "playing with modules?");
1864 free(ks);
1865 return 0;
1866 }
1867
1868 /* Collect the module information. */
1869
1870 mod = NULL;
1871 nmod = -1;
1872
1873 while (k->name[0] == '#' && k->name[1]) {
1874 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001875
1876 /* Find out how many symbols this module has. */
1877 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1878 continue;
1879 nms = k2 - k - 1;
1880
1881 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1882 mod[nmod].name = k->name + 1;
1883 mod[nmod].addr = k->value;
1884 mod[nmod].used = 0;
1885 mod[nmod].nsyms = nms;
1886 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1887
1888 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1889 s->name = (unsigned long) k->name;
1890 s->value = k->value;
1891 }
1892
1893 k = k2;
1894 }
1895
1896 ext_modules = mod;
1897 n_ext_modules = nmod + 1;
1898
1899 /* Now collect the symbols for the kernel proper. */
1900
1901 if (k->name[0] == '#')
1902 ++k;
1903
1904 nksyms = nms = nks - (k - ks);
1905 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1906
1907 for (i = 0; i < nms; ++i, ++s, ++k) {
1908 s->name = (unsigned long) k->name;
1909 s->value = k->value;
1910 }
1911
1912 return 1;
1913}
1914
1915/* Return the kernel symbol checksum version, or zero if not used. */
1916
1917static int old_is_kernel_checksummed(void)
1918{
1919 /* Using_Versions is the first symbol. */
1920 if (nksyms > 0
1921 && strcmp((char *) ksyms[0].name,
1922 "Using_Versions") == 0) return ksyms[0].value;
1923 else
1924 return 0;
1925}
1926
1927
1928static int old_create_mod_use_count(struct obj_file *f)
1929{
1930 struct obj_section *sec;
1931
1932 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1933 sizeof(long));
1934
1935 obj_add_symbol(f, "mod_use_count_", -1,
1936 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1937 sizeof(long));
1938
1939 return 1;
1940}
1941
1942static int
1943old_init_module(const char *m_name, struct obj_file *f,
1944 unsigned long m_size)
1945{
1946 char *image;
1947 struct old_mod_routines routines;
1948 struct old_symbol_table *symtab;
1949 int ret;
1950
1951 /* Create the symbol table */
1952 {
1953 int nsyms = 0, strsize = 0, total;
1954
1955 /* Size things first... */
1956 if (flag_export) {
1957 int i;
1958 for (i = 0; i < HASH_BUCKETS; ++i) {
1959 struct obj_symbol *sym;
1960 for (sym = f->symtab[i]; sym; sym = sym->next)
1961 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1962 && sym->secidx <= SHN_HIRESERVE)
1963 {
1964 sym->ksymidx = nsyms++;
1965 strsize += strlen(sym->name) + 1;
1966 }
1967 }
1968 }
1969
1970 total = (sizeof(struct old_symbol_table)
1971 + nsyms * sizeof(struct old_module_symbol)
1972 + n_ext_modules_used * sizeof(struct old_module_ref)
1973 + strsize);
1974 symtab = xmalloc(total);
1975 symtab->size = total;
1976 symtab->n_symbols = nsyms;
1977 symtab->n_refs = n_ext_modules_used;
1978
1979 if (flag_export && nsyms) {
1980 struct old_module_symbol *ksym;
1981 char *str;
1982 int i;
1983
1984 ksym = symtab->symbol;
1985 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1986 + n_ext_modules_used * sizeof(struct old_module_ref));
1987
1988 for (i = 0; i < HASH_BUCKETS; ++i) {
1989 struct obj_symbol *sym;
1990 for (sym = f->symtab[i]; sym; sym = sym->next)
1991 if (sym->ksymidx >= 0) {
1992 ksym->addr = obj_symbol_final_value(f, sym);
1993 ksym->name =
1994 (unsigned long) str - (unsigned long) symtab;
1995
Matt Kraai70a78552001-01-04 02:00:17 +00001996 strcpy(str, sym->name);
1997 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001998 ksym++;
1999 }
2000 }
2001 }
2002
2003 if (n_ext_modules_used) {
2004 struct old_module_ref *ref;
2005 int i;
2006
2007 ref = (struct old_module_ref *)
2008 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2009
2010 for (i = 0; i < n_ext_modules; ++i)
2011 if (ext_modules[i].used)
2012 ref++->module = ext_modules[i].addr;
2013 }
2014 }
2015
2016 /* Fill in routines. */
2017
2018 routines.init =
2019 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2020 routines.cleanup =
2021 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2022
2023 /* Whew! All of the initialization is complete. Collect the final
2024 module image and give it to the kernel. */
2025
2026 image = xmalloc(m_size);
2027 obj_create_image(f, image);
2028
2029 /* image holds the complete relocated module, accounting correctly for
2030 mod_use_count. However the old module kernel support assume that
2031 it is receiving something which does not contain mod_use_count. */
2032 ret = old_sys_init_module(m_name, image + sizeof(long),
2033 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2034 : 0), &routines, symtab);
2035 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002036 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002037
2038 free(image);
2039 free(symtab);
2040
2041 return ret == 0;
2042}
2043
2044#else
2045
2046#define old_create_mod_use_count(x) TRUE
2047#define old_init_module(x, y, z) TRUE
2048
Eric Andersenf5d5e772001-01-24 23:34:48 +00002049#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002050
2051
2052
2053/*======================================================================*/
2054/* Functions relating to module loading after 2.1.18. */
2055
2056static int
2057new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2058{
2059 while (argc > 0) {
2060 char *p, *q, *key;
2061 struct obj_symbol *sym;
2062 char *contents, *loc;
2063 int min, max, n;
2064
2065 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002066 if ((q = strchr(p, '=')) == NULL) {
2067 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002068 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002069 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002070
2071 key = alloca(q - p + 6);
2072 memcpy(key, "parm_", 5);
2073 memcpy(key + 5, p, q - p);
2074 key[q - p + 5] = 0;
2075
2076 p = get_modinfo_value(f, key);
2077 key += 5;
2078 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002079 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002080 return 0;
2081 }
2082
2083 sym = obj_find_symbol(f, key);
2084
2085 /* Also check that the parameter was not resolved from the kernel. */
2086 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002087 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002088 return 0;
2089 }
2090
2091 if (isdigit(*p)) {
2092 min = strtoul(p, &p, 10);
2093 if (*p == '-')
2094 max = strtoul(p + 1, &p, 10);
2095 else
2096 max = min;
2097 } else
2098 min = max = 1;
2099
2100 contents = f->sections[sym->secidx]->contents;
2101 loc = contents + sym->value;
2102 n = (*++q != '\0');
2103
2104 while (1) {
2105 if ((*p == 's') || (*p == 'c')) {
2106 char *str;
2107
2108 /* Do C quoting if we begin with a ", else slurp the lot. */
2109 if (*q == '"') {
2110 char *r;
2111
2112 str = alloca(strlen(q));
2113 for (r = str, q++; *q != '"'; ++q, ++r) {
2114 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002115 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002116 key);
2117 return 0;
2118 } else if (*q == '\\')
2119 switch (*++q) {
2120 case 'a':
2121 *r = '\a';
2122 break;
2123 case 'b':
2124 *r = '\b';
2125 break;
2126 case 'e':
2127 *r = '\033';
2128 break;
2129 case 'f':
2130 *r = '\f';
2131 break;
2132 case 'n':
2133 *r = '\n';
2134 break;
2135 case 'r':
2136 *r = '\r';
2137 break;
2138 case 't':
2139 *r = '\t';
2140 break;
2141
2142 case '0':
2143 case '1':
2144 case '2':
2145 case '3':
2146 case '4':
2147 case '5':
2148 case '6':
2149 case '7':
2150 {
2151 int c = *q - '0';
2152 if (q[1] >= '0' && q[1] <= '7') {
2153 c = (c * 8) + *++q - '0';
2154 if (q[1] >= '0' && q[1] <= '7')
2155 c = (c * 8) + *++q - '0';
2156 }
2157 *r = c;
2158 }
2159 break;
2160
2161 default:
2162 *r = *q;
2163 break;
2164 } else
2165 *r = *q;
2166 }
2167 *r = '\0';
2168 ++q;
2169 } else {
2170 char *r;
2171
2172 /* In this case, the string is not quoted. We will break
2173 it using the coma (like for ints). If the user wants to
2174 include comas in a string, he just has to quote it */
2175
2176 /* Search the next coma */
2177 r = strchr(q, ',');
2178
2179 /* Found ? */
2180 if (r != (char *) NULL) {
2181 /* Recopy the current field */
2182 str = alloca(r - q + 1);
2183 memcpy(str, q, r - q);
2184
2185 /* I don't know if it is usefull, as the previous case
2186 doesn't null terminate the string ??? */
2187 str[r - q] = '\0';
2188
2189 /* Keep next fields */
2190 q = r;
2191 } else {
2192 /* last string */
2193 str = q;
2194 q = "";
2195 }
2196 }
2197
2198 if (*p == 's') {
2199 /* Normal string */
2200 obj_string_patch(f, sym->secidx, loc - contents, str);
2201 loc += tgt_sizeof_char_p;
2202 } else {
2203 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002204 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002205
2206 /* Get the size of each member */
2207 /* Probably we should do that outside the loop ? */
2208 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002209 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002210 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002211 return 0;
2212 }
2213 charssize = strtoul(p + 1, (char **) NULL, 10);
2214
2215 /* Check length */
2216 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002217 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002218 charssize - 1);
2219 return 0;
2220 }
2221
2222 /* Copy to location */
2223 strcpy((char *) loc, str);
2224 loc += charssize;
2225 }
2226 } else {
2227 long v = strtoul(q, &q, 0);
2228 switch (*p) {
2229 case 'b':
2230 *loc++ = v;
2231 break;
2232 case 'h':
2233 *(short *) loc = v;
2234 loc += tgt_sizeof_short;
2235 break;
2236 case 'i':
2237 *(int *) loc = v;
2238 loc += tgt_sizeof_int;
2239 break;
2240 case 'l':
2241 *(long *) loc = v;
2242 loc += tgt_sizeof_long;
2243 break;
2244
2245 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002246 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002247 return 0;
2248 }
2249 }
2250
2251 retry_end_of_value:
2252 switch (*q) {
2253 case '\0':
2254 goto end_of_arg;
2255
2256 case ' ':
2257 case '\t':
2258 case '\n':
2259 case '\r':
2260 ++q;
2261 goto retry_end_of_value;
2262
2263 case ',':
2264 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002265 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002266 return 0;
2267 }
2268 ++q;
2269 break;
2270
2271 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002272 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002273 return 0;
2274 }
2275 }
2276
2277 end_of_arg:
2278 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002279 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002280 return 0;
2281 }
2282
2283 argc--, argv++;
2284 }
2285
2286 return 1;
2287}
2288
2289#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2290static int new_is_module_checksummed(struct obj_file *f)
2291{
2292 const char *p = get_modinfo_value(f, "using_checksums");
2293 if (p)
2294 return atoi(p);
2295 else
2296 return 0;
2297}
2298
2299/* Get the module's kernel version in the canonical integer form. */
2300
2301static int
2302new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2303{
2304 char *p, *q;
2305 int a, b, c;
2306
2307 p = get_modinfo_value(f, "kernel_version");
2308 if (p == NULL)
2309 return -1;
2310 strncpy(str, p, STRVERSIONLEN);
2311
2312 a = strtoul(p, &p, 10);
2313 if (*p != '.')
2314 return -1;
2315 b = strtoul(p + 1, &p, 10);
2316 if (*p != '.')
2317 return -1;
2318 c = strtoul(p + 1, &q, 10);
2319 if (p + 1 == q)
2320 return -1;
2321
2322 return a << 16 | b << 8 | c;
2323}
2324
2325#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2326
2327
Eric Andersenf5d5e772001-01-24 23:34:48 +00002328#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002329
2330/* Fetch the loaded modules, and all currently exported symbols. */
2331
2332static int new_get_kernel_symbols(void)
2333{
2334 char *module_names, *mn;
2335 struct external_module *modules, *m;
2336 struct new_module_symbol *syms, *s;
2337 size_t ret, bufsize, nmod, nsyms, i, j;
2338
2339 /* Collect the loaded modules. */
2340
2341 module_names = xmalloc(bufsize = 256);
2342 retry_modules_load:
2343 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002344 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002345 module_names = xrealloc(module_names, bufsize = ret);
2346 goto retry_modules_load;
2347 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002348 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002349 return 0;
2350 }
2351
2352 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002353
2354 /* Collect the modules' symbols. */
2355
Mark Whitley94fd4802001-03-12 23:08:34 +00002356 if (nmod){
2357 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2358 memset(modules, 0, nmod * sizeof(*modules));
2359 for (i = 0, mn = module_names, m = modules;
2360 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2361 struct new_module_info info;
2362
2363 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2364 if (errno == ENOENT) {
2365 /* The module was removed out from underneath us. */
2366 continue;
2367 }
2368 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002369 return 0;
2370 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002371
2372 syms = xmalloc(bufsize = 1024);
2373 retry_mod_sym_load:
2374 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2375 switch (errno) {
2376 case ENOSPC:
2377 syms = xrealloc(syms, bufsize = ret);
2378 goto retry_mod_sym_load;
2379 case ENOENT:
2380 /* The module was removed out from underneath us. */
2381 continue;
2382 default:
2383 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2384 return 0;
2385 }
2386 }
2387 nsyms = ret;
2388
2389 m->name = mn;
2390 m->addr = info.addr;
2391 m->nsyms = nsyms;
2392 m->syms = syms;
2393
2394 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2395 s->name += (unsigned long) syms;
2396 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002397 }
2398 }
2399
2400 /* Collect the kernel's symbols. */
2401
2402 syms = xmalloc(bufsize = 16 * 1024);
2403 retry_kern_sym_load:
2404 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002405 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 syms = xrealloc(syms, bufsize = ret);
2407 goto retry_kern_sym_load;
2408 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002409 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002410 return 0;
2411 }
2412 nksyms = nsyms = ret;
2413 ksyms = syms;
2414
2415 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2416 s->name += (unsigned long) syms;
2417 }
2418 return 1;
2419}
2420
2421
2422/* Return the kernel symbol checksum version, or zero if not used. */
2423
2424static int new_is_kernel_checksummed(void)
2425{
2426 struct new_module_symbol *s;
2427 size_t i;
2428
2429 /* Using_Versions is not the first symbol, but it should be in there. */
2430
2431 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2432 if (strcmp((char *) s->name, "Using_Versions") == 0)
2433 return s->value;
2434
2435 return 0;
2436}
2437
2438
2439static int new_create_this_module(struct obj_file *f, const char *m_name)
2440{
2441 struct obj_section *sec;
2442
2443 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2444 sizeof(struct new_module));
2445 memset(sec->contents, 0, sizeof(struct new_module));
2446
2447 obj_add_symbol(f, "__this_module", -1,
2448 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2449 sizeof(struct new_module));
2450
2451 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2452 m_name);
2453
2454 return 1;
2455}
2456
2457
2458static int new_create_module_ksymtab(struct obj_file *f)
2459{
2460 struct obj_section *sec;
2461 int i;
2462
2463 /* We must always add the module references. */
2464
2465 if (n_ext_modules_used) {
2466 struct new_module_ref *dep;
2467 struct obj_symbol *tm;
2468
2469 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2470 (sizeof(struct new_module_ref)
2471 * n_ext_modules_used));
2472 if (!sec)
2473 return 0;
2474
2475 tm = obj_find_symbol(f, "__this_module");
2476 dep = (struct new_module_ref *) sec->contents;
2477 for (i = 0; i < n_ext_modules; ++i)
2478 if (ext_modules[i].used) {
2479 dep->dep = ext_modules[i].addr;
2480 obj_symbol_patch(f, sec->idx,
2481 (char *) &dep->ref - sec->contents, tm);
2482 dep->next_ref = 0;
2483 ++dep;
2484 }
2485 }
2486
2487 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2488 size_t nsyms;
2489 int *loaded;
2490
2491 sec =
2492 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2493 0);
2494
2495 /* We don't want to export symbols residing in sections that
2496 aren't loaded. There are a number of these created so that
2497 we make sure certain module options don't appear twice. */
2498
2499 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2500 while (--i >= 0)
2501 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2502
2503 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2504 struct obj_symbol *sym;
2505 for (sym = f->symtab[i]; sym; sym = sym->next)
2506 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2507 && sym->secidx <= SHN_HIRESERVE
2508 && (sym->secidx >= SHN_LORESERVE
2509 || loaded[sym->secidx])) {
2510 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2511
2512 obj_symbol_patch(f, sec->idx, ofs, sym);
2513 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2514 sym->name);
2515
2516 nsyms++;
2517 }
2518 }
2519
2520 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2521 }
2522
2523 return 1;
2524}
2525
2526
2527static int
2528new_init_module(const char *m_name, struct obj_file *f,
2529 unsigned long m_size)
2530{
2531 struct new_module *module;
2532 struct obj_section *sec;
2533 void *image;
2534 int ret;
2535 tgt_long m_addr;
2536
2537 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002538 if (!sec || !sec->contents) {
2539 perror_msg_and_die("corrupt module %s?",m_name);
2540 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002541 module = (struct new_module *) sec->contents;
2542 m_addr = sec->header.sh_addr;
2543
2544 module->size_of_struct = sizeof(*module);
2545 module->size = m_size;
2546 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2547
2548 sec = obj_find_section(f, "__ksymtab");
2549 if (sec && sec->header.sh_size) {
2550 module->syms = sec->header.sh_addr;
2551 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2552 }
2553
2554 if (n_ext_modules_used) {
2555 sec = obj_find_section(f, ".kmodtab");
2556 module->deps = sec->header.sh_addr;
2557 module->ndeps = n_ext_modules_used;
2558 }
2559
2560 module->init =
2561 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2562 module->cleanup =
2563 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2564
2565 sec = obj_find_section(f, "__ex_table");
2566 if (sec) {
2567 module->ex_table_start = sec->header.sh_addr;
2568 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2569 }
2570
2571 sec = obj_find_section(f, ".text.init");
2572 if (sec) {
2573 module->runsize = sec->header.sh_addr - m_addr;
2574 }
2575 sec = obj_find_section(f, ".data.init");
2576 if (sec) {
2577 if (!module->runsize ||
2578 module->runsize > sec->header.sh_addr - m_addr)
2579 module->runsize = sec->header.sh_addr - m_addr;
2580 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002581 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2582 if (sec && sec->header.sh_size) {
2583 module->archdata_start = (void*)sec->header.sh_addr;
2584 module->archdata_end = module->archdata_start + sec->header.sh_size;
2585 }
2586 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2587 if (sec && sec->header.sh_size) {
2588 module->kallsyms_start = (void*)sec->header.sh_addr;
2589 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2590 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002591
2592 if (!arch_init_module(f, module))
2593 return 0;
2594
2595 /* Whew! All of the initialization is complete. Collect the final
2596 module image and give it to the kernel. */
2597
2598 image = xmalloc(m_size);
2599 obj_create_image(f, image);
2600
Eric Andersen64c8b172001-04-05 07:33:10 +00002601 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002602 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002603 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002604
2605 free(image);
2606
2607 return ret == 0;
2608}
2609
2610#else
2611
2612#define new_init_module(x, y, z) TRUE
2613#define new_create_this_module(x, y) 0
2614#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002615#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002616
Eric Andersenf5d5e772001-01-24 23:34:48 +00002617#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002618
2619
2620/*======================================================================*/
2621
Eric Andersen044228d2001-07-17 01:12:36 +00002622static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002623obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2624 const char *string)
2625{
2626 struct obj_string_patch *p;
2627 struct obj_section *strsec;
2628 size_t len = strlen(string) + 1;
2629 char *loc;
2630
2631 p = xmalloc(sizeof(*p));
2632 p->next = f->string_patches;
2633 p->reloc_secidx = secidx;
2634 p->reloc_offset = offset;
2635 f->string_patches = p;
2636
2637 strsec = obj_find_section(f, ".kstrtab");
2638 if (strsec == NULL) {
2639 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2640 p->string_offset = 0;
2641 loc = strsec->contents;
2642 } else {
2643 p->string_offset = strsec->header.sh_size;
2644 loc = obj_extend_section(strsec, len);
2645 }
2646 memcpy(loc, string, len);
2647
2648 return 1;
2649}
2650
Eric Andersen044228d2001-07-17 01:12:36 +00002651static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002652obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2653 struct obj_symbol *sym)
2654{
2655 struct obj_symbol_patch *p;
2656
2657 p = xmalloc(sizeof(*p));
2658 p->next = f->symbol_patches;
2659 p->reloc_secidx = secidx;
2660 p->reloc_offset = offset;
2661 p->sym = sym;
2662 f->symbol_patches = p;
2663
2664 return 1;
2665}
2666
Eric Andersen044228d2001-07-17 01:12:36 +00002667static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002668{
2669 unsigned long i;
2670 int ret = 1;
2671
2672 for (i = 0; i < HASH_BUCKETS; ++i) {
2673 struct obj_symbol *sym;
2674 for (sym = f->symtab[i]; sym; sym = sym->next)
2675 if (sym->secidx == SHN_UNDEF) {
2676 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2677 sym->secidx = SHN_ABS;
2678 sym->value = 0;
2679 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002680 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002681 ret = 0;
2682 }
2683 }
2684 }
2685
2686 return ret;
2687}
2688
Eric Andersen044228d2001-07-17 01:12:36 +00002689static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002690{
2691 struct common_entry {
2692 struct common_entry *next;
2693 struct obj_symbol *sym;
2694 } *common_head = NULL;
2695
2696 unsigned long i;
2697
2698 for (i = 0; i < HASH_BUCKETS; ++i) {
2699 struct obj_symbol *sym;
2700 for (sym = f->symtab[i]; sym; sym = sym->next)
2701 if (sym->secidx == SHN_COMMON) {
2702 /* Collect all COMMON symbols and sort them by size so as to
2703 minimize space wasted by alignment requirements. */
2704 {
2705 struct common_entry **p, *n;
2706 for (p = &common_head; *p; p = &(*p)->next)
2707 if (sym->size <= (*p)->sym->size)
2708 break;
2709
2710 n = alloca(sizeof(*n));
2711 n->next = *p;
2712 n->sym = sym;
2713 *p = n;
2714 }
2715 }
2716 }
2717
2718 for (i = 1; i < f->local_symtab_size; ++i) {
2719 struct obj_symbol *sym = f->local_symtab[i];
2720 if (sym && sym->secidx == SHN_COMMON) {
2721 struct common_entry **p, *n;
2722 for (p = &common_head; *p; p = &(*p)->next)
2723 if (sym == (*p)->sym)
2724 break;
2725 else if (sym->size < (*p)->sym->size) {
2726 n = alloca(sizeof(*n));
2727 n->next = *p;
2728 n->sym = sym;
2729 *p = n;
2730 break;
2731 }
2732 }
2733 }
2734
2735 if (common_head) {
2736 /* Find the bss section. */
2737 for (i = 0; i < f->header.e_shnum; ++i)
2738 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2739 break;
2740
2741 /* If for some reason there hadn't been one, create one. */
2742 if (i == f->header.e_shnum) {
2743 struct obj_section *sec;
2744
2745 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2746 f->sections[i] = sec = arch_new_section();
2747 f->header.e_shnum = i + 1;
2748
2749 memset(sec, 0, sizeof(*sec));
2750 sec->header.sh_type = SHT_PROGBITS;
2751 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2752 sec->name = ".bss";
2753 sec->idx = i;
2754 }
2755
2756 /* Allocate the COMMONS. */
2757 {
2758 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2759 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2760 struct common_entry *c;
2761
2762 for (c = common_head; c; c = c->next) {
2763 ElfW(Addr) align = c->sym->value;
2764
2765 if (align > max_align)
2766 max_align = align;
2767 if (bss_size & (align - 1))
2768 bss_size = (bss_size | (align - 1)) + 1;
2769
2770 c->sym->secidx = i;
2771 c->sym->value = bss_size;
2772
2773 bss_size += c->sym->size;
2774 }
2775
2776 f->sections[i]->header.sh_size = bss_size;
2777 f->sections[i]->header.sh_addralign = max_align;
2778 }
2779 }
2780
2781 /* For the sake of patch relocation and parameter initialization,
2782 allocate zeroed data for NOBITS sections now. Note that after
2783 this we cannot assume NOBITS are really empty. */
2784 for (i = 0; i < f->header.e_shnum; ++i) {
2785 struct obj_section *s = f->sections[i];
2786 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002787 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002788 s->contents = memset(xmalloc(s->header.sh_size),
2789 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002790 else
2791 s->contents = NULL;
2792
Eric Andersen9f16d612000-06-12 23:11:16 +00002793 s->header.sh_type = SHT_PROGBITS;
2794 }
2795 }
2796}
2797
Eric Andersen044228d2001-07-17 01:12:36 +00002798static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002799{
2800 unsigned long dot = 0;
2801 struct obj_section *sec;
2802
2803 /* Finalize the positions of the sections relative to one another. */
2804
2805 for (sec = f->load_order; sec; sec = sec->load_next) {
2806 ElfW(Addr) align;
2807
2808 align = sec->header.sh_addralign;
2809 if (align && (dot & (align - 1)))
2810 dot = (dot | (align - 1)) + 1;
2811
2812 sec->header.sh_addr = dot;
2813 dot += sec->header.sh_size;
2814 }
2815
2816 return dot;
2817}
2818
Eric Andersen044228d2001-07-17 01:12:36 +00002819static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002820{
2821 int i, n = f->header.e_shnum;
2822 int ret = 1;
2823
2824 /* Finalize the addresses of the sections. */
2825
2826 f->baseaddr = base;
2827 for (i = 0; i < n; ++i)
2828 f->sections[i]->header.sh_addr += base;
2829
2830 /* And iterate over all of the relocations. */
2831
2832 for (i = 0; i < n; ++i) {
2833 struct obj_section *relsec, *symsec, *targsec, *strsec;
2834 ElfW(RelM) * rel, *relend;
2835 ElfW(Sym) * symtab;
2836 const char *strtab;
2837
2838 relsec = f->sections[i];
2839 if (relsec->header.sh_type != SHT_RELM)
2840 continue;
2841
2842 symsec = f->sections[relsec->header.sh_link];
2843 targsec = f->sections[relsec->header.sh_info];
2844 strsec = f->sections[symsec->header.sh_link];
2845
2846 rel = (ElfW(RelM) *) relsec->contents;
2847 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2848 symtab = (ElfW(Sym) *) symsec->contents;
2849 strtab = (const char *) strsec->contents;
2850
2851 for (; rel < relend; ++rel) {
2852 ElfW(Addr) value = 0;
2853 struct obj_symbol *intsym = NULL;
2854 unsigned long symndx;
2855 ElfW(Sym) * extsym = 0;
2856 const char *errmsg;
2857
2858 /* Attempt to find a value to use for this relocation. */
2859
2860 symndx = ELFW(R_SYM) (rel->r_info);
2861 if (symndx) {
2862 /* Note we've already checked for undefined symbols. */
2863
2864 extsym = &symtab[symndx];
2865 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2866 /* Local symbols we look up in the local table to be sure
2867 we get the one that is really intended. */
2868 intsym = f->local_symtab[symndx];
2869 } else {
2870 /* Others we look up in the hash table. */
2871 const char *name;
2872 if (extsym->st_name)
2873 name = strtab + extsym->st_name;
2874 else
2875 name = f->sections[extsym->st_shndx]->name;
2876 intsym = obj_find_symbol(f, name);
2877 }
2878
2879 value = obj_symbol_final_value(f, intsym);
2880 intsym->referenced = 1;
2881 }
2882#if SHT_RELM == SHT_RELA
2883#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2884 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2885 if (!extsym || !extsym->st_name ||
2886 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2887#endif
2888 value += rel->r_addend;
2889#endif
2890
2891 /* Do it! */
2892 switch (arch_apply_relocation
2893 (f, targsec, symsec, intsym, rel, value)) {
2894 case obj_reloc_ok:
2895 break;
2896
2897 case obj_reloc_overflow:
2898 errmsg = "Relocation overflow";
2899 goto bad_reloc;
2900 case obj_reloc_dangerous:
2901 errmsg = "Dangerous relocation";
2902 goto bad_reloc;
2903 case obj_reloc_unhandled:
2904 errmsg = "Unhandled relocation";
2905 bad_reloc:
2906 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002907 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002908 (long) ELFW(R_TYPE) (rel->r_info),
2909 strtab + extsym->st_name);
2910 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002911 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002912 (long) ELFW(R_TYPE) (rel->r_info));
2913 }
2914 ret = 0;
2915 break;
2916 }
2917 }
2918 }
2919
2920 /* Finally, take care of the patches. */
2921
2922 if (f->string_patches) {
2923 struct obj_string_patch *p;
2924 struct obj_section *strsec;
2925 ElfW(Addr) strsec_base;
2926 strsec = obj_find_section(f, ".kstrtab");
2927 strsec_base = strsec->header.sh_addr;
2928
2929 for (p = f->string_patches; p; p = p->next) {
2930 struct obj_section *targsec = f->sections[p->reloc_secidx];
2931 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2932 = strsec_base + p->string_offset;
2933 }
2934 }
2935
2936 if (f->symbol_patches) {
2937 struct obj_symbol_patch *p;
2938
2939 for (p = f->symbol_patches; p; p = p->next) {
2940 struct obj_section *targsec = f->sections[p->reloc_secidx];
2941 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2942 = obj_symbol_final_value(f, p->sym);
2943 }
2944 }
2945
2946 return ret;
2947}
2948
Eric Andersen044228d2001-07-17 01:12:36 +00002949static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002950{
2951 struct obj_section *sec;
2952 ElfW(Addr) base = f->baseaddr;
2953
2954 for (sec = f->load_order; sec; sec = sec->load_next) {
2955 char *secimg;
2956
Eric Andersen2bf658d2001-02-24 20:01:53 +00002957 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 continue;
2959
2960 secimg = image + (sec->header.sh_addr - base);
2961
2962 /* Note that we allocated data for NOBITS sections earlier. */
2963 memcpy(secimg, sec->contents, sec->header.sh_size);
2964 }
2965
2966 return 1;
2967}
2968
2969/*======================================================================*/
2970
Eric Andersen044228d2001-07-17 01:12:36 +00002971static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002972{
2973 struct obj_file *f;
2974 ElfW(Shdr) * section_headers;
2975 int shnum, i;
2976 char *shstrtab;
2977
2978 /* Read the file header. */
2979
2980 f = arch_new_file();
2981 memset(f, 0, sizeof(*f));
2982 f->symbol_cmp = strcmp;
2983 f->symbol_hash = obj_elf_hash;
2984 f->load_order_search_start = &f->load_order;
2985
2986 fseek(fp, 0, SEEK_SET);
2987 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002988 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002989 return NULL;
2990 }
2991
2992 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2993 || f->header.e_ident[EI_MAG1] != ELFMAG1
2994 || f->header.e_ident[EI_MAG2] != ELFMAG2
2995 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002996 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002997 return NULL;
2998 }
2999 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3000 || f->header.e_ident[EI_DATA] != ELFDATAM
3001 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3002 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003003 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003004 return NULL;
3005 }
3006 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003007 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003008 return NULL;
3009 }
3010
3011 /* Read the section headers. */
3012
3013 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003014 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 (unsigned long) f->header.e_shentsize,
3016 (unsigned long) sizeof(ElfW(Shdr)));
3017 return NULL;
3018 }
3019
3020 shnum = f->header.e_shnum;
3021 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3022 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3023
3024 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3025 fseek(fp, f->header.e_shoff, SEEK_SET);
3026 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003027 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003028 return NULL;
3029 }
3030
3031 /* Read the section data. */
3032
3033 for (i = 0; i < shnum; ++i) {
3034 struct obj_section *sec;
3035
3036 f->sections[i] = sec = arch_new_section();
3037 memset(sec, 0, sizeof(*sec));
3038
3039 sec->header = section_headers[i];
3040 sec->idx = i;
3041
Eric Andersen2bf658d2001-02-24 20:01:53 +00003042 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003043 case SHT_NULL:
3044 case SHT_NOTE:
3045 case SHT_NOBITS:
3046 /* ignore */
3047 break;
3048
3049 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003050#if LOADBITS
3051 if (!loadprogbits) {
3052 sec->contents = NULL;
3053 break;
3054 }
3055#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003056 case SHT_SYMTAB:
3057 case SHT_STRTAB:
3058 case SHT_RELM:
3059 if (sec->header.sh_size > 0) {
3060 sec->contents = xmalloc(sec->header.sh_size);
3061 fseek(fp, sec->header.sh_offset, SEEK_SET);
3062 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003063 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003064 return NULL;
3065 }
3066 } else {
3067 sec->contents = NULL;
3068 }
3069 break;
3070
3071#if SHT_RELM == SHT_REL
3072 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003073 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003074 return NULL;
3075#else
3076 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003077 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003078 return NULL;
3079#endif
3080
3081 default:
3082 if (sec->header.sh_type >= SHT_LOPROC) {
3083 /* Assume processor specific section types are debug
3084 info and can safely be ignored. If this is ever not
3085 the case (Hello MIPS?), don't put ifdefs here but
3086 create an arch_load_proc_section(). */
3087 break;
3088 }
3089
Matt Kraaidd19c692001-01-31 19:00:21 +00003090 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003091 (long) sec->header.sh_type);
3092 return NULL;
3093 }
3094 }
3095
3096 /* Do what sort of interpretation as needed by each section. */
3097
3098 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3099
3100 for (i = 0; i < shnum; ++i) {
3101 struct obj_section *sec = f->sections[i];
3102 sec->name = shstrtab + sec->header.sh_name;
3103 }
3104
3105 for (i = 0; i < shnum; ++i) {
3106 struct obj_section *sec = f->sections[i];
3107
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003108 /* .modinfo should be contents only but gcc has no attribute for that.
3109 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3110 */
3111 if (strcmp(sec->name, ".modinfo") == 0)
3112 sec->header.sh_flags &= ~SHF_ALLOC;
3113
Eric Andersen9f16d612000-06-12 23:11:16 +00003114 if (sec->header.sh_flags & SHF_ALLOC)
3115 obj_insert_section_load_order(f, sec);
3116
3117 switch (sec->header.sh_type) {
3118 case SHT_SYMTAB:
3119 {
3120 unsigned long nsym, j;
3121 char *strtab;
3122 ElfW(Sym) * sym;
3123
3124 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003125 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003126 (unsigned long) sec->header.sh_entsize,
3127 (unsigned long) sizeof(ElfW(Sym)));
3128 return NULL;
3129 }
3130
3131 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3132 strtab = f->sections[sec->header.sh_link]->contents;
3133 sym = (ElfW(Sym) *) sec->contents;
3134
3135 /* Allocate space for a table of local symbols. */
3136 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003137 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003138
3139 /* Insert all symbols into the hash table. */
3140 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3141 const char *name;
3142 if (sym->st_name)
3143 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003144 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003145 name = f->sections[sym->st_shndx]->name;
3146
3147 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3148 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003149 }
3150 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003151 break;
3152
3153 case SHT_RELM:
3154 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003155 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003156 (unsigned long) sec->header.sh_entsize,
3157 (unsigned long) sizeof(ElfW(RelM)));
3158 return NULL;
3159 }
3160 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003161 /* XXX Relocation code from modutils-2.3.19 is not here.
3162 * Why? That's about 20 lines of code from obj/obj_load.c,
3163 * which gets done in a second pass through the sections.
3164 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003165 }
3166 }
3167
3168 return f;
3169}
3170
Eric Andersen8ae319a2001-05-21 16:09:18 +00003171#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3172/*
3173 * load the unloaded sections directly into the memory allocated by
3174 * kernel for the module
3175 */
3176
Eric Andersen044228d2001-07-17 01:12:36 +00003177static int obj_load_progbits(FILE * fp, struct obj_file* f)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003178{
3179 char* imagebase = (char*) f->imagebase;
3180 ElfW(Addr) base = f->baseaddr;
3181 struct obj_section* sec;
3182
3183 for (sec = f->load_order; sec; sec = sec->load_next) {
3184
3185 /* section already loaded? */
3186 if (sec->contents != NULL)
3187 continue;
3188
3189 if (sec->header.sh_size == 0)
3190 continue;
3191
3192 sec->contents = imagebase + (sec->header.sh_addr - base);
3193 fseek(fp, sec->header.sh_offset, SEEK_SET);
3194 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3195 errorMsg("error reading ELF section data: %s\n", strerror(errno));
3196 return 0;
3197 }
3198
3199 }
3200 return 1;
3201}
3202#endif
3203
Eric Andersen9f16d612000-06-12 23:11:16 +00003204static void hide_special_symbols(struct obj_file *f)
3205{
3206 static const char *const specials[] = {
3207 "cleanup_module",
3208 "init_module",
3209 "kernel_version",
3210 NULL
3211 };
3212
3213 struct obj_symbol *sym;
3214 const char *const *p;
3215
3216 for (p = specials; *p; ++p)
3217 if ((sym = obj_find_symbol(f, *p)) != NULL)
3218 sym->info =
3219 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3220}
3221
3222
3223
3224extern int insmod_main( int argc, char **argv)
3225{
Eric Andersena18aaf12001-01-24 19:07:09 +00003226 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003227 int k_crcs;
3228 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003229 int len;
3230 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003231 unsigned long m_size;
3232 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003233 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003234 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003235 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003236 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003237 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003238 int m_has_modinfo;
3239#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3240 int k_version;
3241 char k_strversion[STRVERSIONLEN];
3242 char m_strversion[STRVERSIONLEN];
3243 int m_version;
3244 int m_crcs;
3245#endif
3246
Erik Andersene49d5ec2000-02-08 19:58:47 +00003247 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003248 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003249 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003250 case 'f': /* force loading */
3251 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003252 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003253 case 'k': /* module loaded by kerneld, auto-cleanable */
3254 flag_autoclean = 1;
3255 break;
3256 case 'v': /* verbose output */
3257 flag_verbose = 1;
3258 break;
3259 case 'x': /* do not export externs */
3260 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003261 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003262 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003263 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003264 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003265 case 'L': /* Stub warning */
3266 /* This is needed for compatibility with modprobe.
3267 * In theory, this does locking, but we don't do
3268 * that. So be careful and plan your life around not
3269 * loading the same module 50 times concurrently. */
3270 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003271 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003272 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003273 }
Erik Andersend387d011999-12-21 02:55:11 +00003274 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003275
3276 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003277 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003278 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003279
Erik Andersene49d5ec2000-02-08 19:58:47 +00003280 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003281 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003282 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003283 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003284 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003285 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003286 len = strlen(tmp);
3287
3288 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3289 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003290 memcpy(m_fullName, tmp, len);
3291 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003292 if (*m_name == '\0') {
3293 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003294 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003295 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003296
Eric Andersen14d35432001-05-14 17:07:32 +00003297 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003298 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3299 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003300 struct utsname myuname;
3301
3302 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3303 * but do not error out yet if we fail to find it... */
3304 if (uname(&myuname) == 0) {
3305 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003306 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003307 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3308 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003309 /* Jump through hoops in case /lib/modules/`uname -r`
3310 * is a symlink. We do not want recursive_action to
3311 * follow symlinks, but we do want to follow the
3312 * /lib/modules/`uname -r` dir, So resolve it ourselves
3313 * if it is a link... */
3314 if (realpath (module_dir, real_module_dir) == NULL)
3315 strcpy(real_module_dir, module_dir);
3316 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003317 check_module_name_match, 0, m_fullName);
3318 }
3319
3320 /* Check if we have found anything yet */
3321 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003322 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003323 char module_dir[FILENAME_MAX];
3324 if (realpath (_PATH_MODULES, module_dir) == NULL)
3325 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003326 /* No module found under /lib/modules/`uname -r`, this
3327 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003328 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003329 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003330 {
Eric Andersen14d35432001-05-14 17:07:32 +00003331 if (m_filename[0] == '\0'
3332 || ((fp = fopen(m_filename, "r")) == NULL))
3333 {
3334 error_msg("%s: no module by that name found", m_fullName);
3335 return EXIT_FAILURE;
3336 }
3337 } else
3338 error_msg_and_die("%s: no module by that name found", m_fullName);
3339 }
3340 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003341 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003342
Eric Andersen14d35432001-05-14 17:07:32 +00003343 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003344
Eric Andersen8ae319a2001-05-21 16:09:18 +00003345 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003346 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003347
Eric Andersen9f16d612000-06-12 23:11:16 +00003348 if (get_modinfo_value(f, "kernel_version") == NULL)
3349 m_has_modinfo = 0;
3350 else
3351 m_has_modinfo = 1;
3352
3353#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3354 /* Version correspondence? */
3355
3356 k_version = get_kernel_version(k_strversion);
3357 if (m_has_modinfo) {
3358 m_version = new_get_module_version(f, m_strversion);
3359 } else {
3360 m_version = old_get_module_version(f, m_strversion);
3361 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003362 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003363 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003364 goto out;
3365 }
3366 }
3367
3368 if (strncmp(k_strversion, m_strversion, STRVERSIONLEN) != 0) {
3369 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003370 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003371 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003372 "\twhile this kernel is version %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00003373 m_filename, m_strversion, k_strversion);
3374 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003375 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003376 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003377 "\twhile this kernel is version %s.",
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 m_filename, m_strversion, k_strversion);
3379 goto out;
3380 }
3381 }
3382 k_crcs = 0;
3383#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3384
3385 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3386
3387 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003388#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003389 if (!new_get_kernel_symbols())
3390 goto out;
3391 k_crcs = new_is_kernel_checksummed();
3392#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003393 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003394 goto out;
3395#endif
3396 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003397#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003398 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003399 goto out;
3400 k_crcs = old_is_kernel_checksummed();
3401#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003402 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003403 goto out;
3404#endif
3405 }
3406
3407#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3408 if (m_has_modinfo)
3409 m_crcs = new_is_module_checksummed(f);
3410 else
3411 m_crcs = old_is_module_checksummed(f);
3412
3413 if (m_crcs != k_crcs)
3414 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3415#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3416
Erik Andersene49d5ec2000-02-08 19:58:47 +00003417 /* Let the module know about the kernel symbols. */
3418 add_kernel_symbols(f);
3419
Eric Andersen9f16d612000-06-12 23:11:16 +00003420 /* Allocate common symbols, symbol tables, and string tables. */
3421
3422 if (k_new_syscalls
3423 ? !new_create_this_module(f, m_name)
3424 : !old_create_mod_use_count(f))
3425 {
3426 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003427 }
3428
Eric Andersen9f16d612000-06-12 23:11:16 +00003429 if (!obj_check_undefineds(f)) {
3430 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003431 }
3432 obj_allocate_commons(f);
3433
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003434 /* done with the module name, on to the optional var=value arguments */
3435 ++optind;
3436
Eric Andersen9f16d612000-06-12 23:11:16 +00003437 if (optind < argc) {
3438 if (m_has_modinfo
3439 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3440 : !old_process_module_arguments(f, argc - optind, argv + optind))
3441 {
3442 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003443 }
3444 }
3445
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 arch_create_got(f);
3447 hide_special_symbols(f);
3448
3449 if (k_new_syscalls)
3450 new_create_module_ksymtab(f);
3451
Erik Andersene49d5ec2000-02-08 19:58:47 +00003452 /* Find current size of the module */
3453 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003454
3455
Erik Andersene49d5ec2000-02-08 19:58:47 +00003456 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003457 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003458 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003459 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003460 goto out;
3461 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003462 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003463 m_size);
3464 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003465 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003466 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003467 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003468 }
Erik Andersend387d011999-12-21 02:55:11 +00003469
Eric Andersen8ae319a2001-05-21 16:09:18 +00003470#if !LOADBITS
3471 /*
3472 * the PROGBITS section was not loaded by the obj_load
3473 * now we can load them directly into the kernel memory
3474 */
3475 // f->imagebase = (char*) m_addr;
3476 f->imagebase = (ElfW(Addr)) m_addr;
3477 if (!obj_load_progbits(fp, f)) {
3478 delete_module(m_name);
3479 goto out;
3480 }
3481#endif
3482
Eric Andersen9f16d612000-06-12 23:11:16 +00003483 if (!obj_relocate(f, m_addr)) {
3484 delete_module(m_name);
3485 goto out;
3486 }
Erik Andersend387d011999-12-21 02:55:11 +00003487
Eric Andersen9f16d612000-06-12 23:11:16 +00003488 if (k_new_syscalls
3489 ? !new_init_module(m_name, f, m_size)
3490 : !old_init_module(m_name, f, m_size))
3491 {
3492 delete_module(m_name);
3493 goto out;
3494 }
3495
Matt Kraai3e856ce2000-12-01 02:55:13 +00003496 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003497
3498out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003499 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003500 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003501}