blob: 6b81ca754e0459170bd6727dd6ac870a933b9f42 [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
Eric Andersen1071ccf2001-08-22 05:41:57 +000070# undef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen64c8b172001-04-05 07:33:10 +000071# define new_sys_init_module init_module
72#else
73# define old_sys_init_module init_module
74#endif
75
Eric Andersen8ae319a2001-05-21 16:09:18 +000076#ifdef BB_FEATURE_INSMOD_LOADINKMEM
77#define LOADBITS 0
78#else
79#define LOADBITS 1
80#endif
81
Eric Andersen90fe7fe2001-02-20 20:47:08 +000082#if defined(__powerpc__)
83#define BB_USE_PLT_ENTRIES
84#define BB_PLT_ENTRY_SIZE 16
85#endif
86
87#if defined(__arm__)
88#define BB_USE_PLT_ENTRIES
89#define BB_PLT_ENTRY_SIZE 8
90#define BB_USE_GOT_ENTRIES
91#define BB_GOT_ENTRY_SIZE 8
92#endif
93
94#if defined(__sh__)
95#define BB_USE_GOT_ENTRIES
96#define BB_GOT_ENTRY_SIZE 4
97#endif
98
99#if defined(__i386__)
100#define BB_USE_GOT_ENTRIES
101#define BB_GOT_ENTRY_SIZE 4
102#endif
103
Eric Andersen2bf658d2001-02-24 20:01:53 +0000104#if defined(__mips__)
105// neither used
106#endif
107
Eric Andersen9f16d612000-06-12 23:11:16 +0000108//----------------------------------------------------------------------------
109//--------modutils module.h, lines 45-242
110//----------------------------------------------------------------------------
111
112/* Definitions for the Linux module syscall interface.
113 Copyright 1996, 1997 Linux International.
114
115 Contributed by Richard Henderson <rth@tamu.edu>
116
117 This file is part of the Linux modutils.
118
119 This program is free software; you can redistribute it and/or modify it
120 under the terms of the GNU General Public License as published by the
121 Free Software Foundation; either version 2 of the License, or (at your
122 option) any later version.
123
124 This program is distributed in the hope that it will be useful, but
125 WITHOUT ANY WARRANTY; without even the implied warranty of
126 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
127 General Public License for more details.
128
129 You should have received a copy of the GNU General Public License
130 along with this program; if not, write to the Free Software Foundation,
131 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
132
133
134#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000135static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000136
Eric Andersen1071ccf2001-08-22 05:41:57 +0000137#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000138
139/* This file contains the structures used by the 2.0 and 2.1 kernels.
140 We do not use the kernel headers directly because we do not wish
141 to be dependant on a particular kernel version to compile insmod. */
142
143
144/*======================================================================*/
145/* The structures used by Linux 2.0. */
146
147/* The symbol format used by get_kernel_syms(2). */
148struct old_kernel_sym
149{
150 unsigned long value;
151 char name[60];
152};
153
154struct old_module_ref
155{
156 unsigned long module; /* kernel addresses */
157 unsigned long next;
158};
159
160struct old_module_symbol
161{
162 unsigned long addr;
163 unsigned long name;
164};
165
166struct old_symbol_table
167{
168 int size; /* total, including string table!!! */
169 int n_symbols;
170 int n_refs;
171 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
172 struct old_module_ref ref[0]; /* actual size defined by n_refs */
173};
174
175struct old_mod_routines
176{
177 unsigned long init;
178 unsigned long cleanup;
179};
180
181struct old_module
182{
183 unsigned long next;
184 unsigned long ref; /* the list of modules that refer to me */
185 unsigned long symtab;
186 unsigned long name;
187 int size; /* size of module in pages */
188 unsigned long addr; /* address of module */
189 int state;
190 unsigned long cleanup; /* cleanup routine */
191};
192
193/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000194static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000195
196int get_kernel_syms(struct old_kernel_sym *);
197int old_sys_init_module(const char *name, char *code, unsigned codesize,
198 struct old_mod_routines *, struct old_symbol_table *);
199
200/*======================================================================*/
201/* For sizeof() which are related to the module platform and not to the
202 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
203
204#define tgt_sizeof_char sizeof(char)
205#define tgt_sizeof_short sizeof(short)
206#define tgt_sizeof_int sizeof(int)
207#define tgt_sizeof_long sizeof(long)
208#define tgt_sizeof_char_p sizeof(char *)
209#define tgt_sizeof_void_p sizeof(void *)
210#define tgt_long long
211
212#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
213#undef tgt_sizeof_long
214#undef tgt_sizeof_char_p
215#undef tgt_sizeof_void_p
216#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000217static const int tgt_sizeof_long = 8;
218static const int tgt_sizeof_char_p = 8;
219static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000220#define tgt_long long long
221#endif
222
223/*======================================================================*/
224/* The structures used in Linux 2.1. */
225
226/* Note: new_module_symbol does not use tgt_long intentionally */
227struct new_module_symbol
228{
229 unsigned long value;
230 unsigned long name;
231};
232
233struct new_module_persist;
234
235struct new_module_ref
236{
237 unsigned tgt_long dep; /* kernel addresses */
238 unsigned tgt_long ref;
239 unsigned tgt_long next_ref;
240};
241
242struct new_module
243{
244 unsigned tgt_long size_of_struct; /* == sizeof(module) */
245 unsigned tgt_long next;
246 unsigned tgt_long name;
247 unsigned tgt_long size;
248
249 tgt_long usecount;
250 unsigned tgt_long flags; /* AUTOCLEAN et al */
251
252 unsigned nsyms;
253 unsigned ndeps;
254
255 unsigned tgt_long syms;
256 unsigned tgt_long deps;
257 unsigned tgt_long refs;
258 unsigned tgt_long init;
259 unsigned tgt_long cleanup;
260 unsigned tgt_long ex_table_start;
261 unsigned tgt_long ex_table_end;
262#ifdef __alpha__
263 unsigned tgt_long gp;
264#endif
265 /* Everything after here is extension. */
266 unsigned tgt_long persist_start;
267 unsigned tgt_long persist_end;
268 unsigned tgt_long can_unload;
269 unsigned tgt_long runsize;
Eric Andersen8ae319a2001-05-21 16:09:18 +0000270#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
271 const char *kallsyms_start; /* All symbols for kernel debugging */
272 const char *kallsyms_end;
273 const char *archdata_start; /* arch specific data for module */
274 const char *archdata_end;
275 const char *kernel_data; /* Reserved for kernel internal use */
276#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000277};
278
Eric Andersen8ae319a2001-05-21 16:09:18 +0000279#define ARCHDATA_SEC_NAME "__archdata"
280#define KALLSYMS_SEC_NAME "__kallsyms"
281
282
Eric Andersen9f16d612000-06-12 23:11:16 +0000283struct new_module_info
284{
285 unsigned long addr;
286 unsigned long size;
287 unsigned long flags;
288 long usecount;
289};
290
291/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000292static const int NEW_MOD_RUNNING = 1;
293static const int NEW_MOD_DELETED = 2;
294static const int NEW_MOD_AUTOCLEAN = 4;
295static const int NEW_MOD_VISITED = 8;
296static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000297
Eric Andersen64c8b172001-04-05 07:33:10 +0000298int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000299int query_module(const char *name, int which, void *buf, size_t bufsize,
300 size_t *ret);
301
302/* Values for query_module's which. */
303
Mark Whitley59ab0252001-01-23 22:30:04 +0000304static const int QM_MODULES = 1;
305static const int QM_DEPS = 2;
306static const int QM_REFS = 3;
307static const int QM_SYMBOLS = 4;
308static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000309
310/*======================================================================*/
311/* The system calls unchanged between 2.0 and 2.1. */
312
313unsigned long create_module(const char *, size_t);
314int delete_module(const char *);
315
316
317#endif /* module.h */
318
319//----------------------------------------------------------------------------
320//--------end of modutils module.h
321//----------------------------------------------------------------------------
322
323
324
325//----------------------------------------------------------------------------
326//--------modutils obj.h, lines 253-462
327//----------------------------------------------------------------------------
328
329/* Elf object file loading and relocation routines.
330 Copyright 1996, 1997 Linux International.
331
332 Contributed by Richard Henderson <rth@tamu.edu>
333
334 This file is part of the Linux modutils.
335
336 This program is free software; you can redistribute it and/or modify it
337 under the terms of the GNU General Public License as published by the
338 Free Software Foundation; either version 2 of the License, or (at your
339 option) any later version.
340
341 This program is distributed in the hope that it will be useful, but
342 WITHOUT ANY WARRANTY; without even the implied warranty of
343 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
344 General Public License for more details.
345
346 You should have received a copy of the GNU General Public License
347 along with this program; if not, write to the Free Software Foundation,
348 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
349
350
351#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000352static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000353
Eric Andersen1071ccf2001-08-22 05:41:57 +0000354#ident "$Id: insmod.c,v 1.73 2001/08/22 05:41:57 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000355
356/* The relocatable object is manipulated using elfin types. */
357
358#include <stdio.h>
359#include <elf.h>
360
361
362/* Machine-specific elf macros for i386 et al. */
363
Eric Andersenfe4208f2000-09-24 03:44:29 +0000364/* the SH changes have only been tested on the SH4 in =little endian= mode */
365/* I'm not sure about big endian, so let's warn: */
366
367#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
368#error insmod.c may require changes for use on big endian SH4/SH3
369#endif
370
371/* it may or may not work on the SH1/SH2... So let's error on those
372 also */
373#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
374#error insmod.c may require changes for non-SH3/SH4 use
375#endif
376
Eric Andersen9f16d612000-06-12 23:11:16 +0000377#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000378
Eric Andersenb4a26e62001-06-19 15:00:52 +0000379#if (defined(__mc68000__))
Eric Andersen8ae319a2001-05-21 16:09:18 +0000380#define ELFDATAM ELFDATA2MSB
Eric Andersen8ae319a2001-05-21 16:09:18 +0000381#endif
382
383
384
Eric Andersenfe4208f2000-09-24 03:44:29 +0000385#if defined(__sh__)
386
387#define MATCH_MACHINE(x) (x == EM_SH)
388#define SHT_RELM SHT_RELA
389#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000390#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000391
Eric Andersen21adca72000-12-06 18:18:26 +0000392#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000393
Eric Andersen21adca72000-12-06 18:18:26 +0000394#define MATCH_MACHINE(x) (x == EM_ARM)
395#define SHT_RELM SHT_REL
396#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000397#define ELFDATAM ELFDATA2LSB
398
399#elif defined(__powerpc__)
400
401#define MATCH_MACHINE(x) (x == EM_PPC)
402#define SHT_RELM SHT_RELA
403#define Elf32_RelM Elf32_Rela
Eric Andersen5a9d4412001-05-24 14:16:28 +0000404#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000405
Eric Andersen2bf658d2001-02-24 20:01:53 +0000406#elif defined(__mips__)
407
Eric Andersen82bb8a22001-03-22 19:01:16 +0000408/* Account for ELF spec changes. */
409#ifndef EM_MIPS_RS3_LE
410#ifdef EM_MIPS_RS4_BE
411#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
412#else
413#define EM_MIPS_RS3_LE 10
414#endif
415#endif /* !EM_MIPS_RS3_LE */
416
Eric Andersen2bf658d2001-02-24 20:01:53 +0000417#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
418#define SHT_RELM SHT_REL
419#define Elf32_RelM Elf32_Rel
420#ifdef __MIPSEB__
421#define ELFDATAM ELFDATA2MSB
422#endif
423#ifdef __MIPSEL__
424#define ELFDATAM ELFDATA2LSB
425#endif
426
Eric Andersen21adca72000-12-06 18:18:26 +0000427#elif defined(__i386__)
428
429/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000430/* this is the previous behavior, but it does result in
431 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000432#ifndef EM_486
433#define MATCH_MACHINE(x) (x == EM_386)
434#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000435#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000436#endif
437
Eric Andersen9f16d612000-06-12 23:11:16 +0000438#define SHT_RELM SHT_REL
439#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000440#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000441
Eric Andersenb4a26e62001-06-19 15:00:52 +0000442#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000443
444#define MATCH_MACHINE(x) (x == EM_68K)
445#define SHT_RELM SHT_RELA
446#define Elf32_RelM Elf32_Rela
447
Eric Andersen21adca72000-12-06 18:18:26 +0000448#else
Eric Andersend5cad142001-01-26 02:23:57 +0000449#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000450#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000451
452#ifndef ElfW
453# if ELFCLASSM == ELFCLASS32
454# define ElfW(x) Elf32_ ## x
455# define ELFW(x) ELF32_ ## x
456# else
457# define ElfW(x) Elf64_ ## x
458# define ELFW(x) ELF64_ ## x
459# endif
460#endif
461
462/* For some reason this is missing from libc5. */
463#ifndef ELF32_ST_INFO
464# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
465#endif
466
467#ifndef ELF64_ST_INFO
468# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
469#endif
470
471struct obj_string_patch;
472struct obj_symbol_patch;
473
474struct obj_section
475{
476 ElfW(Shdr) header;
477 const char *name;
478 char *contents;
479 struct obj_section *load_next;
480 int idx;
481};
482
483struct obj_symbol
484{
485 struct obj_symbol *next; /* hash table link */
486 const char *name;
487 unsigned long value;
488 unsigned long size;
489 int secidx; /* the defining section index/module */
490 int info;
491 int ksymidx; /* for export to the kernel symtab */
492 int referenced; /* actually used in the link */
493};
494
495/* Hardcode the hash table size. We shouldn't be needing so many
496 symbols that we begin to degrade performance, and we get a big win
497 by giving the compiler a constant divisor. */
498
499#define HASH_BUCKETS 521
500
501struct obj_file
502{
503 ElfW(Ehdr) header;
504 ElfW(Addr) baseaddr;
505 struct obj_section **sections;
506 struct obj_section *load_order;
507 struct obj_section **load_order_search_start;
508 struct obj_string_patch *string_patches;
509 struct obj_symbol_patch *symbol_patches;
510 int (*symbol_cmp)(const char *, const char *);
511 unsigned long (*symbol_hash)(const char *);
512 unsigned long local_symtab_size;
513 struct obj_symbol **local_symtab;
514 struct obj_symbol *symtab[HASH_BUCKETS];
515};
516
517enum obj_reloc
518{
519 obj_reloc_ok,
520 obj_reloc_overflow,
521 obj_reloc_dangerous,
522 obj_reloc_unhandled
523};
524
525struct obj_string_patch
526{
527 struct obj_string_patch *next;
528 int reloc_secidx;
529 ElfW(Addr) reloc_offset;
530 ElfW(Addr) string_offset;
531};
532
533struct obj_symbol_patch
534{
535 struct obj_symbol_patch *next;
536 int reloc_secidx;
537 ElfW(Addr) reloc_offset;
538 struct obj_symbol *sym;
539};
540
541
542/* Generic object manipulation routines. */
543
Eric Andersen044228d2001-07-17 01:12:36 +0000544static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000545
Eric Andersen044228d2001-07-17 01:12:36 +0000546static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000547
Eric Andersen044228d2001-07-17 01:12:36 +0000548static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000549 const char *name);
550
Eric Andersen044228d2001-07-17 01:12:36 +0000551static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000552 struct obj_symbol *sym);
553
Eric Andersenf672c9e2001-07-31 22:51:49 +0000554#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000555static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000556 int (*cmp)(const char *, const char *),
557 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000558#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000559
Eric Andersen044228d2001-07-17 01:12:36 +0000560static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000561 const char *name);
562
Eric Andersen044228d2001-07-17 01:12:36 +0000563static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000564 struct obj_section *sec);
565
Eric Andersen044228d2001-07-17 01:12:36 +0000566static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000567 const char *name,
568 unsigned long align,
569 unsigned long size);
570
Eric Andersen044228d2001-07-17 01:12:36 +0000571static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000572 const char *name,
573 unsigned long align,
574 unsigned long size);
575
Eric Andersen044228d2001-07-17 01:12:36 +0000576static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000577
Eric Andersen044228d2001-07-17 01:12:36 +0000578static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000579 const char *string);
580
Eric Andersen044228d2001-07-17 01:12:36 +0000581static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000582 struct obj_symbol *sym);
583
Eric Andersen044228d2001-07-17 01:12:36 +0000584static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000585
Eric Andersen044228d2001-07-17 01:12:36 +0000586static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000587
Eric Andersen044228d2001-07-17 01:12:36 +0000588static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000589
Eric Andersen044228d2001-07-17 01:12:36 +0000590static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000591
Eric Andersen044228d2001-07-17 01:12:36 +0000592static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000593
Eric Andersen044228d2001-07-17 01:12:36 +0000594static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000595
596/* Architecture specific manipulation routines. */
597
Eric Andersen044228d2001-07-17 01:12:36 +0000598static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000599
Eric Andersen044228d2001-07-17 01:12:36 +0000600static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000601
Eric Andersen044228d2001-07-17 01:12:36 +0000602static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000605 struct obj_section *targsec,
606 struct obj_section *symsec,
607 struct obj_symbol *sym,
608 ElfW(RelM) *rel, ElfW(Addr) value);
609
Eric Andersen044228d2001-07-17 01:12:36 +0000610static int arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000611
Eric Andersen044228d2001-07-17 01:12:36 +0000612static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000613
614#endif /* obj.h */
615//----------------------------------------------------------------------------
616//--------end of modutils obj.h
617//----------------------------------------------------------------------------
618
619
620
621
Erik Andersen02104321999-12-17 18:57:34 +0000622
Erik Andersend387d011999-12-21 02:55:11 +0000623#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000624static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000625
Eric Andersen9f16d612000-06-12 23:11:16 +0000626/*======================================================================*/
627
Eric Andersen044228d2001-07-17 01:12:36 +0000628static int flag_force_load = 0;
629static int flag_autoclean = 0;
630static int flag_verbose = 0;
631static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000632
633
634/*======================================================================*/
635
Eric Andersenfe4208f2000-09-24 03:44:29 +0000636/* previously, these were named i386_* but since we could be
637 compiling for the sh, I've renamed them to the more general
638 arch_* These structures are the same between the x86 and SH,
639 and we can't support anything else right now anyway. In the
640 future maybe they should be #if defined'd */
641
Eric Andersen21adca72000-12-06 18:18:26 +0000642/* Done ;-) */
643
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000644
645
646#if defined(BB_USE_PLT_ENTRIES)
647struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000648{
649 int offset;
650 int allocated:1;
651 int inited:1; /* has been set up */
652};
653#endif
654
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000655#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000656struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000657 int offset;
658 unsigned offset_done:1;
659 unsigned reloc_done:1;
660};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000661#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000662
Eric Andersen2bf658d2001-02-24 20:01:53 +0000663#if defined(__mips__)
664struct mips_hi16
665{
666 struct mips_hi16 *next;
667 Elf32_Addr *addr;
668 Elf32_Addr value;
669};
670#endif
671
Eric Andersenfe4208f2000-09-24 03:44:29 +0000672struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000673 struct obj_file root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000674#if defined(BB_USE_PLT_ENTRIES)
675 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000676#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000677#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000678 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000679#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000680#if defined(__mips__)
681 struct mips_hi16 *mips_hi16_list;
682#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000683};
684
Eric Andersenfe4208f2000-09-24 03:44:29 +0000685struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000686 struct obj_symbol root;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000687#if defined(BB_USE_PLT_ENTRIES)
688 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000689#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000690#if defined(BB_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000691 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000692#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000693};
694
695
Eric Andersen9f16d612000-06-12 23:11:16 +0000696struct external_module {
697 const char *name;
698 ElfW(Addr) addr;
699 int used;
700 size_t nsyms;
701 struct new_module_symbol *syms;
702};
703
Eric Andersen044228d2001-07-17 01:12:36 +0000704static struct new_module_symbol *ksyms;
705static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000706
Eric Andersen044228d2001-07-17 01:12:36 +0000707static struct external_module *ext_modules;
708static int n_ext_modules;
709static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000710extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000711
Eric Andersen14d35432001-05-14 17:07:32 +0000712static char m_filename[FILENAME_MAX + 1];
713static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000714
Eric Andersenfe4208f2000-09-24 03:44:29 +0000715
Erik Andersen02104321999-12-17 18:57:34 +0000716
Eric Andersen9f16d612000-06-12 23:11:16 +0000717/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000718
Eric Andersen9f16d612000-06-12 23:11:16 +0000719
Eric Andersen14d35432001-05-14 17:07:32 +0000720static int check_module_name_match(const char *filename, struct stat *statbuf,
721 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000722{
Eric Andersen14d35432001-05-14 17:07:32 +0000723 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000724
Eric Andersen14d35432001-05-14 17:07:32 +0000725 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000726 return (FALSE);
727 else {
Eric Andersen14d35432001-05-14 17:07:32 +0000728 char *tmp, *tmp1 = strdup(filename);
729 tmp = get_last_path_component(tmp1);
730 if (strcmp(tmp, fullname) == 0) {
731 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000732 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000733 safe_strncpy(m_filename, filename, sizeof(m_filename));
734 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000735 }
Eric Andersen14d35432001-05-14 17:07:32 +0000736 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000737 }
Eric Andersen14d35432001-05-14 17:07:32 +0000738 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000739}
740
Erik Andersen02104321999-12-17 18:57:34 +0000741
Eric Andersen9f16d612000-06-12 23:11:16 +0000742/*======================================================================*/
743
Eric Andersen044228d2001-07-17 01:12:36 +0000744static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000745{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000746 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000747 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000748
749#if defined(BB_USE_PLT_ENTRIES)
750 f->plt = NULL;
751#endif
752#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000753 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000754#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000755#if defined(__mips__)
756 f->mips_hi16_list = NULL;
757#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000758
Eric Andersen9f16d612000-06-12 23:11:16 +0000759 return &f->root;
760}
761
Eric Andersen044228d2001-07-17 01:12:36 +0000762static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000763{
764 return xmalloc(sizeof(struct obj_section));
765}
766
Eric Andersen044228d2001-07-17 01:12:36 +0000767static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000768{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000769 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000770 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000771
772#if defined(BB_USE_PLT_ENTRIES)
773 memset(&sym->pltent, 0, sizeof(sym->pltent));
774#endif
775#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000776 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000777#endif
778
Eric Andersen9f16d612000-06-12 23:11:16 +0000779 return &sym->root;
780}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000781
Eric Andersen044228d2001-07-17 01:12:36 +0000782static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000783arch_apply_relocation(struct obj_file *f,
784 struct obj_section *targsec,
785 struct obj_section *symsec,
786 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000787 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000788{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000789 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000790#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000791 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000792#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000793
Eric Andersen21adca72000-12-06 18:18:26 +0000794 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
795 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000796#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000797 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000798#endif
799#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000800 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000801 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000802 unsigned long *ip;
803#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000804 enum obj_reloc ret = obj_reloc_ok;
805
806 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000807
808/* even though these constants seem to be the same for
809 the i386 and the sh, we "#if define" them for clarity
810 and in case that ever changes */
811#if defined(__sh__)
812 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000813#elif defined(__arm__)
814 case R_ARM_NONE:
815#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000816 case R_386_NONE:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000817#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000818 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000819#elif defined(__powerpc__)
820 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000821#elif defined(__mips__)
822 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000823#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000824 break;
825
Eric Andersenfe4208f2000-09-24 03:44:29 +0000826#if defined(__sh__)
827 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000828#elif defined(__arm__)
829 case R_ARM_ABS32:
830#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831 case R_386_32:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000832#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000833 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000834#elif defined(__powerpc__)
835 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000836#elif defined(__mips__)
837 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000838#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000839 *loc += v;
840 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000841#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000842 case R_68K_8:
843 if (v > 0xff)
844 ret = obj_reloc_overflow;
845 *(char *)loc = v;
846 break;
847 case R_68K_16:
848 if (v > 0xffff)
849 ret = obj_reloc_overflow;
850 *(short *)loc = v;
851 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000852#endif /* __mc68000__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000853
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000854#if defined(__powerpc__)
855 case R_PPC_ADDR16_HA:
856 *(unsigned short *)loc = (v + 0x8000) >> 16;
857 break;
858
859 case R_PPC_ADDR16_HI:
860 *(unsigned short *)loc = v >> 16;
861 break;
862
863 case R_PPC_ADDR16_LO:
864 *(unsigned short *)loc = v;
865 break;
866#endif
867
Eric Andersen2bf658d2001-02-24 20:01:53 +0000868#if defined(__mips__)
869 case R_MIPS_26:
870 if (v % 4)
871 ret = obj_reloc_dangerous;
872 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
873 ret = obj_reloc_overflow;
874 *loc =
875 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
876 0x03ffffff);
877 break;
878
879 case R_MIPS_HI16:
880 {
881 struct mips_hi16 *n;
882
883 /* We cannot relocate this one now because we don't know the value
884 of the carry we need to add. Save the information, and let LO16
885 do the actual relocation. */
886 n = (struct mips_hi16 *) xmalloc(sizeof *n);
887 n->addr = loc;
888 n->value = v;
889 n->next = ifile->mips_hi16_list;
890 ifile->mips_hi16_list = n;
891 break;
892 }
893
894 case R_MIPS_LO16:
895 {
896 unsigned long insnlo = *loc;
897 Elf32_Addr val, vallo;
898
899 /* Sign extend the addend we extract from the lo insn. */
900 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
901
902 if (ifile->mips_hi16_list != NULL) {
903 struct mips_hi16 *l;
904
905 l = ifile->mips_hi16_list;
906 while (l != NULL) {
907 struct mips_hi16 *next;
908 unsigned long insn;
909
910 /* The value for the HI16 had best be the same. */
911 assert(v == l->value);
912
913 /* Do the HI16 relocation. Note that we actually don't
914 need to know anything about the LO16 itself, except where
915 to find the low 16 bits of the addend needed by the LO16. */
916 insn = *l->addr;
917 val =
918 ((insn & 0xffff) << 16) +
919 vallo;
920 val += v;
921
922 /* Account for the sign extension that will happen in the
923 low bits. */
924 val =
925 ((val >> 16) +
926 ((val & 0x8000) !=
927 0)) & 0xffff;
928
929 insn = (insn & ~0xffff) | val;
930 *l->addr = insn;
931
932 next = l->next;
933 free(l);
934 l = next;
935 }
936
937 ifile->mips_hi16_list = NULL;
938 }
939
940 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
941 val = v + vallo;
942 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
943 *loc = insnlo;
944 break;
945 }
946#endif
947
Eric Andersen21adca72000-12-06 18:18:26 +0000948#if defined(__arm__)
949#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000950 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000951 *loc += v - dot;
952 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000953#elif defined(__i386__)
954 case R_386_PLT32:
955 case R_386_PC32:
956 *loc += v - dot;
957 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000958#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000959 case R_68K_PC8:
960 v -= dot;
961 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
962 ret = obj_reloc_overflow;
963 *(char *)loc = v;
964 break;
965 case R_68K_PC16:
966 v -= dot;
967 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
968 ret = obj_reloc_overflow;
969 *(short *)loc = v;
970 break;
971 case R_68K_PC32:
972 *(int *)loc = v - dot;
973 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000974#elif defined(__powerpc__)
975 case R_PPC_REL32:
976 *loc = v - dot;
977 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000978#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000979
Eric Andersenfe4208f2000-09-24 03:44:29 +0000980#if defined(__sh__)
981 case R_SH_PLT32:
982 *loc = v - dot;
983 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000984#elif defined(__i386__)
985#endif
986
987#if defined(BB_USE_PLT_ENTRIES)
988
989#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000990 case R_ARM_PC24:
991 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000992#endif
993#if defined(__powerpc__)
994 case R_PPC_REL24:
995#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000996 /* find the plt entry and initialize it if necessary */
997 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000998
999 pe = (struct arch_plt_entry*) &isym->pltent;
1000
Eric Andersen21adca72000-12-06 18:18:26 +00001001 if (! pe->inited) {
1002 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001003
1004 /* generate some machine code */
1005
1006#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001007 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1008 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001009#endif
1010#if defined(__powerpc__)
1011 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1012 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1013 ip[2] = 0x7d6903a6; /* mtctr r11 */
1014 ip[3] = 0x4e800420; /* bctr */
1015#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001016 pe->inited = 1;
1017 }
1018
1019 /* relative distance to target */
1020 v -= dot;
1021 /* if the target is too far away.... */
1022 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1023 /* go via the plt */
1024 v = plt + pe->offset - dot;
1025 }
1026 if (v & 3)
1027 ret = obj_reloc_dangerous;
1028
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001029 /* merge the offset into the instruction. */
1030#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001031 /* Convert to words. */
1032 v >>= 2;
1033
Eric Andersen21adca72000-12-06 18:18:26 +00001034 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001035#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001036#if defined(__powerpc__)
1037 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1038#endif
1039 break;
1040#endif /* BB_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001041
Eric Andersen21adca72000-12-06 18:18:26 +00001042#if defined(__arm__)
1043#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001044 case R_SH_GLOB_DAT:
1045 case R_SH_JMP_SLOT:
1046 *loc = v;
1047 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001048#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001049 case R_386_GLOB_DAT:
1050 case R_386_JMP_SLOT:
1051 *loc = v;
1052 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001053#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001054 case R_68K_GLOB_DAT:
1055 case R_68K_JMP_SLOT:
1056 *loc = v;
1057 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001058#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001059
Eric Andersen21adca72000-12-06 18:18:26 +00001060#if defined(__arm__)
1061#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001062 case R_SH_RELATIVE:
1063 *loc += f->baseaddr + rel->r_addend;
1064 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001065#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001066 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001067 *loc += f->baseaddr;
1068 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001069#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001070 case R_68K_RELATIVE:
1071 *(int *)loc += f->baseaddr;
1072 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001073#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001074
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001075#if defined(BB_USE_GOT_ENTRIES)
1076
Eric Andersen8ae319a2001-05-21 16:09:18 +00001077#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001078#if defined(__sh__)
1079 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001080#elif defined(__arm__)
1081 case R_ARM_GOTPC:
1082#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001083 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001084#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001085 assert(got != 0);
1086#if defined(__sh__)
1087 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001088#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001089 *loc += got - dot;
1090#endif
1091 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001092#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001093
Eric Andersenfe4208f2000-09-24 03:44:29 +00001094#if defined(__sh__)
1095 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001096#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001097 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001098#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001099 case R_386_GOT32:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001100#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001101 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001102#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001103 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001104 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001105 if (!isym->gotent.reloc_done) {
1106 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001107 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001108 }
Eric Andersen21adca72000-12-06 18:18:26 +00001109 /* make the reloc with_respect_to_.got */
1110#if defined(__sh__)
1111 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001112#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001113 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001114#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001115 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001116
Eric Andersen21adca72000-12-06 18:18:26 +00001117 /* address relative to the got */
Eric Andersenb4a26e62001-06-19 15:00:52 +00001118#if !defined(__mc68000__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001119#if defined(__sh__)
1120 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001121#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001122 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001123#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001124 case R_386_GOTOFF:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001125#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001126 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001127#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001128 assert(got != 0);
1129 *loc += v - got;
1130 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001131#endif // __mc68000__
Eric Andersen9f16d612000-06-12 23:11:16 +00001132
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001133#endif /* BB_USE_GOT_ENTRIES */
1134
Eric Andersen9f16d612000-06-12 23:11:16 +00001135 default:
Eric Andersen21125542000-12-13 16:41:29 +00001136 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001137 ret = obj_reloc_unhandled;
1138 break;
1139 }
1140
1141 return ret;
1142}
1143
Eric Andersen044228d2001-07-17 01:12:36 +00001144static int arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001145{
Eric Andersen2bf658d2001-02-24 20:01:53 +00001146#if defined(BB_USE_GOT_ENTRIES) || defined(BB_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001147 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001148 int i;
1149#if defined(BB_USE_GOT_ENTRIES)
1150 int got_offset = 0, gotneeded = 0;
1151#endif
1152#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001153 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001154#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001155 struct obj_section *relsec, *symsec, *strsec;
1156 ElfW(RelM) *rel, *relend;
1157 ElfW(Sym) *symtab, *extsym;
1158 const char *strtab, *name;
1159 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001160
Eric Andersen21adca72000-12-06 18:18:26 +00001161 for (i = 0; i < f->header.e_shnum; ++i) {
1162 relsec = f->sections[i];
1163 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001164 continue;
1165
Eric Andersen21adca72000-12-06 18:18:26 +00001166 symsec = f->sections[relsec->header.sh_link];
1167 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001168
Eric Andersen21adca72000-12-06 18:18:26 +00001169 rel = (ElfW(RelM) *) relsec->contents;
1170 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1171 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001172 strtab = (const char *) strsec->contents;
1173
1174 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001175 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001176
1177 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001178#if defined(__arm__)
1179 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001180 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001181#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001182 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001183 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001184#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001185 case R_386_GOT32:
1186 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001187#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001188 case R_68K_GOT32:
1189 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001190#endif
1191
1192#if defined(__powerpc__)
1193 case R_PPC_REL24:
1194 pltneeded = 1;
1195 break;
1196#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001197
1198#if defined(__arm__)
1199 case R_ARM_PC24:
1200 case R_ARM_PLT32:
1201 pltneeded = 1;
1202 break;
1203
1204 case R_ARM_GOTPC:
1205 case R_ARM_GOTOFF:
1206 gotneeded = 1;
1207 if (got_offset == 0)
1208 got_offset = 4;
1209#elif defined(__sh__)
1210 case R_SH_GOTPC:
1211 case R_SH_GOTOFF:
1212 gotneeded = 1;
1213#elif defined(__i386__)
1214 case R_386_GOTPC:
1215 case R_386_GOTOFF:
1216 gotneeded = 1;
1217#endif
1218
1219 default:
1220 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001221 }
1222
Eric Andersen21adca72000-12-06 18:18:26 +00001223 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001224 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001225 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001226 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001227 }
1228 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001229#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001230 if (!intsym->gotent.offset_done) {
1231 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001232 intsym->gotent.offset = got_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001233 got_offset += BB_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001234 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001235#endif
1236#if defined(BB_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001237 if (pltneeded && intsym->pltent.allocated == 0) {
1238 intsym->pltent.allocated = 1;
1239 intsym->pltent.offset = plt_offset;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001240 plt_offset += BB_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001241 intsym->pltent.inited = 0;
1242 pltneeded = 0;
1243 }
1244#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001245 }
1246 }
Eric Andersen21adca72000-12-06 18:18:26 +00001247
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001248#if defined(BB_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001249 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001250 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001251
Eric Andersene76c3b02001-04-05 03:14:39 +00001252 if (myrelsec) {
1253 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001254 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001255 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001256 BB_GOT_ENTRY_SIZE,
1257 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001258 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001259 }
1260
Eric Andersene76c3b02001-04-05 03:14:39 +00001261 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001262 }
Eric Andersen21adca72000-12-06 18:18:26 +00001263#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001264
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001265#if defined(BB_USE_PLT_ENTRIES)
1266 if (plt_offset)
1267 ifile->plt = obj_create_alloced_section(f, ".plt",
1268 BB_PLT_ENTRY_SIZE,
1269 plt_offset);
1270#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001271#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001272 return 1;
1273}
1274
Eric Andersen044228d2001-07-17 01:12:36 +00001275static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001276{
1277 return 1;
1278}
1279
1280
1281/*======================================================================*/
1282
1283/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001284static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001285{
1286 unsigned long h = 0;
1287 unsigned long g;
1288 unsigned char ch;
1289
1290 while (n > 0) {
1291 ch = *name++;
1292 h = (h << 4) + ch;
1293 if ((g = (h & 0xf0000000)) != 0) {
1294 h ^= g >> 24;
1295 h &= ~g;
1296 }
1297 n--;
1298 }
1299 return h;
1300}
1301
Eric Andersen044228d2001-07-17 01:12:36 +00001302static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001303{
1304 return obj_elf_hash_n(name, strlen(name));
1305}
1306
1307#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001308/* String comparison for non-co-versioned kernel and module. */
1309
1310static int ncv_strcmp(const char *a, const char *b)
1311{
1312 size_t alen = strlen(a), blen = strlen(b);
1313
1314 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1315 return strncmp(a, b, alen);
1316 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1317 return strncmp(a, b, blen);
1318 else
1319 return strcmp(a, b);
1320}
1321
1322/* String hashing for non-co-versioned kernel and module. Here
1323 we are simply forced to drop the crc from the hash. */
1324
1325static unsigned long ncv_symbol_hash(const char *str)
1326{
1327 size_t len = strlen(str);
1328 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1329 len -= 10;
1330 return obj_elf_hash_n(str, len);
1331}
1332
Eric Andersen044228d2001-07-17 01:12:36 +00001333static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001334obj_set_symbol_compare(struct obj_file *f,
1335 int (*cmp) (const char *, const char *),
1336 unsigned long (*hash) (const char *))
1337{
1338 if (cmp)
1339 f->symbol_cmp = cmp;
1340 if (hash) {
1341 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1342 int i;
1343
1344 f->symbol_hash = hash;
1345
1346 memcpy(tmptab, f->symtab, sizeof(tmptab));
1347 memset(f->symtab, 0, sizeof(f->symtab));
1348
1349 for (i = 0; i < HASH_BUCKETS; ++i)
1350 for (sym = tmptab[i]; sym; sym = next) {
1351 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1352 next = sym->next;
1353 sym->next = f->symtab[h];
1354 f->symtab[h] = sym;
1355 }
1356 }
1357}
1358
1359#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1360
Eric Andersen044228d2001-07-17 01:12:36 +00001361static struct obj_symbol *
1362obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001363 unsigned long symidx, int info,
1364 int secidx, ElfW(Addr) value,
1365 unsigned long size)
1366{
1367 struct obj_symbol *sym;
1368 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1369 int n_type = ELFW(ST_TYPE) (info);
1370 int n_binding = ELFW(ST_BIND) (info);
1371
1372 for (sym = f->symtab[hash]; sym; sym = sym->next)
1373 if (f->symbol_cmp(sym->name, name) == 0) {
1374 int o_secidx = sym->secidx;
1375 int o_info = sym->info;
1376 int o_type = ELFW(ST_TYPE) (o_info);
1377 int o_binding = ELFW(ST_BIND) (o_info);
1378
1379 /* A redefinition! Is it legal? */
1380
1381 if (secidx == SHN_UNDEF)
1382 return sym;
1383 else if (o_secidx == SHN_UNDEF)
1384 goto found;
1385 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1386 /* Cope with local and global symbols of the same name
1387 in the same object file, as might have been created
1388 by ld -r. The only reason locals are now seen at this
1389 level at all is so that we can do semi-sensible things
1390 with parameters. */
1391
1392 struct obj_symbol *nsym, **p;
1393
1394 nsym = arch_new_symbol();
1395 nsym->next = sym->next;
1396 nsym->ksymidx = -1;
1397
1398 /* Excise the old (local) symbol from the hash chain. */
1399 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1400 continue;
1401 *p = sym = nsym;
1402 goto found;
1403 } else if (n_binding == STB_LOCAL) {
1404 /* Another symbol of the same name has already been defined.
1405 Just add this to the local table. */
1406 sym = arch_new_symbol();
1407 sym->next = NULL;
1408 sym->ksymidx = -1;
1409 f->local_symtab[symidx] = sym;
1410 goto found;
1411 } else if (n_binding == STB_WEAK)
1412 return sym;
1413 else if (o_binding == STB_WEAK)
1414 goto found;
1415 /* Don't unify COMMON symbols with object types the programmer
1416 doesn't expect. */
1417 else if (secidx == SHN_COMMON
1418 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1419 return sym;
1420 else if (o_secidx == SHN_COMMON
1421 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1422 goto found;
1423 else {
1424 /* Don't report an error if the symbol is coming from
1425 the kernel or some external module. */
1426 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001427 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001428 return sym;
1429 }
1430 }
1431
1432 /* Completely new symbol. */
1433 sym = arch_new_symbol();
1434 sym->next = f->symtab[hash];
1435 f->symtab[hash] = sym;
1436 sym->ksymidx = -1;
1437
Eric Andersen66ca9482001-06-28 21:36:06 +00001438 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1439 if (symidx >= f->local_symtab_size)
1440 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1441 name, (long) symidx, (long) f->local_symtab_size);
1442 else
1443 f->local_symtab[symidx] = sym;
1444 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001445
1446 found:
1447 sym->name = name;
1448 sym->value = value;
1449 sym->size = size;
1450 sym->secidx = secidx;
1451 sym->info = info;
1452
1453 return sym;
1454}
1455
Eric Andersen044228d2001-07-17 01:12:36 +00001456static struct obj_symbol *
1457obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001458{
1459 struct obj_symbol *sym;
1460 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1461
1462 for (sym = f->symtab[hash]; sym; sym = sym->next)
1463 if (f->symbol_cmp(sym->name, name) == 0)
1464 return sym;
1465
1466 return NULL;
1467}
1468
Eric Andersen044228d2001-07-17 01:12:36 +00001469static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001470 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1471{
1472 if (sym) {
1473 if (sym->secidx >= SHN_LORESERVE)
1474 return sym->value;
1475
1476 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1477 } else {
1478 /* As a special case, a NULL sym has value zero. */
1479 return 0;
1480 }
1481}
1482
Eric Andersen044228d2001-07-17 01:12:36 +00001483static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001484{
1485 int i, n = f->header.e_shnum;
1486
1487 for (i = 0; i < n; ++i)
1488 if (strcmp(f->sections[i]->name, name) == 0)
1489 return f->sections[i];
1490
1491 return NULL;
1492}
1493
1494static int obj_load_order_prio(struct obj_section *a)
1495{
1496 unsigned long af, ac;
1497
1498 af = a->header.sh_flags;
1499
1500 ac = 0;
1501 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1502 strcmp(a->name + 5, ".init"))
1503 ac |= 32;
1504 if (af & SHF_ALLOC)
1505 ac |= 16;
1506 if (!(af & SHF_WRITE))
1507 ac |= 8;
1508 if (af & SHF_EXECINSTR)
1509 ac |= 4;
1510 if (a->header.sh_type != SHT_NOBITS)
1511 ac |= 2;
1512
1513 return ac;
1514}
1515
Eric Andersen044228d2001-07-17 01:12:36 +00001516static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001517obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1518{
1519 struct obj_section **p;
1520 int prio = obj_load_order_prio(sec);
1521 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1522 if (obj_load_order_prio(*p) < prio)
1523 break;
1524 sec->load_next = *p;
1525 *p = sec;
1526}
1527
Eric Andersen044228d2001-07-17 01:12:36 +00001528static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001529 const char *name,
1530 unsigned long align,
1531 unsigned long size)
1532{
1533 int newidx = f->header.e_shnum++;
1534 struct obj_section *sec;
1535
1536 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1537 f->sections[newidx] = sec = arch_new_section();
1538
1539 memset(sec, 0, sizeof(*sec));
1540 sec->header.sh_type = SHT_PROGBITS;
1541 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1542 sec->header.sh_size = size;
1543 sec->header.sh_addralign = align;
1544 sec->name = name;
1545 sec->idx = newidx;
1546 if (size)
1547 sec->contents = xmalloc(size);
1548
1549 obj_insert_section_load_order(f, sec);
1550
1551 return sec;
1552}
1553
Eric Andersen044228d2001-07-17 01:12:36 +00001554static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001555 const char *name,
1556 unsigned long align,
1557 unsigned long size)
1558{
1559 int newidx = f->header.e_shnum++;
1560 struct obj_section *sec;
1561
1562 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1563 f->sections[newidx] = sec = arch_new_section();
1564
1565 memset(sec, 0, sizeof(*sec));
1566 sec->header.sh_type = SHT_PROGBITS;
1567 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1568 sec->header.sh_size = size;
1569 sec->header.sh_addralign = align;
1570 sec->name = name;
1571 sec->idx = newidx;
1572 if (size)
1573 sec->contents = xmalloc(size);
1574
1575 sec->load_next = f->load_order;
1576 f->load_order = sec;
1577 if (f->load_order_search_start == &f->load_order)
1578 f->load_order_search_start = &sec->load_next;
1579
1580 return sec;
1581}
1582
Eric Andersen044228d2001-07-17 01:12:36 +00001583static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001584{
1585 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001586 if (more) {
1587 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1588 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001589 return sec->contents + oldsize;
1590}
1591
1592
Eric Andersen9f16d612000-06-12 23:11:16 +00001593/* Conditionally add the symbols from the given symbol set to the
1594 new module. */
1595
1596static int
1597add_symbols_from(
1598 struct obj_file *f,
1599 int idx, struct new_module_symbol *syms, size_t nsyms)
1600{
1601 struct new_module_symbol *s;
1602 size_t i;
1603 int used = 0;
1604
1605 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1606
1607 /* Only add symbols that are already marked external. If we
1608 override locals we may cause problems for argument initialization.
1609 We will also create a false dependency on the module. */
1610 struct obj_symbol *sym;
1611
1612 sym = obj_find_symbol(f, (char *) s->name);
1613 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1614 sym = obj_add_symbol(f, (char *) s->name, -1,
1615 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1616 idx, s->value, 0);
1617 /* Did our symbol just get installed? If so, mark the
1618 module as "used". */
1619 if (sym->secidx == idx)
1620 used = 1;
1621 }
1622 }
1623
1624 return used;
1625}
1626
1627static void add_kernel_symbols(struct obj_file *f)
1628{
1629 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001630 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001631
1632 /* Add module symbols first. */
1633
1634 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1635 if (m->nsyms
1636 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1637 m->nsyms)) m->used = 1, ++nused;
1638
1639 n_ext_modules_used = nused;
1640
1641 /* And finally the symbols from the kernel proper. */
1642
1643 if (nksyms)
1644 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1645}
1646
1647static char *get_modinfo_value(struct obj_file *f, const char *key)
1648{
1649 struct obj_section *sec;
1650 char *p, *v, *n, *ep;
1651 size_t klen = strlen(key);
1652
1653 sec = obj_find_section(f, ".modinfo");
1654 if (sec == NULL)
1655 return NULL;
1656 p = sec->contents;
1657 ep = p + sec->header.sh_size;
1658 while (p < ep) {
1659 v = strchr(p, '=');
1660 n = strchr(p, '\0');
1661 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001662 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001663 return v + 1;
1664 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001665 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001666 return n;
1667 }
1668 p = n + 1;
1669 }
1670
1671 return NULL;
1672}
1673
1674
1675/*======================================================================*/
1676/* Functions relating to module loading in pre 2.1 kernels. */
1677
1678static int
1679old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1680{
1681 while (argc > 0) {
1682 char *p, *q;
1683 struct obj_symbol *sym;
1684 int *loc;
1685
1686 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001687 if ((q = strchr(p, '=')) == NULL) {
1688 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001689 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001690 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001691 *q++ = '\0';
1692
1693 sym = obj_find_symbol(f, p);
1694
1695 /* Also check that the parameter was not resolved from the kernel. */
1696 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001697 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001698 return 0;
1699 }
1700
1701 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1702
1703 /* Do C quoting if we begin with a ". */
1704 if (*q == '"') {
1705 char *r, *str;
1706
1707 str = alloca(strlen(q));
1708 for (r = str, q++; *q != '"'; ++q, ++r) {
1709 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001710 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001711 return 0;
1712 } else if (*q == '\\')
1713 switch (*++q) {
1714 case 'a':
1715 *r = '\a';
1716 break;
1717 case 'b':
1718 *r = '\b';
1719 break;
1720 case 'e':
1721 *r = '\033';
1722 break;
1723 case 'f':
1724 *r = '\f';
1725 break;
1726 case 'n':
1727 *r = '\n';
1728 break;
1729 case 'r':
1730 *r = '\r';
1731 break;
1732 case 't':
1733 *r = '\t';
1734 break;
1735
1736 case '0':
1737 case '1':
1738 case '2':
1739 case '3':
1740 case '4':
1741 case '5':
1742 case '6':
1743 case '7':
1744 {
1745 int c = *q - '0';
1746 if (q[1] >= '0' && q[1] <= '7') {
1747 c = (c * 8) + *++q - '0';
1748 if (q[1] >= '0' && q[1] <= '7')
1749 c = (c * 8) + *++q - '0';
1750 }
1751 *r = c;
1752 }
1753 break;
1754
1755 default:
1756 *r = *q;
1757 break;
1758 } else
1759 *r = *q;
1760 }
1761 *r = '\0';
1762 obj_string_patch(f, sym->secidx, sym->value, str);
1763 } else if (*q >= '0' && *q <= '9') {
1764 do
1765 *loc++ = strtoul(q, &q, 0);
1766 while (*q++ == ',');
1767 } else {
1768 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001769 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001770 char *r; /* To search for commas */
1771
1772 /* Break the string with comas */
1773 while ((r = strchr(q, ',')) != (char *) NULL) {
1774 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001775 obj_string_patch(f, sym->secidx, myloc - contents, q);
1776 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001777 q = r;
1778 }
1779
1780 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001781 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001782 }
1783
1784 argc--, argv++;
1785 }
1786
1787 return 1;
1788}
1789
1790#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
1791static int old_is_module_checksummed(struct obj_file *f)
1792{
1793 return obj_find_symbol(f, "Using_Versions") != NULL;
1794}
1795/* Get the module's kernel version in the canonical integer form. */
1796
1797static int
1798old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1799{
1800 struct obj_symbol *sym;
1801 char *p, *q;
1802 int a, b, c;
1803
1804 sym = obj_find_symbol(f, "kernel_version");
1805 if (sym == NULL)
1806 return -1;
1807
1808 p = f->sections[sym->secidx]->contents + sym->value;
1809 strncpy(str, p, STRVERSIONLEN);
1810
1811 a = strtoul(p, &p, 10);
1812 if (*p != '.')
1813 return -1;
1814 b = strtoul(p + 1, &p, 10);
1815 if (*p != '.')
1816 return -1;
1817 c = strtoul(p + 1, &q, 10);
1818 if (p + 1 == q)
1819 return -1;
1820
1821 return a << 16 | b << 8 | c;
1822}
1823
1824#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
1825
Eric Andersenf5d5e772001-01-24 23:34:48 +00001826#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001827
1828/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1829
Eric Andersen8c185f92000-09-22 00:38:07 +00001830static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001831{
1832 struct old_kernel_sym *ks, *k;
1833 struct new_module_symbol *s;
1834 struct external_module *mod;
1835 int nks, nms, nmod, i;
1836
1837 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001838 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001839 if (nks)
1840 perror_msg("get_kernel_syms: %s", m_name);
1841 else
1842 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001843 return 0;
1844 }
1845
1846 ks = k = xmalloc(nks * sizeof(*ks));
1847
1848 if (get_kernel_syms(ks) != nks) {
1849 perror("inconsistency with get_kernel_syms -- is someone else "
1850 "playing with modules?");
1851 free(ks);
1852 return 0;
1853 }
1854
1855 /* Collect the module information. */
1856
1857 mod = NULL;
1858 nmod = -1;
1859
1860 while (k->name[0] == '#' && k->name[1]) {
1861 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001862
1863 /* Find out how many symbols this module has. */
1864 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1865 continue;
1866 nms = k2 - k - 1;
1867
1868 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1869 mod[nmod].name = k->name + 1;
1870 mod[nmod].addr = k->value;
1871 mod[nmod].used = 0;
1872 mod[nmod].nsyms = nms;
1873 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1874
1875 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1876 s->name = (unsigned long) k->name;
1877 s->value = k->value;
1878 }
1879
1880 k = k2;
1881 }
1882
1883 ext_modules = mod;
1884 n_ext_modules = nmod + 1;
1885
1886 /* Now collect the symbols for the kernel proper. */
1887
1888 if (k->name[0] == '#')
1889 ++k;
1890
1891 nksyms = nms = nks - (k - ks);
1892 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1893
1894 for (i = 0; i < nms; ++i, ++s, ++k) {
1895 s->name = (unsigned long) k->name;
1896 s->value = k->value;
1897 }
1898
1899 return 1;
1900}
1901
1902/* Return the kernel symbol checksum version, or zero if not used. */
1903
1904static int old_is_kernel_checksummed(void)
1905{
1906 /* Using_Versions is the first symbol. */
1907 if (nksyms > 0
1908 && strcmp((char *) ksyms[0].name,
1909 "Using_Versions") == 0) return ksyms[0].value;
1910 else
1911 return 0;
1912}
1913
1914
1915static int old_create_mod_use_count(struct obj_file *f)
1916{
1917 struct obj_section *sec;
1918
1919 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1920 sizeof(long));
1921
1922 obj_add_symbol(f, "mod_use_count_", -1,
1923 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1924 sizeof(long));
1925
1926 return 1;
1927}
1928
1929static int
1930old_init_module(const char *m_name, struct obj_file *f,
1931 unsigned long m_size)
1932{
1933 char *image;
1934 struct old_mod_routines routines;
1935 struct old_symbol_table *symtab;
1936 int ret;
1937
1938 /* Create the symbol table */
1939 {
1940 int nsyms = 0, strsize = 0, total;
1941
1942 /* Size things first... */
1943 if (flag_export) {
1944 int i;
1945 for (i = 0; i < HASH_BUCKETS; ++i) {
1946 struct obj_symbol *sym;
1947 for (sym = f->symtab[i]; sym; sym = sym->next)
1948 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1949 && sym->secidx <= SHN_HIRESERVE)
1950 {
1951 sym->ksymidx = nsyms++;
1952 strsize += strlen(sym->name) + 1;
1953 }
1954 }
1955 }
1956
1957 total = (sizeof(struct old_symbol_table)
1958 + nsyms * sizeof(struct old_module_symbol)
1959 + n_ext_modules_used * sizeof(struct old_module_ref)
1960 + strsize);
1961 symtab = xmalloc(total);
1962 symtab->size = total;
1963 symtab->n_symbols = nsyms;
1964 symtab->n_refs = n_ext_modules_used;
1965
1966 if (flag_export && nsyms) {
1967 struct old_module_symbol *ksym;
1968 char *str;
1969 int i;
1970
1971 ksym = symtab->symbol;
1972 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1973 + n_ext_modules_used * sizeof(struct old_module_ref));
1974
1975 for (i = 0; i < HASH_BUCKETS; ++i) {
1976 struct obj_symbol *sym;
1977 for (sym = f->symtab[i]; sym; sym = sym->next)
1978 if (sym->ksymidx >= 0) {
1979 ksym->addr = obj_symbol_final_value(f, sym);
1980 ksym->name =
1981 (unsigned long) str - (unsigned long) symtab;
1982
Matt Kraai70a78552001-01-04 02:00:17 +00001983 strcpy(str, sym->name);
1984 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001985 ksym++;
1986 }
1987 }
1988 }
1989
1990 if (n_ext_modules_used) {
1991 struct old_module_ref *ref;
1992 int i;
1993
1994 ref = (struct old_module_ref *)
1995 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1996
1997 for (i = 0; i < n_ext_modules; ++i)
1998 if (ext_modules[i].used)
1999 ref++->module = ext_modules[i].addr;
2000 }
2001 }
2002
2003 /* Fill in routines. */
2004
2005 routines.init =
2006 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2007 routines.cleanup =
2008 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2009
2010 /* Whew! All of the initialization is complete. Collect the final
2011 module image and give it to the kernel. */
2012
2013 image = xmalloc(m_size);
2014 obj_create_image(f, image);
2015
2016 /* image holds the complete relocated module, accounting correctly for
2017 mod_use_count. However the old module kernel support assume that
2018 it is receiving something which does not contain mod_use_count. */
2019 ret = old_sys_init_module(m_name, image + sizeof(long),
2020 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2021 : 0), &routines, symtab);
2022 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002023 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002024
2025 free(image);
2026 free(symtab);
2027
2028 return ret == 0;
2029}
2030
2031#else
2032
2033#define old_create_mod_use_count(x) TRUE
2034#define old_init_module(x, y, z) TRUE
2035
Eric Andersenf5d5e772001-01-24 23:34:48 +00002036#endif /* BB_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002037
2038
2039
2040/*======================================================================*/
2041/* Functions relating to module loading after 2.1.18. */
2042
2043static int
2044new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2045{
2046 while (argc > 0) {
2047 char *p, *q, *key;
2048 struct obj_symbol *sym;
2049 char *contents, *loc;
2050 int min, max, n;
2051
2052 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002053 if ((q = strchr(p, '=')) == NULL) {
2054 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002055 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002056 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002057
2058 key = alloca(q - p + 6);
2059 memcpy(key, "parm_", 5);
2060 memcpy(key + 5, p, q - p);
2061 key[q - p + 5] = 0;
2062
2063 p = get_modinfo_value(f, key);
2064 key += 5;
2065 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002066 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002067 return 0;
2068 }
2069
2070 sym = obj_find_symbol(f, key);
2071
2072 /* Also check that the parameter was not resolved from the kernel. */
2073 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002074 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002075 return 0;
2076 }
2077
2078 if (isdigit(*p)) {
2079 min = strtoul(p, &p, 10);
2080 if (*p == '-')
2081 max = strtoul(p + 1, &p, 10);
2082 else
2083 max = min;
2084 } else
2085 min = max = 1;
2086
2087 contents = f->sections[sym->secidx]->contents;
2088 loc = contents + sym->value;
2089 n = (*++q != '\0');
2090
2091 while (1) {
2092 if ((*p == 's') || (*p == 'c')) {
2093 char *str;
2094
2095 /* Do C quoting if we begin with a ", else slurp the lot. */
2096 if (*q == '"') {
2097 char *r;
2098
2099 str = alloca(strlen(q));
2100 for (r = str, q++; *q != '"'; ++q, ++r) {
2101 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002102 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002103 key);
2104 return 0;
2105 } else if (*q == '\\')
2106 switch (*++q) {
2107 case 'a':
2108 *r = '\a';
2109 break;
2110 case 'b':
2111 *r = '\b';
2112 break;
2113 case 'e':
2114 *r = '\033';
2115 break;
2116 case 'f':
2117 *r = '\f';
2118 break;
2119 case 'n':
2120 *r = '\n';
2121 break;
2122 case 'r':
2123 *r = '\r';
2124 break;
2125 case 't':
2126 *r = '\t';
2127 break;
2128
2129 case '0':
2130 case '1':
2131 case '2':
2132 case '3':
2133 case '4':
2134 case '5':
2135 case '6':
2136 case '7':
2137 {
2138 int c = *q - '0';
2139 if (q[1] >= '0' && q[1] <= '7') {
2140 c = (c * 8) + *++q - '0';
2141 if (q[1] >= '0' && q[1] <= '7')
2142 c = (c * 8) + *++q - '0';
2143 }
2144 *r = c;
2145 }
2146 break;
2147
2148 default:
2149 *r = *q;
2150 break;
2151 } else
2152 *r = *q;
2153 }
2154 *r = '\0';
2155 ++q;
2156 } else {
2157 char *r;
2158
2159 /* In this case, the string is not quoted. We will break
2160 it using the coma (like for ints). If the user wants to
2161 include comas in a string, he just has to quote it */
2162
2163 /* Search the next coma */
2164 r = strchr(q, ',');
2165
2166 /* Found ? */
2167 if (r != (char *) NULL) {
2168 /* Recopy the current field */
2169 str = alloca(r - q + 1);
2170 memcpy(str, q, r - q);
2171
2172 /* I don't know if it is usefull, as the previous case
2173 doesn't null terminate the string ??? */
2174 str[r - q] = '\0';
2175
2176 /* Keep next fields */
2177 q = r;
2178 } else {
2179 /* last string */
2180 str = q;
2181 q = "";
2182 }
2183 }
2184
2185 if (*p == 's') {
2186 /* Normal string */
2187 obj_string_patch(f, sym->secidx, loc - contents, str);
2188 loc += tgt_sizeof_char_p;
2189 } else {
2190 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002191 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002192
2193 /* Get the size of each member */
2194 /* Probably we should do that outside the loop ? */
2195 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002196 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002197 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002198 return 0;
2199 }
2200 charssize = strtoul(p + 1, (char **) NULL, 10);
2201
2202 /* Check length */
2203 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002204 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002205 charssize - 1);
2206 return 0;
2207 }
2208
2209 /* Copy to location */
2210 strcpy((char *) loc, str);
2211 loc += charssize;
2212 }
2213 } else {
2214 long v = strtoul(q, &q, 0);
2215 switch (*p) {
2216 case 'b':
2217 *loc++ = v;
2218 break;
2219 case 'h':
2220 *(short *) loc = v;
2221 loc += tgt_sizeof_short;
2222 break;
2223 case 'i':
2224 *(int *) loc = v;
2225 loc += tgt_sizeof_int;
2226 break;
2227 case 'l':
2228 *(long *) loc = v;
2229 loc += tgt_sizeof_long;
2230 break;
2231
2232 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002233 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002234 return 0;
2235 }
2236 }
2237
2238 retry_end_of_value:
2239 switch (*q) {
2240 case '\0':
2241 goto end_of_arg;
2242
2243 case ' ':
2244 case '\t':
2245 case '\n':
2246 case '\r':
2247 ++q;
2248 goto retry_end_of_value;
2249
2250 case ',':
2251 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002252 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002253 return 0;
2254 }
2255 ++q;
2256 break;
2257
2258 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002259 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002260 return 0;
2261 }
2262 }
2263
2264 end_of_arg:
2265 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002266 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002267 return 0;
2268 }
2269
2270 argc--, argv++;
2271 }
2272
2273 return 1;
2274}
2275
2276#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
2277static int new_is_module_checksummed(struct obj_file *f)
2278{
2279 const char *p = get_modinfo_value(f, "using_checksums");
2280 if (p)
2281 return atoi(p);
2282 else
2283 return 0;
2284}
2285
2286/* Get the module's kernel version in the canonical integer form. */
2287
2288static int
2289new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2290{
2291 char *p, *q;
2292 int a, b, c;
2293
2294 p = get_modinfo_value(f, "kernel_version");
2295 if (p == NULL)
2296 return -1;
2297 strncpy(str, p, STRVERSIONLEN);
2298
2299 a = strtoul(p, &p, 10);
2300 if (*p != '.')
2301 return -1;
2302 b = strtoul(p + 1, &p, 10);
2303 if (*p != '.')
2304 return -1;
2305 c = strtoul(p + 1, &q, 10);
2306 if (p + 1 == q)
2307 return -1;
2308
2309 return a << 16 | b << 8 | c;
2310}
2311
2312#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
2313
2314
Eric Andersenf5d5e772001-01-24 23:34:48 +00002315#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002316
2317/* Fetch the loaded modules, and all currently exported symbols. */
2318
2319static int new_get_kernel_symbols(void)
2320{
2321 char *module_names, *mn;
2322 struct external_module *modules, *m;
2323 struct new_module_symbol *syms, *s;
2324 size_t ret, bufsize, nmod, nsyms, i, j;
2325
2326 /* Collect the loaded modules. */
2327
2328 module_names = xmalloc(bufsize = 256);
2329 retry_modules_load:
2330 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002331 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002332 module_names = xrealloc(module_names, bufsize = ret);
2333 goto retry_modules_load;
2334 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002335 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002336 return 0;
2337 }
2338
2339 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002340
2341 /* Collect the modules' symbols. */
2342
Mark Whitley94fd4802001-03-12 23:08:34 +00002343 if (nmod){
2344 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2345 memset(modules, 0, nmod * sizeof(*modules));
2346 for (i = 0, mn = module_names, m = modules;
2347 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2348 struct new_module_info info;
2349
2350 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2351 if (errno == ENOENT) {
2352 /* The module was removed out from underneath us. */
2353 continue;
2354 }
2355 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002356 return 0;
2357 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002358
2359 syms = xmalloc(bufsize = 1024);
2360 retry_mod_sym_load:
2361 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2362 switch (errno) {
2363 case ENOSPC:
2364 syms = xrealloc(syms, bufsize = ret);
2365 goto retry_mod_sym_load;
2366 case ENOENT:
2367 /* The module was removed out from underneath us. */
2368 continue;
2369 default:
2370 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2371 return 0;
2372 }
2373 }
2374 nsyms = ret;
2375
2376 m->name = mn;
2377 m->addr = info.addr;
2378 m->nsyms = nsyms;
2379 m->syms = syms;
2380
2381 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2382 s->name += (unsigned long) syms;
2383 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002384 }
2385 }
2386
2387 /* Collect the kernel's symbols. */
2388
2389 syms = xmalloc(bufsize = 16 * 1024);
2390 retry_kern_sym_load:
2391 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002392 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002393 syms = xrealloc(syms, bufsize = ret);
2394 goto retry_kern_sym_load;
2395 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002396 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002397 return 0;
2398 }
2399 nksyms = nsyms = ret;
2400 ksyms = syms;
2401
2402 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2403 s->name += (unsigned long) syms;
2404 }
2405 return 1;
2406}
2407
2408
2409/* Return the kernel symbol checksum version, or zero if not used. */
2410
2411static int new_is_kernel_checksummed(void)
2412{
2413 struct new_module_symbol *s;
2414 size_t i;
2415
2416 /* Using_Versions is not the first symbol, but it should be in there. */
2417
2418 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2419 if (strcmp((char *) s->name, "Using_Versions") == 0)
2420 return s->value;
2421
2422 return 0;
2423}
2424
2425
2426static int new_create_this_module(struct obj_file *f, const char *m_name)
2427{
2428 struct obj_section *sec;
2429
2430 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2431 sizeof(struct new_module));
2432 memset(sec->contents, 0, sizeof(struct new_module));
2433
2434 obj_add_symbol(f, "__this_module", -1,
2435 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2436 sizeof(struct new_module));
2437
2438 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2439 m_name);
2440
2441 return 1;
2442}
2443
2444
2445static int new_create_module_ksymtab(struct obj_file *f)
2446{
2447 struct obj_section *sec;
2448 int i;
2449
2450 /* We must always add the module references. */
2451
2452 if (n_ext_modules_used) {
2453 struct new_module_ref *dep;
2454 struct obj_symbol *tm;
2455
2456 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2457 (sizeof(struct new_module_ref)
2458 * n_ext_modules_used));
2459 if (!sec)
2460 return 0;
2461
2462 tm = obj_find_symbol(f, "__this_module");
2463 dep = (struct new_module_ref *) sec->contents;
2464 for (i = 0; i < n_ext_modules; ++i)
2465 if (ext_modules[i].used) {
2466 dep->dep = ext_modules[i].addr;
2467 obj_symbol_patch(f, sec->idx,
2468 (char *) &dep->ref - sec->contents, tm);
2469 dep->next_ref = 0;
2470 ++dep;
2471 }
2472 }
2473
2474 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2475 size_t nsyms;
2476 int *loaded;
2477
2478 sec =
2479 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2480 0);
2481
2482 /* We don't want to export symbols residing in sections that
2483 aren't loaded. There are a number of these created so that
2484 we make sure certain module options don't appear twice. */
2485
2486 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2487 while (--i >= 0)
2488 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2489
2490 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2491 struct obj_symbol *sym;
2492 for (sym = f->symtab[i]; sym; sym = sym->next)
2493 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2494 && sym->secidx <= SHN_HIRESERVE
2495 && (sym->secidx >= SHN_LORESERVE
2496 || loaded[sym->secidx])) {
2497 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2498
2499 obj_symbol_patch(f, sec->idx, ofs, sym);
2500 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2501 sym->name);
2502
2503 nsyms++;
2504 }
2505 }
2506
2507 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2508 }
2509
2510 return 1;
2511}
2512
2513
2514static int
2515new_init_module(const char *m_name, struct obj_file *f,
2516 unsigned long m_size)
2517{
2518 struct new_module *module;
2519 struct obj_section *sec;
2520 void *image;
2521 int ret;
2522 tgt_long m_addr;
2523
2524 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002525 if (!sec || !sec->contents) {
2526 perror_msg_and_die("corrupt module %s?",m_name);
2527 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002528 module = (struct new_module *) sec->contents;
2529 m_addr = sec->header.sh_addr;
2530
2531 module->size_of_struct = sizeof(*module);
2532 module->size = m_size;
2533 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2534
2535 sec = obj_find_section(f, "__ksymtab");
2536 if (sec && sec->header.sh_size) {
2537 module->syms = sec->header.sh_addr;
2538 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2539 }
2540
2541 if (n_ext_modules_used) {
2542 sec = obj_find_section(f, ".kmodtab");
2543 module->deps = sec->header.sh_addr;
2544 module->ndeps = n_ext_modules_used;
2545 }
2546
2547 module->init =
2548 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2549 module->cleanup =
2550 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2551
2552 sec = obj_find_section(f, "__ex_table");
2553 if (sec) {
2554 module->ex_table_start = sec->header.sh_addr;
2555 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2556 }
2557
2558 sec = obj_find_section(f, ".text.init");
2559 if (sec) {
2560 module->runsize = sec->header.sh_addr - m_addr;
2561 }
2562 sec = obj_find_section(f, ".data.init");
2563 if (sec) {
2564 if (!module->runsize ||
2565 module->runsize > sec->header.sh_addr - m_addr)
2566 module->runsize = sec->header.sh_addr - m_addr;
2567 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002568 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2569 if (sec && sec->header.sh_size) {
2570 module->archdata_start = (void*)sec->header.sh_addr;
2571 module->archdata_end = module->archdata_start + sec->header.sh_size;
2572 }
2573 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2574 if (sec && sec->header.sh_size) {
2575 module->kallsyms_start = (void*)sec->header.sh_addr;
2576 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2577 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002578
2579 if (!arch_init_module(f, module))
2580 return 0;
2581
2582 /* Whew! All of the initialization is complete. Collect the final
2583 module image and give it to the kernel. */
2584
2585 image = xmalloc(m_size);
2586 obj_create_image(f, image);
2587
Eric Andersen64c8b172001-04-05 07:33:10 +00002588 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002589 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002590 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002591
2592 free(image);
2593
2594 return ret == 0;
2595}
2596
2597#else
2598
2599#define new_init_module(x, y, z) TRUE
2600#define new_create_this_module(x, y) 0
2601#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002602#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002603
Eric Andersenf5d5e772001-01-24 23:34:48 +00002604#endif /* BB_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002605
2606
2607/*======================================================================*/
2608
Eric Andersen044228d2001-07-17 01:12:36 +00002609static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002610obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2611 const char *string)
2612{
2613 struct obj_string_patch *p;
2614 struct obj_section *strsec;
2615 size_t len = strlen(string) + 1;
2616 char *loc;
2617
2618 p = xmalloc(sizeof(*p));
2619 p->next = f->string_patches;
2620 p->reloc_secidx = secidx;
2621 p->reloc_offset = offset;
2622 f->string_patches = p;
2623
2624 strsec = obj_find_section(f, ".kstrtab");
2625 if (strsec == NULL) {
2626 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2627 p->string_offset = 0;
2628 loc = strsec->contents;
2629 } else {
2630 p->string_offset = strsec->header.sh_size;
2631 loc = obj_extend_section(strsec, len);
2632 }
2633 memcpy(loc, string, len);
2634
2635 return 1;
2636}
2637
Eric Andersen044228d2001-07-17 01:12:36 +00002638static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002639obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2640 struct obj_symbol *sym)
2641{
2642 struct obj_symbol_patch *p;
2643
2644 p = xmalloc(sizeof(*p));
2645 p->next = f->symbol_patches;
2646 p->reloc_secidx = secidx;
2647 p->reloc_offset = offset;
2648 p->sym = sym;
2649 f->symbol_patches = p;
2650
2651 return 1;
2652}
2653
Eric Andersen044228d2001-07-17 01:12:36 +00002654static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002655{
2656 unsigned long i;
2657 int ret = 1;
2658
2659 for (i = 0; i < HASH_BUCKETS; ++i) {
2660 struct obj_symbol *sym;
2661 for (sym = f->symtab[i]; sym; sym = sym->next)
2662 if (sym->secidx == SHN_UNDEF) {
2663 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2664 sym->secidx = SHN_ABS;
2665 sym->value = 0;
2666 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002667 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002668 ret = 0;
2669 }
2670 }
2671 }
2672
2673 return ret;
2674}
2675
Eric Andersen044228d2001-07-17 01:12:36 +00002676static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002677{
2678 struct common_entry {
2679 struct common_entry *next;
2680 struct obj_symbol *sym;
2681 } *common_head = NULL;
2682
2683 unsigned long i;
2684
2685 for (i = 0; i < HASH_BUCKETS; ++i) {
2686 struct obj_symbol *sym;
2687 for (sym = f->symtab[i]; sym; sym = sym->next)
2688 if (sym->secidx == SHN_COMMON) {
2689 /* Collect all COMMON symbols and sort them by size so as to
2690 minimize space wasted by alignment requirements. */
2691 {
2692 struct common_entry **p, *n;
2693 for (p = &common_head; *p; p = &(*p)->next)
2694 if (sym->size <= (*p)->sym->size)
2695 break;
2696
2697 n = alloca(sizeof(*n));
2698 n->next = *p;
2699 n->sym = sym;
2700 *p = n;
2701 }
2702 }
2703 }
2704
2705 for (i = 1; i < f->local_symtab_size; ++i) {
2706 struct obj_symbol *sym = f->local_symtab[i];
2707 if (sym && sym->secidx == SHN_COMMON) {
2708 struct common_entry **p, *n;
2709 for (p = &common_head; *p; p = &(*p)->next)
2710 if (sym == (*p)->sym)
2711 break;
2712 else if (sym->size < (*p)->sym->size) {
2713 n = alloca(sizeof(*n));
2714 n->next = *p;
2715 n->sym = sym;
2716 *p = n;
2717 break;
2718 }
2719 }
2720 }
2721
2722 if (common_head) {
2723 /* Find the bss section. */
2724 for (i = 0; i < f->header.e_shnum; ++i)
2725 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2726 break;
2727
2728 /* If for some reason there hadn't been one, create one. */
2729 if (i == f->header.e_shnum) {
2730 struct obj_section *sec;
2731
2732 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2733 f->sections[i] = sec = arch_new_section();
2734 f->header.e_shnum = i + 1;
2735
2736 memset(sec, 0, sizeof(*sec));
2737 sec->header.sh_type = SHT_PROGBITS;
2738 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2739 sec->name = ".bss";
2740 sec->idx = i;
2741 }
2742
2743 /* Allocate the COMMONS. */
2744 {
2745 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2746 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2747 struct common_entry *c;
2748
2749 for (c = common_head; c; c = c->next) {
2750 ElfW(Addr) align = c->sym->value;
2751
2752 if (align > max_align)
2753 max_align = align;
2754 if (bss_size & (align - 1))
2755 bss_size = (bss_size | (align - 1)) + 1;
2756
2757 c->sym->secidx = i;
2758 c->sym->value = bss_size;
2759
2760 bss_size += c->sym->size;
2761 }
2762
2763 f->sections[i]->header.sh_size = bss_size;
2764 f->sections[i]->header.sh_addralign = max_align;
2765 }
2766 }
2767
2768 /* For the sake of patch relocation and parameter initialization,
2769 allocate zeroed data for NOBITS sections now. Note that after
2770 this we cannot assume NOBITS are really empty. */
2771 for (i = 0; i < f->header.e_shnum; ++i) {
2772 struct obj_section *s = f->sections[i];
2773 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002774 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002775 s->contents = memset(xmalloc(s->header.sh_size),
2776 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002777 else
2778 s->contents = NULL;
2779
Eric Andersen9f16d612000-06-12 23:11:16 +00002780 s->header.sh_type = SHT_PROGBITS;
2781 }
2782 }
2783}
2784
Eric Andersen044228d2001-07-17 01:12:36 +00002785static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002786{
2787 unsigned long dot = 0;
2788 struct obj_section *sec;
2789
2790 /* Finalize the positions of the sections relative to one another. */
2791
2792 for (sec = f->load_order; sec; sec = sec->load_next) {
2793 ElfW(Addr) align;
2794
2795 align = sec->header.sh_addralign;
2796 if (align && (dot & (align - 1)))
2797 dot = (dot | (align - 1)) + 1;
2798
2799 sec->header.sh_addr = dot;
2800 dot += sec->header.sh_size;
2801 }
2802
2803 return dot;
2804}
2805
Eric Andersen044228d2001-07-17 01:12:36 +00002806static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002807{
2808 int i, n = f->header.e_shnum;
2809 int ret = 1;
2810
2811 /* Finalize the addresses of the sections. */
2812
2813 f->baseaddr = base;
2814 for (i = 0; i < n; ++i)
2815 f->sections[i]->header.sh_addr += base;
2816
2817 /* And iterate over all of the relocations. */
2818
2819 for (i = 0; i < n; ++i) {
2820 struct obj_section *relsec, *symsec, *targsec, *strsec;
2821 ElfW(RelM) * rel, *relend;
2822 ElfW(Sym) * symtab;
2823 const char *strtab;
2824
2825 relsec = f->sections[i];
2826 if (relsec->header.sh_type != SHT_RELM)
2827 continue;
2828
2829 symsec = f->sections[relsec->header.sh_link];
2830 targsec = f->sections[relsec->header.sh_info];
2831 strsec = f->sections[symsec->header.sh_link];
2832
2833 rel = (ElfW(RelM) *) relsec->contents;
2834 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2835 symtab = (ElfW(Sym) *) symsec->contents;
2836 strtab = (const char *) strsec->contents;
2837
2838 for (; rel < relend; ++rel) {
2839 ElfW(Addr) value = 0;
2840 struct obj_symbol *intsym = NULL;
2841 unsigned long symndx;
2842 ElfW(Sym) * extsym = 0;
2843 const char *errmsg;
2844
2845 /* Attempt to find a value to use for this relocation. */
2846
2847 symndx = ELFW(R_SYM) (rel->r_info);
2848 if (symndx) {
2849 /* Note we've already checked for undefined symbols. */
2850
2851 extsym = &symtab[symndx];
2852 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2853 /* Local symbols we look up in the local table to be sure
2854 we get the one that is really intended. */
2855 intsym = f->local_symtab[symndx];
2856 } else {
2857 /* Others we look up in the hash table. */
2858 const char *name;
2859 if (extsym->st_name)
2860 name = strtab + extsym->st_name;
2861 else
2862 name = f->sections[extsym->st_shndx]->name;
2863 intsym = obj_find_symbol(f, name);
2864 }
2865
2866 value = obj_symbol_final_value(f, intsym);
2867 intsym->referenced = 1;
2868 }
2869#if SHT_RELM == SHT_RELA
2870#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2871 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2872 if (!extsym || !extsym->st_name ||
2873 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2874#endif
2875 value += rel->r_addend;
2876#endif
2877
2878 /* Do it! */
2879 switch (arch_apply_relocation
2880 (f, targsec, symsec, intsym, rel, value)) {
2881 case obj_reloc_ok:
2882 break;
2883
2884 case obj_reloc_overflow:
2885 errmsg = "Relocation overflow";
2886 goto bad_reloc;
2887 case obj_reloc_dangerous:
2888 errmsg = "Dangerous relocation";
2889 goto bad_reloc;
2890 case obj_reloc_unhandled:
2891 errmsg = "Unhandled relocation";
2892 bad_reloc:
2893 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002894 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002895 (long) ELFW(R_TYPE) (rel->r_info),
2896 strtab + extsym->st_name);
2897 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002898 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002899 (long) ELFW(R_TYPE) (rel->r_info));
2900 }
2901 ret = 0;
2902 break;
2903 }
2904 }
2905 }
2906
2907 /* Finally, take care of the patches. */
2908
2909 if (f->string_patches) {
2910 struct obj_string_patch *p;
2911 struct obj_section *strsec;
2912 ElfW(Addr) strsec_base;
2913 strsec = obj_find_section(f, ".kstrtab");
2914 strsec_base = strsec->header.sh_addr;
2915
2916 for (p = f->string_patches; p; p = p->next) {
2917 struct obj_section *targsec = f->sections[p->reloc_secidx];
2918 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2919 = strsec_base + p->string_offset;
2920 }
2921 }
2922
2923 if (f->symbol_patches) {
2924 struct obj_symbol_patch *p;
2925
2926 for (p = f->symbol_patches; p; p = p->next) {
2927 struct obj_section *targsec = f->sections[p->reloc_secidx];
2928 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2929 = obj_symbol_final_value(f, p->sym);
2930 }
2931 }
2932
2933 return ret;
2934}
2935
Eric Andersen044228d2001-07-17 01:12:36 +00002936static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002937{
2938 struct obj_section *sec;
2939 ElfW(Addr) base = f->baseaddr;
2940
2941 for (sec = f->load_order; sec; sec = sec->load_next) {
2942 char *secimg;
2943
Eric Andersen2bf658d2001-02-24 20:01:53 +00002944 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002945 continue;
2946
2947 secimg = image + (sec->header.sh_addr - base);
2948
2949 /* Note that we allocated data for NOBITS sections earlier. */
2950 memcpy(secimg, sec->contents, sec->header.sh_size);
2951 }
2952
2953 return 1;
2954}
2955
2956/*======================================================================*/
2957
Eric Andersen044228d2001-07-17 01:12:36 +00002958static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002959{
2960 struct obj_file *f;
2961 ElfW(Shdr) * section_headers;
2962 int shnum, i;
2963 char *shstrtab;
2964
2965 /* Read the file header. */
2966
2967 f = arch_new_file();
2968 memset(f, 0, sizeof(*f));
2969 f->symbol_cmp = strcmp;
2970 f->symbol_hash = obj_elf_hash;
2971 f->load_order_search_start = &f->load_order;
2972
2973 fseek(fp, 0, SEEK_SET);
2974 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002975 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002976 return NULL;
2977 }
2978
2979 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2980 || f->header.e_ident[EI_MAG1] != ELFMAG1
2981 || f->header.e_ident[EI_MAG2] != ELFMAG2
2982 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002983 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002984 return NULL;
2985 }
2986 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2987 || f->header.e_ident[EI_DATA] != ELFDATAM
2988 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2989 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002990 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002991 return NULL;
2992 }
2993 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002994 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002995 return NULL;
2996 }
2997
2998 /* Read the section headers. */
2999
3000 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003001 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003002 (unsigned long) f->header.e_shentsize,
3003 (unsigned long) sizeof(ElfW(Shdr)));
3004 return NULL;
3005 }
3006
3007 shnum = f->header.e_shnum;
3008 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3009 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3010
3011 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3012 fseek(fp, f->header.e_shoff, SEEK_SET);
3013 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003014 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 return NULL;
3016 }
3017
3018 /* Read the section data. */
3019
3020 for (i = 0; i < shnum; ++i) {
3021 struct obj_section *sec;
3022
3023 f->sections[i] = sec = arch_new_section();
3024 memset(sec, 0, sizeof(*sec));
3025
3026 sec->header = section_headers[i];
3027 sec->idx = i;
3028
Eric Andersen2bf658d2001-02-24 20:01:53 +00003029 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003030 case SHT_NULL:
3031 case SHT_NOTE:
3032 case SHT_NOBITS:
3033 /* ignore */
3034 break;
3035
3036 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003037#if LOADBITS
3038 if (!loadprogbits) {
3039 sec->contents = NULL;
3040 break;
3041 }
3042#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003043 case SHT_SYMTAB:
3044 case SHT_STRTAB:
3045 case SHT_RELM:
3046 if (sec->header.sh_size > 0) {
3047 sec->contents = xmalloc(sec->header.sh_size);
3048 fseek(fp, sec->header.sh_offset, SEEK_SET);
3049 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003050 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003051 return NULL;
3052 }
3053 } else {
3054 sec->contents = NULL;
3055 }
3056 break;
3057
3058#if SHT_RELM == SHT_REL
3059 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003060 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003061 return NULL;
3062#else
3063 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003064 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003065 return NULL;
3066#endif
3067
3068 default:
3069 if (sec->header.sh_type >= SHT_LOPROC) {
3070 /* Assume processor specific section types are debug
3071 info and can safely be ignored. If this is ever not
3072 the case (Hello MIPS?), don't put ifdefs here but
3073 create an arch_load_proc_section(). */
3074 break;
3075 }
3076
Matt Kraaidd19c692001-01-31 19:00:21 +00003077 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003078 (long) sec->header.sh_type);
3079 return NULL;
3080 }
3081 }
3082
3083 /* Do what sort of interpretation as needed by each section. */
3084
3085 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3086
3087 for (i = 0; i < shnum; ++i) {
3088 struct obj_section *sec = f->sections[i];
3089 sec->name = shstrtab + sec->header.sh_name;
3090 }
3091
3092 for (i = 0; i < shnum; ++i) {
3093 struct obj_section *sec = f->sections[i];
3094
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003095 /* .modinfo should be contents only but gcc has no attribute for that.
3096 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3097 */
3098 if (strcmp(sec->name, ".modinfo") == 0)
3099 sec->header.sh_flags &= ~SHF_ALLOC;
3100
Eric Andersen9f16d612000-06-12 23:11:16 +00003101 if (sec->header.sh_flags & SHF_ALLOC)
3102 obj_insert_section_load_order(f, sec);
3103
3104 switch (sec->header.sh_type) {
3105 case SHT_SYMTAB:
3106 {
3107 unsigned long nsym, j;
3108 char *strtab;
3109 ElfW(Sym) * sym;
3110
3111 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003112 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003113 (unsigned long) sec->header.sh_entsize,
3114 (unsigned long) sizeof(ElfW(Sym)));
3115 return NULL;
3116 }
3117
3118 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3119 strtab = f->sections[sec->header.sh_link]->contents;
3120 sym = (ElfW(Sym) *) sec->contents;
3121
3122 /* Allocate space for a table of local symbols. */
3123 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003124 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003125
3126 /* Insert all symbols into the hash table. */
3127 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3128 const char *name;
3129 if (sym->st_name)
3130 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003131 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 name = f->sections[sym->st_shndx]->name;
3133
3134 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3135 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003136 }
3137 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003138 break;
3139
3140 case SHT_RELM:
3141 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003142 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003143 (unsigned long) sec->header.sh_entsize,
3144 (unsigned long) sizeof(ElfW(RelM)));
3145 return NULL;
3146 }
3147 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003148 /* XXX Relocation code from modutils-2.3.19 is not here.
3149 * Why? That's about 20 lines of code from obj/obj_load.c,
3150 * which gets done in a second pass through the sections.
3151 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003152 }
3153 }
3154
3155 return f;
3156}
3157
Eric Andersen8ae319a2001-05-21 16:09:18 +00003158#ifdef BB_FEATURE_INSMOD_LOADINKMEM
3159/*
3160 * load the unloaded sections directly into the memory allocated by
3161 * kernel for the module
3162 */
3163
Eric Andersenac5dbd12001-08-22 05:26:08 +00003164static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003165{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003166 ElfW(Addr) base = f->baseaddr;
3167 struct obj_section* sec;
3168
3169 for (sec = f->load_order; sec; sec = sec->load_next) {
3170
3171 /* section already loaded? */
3172 if (sec->contents != NULL)
3173 continue;
3174
3175 if (sec->header.sh_size == 0)
3176 continue;
3177
3178 sec->contents = imagebase + (sec->header.sh_addr - base);
3179 fseek(fp, sec->header.sh_offset, SEEK_SET);
3180 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Eric Andersenac5dbd12001-08-22 05:26:08 +00003181 error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003182 return 0;
3183 }
3184
3185 }
3186 return 1;
3187}
3188#endif
3189
Eric Andersen9f16d612000-06-12 23:11:16 +00003190static void hide_special_symbols(struct obj_file *f)
3191{
3192 static const char *const specials[] = {
3193 "cleanup_module",
3194 "init_module",
3195 "kernel_version",
3196 NULL
3197 };
3198
3199 struct obj_symbol *sym;
3200 const char *const *p;
3201
3202 for (p = specials; *p; ++p)
3203 if ((sym = obj_find_symbol(f, *p)) != NULL)
3204 sym->info =
3205 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3206}
3207
3208
3209
3210extern int insmod_main( int argc, char **argv)
3211{
Eric Andersena18aaf12001-01-24 19:07:09 +00003212 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003213 int k_crcs;
3214 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003215 int len;
3216 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003217 unsigned long m_size;
3218 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003219 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003220 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003221 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003222 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003223 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003224 int m_has_modinfo;
3225#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003226 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003227 char m_strversion[STRVERSIONLEN];
3228 int m_version;
3229 int m_crcs;
3230#endif
3231
Erik Andersene49d5ec2000-02-08 19:58:47 +00003232 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003233 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003234 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003235 case 'f': /* force loading */
3236 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003237 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003238 case 'k': /* module loaded by kerneld, auto-cleanable */
3239 flag_autoclean = 1;
3240 break;
3241 case 'v': /* verbose output */
3242 flag_verbose = 1;
3243 break;
3244 case 'x': /* do not export externs */
3245 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003246 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003247 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003248 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003249 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003250 case 'L': /* Stub warning */
3251 /* This is needed for compatibility with modprobe.
3252 * In theory, this does locking, but we don't do
3253 * that. So be careful and plan your life around not
3254 * loading the same module 50 times concurrently. */
3255 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003256 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003257 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003258 }
Erik Andersend387d011999-12-21 02:55:11 +00003259 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003260
3261 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003262 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003263 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003264
Erik Andersene49d5ec2000-02-08 19:58:47 +00003265 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003266 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003267 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003268 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003269 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003270 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003271 len = strlen(tmp);
3272
3273 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3274 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003275 memcpy(m_fullName, tmp, len);
3276 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003277 if (*m_name == '\0') {
3278 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003279 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003280 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003281
Eric Andersen14d35432001-05-14 17:07:32 +00003282 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003283 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3284 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003285 struct utsname myuname;
3286
3287 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3288 * but do not error out yet if we fail to find it... */
3289 if (uname(&myuname) == 0) {
3290 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003291 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003292 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3293 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003294 /* Jump through hoops in case /lib/modules/`uname -r`
3295 * is a symlink. We do not want recursive_action to
3296 * follow symlinks, but we do want to follow the
3297 * /lib/modules/`uname -r` dir, So resolve it ourselves
3298 * if it is a link... */
3299 if (realpath (module_dir, real_module_dir) == NULL)
3300 strcpy(real_module_dir, module_dir);
3301 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003302 check_module_name_match, 0, m_fullName);
3303 }
3304
3305 /* Check if we have found anything yet */
3306 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003307 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003308 char module_dir[FILENAME_MAX];
3309 if (realpath (_PATH_MODULES, module_dir) == NULL)
3310 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003311 /* No module found under /lib/modules/`uname -r`, this
3312 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003313 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003314 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003315 {
Eric Andersen14d35432001-05-14 17:07:32 +00003316 if (m_filename[0] == '\0'
3317 || ((fp = fopen(m_filename, "r")) == NULL))
3318 {
3319 error_msg("%s: no module by that name found", m_fullName);
3320 return EXIT_FAILURE;
3321 }
3322 } else
3323 error_msg_and_die("%s: no module by that name found", m_fullName);
3324 }
3325 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003326 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003327
Eric Andersen14d35432001-05-14 17:07:32 +00003328 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003329
Eric Andersen8ae319a2001-05-21 16:09:18 +00003330 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003331 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003332
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 if (get_modinfo_value(f, "kernel_version") == NULL)
3334 m_has_modinfo = 0;
3335 else
3336 m_has_modinfo = 1;
3337
3338#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3339 /* Version correspondence? */
3340
Matt Kraai063c1f52001-08-06 14:18:08 +00003341 if (uname(&uts_info) < 0)
3342 uts_info.release[0] = '\0';
Eric Andersen9f16d612000-06-12 23:11:16 +00003343 if (m_has_modinfo) {
3344 m_version = new_get_module_version(f, m_strversion);
3345 } else {
3346 m_version = old_get_module_version(f, m_strversion);
3347 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003348 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003349 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003350 goto out;
3351 }
3352 }
3353
Matt Kraai063c1f52001-08-06 14:18:08 +00003354 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003355 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003356 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003358 "\twhile this kernel is version %s",
Matt Kraai063c1f52001-08-06 14:18:08 +00003359 m_filename, m_strversion, uts_info.release);
Eric Andersen9f16d612000-06-12 23:11:16 +00003360 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003361 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003362 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003363 "\twhile this kernel is version %s.",
Matt Kraai063c1f52001-08-06 14:18:08 +00003364 m_filename, m_strversion, uts_info.release);
Eric Andersen9f16d612000-06-12 23:11:16 +00003365 goto out;
3366 }
3367 }
3368 k_crcs = 0;
3369#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3370
3371 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3372
3373 if (k_new_syscalls) {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003374#ifdef BB_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003375 if (!new_get_kernel_symbols())
3376 goto out;
3377 k_crcs = new_is_kernel_checksummed();
3378#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003379 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 goto out;
3381#endif
3382 } else {
Eric Andersenf5d5e772001-01-24 23:34:48 +00003383#ifdef BB_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003384 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003385 goto out;
3386 k_crcs = old_is_kernel_checksummed();
3387#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003388 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003389 goto out;
3390#endif
3391 }
3392
3393#ifdef BB_FEATURE_INSMOD_VERSION_CHECKING
3394 if (m_has_modinfo)
3395 m_crcs = new_is_module_checksummed(f);
3396 else
3397 m_crcs = old_is_module_checksummed(f);
3398
3399 if (m_crcs != k_crcs)
3400 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
3401#endif /* BB_FEATURE_INSMOD_VERSION_CHECKING */
3402
Erik Andersene49d5ec2000-02-08 19:58:47 +00003403 /* Let the module know about the kernel symbols. */
3404 add_kernel_symbols(f);
3405
Eric Andersen9f16d612000-06-12 23:11:16 +00003406 /* Allocate common symbols, symbol tables, and string tables. */
3407
3408 if (k_new_syscalls
3409 ? !new_create_this_module(f, m_name)
3410 : !old_create_mod_use_count(f))
3411 {
3412 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003413 }
3414
Eric Andersen9f16d612000-06-12 23:11:16 +00003415 if (!obj_check_undefineds(f)) {
3416 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003417 }
3418 obj_allocate_commons(f);
3419
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003420 /* done with the module name, on to the optional var=value arguments */
3421 ++optind;
3422
Eric Andersen9f16d612000-06-12 23:11:16 +00003423 if (optind < argc) {
3424 if (m_has_modinfo
3425 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3426 : !old_process_module_arguments(f, argc - optind, argv + optind))
3427 {
3428 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003429 }
3430 }
3431
Eric Andersen9f16d612000-06-12 23:11:16 +00003432 arch_create_got(f);
3433 hide_special_symbols(f);
3434
3435 if (k_new_syscalls)
3436 new_create_module_ksymtab(f);
3437
Erik Andersene49d5ec2000-02-08 19:58:47 +00003438 /* Find current size of the module */
3439 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003440
3441
Erik Andersene49d5ec2000-02-08 19:58:47 +00003442 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003443 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003444 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003445 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 goto out;
3447 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003448 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003449 m_size);
3450 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003451 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003452 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003453 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003454 }
Erik Andersend387d011999-12-21 02:55:11 +00003455
Eric Andersen8ae319a2001-05-21 16:09:18 +00003456#if !LOADBITS
3457 /*
3458 * the PROGBITS section was not loaded by the obj_load
3459 * now we can load them directly into the kernel memory
3460 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00003461 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00003462 delete_module(m_name);
3463 goto out;
3464 }
3465#endif
3466
Eric Andersen9f16d612000-06-12 23:11:16 +00003467 if (!obj_relocate(f, m_addr)) {
3468 delete_module(m_name);
3469 goto out;
3470 }
Erik Andersend387d011999-12-21 02:55:11 +00003471
Eric Andersen9f16d612000-06-12 23:11:16 +00003472 if (k_new_syscalls
3473 ? !new_init_module(m_name, f, m_size)
3474 : !old_init_module(m_name, f, m_size))
3475 {
3476 delete_module(m_name);
3477 goto out;
3478 }
3479
Matt Kraai3e856ce2000-12-01 02:55:13 +00003480 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003481
3482out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003483 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003484 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003485}