blob: 8668aaa0fe0efdf8ba3a14656721341867b1dd9e [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 *
Eric Andersenbdfd0d72001-10-24 05:00:29 +00008 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
9 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
Eric Andersen9f16d612000-06-12 23:11:16 +000010 * and Ron Alder <alder@lineo.com>
11 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000012 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000013 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
14 *
15 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
16 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
17 * very minor changes required to also work with StrongArm and presumably
18 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000019 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000020 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
21 * PowerPC specific code stolen from modutils-2.3.16,
22 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
23 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000024 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000025 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000026 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
27 * based on modutils-2.4.2
28 * MIPS specific support for Elf loading and relocation.
29 * Copyright 1996, 1997 Linux International.
30 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
31 *
Eric Andersen9f16d612000-06-12 23:11:16 +000032 * Based almost entirely on the Linux modutils-2.3.11 implementation.
33 * Copyright 1996, 1997 Linux International.
34 * New implementation contributed by Richard Henderson <rth@tamu.edu>
35 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
36 * Restructured (and partly rewritten) by:
37 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000038 *
39 * This program is free software; you can redistribute it and/or modify
40 * it under the terms of the GNU General Public License as published by
41 * the Free Software Foundation; either version 2 of the License, or
42 * (at your option) any later version.
43 *
44 * This program is distributed in the hope that it will be useful,
45 * but WITHOUT ANY WARRANTY; without even the implied warranty of
46 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47 * General Public License for more details.
48 *
49 * You should have received a copy of the GNU General Public License
50 * along with this program; if not, write to the Free Software
51 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52 *
53 */
54
Erik Andersen02104321999-12-17 18:57:34 +000055#include <stdlib.h>
56#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000057#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000058#include <errno.h>
59#include <unistd.h>
60#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000061#include <ctype.h>
62#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000063#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000064#include <getopt.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000065#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000066#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000067
Eric Andersenbdfd0d72001-10-24 05:00:29 +000068#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
69# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen64c8b172001-04-05 07:33:10 +000070# define new_sys_init_module init_module
71#else
72# define old_sys_init_module init_module
73#endif
74
Eric Andersenbdfd0d72001-10-24 05:00:29 +000075#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +000076#define LOADBITS 0
77#else
78#define LOADBITS 1
79#endif
80
Eric Andersen90fe7fe2001-02-20 20:47:08 +000081#if defined(__powerpc__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000082#define CONFIG_USE_PLT_ENTRIES
83#define CONFIG_PLT_ENTRY_SIZE 16
Eric Andersen90fe7fe2001-02-20 20:47:08 +000084#endif
85
86#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000087#define CONFIG_USE_PLT_ENTRIES
88#define CONFIG_PLT_ENTRY_SIZE 8
89#define CONFIG_USE_GOT_ENTRIES
90#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersen90fe7fe2001-02-20 20:47:08 +000091#endif
92
93#if defined(__sh__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000094#define CONFIG_USE_GOT_ENTRIES
95#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersen90fe7fe2001-02-20 20:47:08 +000096#endif
97
98#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000099#define CONFIG_USE_GOT_ENTRIES
100#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000101#endif
102
Eric Andersen2bf658d2001-02-24 20:01:53 +0000103#if defined(__mips__)
104// neither used
105#endif
106
Eric Andersen9f16d612000-06-12 23:11:16 +0000107//----------------------------------------------------------------------------
108//--------modutils module.h, lines 45-242
109//----------------------------------------------------------------------------
110
111/* Definitions for the Linux module syscall interface.
112 Copyright 1996, 1997 Linux International.
113
114 Contributed by Richard Henderson <rth@tamu.edu>
115
116 This file is part of the Linux modutils.
117
118 This program is free software; you can redistribute it and/or modify it
119 under the terms of the GNU General Public License as published by the
120 Free Software Foundation; either version 2 of the License, or (at your
121 option) any later version.
122
123 This program is distributed in the hope that it will be useful, but
124 WITHOUT ANY WARRANTY; without even the implied warranty of
125 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
126 General Public License for more details.
127
128 You should have received a copy of the GNU General Public License
129 along with this program; if not, write to the Free Software Foundation,
130 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
131
132
133#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000134static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000135
Matt Kraaic8227632001-11-12 16:57:27 +0000136#ident "$Id: insmod.c,v 1.75 2001/11/12 16:57:26 kraai Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000137
138/* This file contains the structures used by the 2.0 and 2.1 kernels.
139 We do not use the kernel headers directly because we do not wish
140 to be dependant on a particular kernel version to compile insmod. */
141
142
143/*======================================================================*/
144/* The structures used by Linux 2.0. */
145
146/* The symbol format used by get_kernel_syms(2). */
147struct old_kernel_sym
148{
149 unsigned long value;
150 char name[60];
151};
152
153struct old_module_ref
154{
155 unsigned long module; /* kernel addresses */
156 unsigned long next;
157};
158
159struct old_module_symbol
160{
161 unsigned long addr;
162 unsigned long name;
163};
164
165struct old_symbol_table
166{
167 int size; /* total, including string table!!! */
168 int n_symbols;
169 int n_refs;
170 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
171 struct old_module_ref ref[0]; /* actual size defined by n_refs */
172};
173
174struct old_mod_routines
175{
176 unsigned long init;
177 unsigned long cleanup;
178};
179
180struct old_module
181{
182 unsigned long next;
183 unsigned long ref; /* the list of modules that refer to me */
184 unsigned long symtab;
185 unsigned long name;
186 int size; /* size of module in pages */
187 unsigned long addr; /* address of module */
188 int state;
189 unsigned long cleanup; /* cleanup routine */
190};
191
192/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000193static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000194
195int get_kernel_syms(struct old_kernel_sym *);
196int old_sys_init_module(const char *name, char *code, unsigned codesize,
197 struct old_mod_routines *, struct old_symbol_table *);
198
199/*======================================================================*/
200/* For sizeof() which are related to the module platform and not to the
201 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
202
203#define tgt_sizeof_char sizeof(char)
204#define tgt_sizeof_short sizeof(short)
205#define tgt_sizeof_int sizeof(int)
206#define tgt_sizeof_long sizeof(long)
207#define tgt_sizeof_char_p sizeof(char *)
208#define tgt_sizeof_void_p sizeof(void *)
209#define tgt_long long
210
211#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
212#undef tgt_sizeof_long
213#undef tgt_sizeof_char_p
214#undef tgt_sizeof_void_p
215#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000216static const int tgt_sizeof_long = 8;
217static const int tgt_sizeof_char_p = 8;
218static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000219#define tgt_long long long
220#endif
221
222/*======================================================================*/
223/* The structures used in Linux 2.1. */
224
225/* Note: new_module_symbol does not use tgt_long intentionally */
226struct new_module_symbol
227{
228 unsigned long value;
229 unsigned long name;
230};
231
232struct new_module_persist;
233
234struct new_module_ref
235{
236 unsigned tgt_long dep; /* kernel addresses */
237 unsigned tgt_long ref;
238 unsigned tgt_long next_ref;
239};
240
241struct new_module
242{
243 unsigned tgt_long size_of_struct; /* == sizeof(module) */
244 unsigned tgt_long next;
245 unsigned tgt_long name;
246 unsigned tgt_long size;
247
248 tgt_long usecount;
249 unsigned tgt_long flags; /* AUTOCLEAN et al */
250
251 unsigned nsyms;
252 unsigned ndeps;
253
254 unsigned tgt_long syms;
255 unsigned tgt_long deps;
256 unsigned tgt_long refs;
257 unsigned tgt_long init;
258 unsigned tgt_long cleanup;
259 unsigned tgt_long ex_table_start;
260 unsigned tgt_long ex_table_end;
261#ifdef __alpha__
262 unsigned tgt_long gp;
263#endif
264 /* Everything after here is extension. */
265 unsigned tgt_long persist_start;
266 unsigned tgt_long persist_end;
267 unsigned tgt_long can_unload;
268 unsigned tgt_long runsize;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000269#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen8ae319a2001-05-21 16:09:18 +0000270 const char *kallsyms_start; /* All symbols for kernel debugging */
271 const char *kallsyms_end;
272 const char *archdata_start; /* arch specific data for module */
273 const char *archdata_end;
274 const char *kernel_data; /* Reserved for kernel internal use */
275#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000276};
277
Eric Andersen8ae319a2001-05-21 16:09:18 +0000278#define ARCHDATA_SEC_NAME "__archdata"
279#define KALLSYMS_SEC_NAME "__kallsyms"
280
281
Eric Andersen9f16d612000-06-12 23:11:16 +0000282struct new_module_info
283{
284 unsigned long addr;
285 unsigned long size;
286 unsigned long flags;
287 long usecount;
288};
289
290/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000291static const int NEW_MOD_RUNNING = 1;
292static const int NEW_MOD_DELETED = 2;
293static const int NEW_MOD_AUTOCLEAN = 4;
294static const int NEW_MOD_VISITED = 8;
295static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000296
Eric Andersen64c8b172001-04-05 07:33:10 +0000297int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000298int query_module(const char *name, int which, void *buf, size_t bufsize,
299 size_t *ret);
300
301/* Values for query_module's which. */
302
Mark Whitley59ab0252001-01-23 22:30:04 +0000303static const int QM_MODULES = 1;
304static const int QM_DEPS = 2;
305static const int QM_REFS = 3;
306static const int QM_SYMBOLS = 4;
307static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000308
309/*======================================================================*/
310/* The system calls unchanged between 2.0 and 2.1. */
311
312unsigned long create_module(const char *, size_t);
313int delete_module(const char *);
314
315
316#endif /* module.h */
317
318//----------------------------------------------------------------------------
319//--------end of modutils module.h
320//----------------------------------------------------------------------------
321
322
323
324//----------------------------------------------------------------------------
325//--------modutils obj.h, lines 253-462
326//----------------------------------------------------------------------------
327
328/* Elf object file loading and relocation routines.
329 Copyright 1996, 1997 Linux International.
330
331 Contributed by Richard Henderson <rth@tamu.edu>
332
333 This file is part of the Linux modutils.
334
335 This program is free software; you can redistribute it and/or modify it
336 under the terms of the GNU General Public License as published by the
337 Free Software Foundation; either version 2 of the License, or (at your
338 option) any later version.
339
340 This program is distributed in the hope that it will be useful, but
341 WITHOUT ANY WARRANTY; without even the implied warranty of
342 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
343 General Public License for more details.
344
345 You should have received a copy of the GNU General Public License
346 along with this program; if not, write to the Free Software Foundation,
347 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
348
349
350#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000351static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000352
Matt Kraaic8227632001-11-12 16:57:27 +0000353#ident "$Id: insmod.c,v 1.75 2001/11/12 16:57:26 kraai Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000354
355/* The relocatable object is manipulated using elfin types. */
356
357#include <stdio.h>
358#include <elf.h>
359
360
361/* Machine-specific elf macros for i386 et al. */
362
Eric Andersenfe4208f2000-09-24 03:44:29 +0000363/* the SH changes have only been tested on the SH4 in =little endian= mode */
364/* I'm not sure about big endian, so let's warn: */
365
366#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
367#error insmod.c may require changes for use on big endian SH4/SH3
368#endif
369
370/* it may or may not work on the SH1/SH2... So let's error on those
371 also */
372#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
373#error insmod.c may require changes for non-SH3/SH4 use
374#endif
375
Eric Andersen9f16d612000-06-12 23:11:16 +0000376#define ELFCLASSM ELFCLASS32
Eric Andersenfe4208f2000-09-24 03:44:29 +0000377
Eric Andersenb4a26e62001-06-19 15:00:52 +0000378#if (defined(__mc68000__))
Eric Andersen8ae319a2001-05-21 16:09:18 +0000379#define ELFDATAM ELFDATA2MSB
Eric Andersen8ae319a2001-05-21 16:09:18 +0000380#endif
381
382
383
Eric Andersenfe4208f2000-09-24 03:44:29 +0000384#if defined(__sh__)
385
386#define MATCH_MACHINE(x) (x == EM_SH)
387#define SHT_RELM SHT_RELA
388#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000389#define ELFDATAM ELFDATA2LSB
Eric Andersenfe4208f2000-09-24 03:44:29 +0000390
Eric Andersen21adca72000-12-06 18:18:26 +0000391#elif defined(__arm__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000392
Eric Andersen21adca72000-12-06 18:18:26 +0000393#define MATCH_MACHINE(x) (x == EM_ARM)
394#define SHT_RELM SHT_REL
395#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000396#define ELFDATAM ELFDATA2LSB
397
398#elif defined(__powerpc__)
399
400#define MATCH_MACHINE(x) (x == EM_PPC)
401#define SHT_RELM SHT_RELA
402#define Elf32_RelM Elf32_Rela
Eric Andersen5a9d4412001-05-24 14:16:28 +0000403#define ELFDATAM ELFDATA2MSB
Eric Andersen21adca72000-12-06 18:18:26 +0000404
Eric Andersen2bf658d2001-02-24 20:01:53 +0000405#elif defined(__mips__)
406
Eric Andersen82bb8a22001-03-22 19:01:16 +0000407/* Account for ELF spec changes. */
408#ifndef EM_MIPS_RS3_LE
409#ifdef EM_MIPS_RS4_BE
410#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
411#else
412#define EM_MIPS_RS3_LE 10
413#endif
414#endif /* !EM_MIPS_RS3_LE */
415
Eric Andersen2bf658d2001-02-24 20:01:53 +0000416#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
417#define SHT_RELM SHT_REL
418#define Elf32_RelM Elf32_Rel
419#ifdef __MIPSEB__
420#define ELFDATAM ELFDATA2MSB
421#endif
422#ifdef __MIPSEL__
423#define ELFDATAM ELFDATA2LSB
424#endif
425
Eric Andersen21adca72000-12-06 18:18:26 +0000426#elif defined(__i386__)
427
428/* presumably we can use these for anything but the SH and ARM*/
Eric Andersenfe4208f2000-09-24 03:44:29 +0000429/* this is the previous behavior, but it does result in
430 insmod.c being broken on anything except i386 */
Pavel Roskin43f3e612000-09-28 20:52:55 +0000431#ifndef EM_486
432#define MATCH_MACHINE(x) (x == EM_386)
433#else
Eric Andersenfe4208f2000-09-24 03:44:29 +0000434#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
Pavel Roskin43f3e612000-09-28 20:52:55 +0000435#endif
436
Eric Andersen9f16d612000-06-12 23:11:16 +0000437#define SHT_RELM SHT_REL
438#define Elf32_RelM Elf32_Rel
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000439#define ELFDATAM ELFDATA2LSB
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersenb4a26e62001-06-19 15:00:52 +0000441#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000442
443#define MATCH_MACHINE(x) (x == EM_68K)
444#define SHT_RELM SHT_RELA
445#define Elf32_RelM Elf32_Rela
446
Eric Andersen21adca72000-12-06 18:18:26 +0000447#else
Eric Andersend5cad142001-01-26 02:23:57 +0000448#error Sorry, but insmod.c does not yet support this architecture...
Eric Andersenfe4208f2000-09-24 03:44:29 +0000449#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000450
451#ifndef ElfW
452# if ELFCLASSM == ELFCLASS32
453# define ElfW(x) Elf32_ ## x
454# define ELFW(x) ELF32_ ## x
455# else
456# define ElfW(x) Elf64_ ## x
457# define ELFW(x) ELF64_ ## x
458# endif
459#endif
460
461/* For some reason this is missing from libc5. */
462#ifndef ELF32_ST_INFO
463# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
464#endif
465
466#ifndef ELF64_ST_INFO
467# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
468#endif
469
470struct obj_string_patch;
471struct obj_symbol_patch;
472
473struct obj_section
474{
475 ElfW(Shdr) header;
476 const char *name;
477 char *contents;
478 struct obj_section *load_next;
479 int idx;
480};
481
482struct obj_symbol
483{
484 struct obj_symbol *next; /* hash table link */
485 const char *name;
486 unsigned long value;
487 unsigned long size;
488 int secidx; /* the defining section index/module */
489 int info;
490 int ksymidx; /* for export to the kernel symtab */
491 int referenced; /* actually used in the link */
492};
493
494/* Hardcode the hash table size. We shouldn't be needing so many
495 symbols that we begin to degrade performance, and we get a big win
496 by giving the compiler a constant divisor. */
497
498#define HASH_BUCKETS 521
499
500struct obj_file
501{
502 ElfW(Ehdr) header;
503 ElfW(Addr) baseaddr;
504 struct obj_section **sections;
505 struct obj_section *load_order;
506 struct obj_section **load_order_search_start;
507 struct obj_string_patch *string_patches;
508 struct obj_symbol_patch *symbol_patches;
509 int (*symbol_cmp)(const char *, const char *);
510 unsigned long (*symbol_hash)(const char *);
511 unsigned long local_symtab_size;
512 struct obj_symbol **local_symtab;
513 struct obj_symbol *symtab[HASH_BUCKETS];
514};
515
516enum obj_reloc
517{
518 obj_reloc_ok,
519 obj_reloc_overflow,
520 obj_reloc_dangerous,
521 obj_reloc_unhandled
522};
523
524struct obj_string_patch
525{
526 struct obj_string_patch *next;
527 int reloc_secidx;
528 ElfW(Addr) reloc_offset;
529 ElfW(Addr) string_offset;
530};
531
532struct obj_symbol_patch
533{
534 struct obj_symbol_patch *next;
535 int reloc_secidx;
536 ElfW(Addr) reloc_offset;
537 struct obj_symbol *sym;
538};
539
540
541/* Generic object manipulation routines. */
542
Eric Andersen044228d2001-07-17 01:12:36 +0000543static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000544
Eric Andersen044228d2001-07-17 01:12:36 +0000545static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000546
Eric Andersen044228d2001-07-17 01:12:36 +0000547static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000548 const char *name);
549
Eric Andersen044228d2001-07-17 01:12:36 +0000550static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000551 struct obj_symbol *sym);
552
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000553#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000554static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000555 int (*cmp)(const char *, const char *),
556 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000557#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000558
Eric Andersen044228d2001-07-17 01:12:36 +0000559static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000560 const char *name);
561
Eric Andersen044228d2001-07-17 01:12:36 +0000562static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000563 struct obj_section *sec);
564
Eric Andersen044228d2001-07-17 01:12:36 +0000565static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000566 const char *name,
567 unsigned long align,
568 unsigned long size);
569
Eric Andersen044228d2001-07-17 01:12:36 +0000570static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000571 const char *name,
572 unsigned long align,
573 unsigned long size);
574
Eric Andersen044228d2001-07-17 01:12:36 +0000575static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000576
Eric Andersen044228d2001-07-17 01:12:36 +0000577static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000578 const char *string);
579
Eric Andersen044228d2001-07-17 01:12:36 +0000580static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000581 struct obj_symbol *sym);
582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000584
Eric Andersen044228d2001-07-17 01:12:36 +0000585static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000586
Eric Andersen044228d2001-07-17 01:12:36 +0000587static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000588
Eric Andersen044228d2001-07-17 01:12:36 +0000589static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000590
Eric Andersen044228d2001-07-17 01:12:36 +0000591static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000592
Eric Andersen044228d2001-07-17 01:12:36 +0000593static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000594
595/* Architecture specific manipulation routines. */
596
Eric Andersen044228d2001-07-17 01:12:36 +0000597static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000602
Eric Andersen044228d2001-07-17 01:12:36 +0000603static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000604 struct obj_section *targsec,
605 struct obj_section *symsec,
606 struct obj_symbol *sym,
607 ElfW(RelM) *rel, ElfW(Addr) value);
608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static int arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000612
613#endif /* obj.h */
614//----------------------------------------------------------------------------
615//--------end of modutils obj.h
616//----------------------------------------------------------------------------
617
618
619
620
Erik Andersen02104321999-12-17 18:57:34 +0000621
Erik Andersend387d011999-12-21 02:55:11 +0000622#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000623static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000624
Eric Andersen9f16d612000-06-12 23:11:16 +0000625/*======================================================================*/
626
Eric Andersen044228d2001-07-17 01:12:36 +0000627static int flag_force_load = 0;
628static int flag_autoclean = 0;
629static int flag_verbose = 0;
630static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000631
632
633/*======================================================================*/
634
Eric Andersenfe4208f2000-09-24 03:44:29 +0000635/* previously, these were named i386_* but since we could be
636 compiling for the sh, I've renamed them to the more general
637 arch_* These structures are the same between the x86 and SH,
638 and we can't support anything else right now anyway. In the
639 future maybe they should be #if defined'd */
640
Eric Andersen21adca72000-12-06 18:18:26 +0000641/* Done ;-) */
642
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000643
644
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000645#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000646struct arch_plt_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000647{
648 int offset;
649 int allocated:1;
650 int inited:1; /* has been set up */
651};
652#endif
653
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000654#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000655struct arch_got_entry {
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 int offset;
657 unsigned offset_done:1;
658 unsigned reloc_done:1;
659};
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000660#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen2bf658d2001-02-24 20:01:53 +0000662#if defined(__mips__)
663struct mips_hi16
664{
665 struct mips_hi16 *next;
666 Elf32_Addr *addr;
667 Elf32_Addr value;
668};
669#endif
670
Eric Andersenfe4208f2000-09-24 03:44:29 +0000671struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000672 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000673#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000674 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000675#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000676#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000677 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000678#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000679#if defined(__mips__)
680 struct mips_hi16 *mips_hi16_list;
681#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000682};
683
Eric Andersenfe4208f2000-09-24 03:44:29 +0000684struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000685 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000686#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000687 struct arch_plt_entry pltent;
Eric Andersen21adca72000-12-06 18:18:26 +0000688#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000689#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000690 struct arch_got_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000691#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000692};
693
694
Eric Andersen9f16d612000-06-12 23:11:16 +0000695struct external_module {
696 const char *name;
697 ElfW(Addr) addr;
698 int used;
699 size_t nsyms;
700 struct new_module_symbol *syms;
701};
702
Eric Andersen044228d2001-07-17 01:12:36 +0000703static struct new_module_symbol *ksyms;
704static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000705
Eric Andersen044228d2001-07-17 01:12:36 +0000706static struct external_module *ext_modules;
707static int n_ext_modules;
708static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000709extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000710
Eric Andersen14d35432001-05-14 17:07:32 +0000711static char m_filename[FILENAME_MAX + 1];
712static char m_fullName[FILENAME_MAX + 1];
Erik Andersen02104321999-12-17 18:57:34 +0000713
Eric Andersenfe4208f2000-09-24 03:44:29 +0000714
Erik Andersen02104321999-12-17 18:57:34 +0000715
Eric Andersen9f16d612000-06-12 23:11:16 +0000716/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000717
Eric Andersen9f16d612000-06-12 23:11:16 +0000718
Eric Andersen14d35432001-05-14 17:07:32 +0000719static int check_module_name_match(const char *filename, struct stat *statbuf,
720 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000721{
Eric Andersen14d35432001-05-14 17:07:32 +0000722 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000723
Eric Andersen14d35432001-05-14 17:07:32 +0000724 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000725 return (FALSE);
726 else {
Matt Kraaic8227632001-11-12 16:57:27 +0000727 char *tmp, *tmp1 = xstrdup(filename);
Eric Andersen14d35432001-05-14 17:07:32 +0000728 tmp = get_last_path_component(tmp1);
729 if (strcmp(tmp, fullname) == 0) {
730 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000731 /* Stop searching if we find a match */
Eric Andersen14d35432001-05-14 17:07:32 +0000732 safe_strncpy(m_filename, filename, sizeof(m_filename));
733 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000734 }
Eric Andersen14d35432001-05-14 17:07:32 +0000735 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000736 }
Eric Andersen14d35432001-05-14 17:07:32 +0000737 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000738}
739
Erik Andersen02104321999-12-17 18:57:34 +0000740
Eric Andersen9f16d612000-06-12 23:11:16 +0000741/*======================================================================*/
742
Eric Andersen044228d2001-07-17 01:12:36 +0000743static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000744{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000745 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000747
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000748#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000749 f->plt = NULL;
750#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000751#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000752 f->got = NULL;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000753#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000754#if defined(__mips__)
755 f->mips_hi16_list = NULL;
756#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000757
Eric Andersen9f16d612000-06-12 23:11:16 +0000758 return &f->root;
759}
760
Eric Andersen044228d2001-07-17 01:12:36 +0000761static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000762{
763 return xmalloc(sizeof(struct obj_section));
764}
765
Eric Andersen044228d2001-07-17 01:12:36 +0000766static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000767{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000768 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000769 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000770
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000771#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000772 memset(&sym->pltent, 0, sizeof(sym->pltent));
773#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000774#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000775 memset(&sym->gotent, 0, sizeof(sym->gotent));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000776#endif
777
Eric Andersen9f16d612000-06-12 23:11:16 +0000778 return &sym->root;
779}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000780
Eric Andersen044228d2001-07-17 01:12:36 +0000781static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000782arch_apply_relocation(struct obj_file *f,
783 struct obj_section *targsec,
784 struct obj_section *symsec,
785 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000786 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000787{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000788 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000789#if !(defined(__mips__))
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790 struct arch_symbol *isym = (struct arch_symbol *) sym;
Eric Andersen82bb8a22001-03-22 19:01:16 +0000791#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000792
Eric Andersen21adca72000-12-06 18:18:26 +0000793 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
794 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000795#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000796 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000797#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000798#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000799 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000800 struct arch_plt_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000801 unsigned long *ip;
802#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000803 enum obj_reloc ret = obj_reloc_ok;
804
805 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000806
807/* even though these constants seem to be the same for
808 the i386 and the sh, we "#if define" them for clarity
809 and in case that ever changes */
810#if defined(__sh__)
811 case R_SH_NONE:
Eric Andersen21adca72000-12-06 18:18:26 +0000812#elif defined(__arm__)
813 case R_ARM_NONE:
814#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +0000815 case R_386_NONE:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000816#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000817 case R_68K_NONE:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000818#elif defined(__powerpc__)
819 case R_PPC_NONE:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000820#elif defined(__mips__)
821 case R_MIPS_NONE:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000822#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000823 break;
824
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825#if defined(__sh__)
826 case R_SH_DIR32:
Eric Andersen21adca72000-12-06 18:18:26 +0000827#elif defined(__arm__)
828 case R_ARM_ABS32:
829#elif defined(__i386__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830 case R_386_32:
Eric Andersenb4a26e62001-06-19 15:00:52 +0000831#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000832 case R_68K_32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833#elif defined(__powerpc__)
834 case R_PPC_ADDR32:
Eric Andersen2bf658d2001-02-24 20:01:53 +0000835#elif defined(__mips__)
836 case R_MIPS_32:
Eric Andersenfe4208f2000-09-24 03:44:29 +0000837#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000838 *loc += v;
839 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000840#if defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000841 case R_68K_8:
842 if (v > 0xff)
843 ret = obj_reloc_overflow;
844 *(char *)loc = v;
845 break;
846 case R_68K_16:
847 if (v > 0xffff)
848 ret = obj_reloc_overflow;
849 *(short *)loc = v;
850 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000851#endif /* __mc68000__ */
Eric Andersen9f16d612000-06-12 23:11:16 +0000852
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000853#if defined(__powerpc__)
854 case R_PPC_ADDR16_HA:
855 *(unsigned short *)loc = (v + 0x8000) >> 16;
856 break;
857
858 case R_PPC_ADDR16_HI:
859 *(unsigned short *)loc = v >> 16;
860 break;
861
862 case R_PPC_ADDR16_LO:
863 *(unsigned short *)loc = v;
864 break;
865#endif
866
Eric Andersen2bf658d2001-02-24 20:01:53 +0000867#if defined(__mips__)
868 case R_MIPS_26:
869 if (v % 4)
870 ret = obj_reloc_dangerous;
871 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
872 ret = obj_reloc_overflow;
873 *loc =
874 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
875 0x03ffffff);
876 break;
877
878 case R_MIPS_HI16:
879 {
880 struct mips_hi16 *n;
881
882 /* We cannot relocate this one now because we don't know the value
883 of the carry we need to add. Save the information, and let LO16
884 do the actual relocation. */
885 n = (struct mips_hi16 *) xmalloc(sizeof *n);
886 n->addr = loc;
887 n->value = v;
888 n->next = ifile->mips_hi16_list;
889 ifile->mips_hi16_list = n;
890 break;
891 }
892
893 case R_MIPS_LO16:
894 {
895 unsigned long insnlo = *loc;
896 Elf32_Addr val, vallo;
897
898 /* Sign extend the addend we extract from the lo insn. */
899 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
900
901 if (ifile->mips_hi16_list != NULL) {
902 struct mips_hi16 *l;
903
904 l = ifile->mips_hi16_list;
905 while (l != NULL) {
906 struct mips_hi16 *next;
907 unsigned long insn;
908
909 /* The value for the HI16 had best be the same. */
910 assert(v == l->value);
911
912 /* Do the HI16 relocation. Note that we actually don't
913 need to know anything about the LO16 itself, except where
914 to find the low 16 bits of the addend needed by the LO16. */
915 insn = *l->addr;
916 val =
917 ((insn & 0xffff) << 16) +
918 vallo;
919 val += v;
920
921 /* Account for the sign extension that will happen in the
922 low bits. */
923 val =
924 ((val >> 16) +
925 ((val & 0x8000) !=
926 0)) & 0xffff;
927
928 insn = (insn & ~0xffff) | val;
929 *l->addr = insn;
930
931 next = l->next;
932 free(l);
933 l = next;
934 }
935
936 ifile->mips_hi16_list = NULL;
937 }
938
939 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
940 val = v + vallo;
941 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
942 *loc = insnlo;
943 break;
944 }
945#endif
946
Eric Andersen21adca72000-12-06 18:18:26 +0000947#if defined(__arm__)
948#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000949 case R_SH_REL32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000950 *loc += v - dot;
951 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000952#elif defined(__i386__)
953 case R_386_PLT32:
954 case R_386_PC32:
955 *loc += v - dot;
956 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +0000957#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +0000958 case R_68K_PC8:
959 v -= dot;
960 if ((Elf32_Sword)v > 0x7f || (Elf32_Sword)v < -(Elf32_Sword)0x80)
961 ret = obj_reloc_overflow;
962 *(char *)loc = v;
963 break;
964 case R_68K_PC16:
965 v -= dot;
966 if ((Elf32_Sword)v > 0x7fff || (Elf32_Sword)v < -(Elf32_Sword)0x8000)
967 ret = obj_reloc_overflow;
968 *(short *)loc = v;
969 break;
970 case R_68K_PC32:
971 *(int *)loc = v - dot;
972 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000973#elif defined(__powerpc__)
974 case R_PPC_REL32:
975 *loc = v - dot;
976 break;
Eric Andersen21adca72000-12-06 18:18:26 +0000977#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000978
Eric Andersenfe4208f2000-09-24 03:44:29 +0000979#if defined(__sh__)
980 case R_SH_PLT32:
981 *loc = v - dot;
982 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000983#elif defined(__i386__)
984#endif
985
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000986#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000987
988#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000989 case R_ARM_PC24:
990 case R_ARM_PLT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000991#endif
992#if defined(__powerpc__)
993 case R_PPC_REL24:
994#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000995 /* find the plt entry and initialize it if necessary */
996 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000997
998 pe = (struct arch_plt_entry*) &isym->pltent;
999
Eric Andersen21adca72000-12-06 18:18:26 +00001000 if (! pe->inited) {
1001 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001002
1003 /* generate some machine code */
1004
1005#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001006 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1007 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001008#endif
1009#if defined(__powerpc__)
1010 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1011 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1012 ip[2] = 0x7d6903a6; /* mtctr r11 */
1013 ip[3] = 0x4e800420; /* bctr */
1014#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001015 pe->inited = 1;
1016 }
1017
1018 /* relative distance to target */
1019 v -= dot;
1020 /* if the target is too far away.... */
1021 if ((int)v < -0x02000000 || (int)v >= 0x02000000) {
1022 /* go via the plt */
1023 v = plt + pe->offset - dot;
1024 }
1025 if (v & 3)
1026 ret = obj_reloc_dangerous;
1027
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001028 /* merge the offset into the instruction. */
1029#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001030 /* Convert to words. */
1031 v >>= 2;
1032
Eric Andersen21adca72000-12-06 18:18:26 +00001033 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001034#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001035#if defined(__powerpc__)
1036 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1037#endif
1038 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001039#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001040
Eric Andersen21adca72000-12-06 18:18:26 +00001041#if defined(__arm__)
1042#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001043 case R_SH_GLOB_DAT:
1044 case R_SH_JMP_SLOT:
1045 *loc = v;
1046 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001047#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001048 case R_386_GLOB_DAT:
1049 case R_386_JMP_SLOT:
1050 *loc = v;
1051 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001052#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001053 case R_68K_GLOB_DAT:
1054 case R_68K_JMP_SLOT:
1055 *loc = v;
1056 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001057#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001058
Eric Andersen21adca72000-12-06 18:18:26 +00001059#if defined(__arm__)
1060#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001061 case R_SH_RELATIVE:
1062 *loc += f->baseaddr + rel->r_addend;
1063 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001064#elif defined(__i386__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001065 case R_386_RELATIVE:
Eric Andersen9f16d612000-06-12 23:11:16 +00001066 *loc += f->baseaddr;
1067 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001068#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001069 case R_68K_RELATIVE:
1070 *(int *)loc += f->baseaddr;
1071 break;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001072#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001073
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001074#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001075
Eric Andersen8ae319a2001-05-21 16:09:18 +00001076#if !defined(__68k__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001077#if defined(__sh__)
1078 case R_SH_GOTPC:
Eric Andersen21adca72000-12-06 18:18:26 +00001079#elif defined(__arm__)
1080 case R_ARM_GOTPC:
1081#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001082 case R_386_GOTPC:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001083#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001084 assert(got != 0);
1085#if defined(__sh__)
1086 *loc += got - dot + rel->r_addend;;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001087#elif defined(__i386__) || defined(__arm__) || defined(__m68k_)
Eric Andersen21adca72000-12-06 18:18:26 +00001088 *loc += got - dot;
1089#endif
1090 break;
Eric Andersen8ae319a2001-05-21 16:09:18 +00001091#endif // __68k__
Eric Andersen9f16d612000-06-12 23:11:16 +00001092
Eric Andersenfe4208f2000-09-24 03:44:29 +00001093#if defined(__sh__)
1094 case R_SH_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001095#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001096 case R_ARM_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001097#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001098 case R_386_GOT32:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001099#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001100 case R_68K_GOT32:
Eric Andersen21adca72000-12-06 18:18:26 +00001101#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001102 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001103 /* needs an entry in the .got: set it, once */
Eric Andersen9f16d612000-06-12 23:11:16 +00001104 if (!isym->gotent.reloc_done) {
1105 isym->gotent.reloc_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001106 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001107 }
Eric Andersen21adca72000-12-06 18:18:26 +00001108 /* make the reloc with_respect_to_.got */
1109#if defined(__sh__)
1110 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001111#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001112 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001113#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001114 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001115
Eric Andersen21adca72000-12-06 18:18:26 +00001116 /* address relative to the got */
Eric Andersenb4a26e62001-06-19 15:00:52 +00001117#if !defined(__mc68000__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001118#if defined(__sh__)
1119 case R_SH_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001120#elif defined(__arm__)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001121 case R_ARM_GOTOFF:
Eric Andersen21adca72000-12-06 18:18:26 +00001122#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001123 case R_386_GOTOFF:
Eric Andersenb4a26e62001-06-19 15:00:52 +00001124#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001125 case R_68K_GOTOFF:
Eric Andersenfe4208f2000-09-24 03:44:29 +00001126#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001127 assert(got != 0);
1128 *loc += v - got;
1129 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001130#endif // __mc68000__
Eric Andersen9f16d612000-06-12 23:11:16 +00001131
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001132#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001133
Eric Andersen9f16d612000-06-12 23:11:16 +00001134 default:
Eric Andersen21125542000-12-13 16:41:29 +00001135 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
Eric Andersen9f16d612000-06-12 23:11:16 +00001136 ret = obj_reloc_unhandled;
1137 break;
1138 }
1139
1140 return ret;
1141}
1142
Eric Andersen044228d2001-07-17 01:12:36 +00001143static int arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001144{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001145#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001146 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001147 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001148#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001149 int got_offset = 0, gotneeded = 0;
1150#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001151#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001152 int plt_offset = 0, pltneeded = 0;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001153#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001154 struct obj_section *relsec, *symsec, *strsec;
1155 ElfW(RelM) *rel, *relend;
1156 ElfW(Sym) *symtab, *extsym;
1157 const char *strtab, *name;
1158 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001159
Eric Andersen21adca72000-12-06 18:18:26 +00001160 for (i = 0; i < f->header.e_shnum; ++i) {
1161 relsec = f->sections[i];
1162 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001163 continue;
1164
Eric Andersen21adca72000-12-06 18:18:26 +00001165 symsec = f->sections[relsec->header.sh_link];
1166 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001167
Eric Andersen21adca72000-12-06 18:18:26 +00001168 rel = (ElfW(RelM) *) relsec->contents;
1169 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1170 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001171 strtab = (const char *) strsec->contents;
1172
1173 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001174 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001175
1176 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001177#if defined(__arm__)
1178 case R_ARM_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001179 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001180#elif defined(__sh__)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001181 case R_SH_GOT32:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001182 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001183#elif defined(__i386__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001184 case R_386_GOT32:
1185 break;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001186#elif defined(__mc68000__)
Eric Andersen8ae319a2001-05-21 16:09:18 +00001187 case R_68K_GOT32:
1188 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001189#endif
1190
1191#if defined(__powerpc__)
1192 case R_PPC_REL24:
1193 pltneeded = 1;
1194 break;
1195#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001196
1197#if defined(__arm__)
1198 case R_ARM_PC24:
1199 case R_ARM_PLT32:
1200 pltneeded = 1;
1201 break;
1202
1203 case R_ARM_GOTPC:
1204 case R_ARM_GOTOFF:
1205 gotneeded = 1;
1206 if (got_offset == 0)
1207 got_offset = 4;
1208#elif defined(__sh__)
1209 case R_SH_GOTPC:
1210 case R_SH_GOTOFF:
1211 gotneeded = 1;
1212#elif defined(__i386__)
1213 case R_386_GOTPC:
1214 case R_386_GOTOFF:
1215 gotneeded = 1;
1216#endif
1217
1218 default:
1219 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001220 }
1221
Eric Andersen21adca72000-12-06 18:18:26 +00001222 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001223 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001224 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001225 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001226 }
1227 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001228#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +00001229 if (!intsym->gotent.offset_done) {
1230 intsym->gotent.offset_done = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001231 intsym->gotent.offset = got_offset;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001232 got_offset += CONFIG_GOT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001233 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001234#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001235#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001236 if (pltneeded && intsym->pltent.allocated == 0) {
1237 intsym->pltent.allocated = 1;
1238 intsym->pltent.offset = plt_offset;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001239 plt_offset += CONFIG_PLT_ENTRY_SIZE;
Eric Andersen21adca72000-12-06 18:18:26 +00001240 intsym->pltent.inited = 0;
1241 pltneeded = 0;
1242 }
1243#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001244 }
1245 }
Eric Andersen21adca72000-12-06 18:18:26 +00001246
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001247#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +00001248 if (got_offset) {
Eric Andersene76c3b02001-04-05 03:14:39 +00001249 struct obj_section* myrelsec = obj_find_section(f, ".got");
Eric Andersen21adca72000-12-06 18:18:26 +00001250
Eric Andersene76c3b02001-04-05 03:14:39 +00001251 if (myrelsec) {
1252 obj_extend_section(myrelsec, got_offset);
Eric Andersen21adca72000-12-06 18:18:26 +00001253 } else {
Eric Andersene76c3b02001-04-05 03:14:39 +00001254 myrelsec = obj_create_alloced_section(f, ".got",
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001255 CONFIG_GOT_ENTRY_SIZE,
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001256 got_offset);
Eric Andersene76c3b02001-04-05 03:14:39 +00001257 assert(myrelsec);
Eric Andersen21adca72000-12-06 18:18:26 +00001258 }
1259
Eric Andersene76c3b02001-04-05 03:14:39 +00001260 ifile->got = myrelsec;
Eric Andersen9f16d612000-06-12 23:11:16 +00001261 }
Eric Andersen21adca72000-12-06 18:18:26 +00001262#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001263
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001264#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001265 if (plt_offset)
1266 ifile->plt = obj_create_alloced_section(f, ".plt",
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001267 CONFIG_PLT_ENTRY_SIZE,
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001268 plt_offset);
1269#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +00001270#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001271 return 1;
1272}
1273
Eric Andersen044228d2001-07-17 01:12:36 +00001274static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001275{
1276 return 1;
1277}
1278
1279
1280/*======================================================================*/
1281
1282/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001283static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001284{
1285 unsigned long h = 0;
1286 unsigned long g;
1287 unsigned char ch;
1288
1289 while (n > 0) {
1290 ch = *name++;
1291 h = (h << 4) + ch;
1292 if ((g = (h & 0xf0000000)) != 0) {
1293 h ^= g >> 24;
1294 h &= ~g;
1295 }
1296 n--;
1297 }
1298 return h;
1299}
1300
Eric Andersen044228d2001-07-17 01:12:36 +00001301static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001302{
1303 return obj_elf_hash_n(name, strlen(name));
1304}
1305
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001306#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001307/* String comparison for non-co-versioned kernel and module. */
1308
1309static int ncv_strcmp(const char *a, const char *b)
1310{
1311 size_t alen = strlen(a), blen = strlen(b);
1312
1313 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1314 return strncmp(a, b, alen);
1315 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1316 return strncmp(a, b, blen);
1317 else
1318 return strcmp(a, b);
1319}
1320
1321/* String hashing for non-co-versioned kernel and module. Here
1322 we are simply forced to drop the crc from the hash. */
1323
1324static unsigned long ncv_symbol_hash(const char *str)
1325{
1326 size_t len = strlen(str);
1327 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1328 len -= 10;
1329 return obj_elf_hash_n(str, len);
1330}
1331
Eric Andersen044228d2001-07-17 01:12:36 +00001332static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001333obj_set_symbol_compare(struct obj_file *f,
1334 int (*cmp) (const char *, const char *),
1335 unsigned long (*hash) (const char *))
1336{
1337 if (cmp)
1338 f->symbol_cmp = cmp;
1339 if (hash) {
1340 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1341 int i;
1342
1343 f->symbol_hash = hash;
1344
1345 memcpy(tmptab, f->symtab, sizeof(tmptab));
1346 memset(f->symtab, 0, sizeof(f->symtab));
1347
1348 for (i = 0; i < HASH_BUCKETS; ++i)
1349 for (sym = tmptab[i]; sym; sym = next) {
1350 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1351 next = sym->next;
1352 sym->next = f->symtab[h];
1353 f->symtab[h] = sym;
1354 }
1355 }
1356}
1357
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001358#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001359
Eric Andersen044228d2001-07-17 01:12:36 +00001360static struct obj_symbol *
1361obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001362 unsigned long symidx, int info,
1363 int secidx, ElfW(Addr) value,
1364 unsigned long size)
1365{
1366 struct obj_symbol *sym;
1367 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1368 int n_type = ELFW(ST_TYPE) (info);
1369 int n_binding = ELFW(ST_BIND) (info);
1370
1371 for (sym = f->symtab[hash]; sym; sym = sym->next)
1372 if (f->symbol_cmp(sym->name, name) == 0) {
1373 int o_secidx = sym->secidx;
1374 int o_info = sym->info;
1375 int o_type = ELFW(ST_TYPE) (o_info);
1376 int o_binding = ELFW(ST_BIND) (o_info);
1377
1378 /* A redefinition! Is it legal? */
1379
1380 if (secidx == SHN_UNDEF)
1381 return sym;
1382 else if (o_secidx == SHN_UNDEF)
1383 goto found;
1384 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1385 /* Cope with local and global symbols of the same name
1386 in the same object file, as might have been created
1387 by ld -r. The only reason locals are now seen at this
1388 level at all is so that we can do semi-sensible things
1389 with parameters. */
1390
1391 struct obj_symbol *nsym, **p;
1392
1393 nsym = arch_new_symbol();
1394 nsym->next = sym->next;
1395 nsym->ksymidx = -1;
1396
1397 /* Excise the old (local) symbol from the hash chain. */
1398 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1399 continue;
1400 *p = sym = nsym;
1401 goto found;
1402 } else if (n_binding == STB_LOCAL) {
1403 /* Another symbol of the same name has already been defined.
1404 Just add this to the local table. */
1405 sym = arch_new_symbol();
1406 sym->next = NULL;
1407 sym->ksymidx = -1;
1408 f->local_symtab[symidx] = sym;
1409 goto found;
1410 } else if (n_binding == STB_WEAK)
1411 return sym;
1412 else if (o_binding == STB_WEAK)
1413 goto found;
1414 /* Don't unify COMMON symbols with object types the programmer
1415 doesn't expect. */
1416 else if (secidx == SHN_COMMON
1417 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1418 return sym;
1419 else if (o_secidx == SHN_COMMON
1420 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1421 goto found;
1422 else {
1423 /* Don't report an error if the symbol is coming from
1424 the kernel or some external module. */
1425 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001426 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001427 return sym;
1428 }
1429 }
1430
1431 /* Completely new symbol. */
1432 sym = arch_new_symbol();
1433 sym->next = f->symtab[hash];
1434 f->symtab[hash] = sym;
1435 sym->ksymidx = -1;
1436
Eric Andersen66ca9482001-06-28 21:36:06 +00001437 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1438 if (symidx >= f->local_symtab_size)
1439 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1440 name, (long) symidx, (long) f->local_symtab_size);
1441 else
1442 f->local_symtab[symidx] = sym;
1443 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001444
1445 found:
1446 sym->name = name;
1447 sym->value = value;
1448 sym->size = size;
1449 sym->secidx = secidx;
1450 sym->info = info;
1451
1452 return sym;
1453}
1454
Eric Andersen044228d2001-07-17 01:12:36 +00001455static struct obj_symbol *
1456obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001457{
1458 struct obj_symbol *sym;
1459 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1460
1461 for (sym = f->symtab[hash]; sym; sym = sym->next)
1462 if (f->symbol_cmp(sym->name, name) == 0)
1463 return sym;
1464
1465 return NULL;
1466}
1467
Eric Andersen044228d2001-07-17 01:12:36 +00001468static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001469 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1470{
1471 if (sym) {
1472 if (sym->secidx >= SHN_LORESERVE)
1473 return sym->value;
1474
1475 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1476 } else {
1477 /* As a special case, a NULL sym has value zero. */
1478 return 0;
1479 }
1480}
1481
Eric Andersen044228d2001-07-17 01:12:36 +00001482static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001483{
1484 int i, n = f->header.e_shnum;
1485
1486 for (i = 0; i < n; ++i)
1487 if (strcmp(f->sections[i]->name, name) == 0)
1488 return f->sections[i];
1489
1490 return NULL;
1491}
1492
1493static int obj_load_order_prio(struct obj_section *a)
1494{
1495 unsigned long af, ac;
1496
1497 af = a->header.sh_flags;
1498
1499 ac = 0;
1500 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1501 strcmp(a->name + 5, ".init"))
1502 ac |= 32;
1503 if (af & SHF_ALLOC)
1504 ac |= 16;
1505 if (!(af & SHF_WRITE))
1506 ac |= 8;
1507 if (af & SHF_EXECINSTR)
1508 ac |= 4;
1509 if (a->header.sh_type != SHT_NOBITS)
1510 ac |= 2;
1511
1512 return ac;
1513}
1514
Eric Andersen044228d2001-07-17 01:12:36 +00001515static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001516obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1517{
1518 struct obj_section **p;
1519 int prio = obj_load_order_prio(sec);
1520 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1521 if (obj_load_order_prio(*p) < prio)
1522 break;
1523 sec->load_next = *p;
1524 *p = sec;
1525}
1526
Eric Andersen044228d2001-07-17 01:12:36 +00001527static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001528 const char *name,
1529 unsigned long align,
1530 unsigned long size)
1531{
1532 int newidx = f->header.e_shnum++;
1533 struct obj_section *sec;
1534
1535 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1536 f->sections[newidx] = sec = arch_new_section();
1537
1538 memset(sec, 0, sizeof(*sec));
1539 sec->header.sh_type = SHT_PROGBITS;
1540 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1541 sec->header.sh_size = size;
1542 sec->header.sh_addralign = align;
1543 sec->name = name;
1544 sec->idx = newidx;
1545 if (size)
1546 sec->contents = xmalloc(size);
1547
1548 obj_insert_section_load_order(f, sec);
1549
1550 return sec;
1551}
1552
Eric Andersen044228d2001-07-17 01:12:36 +00001553static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001554 const char *name,
1555 unsigned long align,
1556 unsigned long size)
1557{
1558 int newidx = f->header.e_shnum++;
1559 struct obj_section *sec;
1560
1561 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1562 f->sections[newidx] = sec = arch_new_section();
1563
1564 memset(sec, 0, sizeof(*sec));
1565 sec->header.sh_type = SHT_PROGBITS;
1566 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1567 sec->header.sh_size = size;
1568 sec->header.sh_addralign = align;
1569 sec->name = name;
1570 sec->idx = newidx;
1571 if (size)
1572 sec->contents = xmalloc(size);
1573
1574 sec->load_next = f->load_order;
1575 f->load_order = sec;
1576 if (f->load_order_search_start == &f->load_order)
1577 f->load_order_search_start = &sec->load_next;
1578
1579 return sec;
1580}
1581
Eric Andersen044228d2001-07-17 01:12:36 +00001582static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001583{
1584 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001585 if (more) {
1586 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1587 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001588 return sec->contents + oldsize;
1589}
1590
1591
Eric Andersen9f16d612000-06-12 23:11:16 +00001592/* Conditionally add the symbols from the given symbol set to the
1593 new module. */
1594
1595static int
1596add_symbols_from(
1597 struct obj_file *f,
1598 int idx, struct new_module_symbol *syms, size_t nsyms)
1599{
1600 struct new_module_symbol *s;
1601 size_t i;
1602 int used = 0;
1603
1604 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
1605
1606 /* Only add symbols that are already marked external. If we
1607 override locals we may cause problems for argument initialization.
1608 We will also create a false dependency on the module. */
1609 struct obj_symbol *sym;
1610
1611 sym = obj_find_symbol(f, (char *) s->name);
1612 if (sym && !ELFW(ST_BIND) (sym->info) == STB_LOCAL) {
1613 sym = obj_add_symbol(f, (char *) s->name, -1,
1614 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
1615 idx, s->value, 0);
1616 /* Did our symbol just get installed? If so, mark the
1617 module as "used". */
1618 if (sym->secidx == idx)
1619 used = 1;
1620 }
1621 }
1622
1623 return used;
1624}
1625
1626static void add_kernel_symbols(struct obj_file *f)
1627{
1628 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001629 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001630
1631 /* Add module symbols first. */
1632
1633 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1634 if (m->nsyms
1635 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1636 m->nsyms)) m->used = 1, ++nused;
1637
1638 n_ext_modules_used = nused;
1639
1640 /* And finally the symbols from the kernel proper. */
1641
1642 if (nksyms)
1643 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1644}
1645
1646static char *get_modinfo_value(struct obj_file *f, const char *key)
1647{
1648 struct obj_section *sec;
1649 char *p, *v, *n, *ep;
1650 size_t klen = strlen(key);
1651
1652 sec = obj_find_section(f, ".modinfo");
1653 if (sec == NULL)
1654 return NULL;
1655 p = sec->contents;
1656 ep = p + sec->header.sh_size;
1657 while (p < ep) {
1658 v = strchr(p, '=');
1659 n = strchr(p, '\0');
1660 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001661 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001662 return v + 1;
1663 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001664 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001665 return n;
1666 }
1667 p = n + 1;
1668 }
1669
1670 return NULL;
1671}
1672
1673
1674/*======================================================================*/
1675/* Functions relating to module loading in pre 2.1 kernels. */
1676
1677static int
1678old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1679{
1680 while (argc > 0) {
1681 char *p, *q;
1682 struct obj_symbol *sym;
1683 int *loc;
1684
1685 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001686 if ((q = strchr(p, '=')) == NULL) {
1687 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001688 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001689 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001690 *q++ = '\0';
1691
1692 sym = obj_find_symbol(f, p);
1693
1694 /* Also check that the parameter was not resolved from the kernel. */
1695 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001696 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001697 return 0;
1698 }
1699
1700 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1701
1702 /* Do C quoting if we begin with a ". */
1703 if (*q == '"') {
1704 char *r, *str;
1705
1706 str = alloca(strlen(q));
1707 for (r = str, q++; *q != '"'; ++q, ++r) {
1708 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001709 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001710 return 0;
1711 } else if (*q == '\\')
1712 switch (*++q) {
1713 case 'a':
1714 *r = '\a';
1715 break;
1716 case 'b':
1717 *r = '\b';
1718 break;
1719 case 'e':
1720 *r = '\033';
1721 break;
1722 case 'f':
1723 *r = '\f';
1724 break;
1725 case 'n':
1726 *r = '\n';
1727 break;
1728 case 'r':
1729 *r = '\r';
1730 break;
1731 case 't':
1732 *r = '\t';
1733 break;
1734
1735 case '0':
1736 case '1':
1737 case '2':
1738 case '3':
1739 case '4':
1740 case '5':
1741 case '6':
1742 case '7':
1743 {
1744 int c = *q - '0';
1745 if (q[1] >= '0' && q[1] <= '7') {
1746 c = (c * 8) + *++q - '0';
1747 if (q[1] >= '0' && q[1] <= '7')
1748 c = (c * 8) + *++q - '0';
1749 }
1750 *r = c;
1751 }
1752 break;
1753
1754 default:
1755 *r = *q;
1756 break;
1757 } else
1758 *r = *q;
1759 }
1760 *r = '\0';
1761 obj_string_patch(f, sym->secidx, sym->value, str);
1762 } else if (*q >= '0' && *q <= '9') {
1763 do
1764 *loc++ = strtoul(q, &q, 0);
1765 while (*q++ == ',');
1766 } else {
1767 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001768 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001769 char *r; /* To search for commas */
1770
1771 /* Break the string with comas */
1772 while ((r = strchr(q, ',')) != (char *) NULL) {
1773 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001774 obj_string_patch(f, sym->secidx, myloc - contents, q);
1775 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001776 q = r;
1777 }
1778
1779 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001780 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001781 }
1782
1783 argc--, argv++;
1784 }
1785
1786 return 1;
1787}
1788
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001789#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001790static int old_is_module_checksummed(struct obj_file *f)
1791{
1792 return obj_find_symbol(f, "Using_Versions") != NULL;
1793}
1794/* Get the module's kernel version in the canonical integer form. */
1795
1796static int
1797old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
1798{
1799 struct obj_symbol *sym;
1800 char *p, *q;
1801 int a, b, c;
1802
1803 sym = obj_find_symbol(f, "kernel_version");
1804 if (sym == NULL)
1805 return -1;
1806
1807 p = f->sections[sym->secidx]->contents + sym->value;
1808 strncpy(str, p, STRVERSIONLEN);
1809
1810 a = strtoul(p, &p, 10);
1811 if (*p != '.')
1812 return -1;
1813 b = strtoul(p + 1, &p, 10);
1814 if (*p != '.')
1815 return -1;
1816 c = strtoul(p + 1, &q, 10);
1817 if (p + 1 == q)
1818 return -1;
1819
1820 return a << 16 | b << 8 | c;
1821}
1822
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001823#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001824
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001825#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00001826
1827/* Fetch all the symbols and divvy them up as appropriate for the modules. */
1828
Eric Andersen8c185f92000-09-22 00:38:07 +00001829static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001830{
1831 struct old_kernel_sym *ks, *k;
1832 struct new_module_symbol *s;
1833 struct external_module *mod;
1834 int nks, nms, nmod, i;
1835
1836 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00001837 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00001838 if (nks)
1839 perror_msg("get_kernel_syms: %s", m_name);
1840 else
1841 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00001842 return 0;
1843 }
1844
1845 ks = k = xmalloc(nks * sizeof(*ks));
1846
1847 if (get_kernel_syms(ks) != nks) {
1848 perror("inconsistency with get_kernel_syms -- is someone else "
1849 "playing with modules?");
1850 free(ks);
1851 return 0;
1852 }
1853
1854 /* Collect the module information. */
1855
1856 mod = NULL;
1857 nmod = -1;
1858
1859 while (k->name[0] == '#' && k->name[1]) {
1860 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00001861
1862 /* Find out how many symbols this module has. */
1863 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
1864 continue;
1865 nms = k2 - k - 1;
1866
1867 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
1868 mod[nmod].name = k->name + 1;
1869 mod[nmod].addr = k->value;
1870 mod[nmod].used = 0;
1871 mod[nmod].nsyms = nms;
1872 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1873
1874 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
1875 s->name = (unsigned long) k->name;
1876 s->value = k->value;
1877 }
1878
1879 k = k2;
1880 }
1881
1882 ext_modules = mod;
1883 n_ext_modules = nmod + 1;
1884
1885 /* Now collect the symbols for the kernel proper. */
1886
1887 if (k->name[0] == '#')
1888 ++k;
1889
1890 nksyms = nms = nks - (k - ks);
1891 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
1892
1893 for (i = 0; i < nms; ++i, ++s, ++k) {
1894 s->name = (unsigned long) k->name;
1895 s->value = k->value;
1896 }
1897
1898 return 1;
1899}
1900
1901/* Return the kernel symbol checksum version, or zero if not used. */
1902
1903static int old_is_kernel_checksummed(void)
1904{
1905 /* Using_Versions is the first symbol. */
1906 if (nksyms > 0
1907 && strcmp((char *) ksyms[0].name,
1908 "Using_Versions") == 0) return ksyms[0].value;
1909 else
1910 return 0;
1911}
1912
1913
1914static int old_create_mod_use_count(struct obj_file *f)
1915{
1916 struct obj_section *sec;
1917
1918 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
1919 sizeof(long));
1920
1921 obj_add_symbol(f, "mod_use_count_", -1,
1922 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
1923 sizeof(long));
1924
1925 return 1;
1926}
1927
1928static int
1929old_init_module(const char *m_name, struct obj_file *f,
1930 unsigned long m_size)
1931{
1932 char *image;
1933 struct old_mod_routines routines;
1934 struct old_symbol_table *symtab;
1935 int ret;
1936
1937 /* Create the symbol table */
1938 {
1939 int nsyms = 0, strsize = 0, total;
1940
1941 /* Size things first... */
1942 if (flag_export) {
1943 int i;
1944 for (i = 0; i < HASH_BUCKETS; ++i) {
1945 struct obj_symbol *sym;
1946 for (sym = f->symtab[i]; sym; sym = sym->next)
1947 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
1948 && sym->secidx <= SHN_HIRESERVE)
1949 {
1950 sym->ksymidx = nsyms++;
1951 strsize += strlen(sym->name) + 1;
1952 }
1953 }
1954 }
1955
1956 total = (sizeof(struct old_symbol_table)
1957 + nsyms * sizeof(struct old_module_symbol)
1958 + n_ext_modules_used * sizeof(struct old_module_ref)
1959 + strsize);
1960 symtab = xmalloc(total);
1961 symtab->size = total;
1962 symtab->n_symbols = nsyms;
1963 symtab->n_refs = n_ext_modules_used;
1964
1965 if (flag_export && nsyms) {
1966 struct old_module_symbol *ksym;
1967 char *str;
1968 int i;
1969
1970 ksym = symtab->symbol;
1971 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
1972 + n_ext_modules_used * sizeof(struct old_module_ref));
1973
1974 for (i = 0; i < HASH_BUCKETS; ++i) {
1975 struct obj_symbol *sym;
1976 for (sym = f->symtab[i]; sym; sym = sym->next)
1977 if (sym->ksymidx >= 0) {
1978 ksym->addr = obj_symbol_final_value(f, sym);
1979 ksym->name =
1980 (unsigned long) str - (unsigned long) symtab;
1981
Matt Kraai70a78552001-01-04 02:00:17 +00001982 strcpy(str, sym->name);
1983 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00001984 ksym++;
1985 }
1986 }
1987 }
1988
1989 if (n_ext_modules_used) {
1990 struct old_module_ref *ref;
1991 int i;
1992
1993 ref = (struct old_module_ref *)
1994 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
1995
1996 for (i = 0; i < n_ext_modules; ++i)
1997 if (ext_modules[i].used)
1998 ref++->module = ext_modules[i].addr;
1999 }
2000 }
2001
2002 /* Fill in routines. */
2003
2004 routines.init =
2005 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2006 routines.cleanup =
2007 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2008
2009 /* Whew! All of the initialization is complete. Collect the final
2010 module image and give it to the kernel. */
2011
2012 image = xmalloc(m_size);
2013 obj_create_image(f, image);
2014
2015 /* image holds the complete relocated module, accounting correctly for
2016 mod_use_count. However the old module kernel support assume that
2017 it is receiving something which does not contain mod_use_count. */
2018 ret = old_sys_init_module(m_name, image + sizeof(long),
2019 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2020 : 0), &routines, symtab);
2021 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002022 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002023
2024 free(image);
2025 free(symtab);
2026
2027 return ret == 0;
2028}
2029
2030#else
2031
2032#define old_create_mod_use_count(x) TRUE
2033#define old_init_module(x, y, z) TRUE
2034
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002035#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002036
2037
2038
2039/*======================================================================*/
2040/* Functions relating to module loading after 2.1.18. */
2041
2042static int
2043new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2044{
2045 while (argc > 0) {
2046 char *p, *q, *key;
2047 struct obj_symbol *sym;
2048 char *contents, *loc;
2049 int min, max, n;
2050
2051 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002052 if ((q = strchr(p, '=')) == NULL) {
2053 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002054 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002055 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002056
2057 key = alloca(q - p + 6);
2058 memcpy(key, "parm_", 5);
2059 memcpy(key + 5, p, q - p);
2060 key[q - p + 5] = 0;
2061
2062 p = get_modinfo_value(f, key);
2063 key += 5;
2064 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002065 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002066 return 0;
2067 }
2068
2069 sym = obj_find_symbol(f, key);
2070
2071 /* Also check that the parameter was not resolved from the kernel. */
2072 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002073 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002074 return 0;
2075 }
2076
2077 if (isdigit(*p)) {
2078 min = strtoul(p, &p, 10);
2079 if (*p == '-')
2080 max = strtoul(p + 1, &p, 10);
2081 else
2082 max = min;
2083 } else
2084 min = max = 1;
2085
2086 contents = f->sections[sym->secidx]->contents;
2087 loc = contents + sym->value;
2088 n = (*++q != '\0');
2089
2090 while (1) {
2091 if ((*p == 's') || (*p == 'c')) {
2092 char *str;
2093
2094 /* Do C quoting if we begin with a ", else slurp the lot. */
2095 if (*q == '"') {
2096 char *r;
2097
2098 str = alloca(strlen(q));
2099 for (r = str, q++; *q != '"'; ++q, ++r) {
2100 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002101 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002102 key);
2103 return 0;
2104 } else if (*q == '\\')
2105 switch (*++q) {
2106 case 'a':
2107 *r = '\a';
2108 break;
2109 case 'b':
2110 *r = '\b';
2111 break;
2112 case 'e':
2113 *r = '\033';
2114 break;
2115 case 'f':
2116 *r = '\f';
2117 break;
2118 case 'n':
2119 *r = '\n';
2120 break;
2121 case 'r':
2122 *r = '\r';
2123 break;
2124 case 't':
2125 *r = '\t';
2126 break;
2127
2128 case '0':
2129 case '1':
2130 case '2':
2131 case '3':
2132 case '4':
2133 case '5':
2134 case '6':
2135 case '7':
2136 {
2137 int c = *q - '0';
2138 if (q[1] >= '0' && q[1] <= '7') {
2139 c = (c * 8) + *++q - '0';
2140 if (q[1] >= '0' && q[1] <= '7')
2141 c = (c * 8) + *++q - '0';
2142 }
2143 *r = c;
2144 }
2145 break;
2146
2147 default:
2148 *r = *q;
2149 break;
2150 } else
2151 *r = *q;
2152 }
2153 *r = '\0';
2154 ++q;
2155 } else {
2156 char *r;
2157
2158 /* In this case, the string is not quoted. We will break
2159 it using the coma (like for ints). If the user wants to
2160 include comas in a string, he just has to quote it */
2161
2162 /* Search the next coma */
2163 r = strchr(q, ',');
2164
2165 /* Found ? */
2166 if (r != (char *) NULL) {
2167 /* Recopy the current field */
2168 str = alloca(r - q + 1);
2169 memcpy(str, q, r - q);
2170
2171 /* I don't know if it is usefull, as the previous case
2172 doesn't null terminate the string ??? */
2173 str[r - q] = '\0';
2174
2175 /* Keep next fields */
2176 q = r;
2177 } else {
2178 /* last string */
2179 str = q;
2180 q = "";
2181 }
2182 }
2183
2184 if (*p == 's') {
2185 /* Normal string */
2186 obj_string_patch(f, sym->secidx, loc - contents, str);
2187 loc += tgt_sizeof_char_p;
2188 } else {
2189 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002190 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002191
2192 /* Get the size of each member */
2193 /* Probably we should do that outside the loop ? */
2194 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002195 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002196 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002197 return 0;
2198 }
2199 charssize = strtoul(p + 1, (char **) NULL, 10);
2200
2201 /* Check length */
2202 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002203 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002204 charssize - 1);
2205 return 0;
2206 }
2207
2208 /* Copy to location */
2209 strcpy((char *) loc, str);
2210 loc += charssize;
2211 }
2212 } else {
2213 long v = strtoul(q, &q, 0);
2214 switch (*p) {
2215 case 'b':
2216 *loc++ = v;
2217 break;
2218 case 'h':
2219 *(short *) loc = v;
2220 loc += tgt_sizeof_short;
2221 break;
2222 case 'i':
2223 *(int *) loc = v;
2224 loc += tgt_sizeof_int;
2225 break;
2226 case 'l':
2227 *(long *) loc = v;
2228 loc += tgt_sizeof_long;
2229 break;
2230
2231 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002232 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002233 return 0;
2234 }
2235 }
2236
2237 retry_end_of_value:
2238 switch (*q) {
2239 case '\0':
2240 goto end_of_arg;
2241
2242 case ' ':
2243 case '\t':
2244 case '\n':
2245 case '\r':
2246 ++q;
2247 goto retry_end_of_value;
2248
2249 case ',':
2250 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002251 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002252 return 0;
2253 }
2254 ++q;
2255 break;
2256
2257 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002258 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002259 return 0;
2260 }
2261 }
2262
2263 end_of_arg:
2264 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002265 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002266 return 0;
2267 }
2268
2269 argc--, argv++;
2270 }
2271
2272 return 1;
2273}
2274
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002275#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002276static int new_is_module_checksummed(struct obj_file *f)
2277{
2278 const char *p = get_modinfo_value(f, "using_checksums");
2279 if (p)
2280 return atoi(p);
2281 else
2282 return 0;
2283}
2284
2285/* Get the module's kernel version in the canonical integer form. */
2286
2287static int
2288new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2289{
2290 char *p, *q;
2291 int a, b, c;
2292
2293 p = get_modinfo_value(f, "kernel_version");
2294 if (p == NULL)
2295 return -1;
2296 strncpy(str, p, STRVERSIONLEN);
2297
2298 a = strtoul(p, &p, 10);
2299 if (*p != '.')
2300 return -1;
2301 b = strtoul(p + 1, &p, 10);
2302 if (*p != '.')
2303 return -1;
2304 c = strtoul(p + 1, &q, 10);
2305 if (p + 1 == q)
2306 return -1;
2307
2308 return a << 16 | b << 8 | c;
2309}
2310
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002311#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002312
2313
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002314#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002315
2316/* Fetch the loaded modules, and all currently exported symbols. */
2317
2318static int new_get_kernel_symbols(void)
2319{
2320 char *module_names, *mn;
2321 struct external_module *modules, *m;
2322 struct new_module_symbol *syms, *s;
2323 size_t ret, bufsize, nmod, nsyms, i, j;
2324
2325 /* Collect the loaded modules. */
2326
2327 module_names = xmalloc(bufsize = 256);
2328 retry_modules_load:
2329 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002330 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002331 module_names = xrealloc(module_names, bufsize = ret);
2332 goto retry_modules_load;
2333 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002334 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002335 return 0;
2336 }
2337
2338 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002339
2340 /* Collect the modules' symbols. */
2341
Mark Whitley94fd4802001-03-12 23:08:34 +00002342 if (nmod){
2343 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2344 memset(modules, 0, nmod * sizeof(*modules));
2345 for (i = 0, mn = module_names, m = modules;
2346 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2347 struct new_module_info info;
2348
2349 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2350 if (errno == ENOENT) {
2351 /* The module was removed out from underneath us. */
2352 continue;
2353 }
2354 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002355 return 0;
2356 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002357
2358 syms = xmalloc(bufsize = 1024);
2359 retry_mod_sym_load:
2360 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2361 switch (errno) {
2362 case ENOSPC:
2363 syms = xrealloc(syms, bufsize = ret);
2364 goto retry_mod_sym_load;
2365 case ENOENT:
2366 /* The module was removed out from underneath us. */
2367 continue;
2368 default:
2369 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2370 return 0;
2371 }
2372 }
2373 nsyms = ret;
2374
2375 m->name = mn;
2376 m->addr = info.addr;
2377 m->nsyms = nsyms;
2378 m->syms = syms;
2379
2380 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2381 s->name += (unsigned long) syms;
2382 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002383 }
2384 }
2385
2386 /* Collect the kernel's symbols. */
2387
2388 syms = xmalloc(bufsize = 16 * 1024);
2389 retry_kern_sym_load:
2390 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002391 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002392 syms = xrealloc(syms, bufsize = ret);
2393 goto retry_kern_sym_load;
2394 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002395 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002396 return 0;
2397 }
2398 nksyms = nsyms = ret;
2399 ksyms = syms;
2400
2401 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2402 s->name += (unsigned long) syms;
2403 }
2404 return 1;
2405}
2406
2407
2408/* Return the kernel symbol checksum version, or zero if not used. */
2409
2410static int new_is_kernel_checksummed(void)
2411{
2412 struct new_module_symbol *s;
2413 size_t i;
2414
2415 /* Using_Versions is not the first symbol, but it should be in there. */
2416
2417 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2418 if (strcmp((char *) s->name, "Using_Versions") == 0)
2419 return s->value;
2420
2421 return 0;
2422}
2423
2424
2425static int new_create_this_module(struct obj_file *f, const char *m_name)
2426{
2427 struct obj_section *sec;
2428
2429 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2430 sizeof(struct new_module));
2431 memset(sec->contents, 0, sizeof(struct new_module));
2432
2433 obj_add_symbol(f, "__this_module", -1,
2434 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2435 sizeof(struct new_module));
2436
2437 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2438 m_name);
2439
2440 return 1;
2441}
2442
2443
2444static int new_create_module_ksymtab(struct obj_file *f)
2445{
2446 struct obj_section *sec;
2447 int i;
2448
2449 /* We must always add the module references. */
2450
2451 if (n_ext_modules_used) {
2452 struct new_module_ref *dep;
2453 struct obj_symbol *tm;
2454
2455 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2456 (sizeof(struct new_module_ref)
2457 * n_ext_modules_used));
2458 if (!sec)
2459 return 0;
2460
2461 tm = obj_find_symbol(f, "__this_module");
2462 dep = (struct new_module_ref *) sec->contents;
2463 for (i = 0; i < n_ext_modules; ++i)
2464 if (ext_modules[i].used) {
2465 dep->dep = ext_modules[i].addr;
2466 obj_symbol_patch(f, sec->idx,
2467 (char *) &dep->ref - sec->contents, tm);
2468 dep->next_ref = 0;
2469 ++dep;
2470 }
2471 }
2472
2473 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2474 size_t nsyms;
2475 int *loaded;
2476
2477 sec =
2478 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2479 0);
2480
2481 /* We don't want to export symbols residing in sections that
2482 aren't loaded. There are a number of these created so that
2483 we make sure certain module options don't appear twice. */
2484
2485 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2486 while (--i >= 0)
2487 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2488
2489 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2490 struct obj_symbol *sym;
2491 for (sym = f->symtab[i]; sym; sym = sym->next)
2492 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2493 && sym->secidx <= SHN_HIRESERVE
2494 && (sym->secidx >= SHN_LORESERVE
2495 || loaded[sym->secidx])) {
2496 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2497
2498 obj_symbol_patch(f, sec->idx, ofs, sym);
2499 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2500 sym->name);
2501
2502 nsyms++;
2503 }
2504 }
2505
2506 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2507 }
2508
2509 return 1;
2510}
2511
2512
2513static int
2514new_init_module(const char *m_name, struct obj_file *f,
2515 unsigned long m_size)
2516{
2517 struct new_module *module;
2518 struct obj_section *sec;
2519 void *image;
2520 int ret;
2521 tgt_long m_addr;
2522
2523 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002524 if (!sec || !sec->contents) {
2525 perror_msg_and_die("corrupt module %s?",m_name);
2526 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002527 module = (struct new_module *) sec->contents;
2528 m_addr = sec->header.sh_addr;
2529
2530 module->size_of_struct = sizeof(*module);
2531 module->size = m_size;
2532 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2533
2534 sec = obj_find_section(f, "__ksymtab");
2535 if (sec && sec->header.sh_size) {
2536 module->syms = sec->header.sh_addr;
2537 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2538 }
2539
2540 if (n_ext_modules_used) {
2541 sec = obj_find_section(f, ".kmodtab");
2542 module->deps = sec->header.sh_addr;
2543 module->ndeps = n_ext_modules_used;
2544 }
2545
2546 module->init =
2547 obj_symbol_final_value(f, obj_find_symbol(f, "init_module"));
2548 module->cleanup =
2549 obj_symbol_final_value(f, obj_find_symbol(f, "cleanup_module"));
2550
2551 sec = obj_find_section(f, "__ex_table");
2552 if (sec) {
2553 module->ex_table_start = sec->header.sh_addr;
2554 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2555 }
2556
2557 sec = obj_find_section(f, ".text.init");
2558 if (sec) {
2559 module->runsize = sec->header.sh_addr - m_addr;
2560 }
2561 sec = obj_find_section(f, ".data.init");
2562 if (sec) {
2563 if (!module->runsize ||
2564 module->runsize > sec->header.sh_addr - m_addr)
2565 module->runsize = sec->header.sh_addr - m_addr;
2566 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002567 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2568 if (sec && sec->header.sh_size) {
2569 module->archdata_start = (void*)sec->header.sh_addr;
2570 module->archdata_end = module->archdata_start + sec->header.sh_size;
2571 }
2572 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2573 if (sec && sec->header.sh_size) {
2574 module->kallsyms_start = (void*)sec->header.sh_addr;
2575 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2576 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002577
2578 if (!arch_init_module(f, module))
2579 return 0;
2580
2581 /* Whew! All of the initialization is complete. Collect the final
2582 module image and give it to the kernel. */
2583
2584 image = xmalloc(m_size);
2585 obj_create_image(f, image);
2586
Eric Andersen64c8b172001-04-05 07:33:10 +00002587 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002588 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002589 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002590
2591 free(image);
2592
2593 return ret == 0;
2594}
2595
2596#else
2597
2598#define new_init_module(x, y, z) TRUE
2599#define new_create_this_module(x, y) 0
2600#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002601#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002602
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002603#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002604
2605
2606/*======================================================================*/
2607
Eric Andersen044228d2001-07-17 01:12:36 +00002608static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002609obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2610 const char *string)
2611{
2612 struct obj_string_patch *p;
2613 struct obj_section *strsec;
2614 size_t len = strlen(string) + 1;
2615 char *loc;
2616
2617 p = xmalloc(sizeof(*p));
2618 p->next = f->string_patches;
2619 p->reloc_secidx = secidx;
2620 p->reloc_offset = offset;
2621 f->string_patches = p;
2622
2623 strsec = obj_find_section(f, ".kstrtab");
2624 if (strsec == NULL) {
2625 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2626 p->string_offset = 0;
2627 loc = strsec->contents;
2628 } else {
2629 p->string_offset = strsec->header.sh_size;
2630 loc = obj_extend_section(strsec, len);
2631 }
2632 memcpy(loc, string, len);
2633
2634 return 1;
2635}
2636
Eric Andersen044228d2001-07-17 01:12:36 +00002637static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002638obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2639 struct obj_symbol *sym)
2640{
2641 struct obj_symbol_patch *p;
2642
2643 p = xmalloc(sizeof(*p));
2644 p->next = f->symbol_patches;
2645 p->reloc_secidx = secidx;
2646 p->reloc_offset = offset;
2647 p->sym = sym;
2648 f->symbol_patches = p;
2649
2650 return 1;
2651}
2652
Eric Andersen044228d2001-07-17 01:12:36 +00002653static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002654{
2655 unsigned long i;
2656 int ret = 1;
2657
2658 for (i = 0; i < HASH_BUCKETS; ++i) {
2659 struct obj_symbol *sym;
2660 for (sym = f->symtab[i]; sym; sym = sym->next)
2661 if (sym->secidx == SHN_UNDEF) {
2662 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2663 sym->secidx = SHN_ABS;
2664 sym->value = 0;
2665 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002666 error_msg("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002667 ret = 0;
2668 }
2669 }
2670 }
2671
2672 return ret;
2673}
2674
Eric Andersen044228d2001-07-17 01:12:36 +00002675static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002676{
2677 struct common_entry {
2678 struct common_entry *next;
2679 struct obj_symbol *sym;
2680 } *common_head = NULL;
2681
2682 unsigned long i;
2683
2684 for (i = 0; i < HASH_BUCKETS; ++i) {
2685 struct obj_symbol *sym;
2686 for (sym = f->symtab[i]; sym; sym = sym->next)
2687 if (sym->secidx == SHN_COMMON) {
2688 /* Collect all COMMON symbols and sort them by size so as to
2689 minimize space wasted by alignment requirements. */
2690 {
2691 struct common_entry **p, *n;
2692 for (p = &common_head; *p; p = &(*p)->next)
2693 if (sym->size <= (*p)->sym->size)
2694 break;
2695
2696 n = alloca(sizeof(*n));
2697 n->next = *p;
2698 n->sym = sym;
2699 *p = n;
2700 }
2701 }
2702 }
2703
2704 for (i = 1; i < f->local_symtab_size; ++i) {
2705 struct obj_symbol *sym = f->local_symtab[i];
2706 if (sym && sym->secidx == SHN_COMMON) {
2707 struct common_entry **p, *n;
2708 for (p = &common_head; *p; p = &(*p)->next)
2709 if (sym == (*p)->sym)
2710 break;
2711 else if (sym->size < (*p)->sym->size) {
2712 n = alloca(sizeof(*n));
2713 n->next = *p;
2714 n->sym = sym;
2715 *p = n;
2716 break;
2717 }
2718 }
2719 }
2720
2721 if (common_head) {
2722 /* Find the bss section. */
2723 for (i = 0; i < f->header.e_shnum; ++i)
2724 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2725 break;
2726
2727 /* If for some reason there hadn't been one, create one. */
2728 if (i == f->header.e_shnum) {
2729 struct obj_section *sec;
2730
2731 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2732 f->sections[i] = sec = arch_new_section();
2733 f->header.e_shnum = i + 1;
2734
2735 memset(sec, 0, sizeof(*sec));
2736 sec->header.sh_type = SHT_PROGBITS;
2737 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2738 sec->name = ".bss";
2739 sec->idx = i;
2740 }
2741
2742 /* Allocate the COMMONS. */
2743 {
2744 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2745 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2746 struct common_entry *c;
2747
2748 for (c = common_head; c; c = c->next) {
2749 ElfW(Addr) align = c->sym->value;
2750
2751 if (align > max_align)
2752 max_align = align;
2753 if (bss_size & (align - 1))
2754 bss_size = (bss_size | (align - 1)) + 1;
2755
2756 c->sym->secidx = i;
2757 c->sym->value = bss_size;
2758
2759 bss_size += c->sym->size;
2760 }
2761
2762 f->sections[i]->header.sh_size = bss_size;
2763 f->sections[i]->header.sh_addralign = max_align;
2764 }
2765 }
2766
2767 /* For the sake of patch relocation and parameter initialization,
2768 allocate zeroed data for NOBITS sections now. Note that after
2769 this we cannot assume NOBITS are really empty. */
2770 for (i = 0; i < f->header.e_shnum; ++i) {
2771 struct obj_section *s = f->sections[i];
2772 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002773 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002774 s->contents = memset(xmalloc(s->header.sh_size),
2775 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002776 else
2777 s->contents = NULL;
2778
Eric Andersen9f16d612000-06-12 23:11:16 +00002779 s->header.sh_type = SHT_PROGBITS;
2780 }
2781 }
2782}
2783
Eric Andersen044228d2001-07-17 01:12:36 +00002784static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002785{
2786 unsigned long dot = 0;
2787 struct obj_section *sec;
2788
2789 /* Finalize the positions of the sections relative to one another. */
2790
2791 for (sec = f->load_order; sec; sec = sec->load_next) {
2792 ElfW(Addr) align;
2793
2794 align = sec->header.sh_addralign;
2795 if (align && (dot & (align - 1)))
2796 dot = (dot | (align - 1)) + 1;
2797
2798 sec->header.sh_addr = dot;
2799 dot += sec->header.sh_size;
2800 }
2801
2802 return dot;
2803}
2804
Eric Andersen044228d2001-07-17 01:12:36 +00002805static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00002806{
2807 int i, n = f->header.e_shnum;
2808 int ret = 1;
2809
2810 /* Finalize the addresses of the sections. */
2811
2812 f->baseaddr = base;
2813 for (i = 0; i < n; ++i)
2814 f->sections[i]->header.sh_addr += base;
2815
2816 /* And iterate over all of the relocations. */
2817
2818 for (i = 0; i < n; ++i) {
2819 struct obj_section *relsec, *symsec, *targsec, *strsec;
2820 ElfW(RelM) * rel, *relend;
2821 ElfW(Sym) * symtab;
2822 const char *strtab;
2823
2824 relsec = f->sections[i];
2825 if (relsec->header.sh_type != SHT_RELM)
2826 continue;
2827
2828 symsec = f->sections[relsec->header.sh_link];
2829 targsec = f->sections[relsec->header.sh_info];
2830 strsec = f->sections[symsec->header.sh_link];
2831
2832 rel = (ElfW(RelM) *) relsec->contents;
2833 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
2834 symtab = (ElfW(Sym) *) symsec->contents;
2835 strtab = (const char *) strsec->contents;
2836
2837 for (; rel < relend; ++rel) {
2838 ElfW(Addr) value = 0;
2839 struct obj_symbol *intsym = NULL;
2840 unsigned long symndx;
2841 ElfW(Sym) * extsym = 0;
2842 const char *errmsg;
2843
2844 /* Attempt to find a value to use for this relocation. */
2845
2846 symndx = ELFW(R_SYM) (rel->r_info);
2847 if (symndx) {
2848 /* Note we've already checked for undefined symbols. */
2849
2850 extsym = &symtab[symndx];
2851 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
2852 /* Local symbols we look up in the local table to be sure
2853 we get the one that is really intended. */
2854 intsym = f->local_symtab[symndx];
2855 } else {
2856 /* Others we look up in the hash table. */
2857 const char *name;
2858 if (extsym->st_name)
2859 name = strtab + extsym->st_name;
2860 else
2861 name = f->sections[extsym->st_shndx]->name;
2862 intsym = obj_find_symbol(f, name);
2863 }
2864
2865 value = obj_symbol_final_value(f, intsym);
2866 intsym->referenced = 1;
2867 }
2868#if SHT_RELM == SHT_RELA
2869#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
2870 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
2871 if (!extsym || !extsym->st_name ||
2872 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
2873#endif
2874 value += rel->r_addend;
2875#endif
2876
2877 /* Do it! */
2878 switch (arch_apply_relocation
2879 (f, targsec, symsec, intsym, rel, value)) {
2880 case obj_reloc_ok:
2881 break;
2882
2883 case obj_reloc_overflow:
2884 errmsg = "Relocation overflow";
2885 goto bad_reloc;
2886 case obj_reloc_dangerous:
2887 errmsg = "Dangerous relocation";
2888 goto bad_reloc;
2889 case obj_reloc_unhandled:
2890 errmsg = "Unhandled relocation";
2891 bad_reloc:
2892 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002893 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002894 (long) ELFW(R_TYPE) (rel->r_info),
2895 strtab + extsym->st_name);
2896 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00002897 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00002898 (long) ELFW(R_TYPE) (rel->r_info));
2899 }
2900 ret = 0;
2901 break;
2902 }
2903 }
2904 }
2905
2906 /* Finally, take care of the patches. */
2907
2908 if (f->string_patches) {
2909 struct obj_string_patch *p;
2910 struct obj_section *strsec;
2911 ElfW(Addr) strsec_base;
2912 strsec = obj_find_section(f, ".kstrtab");
2913 strsec_base = strsec->header.sh_addr;
2914
2915 for (p = f->string_patches; p; p = p->next) {
2916 struct obj_section *targsec = f->sections[p->reloc_secidx];
2917 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2918 = strsec_base + p->string_offset;
2919 }
2920 }
2921
2922 if (f->symbol_patches) {
2923 struct obj_symbol_patch *p;
2924
2925 for (p = f->symbol_patches; p; p = p->next) {
2926 struct obj_section *targsec = f->sections[p->reloc_secidx];
2927 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
2928 = obj_symbol_final_value(f, p->sym);
2929 }
2930 }
2931
2932 return ret;
2933}
2934
Eric Andersen044228d2001-07-17 01:12:36 +00002935static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00002936{
2937 struct obj_section *sec;
2938 ElfW(Addr) base = f->baseaddr;
2939
2940 for (sec = f->load_order; sec; sec = sec->load_next) {
2941 char *secimg;
2942
Eric Andersen2bf658d2001-02-24 20:01:53 +00002943 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002944 continue;
2945
2946 secimg = image + (sec->header.sh_addr - base);
2947
2948 /* Note that we allocated data for NOBITS sections earlier. */
2949 memcpy(secimg, sec->contents, sec->header.sh_size);
2950 }
2951
2952 return 1;
2953}
2954
2955/*======================================================================*/
2956
Eric Andersen044228d2001-07-17 01:12:36 +00002957static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00002958{
2959 struct obj_file *f;
2960 ElfW(Shdr) * section_headers;
2961 int shnum, i;
2962 char *shstrtab;
2963
2964 /* Read the file header. */
2965
2966 f = arch_new_file();
2967 memset(f, 0, sizeof(*f));
2968 f->symbol_cmp = strcmp;
2969 f->symbol_hash = obj_elf_hash;
2970 f->load_order_search_start = &f->load_order;
2971
2972 fseek(fp, 0, SEEK_SET);
2973 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002974 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00002975 return NULL;
2976 }
2977
2978 if (f->header.e_ident[EI_MAG0] != ELFMAG0
2979 || f->header.e_ident[EI_MAG1] != ELFMAG1
2980 || f->header.e_ident[EI_MAG2] != ELFMAG2
2981 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002982 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00002983 return NULL;
2984 }
2985 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
2986 || f->header.e_ident[EI_DATA] != ELFDATAM
2987 || f->header.e_ident[EI_VERSION] != EV_CURRENT
2988 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002989 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00002990 return NULL;
2991 }
2992 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002993 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00002994 return NULL;
2995 }
2996
2997 /* Read the section headers. */
2998
2999 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003000 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003001 (unsigned long) f->header.e_shentsize,
3002 (unsigned long) sizeof(ElfW(Shdr)));
3003 return NULL;
3004 }
3005
3006 shnum = f->header.e_shnum;
3007 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3008 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3009
3010 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3011 fseek(fp, f->header.e_shoff, SEEK_SET);
3012 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003013 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003014 return NULL;
3015 }
3016
3017 /* Read the section data. */
3018
3019 for (i = 0; i < shnum; ++i) {
3020 struct obj_section *sec;
3021
3022 f->sections[i] = sec = arch_new_section();
3023 memset(sec, 0, sizeof(*sec));
3024
3025 sec->header = section_headers[i];
3026 sec->idx = i;
3027
Eric Andersen2bf658d2001-02-24 20:01:53 +00003028 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003029 case SHT_NULL:
3030 case SHT_NOTE:
3031 case SHT_NOBITS:
3032 /* ignore */
3033 break;
3034
3035 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003036#if LOADBITS
3037 if (!loadprogbits) {
3038 sec->contents = NULL;
3039 break;
3040 }
3041#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003042 case SHT_SYMTAB:
3043 case SHT_STRTAB:
3044 case SHT_RELM:
3045 if (sec->header.sh_size > 0) {
3046 sec->contents = xmalloc(sec->header.sh_size);
3047 fseek(fp, sec->header.sh_offset, SEEK_SET);
3048 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003049 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003050 return NULL;
3051 }
3052 } else {
3053 sec->contents = NULL;
3054 }
3055 break;
3056
3057#if SHT_RELM == SHT_REL
3058 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003059 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003060 return NULL;
3061#else
3062 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003063 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003064 return NULL;
3065#endif
3066
3067 default:
3068 if (sec->header.sh_type >= SHT_LOPROC) {
3069 /* Assume processor specific section types are debug
3070 info and can safely be ignored. If this is ever not
3071 the case (Hello MIPS?), don't put ifdefs here but
3072 create an arch_load_proc_section(). */
3073 break;
3074 }
3075
Matt Kraaidd19c692001-01-31 19:00:21 +00003076 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003077 (long) sec->header.sh_type);
3078 return NULL;
3079 }
3080 }
3081
3082 /* Do what sort of interpretation as needed by each section. */
3083
3084 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3085
3086 for (i = 0; i < shnum; ++i) {
3087 struct obj_section *sec = f->sections[i];
3088 sec->name = shstrtab + sec->header.sh_name;
3089 }
3090
3091 for (i = 0; i < shnum; ++i) {
3092 struct obj_section *sec = f->sections[i];
3093
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003094 /* .modinfo should be contents only but gcc has no attribute for that.
3095 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3096 */
3097 if (strcmp(sec->name, ".modinfo") == 0)
3098 sec->header.sh_flags &= ~SHF_ALLOC;
3099
Eric Andersen9f16d612000-06-12 23:11:16 +00003100 if (sec->header.sh_flags & SHF_ALLOC)
3101 obj_insert_section_load_order(f, sec);
3102
3103 switch (sec->header.sh_type) {
3104 case SHT_SYMTAB:
3105 {
3106 unsigned long nsym, j;
3107 char *strtab;
3108 ElfW(Sym) * sym;
3109
3110 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003111 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003112 (unsigned long) sec->header.sh_entsize,
3113 (unsigned long) sizeof(ElfW(Sym)));
3114 return NULL;
3115 }
3116
3117 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3118 strtab = f->sections[sec->header.sh_link]->contents;
3119 sym = (ElfW(Sym) *) sec->contents;
3120
3121 /* Allocate space for a table of local symbols. */
3122 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003123 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003124
3125 /* Insert all symbols into the hash table. */
3126 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3127 const char *name;
3128 if (sym->st_name)
3129 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003130 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003131 name = f->sections[sym->st_shndx]->name;
3132
3133 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3134 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003135 }
3136 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003137 break;
3138
3139 case SHT_RELM:
3140 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003141 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003142 (unsigned long) sec->header.sh_entsize,
3143 (unsigned long) sizeof(ElfW(RelM)));
3144 return NULL;
3145 }
3146 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003147 /* XXX Relocation code from modutils-2.3.19 is not here.
3148 * Why? That's about 20 lines of code from obj/obj_load.c,
3149 * which gets done in a second pass through the sections.
3150 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003151 }
3152 }
3153
3154 return f;
3155}
3156
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003157#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003158/*
3159 * load the unloaded sections directly into the memory allocated by
3160 * kernel for the module
3161 */
3162
Eric Andersenac5dbd12001-08-22 05:26:08 +00003163static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003164{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003165 ElfW(Addr) base = f->baseaddr;
3166 struct obj_section* sec;
3167
3168 for (sec = f->load_order; sec; sec = sec->load_next) {
3169
3170 /* section already loaded? */
3171 if (sec->contents != NULL)
3172 continue;
3173
3174 if (sec->header.sh_size == 0)
3175 continue;
3176
3177 sec->contents = imagebase + (sec->header.sh_addr - base);
3178 fseek(fp, sec->header.sh_offset, SEEK_SET);
3179 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Eric Andersenac5dbd12001-08-22 05:26:08 +00003180 error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003181 return 0;
3182 }
3183
3184 }
3185 return 1;
3186}
3187#endif
3188
Eric Andersen9f16d612000-06-12 23:11:16 +00003189static void hide_special_symbols(struct obj_file *f)
3190{
3191 static const char *const specials[] = {
3192 "cleanup_module",
3193 "init_module",
3194 "kernel_version",
3195 NULL
3196 };
3197
3198 struct obj_symbol *sym;
3199 const char *const *p;
3200
3201 for (p = specials; *p; ++p)
3202 if ((sym = obj_find_symbol(f, *p)) != NULL)
3203 sym->info =
3204 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3205}
3206
3207
3208
3209extern int insmod_main( int argc, char **argv)
3210{
Eric Andersena18aaf12001-01-24 19:07:09 +00003211 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003212 int k_crcs;
3213 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003214 int len;
3215 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003216 unsigned long m_size;
3217 ElfW(Addr) m_addr;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003218 FILE *fp;
Eric Andersen9f16d612000-06-12 23:11:16 +00003219 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003220 struct stat st;
Eric Andersen14d35432001-05-14 17:07:32 +00003221 char m_name[FILENAME_MAX + 1] = "\0";
Matt Kraai3e856ce2000-12-01 02:55:13 +00003222 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003223 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003224#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003225 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003226 char m_strversion[STRVERSIONLEN];
3227 int m_version;
3228 int m_crcs;
3229#endif
3230
Erik Andersene49d5ec2000-02-08 19:58:47 +00003231 /* Parse any options */
Eric Andersen155c89b2001-01-25 04:11:06 +00003232 while ((opt = getopt(argc, argv, "fkvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003233 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003234 case 'f': /* force loading */
3235 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003236 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003237 case 'k': /* module loaded by kerneld, auto-cleanable */
3238 flag_autoclean = 1;
3239 break;
3240 case 'v': /* verbose output */
3241 flag_verbose = 1;
3242 break;
3243 case 'x': /* do not export externs */
3244 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003245 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003246 case 'o': /* name the output module */
Eric Andersen14d35432001-05-14 17:07:32 +00003247 strncpy(m_name, optarg, FILENAME_MAX);
Eric Andersen155c89b2001-01-25 04:11:06 +00003248 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003249 case 'L': /* Stub warning */
3250 /* This is needed for compatibility with modprobe.
3251 * In theory, this does locking, but we don't do
3252 * that. So be careful and plan your life around not
3253 * loading the same module 50 times concurrently. */
3254 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003255 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003256 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003257 }
Erik Andersend387d011999-12-21 02:55:11 +00003258 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003259
3260 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003261 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003262 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003263
Erik Andersene49d5ec2000-02-08 19:58:47 +00003264 /* Grab the module name */
Eric Andersena18aaf12001-01-24 19:07:09 +00003265 if ((tmp = strrchr(argv[optind], '/')) != NULL) {
Erik Andersene49d5ec2000-02-08 19:58:47 +00003266 tmp++;
Eric Andersen9f16d612000-06-12 23:11:16 +00003267 } else {
Eric Andersena18aaf12001-01-24 19:07:09 +00003268 tmp = argv[optind];
Eric Andersen9f16d612000-06-12 23:11:16 +00003269 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003270 len = strlen(tmp);
3271
3272 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
3273 len -= 2;
Eric Andersenf2278152001-04-24 21:41:41 +00003274 memcpy(m_fullName, tmp, len);
3275 m_fullName[len]='\0';
Eric Andersen114ad9c2001-01-26 01:52:14 +00003276 if (*m_name == '\0') {
3277 strcpy(m_name, m_fullName);
Eric Andersen155c89b2001-01-25 04:11:06 +00003278 }
Eric Andersen114ad9c2001-01-26 01:52:14 +00003279 strcat(m_fullName, ".o");
Erik Andersene49d5ec2000-02-08 19:58:47 +00003280
Eric Andersen14d35432001-05-14 17:07:32 +00003281 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003282 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3283 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003284 struct utsname myuname;
3285
3286 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3287 * but do not error out yet if we fail to find it... */
3288 if (uname(&myuname) == 0) {
3289 char module_dir[FILENAME_MAX];
Eric Andersen2416dfc2001-05-14 20:03:04 +00003290 char real_module_dir[FILENAME_MAX];
Eric Andersen14d35432001-05-14 17:07:32 +00003291 snprintf (module_dir, sizeof(module_dir), "%s/%s",
3292 _PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003293 /* Jump through hoops in case /lib/modules/`uname -r`
3294 * is a symlink. We do not want recursive_action to
3295 * follow symlinks, but we do want to follow the
3296 * /lib/modules/`uname -r` dir, So resolve it ourselves
3297 * if it is a link... */
3298 if (realpath (module_dir, real_module_dir) == NULL)
3299 strcpy(real_module_dir, module_dir);
3300 recursive_action(real_module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003301 check_module_name_match, 0, m_fullName);
3302 }
3303
3304 /* Check if we have found anything yet */
3305 if (m_filename[0] == '\0' || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003306 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003307 char module_dir[FILENAME_MAX];
3308 if (realpath (_PATH_MODULES, module_dir) == NULL)
3309 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003310 /* No module found under /lib/modules/`uname -r`, this
3311 * time cast the net a bit wider. Search /lib/modules/ */
Eric Andersen2416dfc2001-05-14 20:03:04 +00003312 if (recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003313 check_module_name_match, 0, m_fullName) == FALSE)
Eric Andersen9f16d612000-06-12 23:11:16 +00003314 {
Eric Andersen14d35432001-05-14 17:07:32 +00003315 if (m_filename[0] == '\0'
3316 || ((fp = fopen(m_filename, "r")) == NULL))
3317 {
3318 error_msg("%s: no module by that name found", m_fullName);
3319 return EXIT_FAILURE;
3320 }
3321 } else
3322 error_msg_and_die("%s: no module by that name found", m_fullName);
3323 }
3324 } else
Eric Andersenf2278152001-04-24 21:41:41 +00003325 safe_strncpy(m_filename, argv[optind], sizeof(m_filename));
Erik Andersend387d011999-12-21 02:55:11 +00003326
Eric Andersen14d35432001-05-14 17:07:32 +00003327 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003328
Eric Andersen8ae319a2001-05-21 16:09:18 +00003329 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003330 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003331
Eric Andersen9f16d612000-06-12 23:11:16 +00003332 if (get_modinfo_value(f, "kernel_version") == NULL)
3333 m_has_modinfo = 0;
3334 else
3335 m_has_modinfo = 1;
3336
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003337#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003338 /* Version correspondence? */
3339
Matt Kraai063c1f52001-08-06 14:18:08 +00003340 if (uname(&uts_info) < 0)
3341 uts_info.release[0] = '\0';
Eric Andersen9f16d612000-06-12 23:11:16 +00003342 if (m_has_modinfo) {
3343 m_version = new_get_module_version(f, m_strversion);
3344 } else {
3345 m_version = old_get_module_version(f, m_strversion);
3346 if (m_version == -1) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003347 error_msg("couldn't find the kernel version the module was "
Matt Kraaidd19c692001-01-31 19:00:21 +00003348 "compiled for");
Eric Andersen9f16d612000-06-12 23:11:16 +00003349 goto out;
3350 }
3351 }
3352
Matt Kraai063c1f52001-08-06 14:18:08 +00003353 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003354 if (flag_force_load) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003355 error_msg("Warning: kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003356 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003357 "\twhile this kernel is version %s",
Matt Kraai063c1f52001-08-06 14:18:08 +00003358 m_filename, m_strversion, uts_info.release);
Eric Andersen9f16d612000-06-12 23:11:16 +00003359 } else {
Mark Whitleyf57c9442000-12-07 19:56:48 +00003360 error_msg("kernel-module version mismatch\n"
Eric Andersen9f16d612000-06-12 23:11:16 +00003361 "\t%s was compiled for kernel version %s\n"
Matt Kraaidd19c692001-01-31 19:00:21 +00003362 "\twhile this kernel is version %s.",
Matt Kraai063c1f52001-08-06 14:18:08 +00003363 m_filename, m_strversion, uts_info.release);
Eric Andersen9f16d612000-06-12 23:11:16 +00003364 goto out;
3365 }
3366 }
3367 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003368#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003369
3370 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3371
3372 if (k_new_syscalls) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003373#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003374 if (!new_get_kernel_symbols())
3375 goto out;
3376 k_crcs = new_is_kernel_checksummed();
3377#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003378 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003379 goto out;
3380#endif
3381 } else {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003382#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003383 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003384 goto out;
3385 k_crcs = old_is_kernel_checksummed();
3386#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003387 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 goto out;
3389#endif
3390 }
3391
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003392#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003393 if (m_has_modinfo)
3394 m_crcs = new_is_module_checksummed(f);
3395 else
3396 m_crcs = old_is_module_checksummed(f);
3397
3398 if (m_crcs != k_crcs)
3399 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003400#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003401
Erik Andersene49d5ec2000-02-08 19:58:47 +00003402 /* Let the module know about the kernel symbols. */
3403 add_kernel_symbols(f);
3404
Eric Andersen9f16d612000-06-12 23:11:16 +00003405 /* Allocate common symbols, symbol tables, and string tables. */
3406
3407 if (k_new_syscalls
3408 ? !new_create_this_module(f, m_name)
3409 : !old_create_mod_use_count(f))
3410 {
3411 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003412 }
3413
Eric Andersen9f16d612000-06-12 23:11:16 +00003414 if (!obj_check_undefineds(f)) {
3415 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003416 }
3417 obj_allocate_commons(f);
3418
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003419 /* done with the module name, on to the optional var=value arguments */
3420 ++optind;
3421
Eric Andersen9f16d612000-06-12 23:11:16 +00003422 if (optind < argc) {
3423 if (m_has_modinfo
3424 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3425 : !old_process_module_arguments(f, argc - optind, argv + optind))
3426 {
3427 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003428 }
3429 }
3430
Eric Andersen9f16d612000-06-12 23:11:16 +00003431 arch_create_got(f);
3432 hide_special_symbols(f);
3433
3434 if (k_new_syscalls)
3435 new_create_module_ksymtab(f);
3436
Erik Andersene49d5ec2000-02-08 19:58:47 +00003437 /* Find current size of the module */
3438 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003439
3440
Erik Andersene49d5ec2000-02-08 19:58:47 +00003441 m_addr = create_module(m_name, m_size);
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003442 if (m_addr==-1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003443 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003444 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003445 goto out;
3446 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003447 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003448 m_size);
3449 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003450 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003451 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003452 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003453 }
Erik Andersend387d011999-12-21 02:55:11 +00003454
Eric Andersen8ae319a2001-05-21 16:09:18 +00003455#if !LOADBITS
3456 /*
3457 * the PROGBITS section was not loaded by the obj_load
3458 * now we can load them directly into the kernel memory
3459 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00003460 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00003461 delete_module(m_name);
3462 goto out;
3463 }
3464#endif
3465
Eric Andersen9f16d612000-06-12 23:11:16 +00003466 if (!obj_relocate(f, m_addr)) {
3467 delete_module(m_name);
3468 goto out;
3469 }
Erik Andersend387d011999-12-21 02:55:11 +00003470
Eric Andersen9f16d612000-06-12 23:11:16 +00003471 if (k_new_syscalls
3472 ? !new_init_module(m_name, f, m_size)
3473 : !old_init_module(m_name, f, m_size))
3474 {
3475 delete_module(m_name);
3476 goto out;
3477 }
3478
Matt Kraai3e856ce2000-12-01 02:55:13 +00003479 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003480
3481out:
Erik Andersene49d5ec2000-02-08 19:58:47 +00003482 fclose(fp);
Eric Andersenbb245ba2000-06-19 19:53:30 +00003483 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003484}