blob: b367e84af1a8901dfe5e10a2ba9e0df24efcc0ac [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,
Miles Baderae28b042002-04-01 09:34:25 +00006 * MIPS, and v850e.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenbdfd0d72001-10-24 05:00:29 +00008 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
Miles Baderae28b042002-04-01 09:34:25 +00009 * Copyright (C) 1999,2000,2001,2002 by Erik Andersen <andersee@debian.org>
Eric Andersen9f16d612000-06-12 23:11:16 +000010 * and Ron Alder <alder@lineo.com>
11 *
Miles Bader75ce8d72002-04-01 14:25:51 +000012 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000013 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000014 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000015 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
16 *
17 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
18 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
19 * very minor changes required to also work with StrongArm and presumably
20 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000021 *
Eric Andersencffd5022002-05-24 06:50:15 +000022 * Magnus Damm <damm@opensource.se> 22-May-2002.
23 * The plt and got code are now using the same structs.
24 * Added generic linked list code to fully support PowerPC.
25 * Replaced the mess in arch_apply_relocation() with architecture blocks.
26 * The arch_create_got() function got cleaned up with architecture blocks.
27 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
28 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000029 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
30 * PowerPC specific code stolen from modutils-2.3.16,
31 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
32 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000033 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000034 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000035 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
36 * based on modutils-2.4.2
37 * MIPS specific support for Elf loading and relocation.
38 * Copyright 1996, 1997 Linux International.
39 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
40 *
Eric Andersen9f16d612000-06-12 23:11:16 +000041 * Based almost entirely on the Linux modutils-2.3.11 implementation.
42 * Copyright 1996, 1997 Linux International.
43 * New implementation contributed by Richard Henderson <rth@tamu.edu>
44 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
45 * Restructured (and partly rewritten) by:
46 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000047 *
48 * This program is free software; you can redistribute it and/or modify
49 * it under the terms of the GNU General Public License as published by
50 * the Free Software Foundation; either version 2 of the License, or
51 * (at your option) any later version.
52 *
53 * This program is distributed in the hope that it will be useful,
54 * but WITHOUT ANY WARRANTY; without even the implied warranty of
55 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56 * General Public License for more details.
57 *
58 * You should have received a copy of the GNU General Public License
59 * along with this program; if not, write to the Free Software
60 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61 *
62 */
63
Erik Andersen02104321999-12-17 18:57:34 +000064#include <stdlib.h>
65#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000066#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000067#include <errno.h>
68#include <unistd.h>
69#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000070#include <ctype.h>
71#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000072#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000073#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000074#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000075#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000076#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000077
Eric Andersenbdfd0d72001-10-24 05:00:29 +000078#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
79# undef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen64c8b172001-04-05 07:33:10 +000080# define new_sys_init_module init_module
81#else
82# define old_sys_init_module init_module
83#endif
84
Eric Andersenbdfd0d72001-10-24 05:00:29 +000085#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +000086#define LOADBITS 0
87#else
88#define LOADBITS 1
89#endif
90
Eric Andersen90fe7fe2001-02-20 20:47:08 +000091
92#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +000093#define CONFIG_USE_PLT_ENTRIES
94#define CONFIG_PLT_ENTRY_SIZE 8
95#define CONFIG_USE_GOT_ENTRIES
96#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +000097#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000103#endif
104
105#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000106#define CONFIG_USE_GOT_ENTRIES
107#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000108#define CONFIG_USE_SINGLE
109
110#ifndef EM_486
111#define MATCH_MACHINE(x) (x == EM_386)
112#else
113#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
114#endif
115
116#define SHT_RELM SHT_REL
117#define Elf32_RelM Elf32_Rel
118#define ELFCLASSM ELFCLASS32
119#endif
120
121#if defined(__mc68000__)
122#define CONFIG_USE_GOT_ENTRIES
123#define CONFIG_GOT_ENTRY_SIZE 4
124#define CONFIG_USE_SINGLE
125
126#define MATCH_MACHINE(x) (x == EM_68K)
127#define SHT_RELM SHT_RELA
128#define Elf32_RelM Elf32_Rela
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000129#endif
130
Eric Andersen2bf658d2001-02-24 20:01:53 +0000131#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000132/* Account for ELF spec changes. */
133#ifndef EM_MIPS_RS3_LE
134#ifdef EM_MIPS_RS4_BE
135#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
136#else
137#define EM_MIPS_RS3_LE 10
138#endif
139#endif /* !EM_MIPS_RS3_LE */
140
141#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
142#define SHT_RELM SHT_REL
143#define Elf32_RelM Elf32_Rel
144#define ELFCLASSM ELFCLASS32
145#define ARCHDATAM "__dbe_table"
146#endif
147
148#if defined(__powerpc__)
149#define CONFIG_USE_PLT_ENTRIES
150#define CONFIG_PLT_ENTRY_SIZE 16
151#define CONFIG_USE_PLT_LIST
152#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
153#define CONFIG_USE_LIST
154
155#define MATCH_MACHINE(x) (x == EM_PPC)
156#define SHT_RELM SHT_RELA
157#define Elf32_RelM Elf32_Rela
158#define ELFCLASSM ELFCLASS32
159#define ARCHDATAM "__ftr_fixup"
160#endif
161
162#if defined(__sh__)
163#define CONFIG_USE_GOT_ENTRIES
164#define CONFIG_GOT_ENTRY_SIZE 4
165#define CONFIG_USE_SINGLE
166
167#define MATCH_MACHINE(x) (x == EM_SH)
168#define SHT_RELM SHT_RELA
169#define Elf32_RelM Elf32_Rela
170#define ELFCLASSM ELFCLASS32
171
172/* the SH changes have only been tested on the SH4 in =little endian= mode */
173/* I'm not sure about big endian, so let's warn: */
174
175#if (defined(__SH4__) || defined(__SH3__)) && defined(__BIG_ENDIAN__)
176#error insmod.c may require changes for use on big endian SH4/SH3
177#endif
178
179/* it may or may not work on the SH1/SH2... So let's error on those
180 also */
181#if (defined(__sh__) && (!(defined(__SH3__) || defined(__SH4__))))
182#error insmod.c may require changes for non-SH3/SH4 use
183#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000184#endif
185
Miles Baderae28b042002-04-01 09:34:25 +0000186#if defined (__v850e__)
187#define CONFIG_USE_PLT_ENTRIES
188#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000189#define CONFIG_USE_SINGLE
190
191#ifndef EM_CYGNUS_V850 /* grumble */
192#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000193#endif
194
Eric Andersencffd5022002-05-24 06:50:15 +0000195#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
196#define SHT_RELM SHT_RELA
197#define Elf32_RelM Elf32_Rela
198#define ELFCLASSM ELFCLASS32
199
200#define SYMBOL_PREFIX "_"
201#endif
202
203#ifndef SHT_RELM
204#error Sorry, but insmod.c does not yet support this architecture...
205#endif
206
207
Eric Andersen9f16d612000-06-12 23:11:16 +0000208//----------------------------------------------------------------------------
209//--------modutils module.h, lines 45-242
210//----------------------------------------------------------------------------
211
212/* Definitions for the Linux module syscall interface.
213 Copyright 1996, 1997 Linux International.
214
215 Contributed by Richard Henderson <rth@tamu.edu>
216
217 This file is part of the Linux modutils.
218
219 This program is free software; you can redistribute it and/or modify it
220 under the terms of the GNU General Public License as published by the
221 Free Software Foundation; either version 2 of the License, or (at your
222 option) any later version.
223
224 This program is distributed in the hope that it will be useful, but
225 WITHOUT ANY WARRANTY; without even the implied warranty of
226 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
227 General Public License for more details.
228
229 You should have received a copy of the GNU General Public License
230 along with this program; if not, write to the Free Software Foundation,
231 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
232
233
234#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000235static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000236
Eric Andersen71ae64b2002-10-10 04:20:21 +0000237#ident "$Id: insmod.c,v 1.91 2002/10/10 04:20:21 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000238
239/* This file contains the structures used by the 2.0 and 2.1 kernels.
240 We do not use the kernel headers directly because we do not wish
241 to be dependant on a particular kernel version to compile insmod. */
242
243
244/*======================================================================*/
245/* The structures used by Linux 2.0. */
246
247/* The symbol format used by get_kernel_syms(2). */
248struct old_kernel_sym
249{
250 unsigned long value;
251 char name[60];
252};
253
254struct old_module_ref
255{
256 unsigned long module; /* kernel addresses */
257 unsigned long next;
258};
259
260struct old_module_symbol
261{
262 unsigned long addr;
263 unsigned long name;
264};
265
266struct old_symbol_table
267{
268 int size; /* total, including string table!!! */
269 int n_symbols;
270 int n_refs;
271 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
272 struct old_module_ref ref[0]; /* actual size defined by n_refs */
273};
274
275struct old_mod_routines
276{
277 unsigned long init;
278 unsigned long cleanup;
279};
280
281struct old_module
282{
283 unsigned long next;
284 unsigned long ref; /* the list of modules that refer to me */
285 unsigned long symtab;
286 unsigned long name;
287 int size; /* size of module in pages */
288 unsigned long addr; /* address of module */
289 int state;
290 unsigned long cleanup; /* cleanup routine */
291};
292
293/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000294static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000295
296int get_kernel_syms(struct old_kernel_sym *);
297int old_sys_init_module(const char *name, char *code, unsigned codesize,
298 struct old_mod_routines *, struct old_symbol_table *);
299
300/*======================================================================*/
301/* For sizeof() which are related to the module platform and not to the
302 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
303
304#define tgt_sizeof_char sizeof(char)
305#define tgt_sizeof_short sizeof(short)
306#define tgt_sizeof_int sizeof(int)
307#define tgt_sizeof_long sizeof(long)
308#define tgt_sizeof_char_p sizeof(char *)
309#define tgt_sizeof_void_p sizeof(void *)
310#define tgt_long long
311
312#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
313#undef tgt_sizeof_long
314#undef tgt_sizeof_char_p
315#undef tgt_sizeof_void_p
316#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000317static const int tgt_sizeof_long = 8;
318static const int tgt_sizeof_char_p = 8;
319static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000320#define tgt_long long long
321#endif
322
323/*======================================================================*/
324/* The structures used in Linux 2.1. */
325
326/* Note: new_module_symbol does not use tgt_long intentionally */
327struct new_module_symbol
328{
329 unsigned long value;
330 unsigned long name;
331};
332
333struct new_module_persist;
334
335struct new_module_ref
336{
337 unsigned tgt_long dep; /* kernel addresses */
338 unsigned tgt_long ref;
339 unsigned tgt_long next_ref;
340};
341
342struct new_module
343{
344 unsigned tgt_long size_of_struct; /* == sizeof(module) */
345 unsigned tgt_long next;
346 unsigned tgt_long name;
347 unsigned tgt_long size;
348
349 tgt_long usecount;
350 unsigned tgt_long flags; /* AUTOCLEAN et al */
351
352 unsigned nsyms;
353 unsigned ndeps;
354
355 unsigned tgt_long syms;
356 unsigned tgt_long deps;
357 unsigned tgt_long refs;
358 unsigned tgt_long init;
359 unsigned tgt_long cleanup;
360 unsigned tgt_long ex_table_start;
361 unsigned tgt_long ex_table_end;
362#ifdef __alpha__
363 unsigned tgt_long gp;
364#endif
365 /* Everything after here is extension. */
366 unsigned tgt_long persist_start;
367 unsigned tgt_long persist_end;
368 unsigned tgt_long can_unload;
369 unsigned tgt_long runsize;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000370#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen8ae319a2001-05-21 16:09:18 +0000371 const char *kallsyms_start; /* All symbols for kernel debugging */
372 const char *kallsyms_end;
373 const char *archdata_start; /* arch specific data for module */
374 const char *archdata_end;
375 const char *kernel_data; /* Reserved for kernel internal use */
376#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000377};
378
Eric Andersencffd5022002-05-24 06:50:15 +0000379#ifdef ARCHDATAM
380#define ARCHDATA_SEC_NAME ARCHDATAM
381#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000382#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000383#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000384#define KALLSYMS_SEC_NAME "__kallsyms"
385
386
Eric Andersen9f16d612000-06-12 23:11:16 +0000387struct new_module_info
388{
389 unsigned long addr;
390 unsigned long size;
391 unsigned long flags;
392 long usecount;
393};
394
395/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000396static const int NEW_MOD_RUNNING = 1;
397static const int NEW_MOD_DELETED = 2;
398static const int NEW_MOD_AUTOCLEAN = 4;
399static const int NEW_MOD_VISITED = 8;
400static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000401
Eric Andersen64c8b172001-04-05 07:33:10 +0000402int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000403int query_module(const char *name, int which, void *buf, size_t bufsize,
404 size_t *ret);
405
406/* Values for query_module's which. */
407
Mark Whitley59ab0252001-01-23 22:30:04 +0000408static const int QM_MODULES = 1;
409static const int QM_DEPS = 2;
410static const int QM_REFS = 3;
411static const int QM_SYMBOLS = 4;
412static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000413
414/*======================================================================*/
415/* The system calls unchanged between 2.0 and 2.1. */
416
417unsigned long create_module(const char *, size_t);
418int delete_module(const char *);
419
420
421#endif /* module.h */
422
423//----------------------------------------------------------------------------
424//--------end of modutils module.h
425//----------------------------------------------------------------------------
426
427
428
429//----------------------------------------------------------------------------
430//--------modutils obj.h, lines 253-462
431//----------------------------------------------------------------------------
432
433/* Elf object file loading and relocation routines.
434 Copyright 1996, 1997 Linux International.
435
436 Contributed by Richard Henderson <rth@tamu.edu>
437
438 This file is part of the Linux modutils.
439
440 This program is free software; you can redistribute it and/or modify it
441 under the terms of the GNU General Public License as published by the
442 Free Software Foundation; either version 2 of the License, or (at your
443 option) any later version.
444
445 This program is distributed in the hope that it will be useful, but
446 WITHOUT ANY WARRANTY; without even the implied warranty of
447 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
448 General Public License for more details.
449
450 You should have received a copy of the GNU General Public License
451 along with this program; if not, write to the Free Software Foundation,
452 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
453
454
455#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000456static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000457
Eric Andersen71ae64b2002-10-10 04:20:21 +0000458#ident "$Id: insmod.c,v 1.91 2002/10/10 04:20:21 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000459
460/* The relocatable object is manipulated using elfin types. */
461
462#include <stdio.h>
463#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000464#include <endian.h>
465
466#if __BYTE_ORDER == __LITTLE_ENDIAN
467#define ELFDATAM ELFDATA2LSB
468#elif __BYTE_ORDER == __BIG_ENDIAN
469#define ELFDATAM ELFDATA2MSB
470#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000471
Eric Andersen9f16d612000-06-12 23:11:16 +0000472#ifndef ElfW
473# if ELFCLASSM == ELFCLASS32
474# define ElfW(x) Elf32_ ## x
475# define ELFW(x) ELF32_ ## x
476# else
477# define ElfW(x) Elf64_ ## x
478# define ELFW(x) ELF64_ ## x
479# endif
480#endif
481
482/* For some reason this is missing from libc5. */
483#ifndef ELF32_ST_INFO
484# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
485#endif
486
487#ifndef ELF64_ST_INFO
488# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
489#endif
490
491struct obj_string_patch;
492struct obj_symbol_patch;
493
494struct obj_section
495{
496 ElfW(Shdr) header;
497 const char *name;
498 char *contents;
499 struct obj_section *load_next;
500 int idx;
501};
502
503struct obj_symbol
504{
505 struct obj_symbol *next; /* hash table link */
506 const char *name;
507 unsigned long value;
508 unsigned long size;
509 int secidx; /* the defining section index/module */
510 int info;
511 int ksymidx; /* for export to the kernel symtab */
512 int referenced; /* actually used in the link */
513};
514
515/* Hardcode the hash table size. We shouldn't be needing so many
516 symbols that we begin to degrade performance, and we get a big win
517 by giving the compiler a constant divisor. */
518
519#define HASH_BUCKETS 521
520
521struct obj_file
522{
523 ElfW(Ehdr) header;
524 ElfW(Addr) baseaddr;
525 struct obj_section **sections;
526 struct obj_section *load_order;
527 struct obj_section **load_order_search_start;
528 struct obj_string_patch *string_patches;
529 struct obj_symbol_patch *symbol_patches;
530 int (*symbol_cmp)(const char *, const char *);
531 unsigned long (*symbol_hash)(const char *);
532 unsigned long local_symtab_size;
533 struct obj_symbol **local_symtab;
534 struct obj_symbol *symtab[HASH_BUCKETS];
535};
536
537enum obj_reloc
538{
539 obj_reloc_ok,
540 obj_reloc_overflow,
541 obj_reloc_dangerous,
542 obj_reloc_unhandled
543};
544
545struct obj_string_patch
546{
547 struct obj_string_patch *next;
548 int reloc_secidx;
549 ElfW(Addr) reloc_offset;
550 ElfW(Addr) string_offset;
551};
552
553struct obj_symbol_patch
554{
555 struct obj_symbol_patch *next;
556 int reloc_secidx;
557 ElfW(Addr) reloc_offset;
558 struct obj_symbol *sym;
559};
560
561
562/* Generic object manipulation routines. */
563
Eric Andersen044228d2001-07-17 01:12:36 +0000564static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000565
Eric Andersen044228d2001-07-17 01:12:36 +0000566static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000567
Eric Andersen044228d2001-07-17 01:12:36 +0000568static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000569 const char *name);
570
Eric Andersen044228d2001-07-17 01:12:36 +0000571static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000572 struct obj_symbol *sym);
573
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000574#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000575static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000576 int (*cmp)(const char *, const char *),
577 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000578#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000579
Eric Andersen044228d2001-07-17 01:12:36 +0000580static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000581 const char *name);
582
Eric Andersen044228d2001-07-17 01:12:36 +0000583static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000584 struct obj_section *sec);
585
Eric Andersen044228d2001-07-17 01:12:36 +0000586static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000587 const char *name,
588 unsigned long align,
589 unsigned long size);
590
Eric Andersen044228d2001-07-17 01:12:36 +0000591static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000592 const char *name,
593 unsigned long align,
594 unsigned long size);
595
Eric Andersen044228d2001-07-17 01:12:36 +0000596static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000597
Eric Andersen044228d2001-07-17 01:12:36 +0000598static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000599 const char *string);
600
Eric Andersen6d139642001-12-29 04:15:13 +0000601#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000602static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000603 struct obj_symbol *sym);
Eric Andersen6d139642001-12-29 04:15:13 +0000604#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000605
Eric Andersen044228d2001-07-17 01:12:36 +0000606static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000607
Eric Andersen044228d2001-07-17 01:12:36 +0000608static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000609
Eric Andersen044228d2001-07-17 01:12:36 +0000610static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000611
Eric Andersen044228d2001-07-17 01:12:36 +0000612static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000613
Eric Andersen044228d2001-07-17 01:12:36 +0000614static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000615
Eric Andersen044228d2001-07-17 01:12:36 +0000616static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000617
618/* Architecture specific manipulation routines. */
619
Eric Andersen044228d2001-07-17 01:12:36 +0000620static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000621
Eric Andersen044228d2001-07-17 01:12:36 +0000622static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000623
Eric Andersen044228d2001-07-17 01:12:36 +0000624static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 struct obj_section *targsec,
628 struct obj_section *symsec,
629 struct obj_symbol *sym,
630 ElfW(RelM) *rel, ElfW(Addr) value);
631
Eric Andersencffd5022002-05-24 06:50:15 +0000632static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000633
Eric Andersen6d139642001-12-29 04:15:13 +0000634#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +0000635static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen6d139642001-12-29 04:15:13 +0000636#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000637
638#endif /* obj.h */
639//----------------------------------------------------------------------------
640//--------end of modutils obj.h
641//----------------------------------------------------------------------------
642
643
644
Miles Baderae28b042002-04-01 09:34:25 +0000645/* SPFX is always a string, so it can be concatenated to string constants. */
646#ifdef SYMBOL_PREFIX
647#define SPFX SYMBOL_PREFIX
648#else
649#define SPFX ""
650#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Erik Andersen02104321999-12-17 18:57:34 +0000652
Erik Andersend387d011999-12-21 02:55:11 +0000653#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000654static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000655
Eric Andersen9f16d612000-06-12 23:11:16 +0000656/*======================================================================*/
657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static int flag_force_load = 0;
659static int flag_autoclean = 0;
660static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000661static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000662static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000663
664
665/*======================================================================*/
666
Eric Andersencffd5022002-05-24 06:50:15 +0000667#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000668
Eric Andersencffd5022002-05-24 06:50:15 +0000669struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000670{
Eric Andersencffd5022002-05-24 06:50:15 +0000671 struct arch_list_entry *next;
672 CONFIG_LIST_ARCHTYPE addend;
673 int offset;
674 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000675};
Eric Andersencffd5022002-05-24 06:50:15 +0000676
Eric Andersen21adca72000-12-06 18:18:26 +0000677#endif
678
Eric Andersencffd5022002-05-24 06:50:15 +0000679#if defined(CONFIG_USE_SINGLE)
680
681struct arch_single_entry
682{
Eric Andersen9f16d612000-06-12 23:11:16 +0000683 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000684 int inited : 1;
685 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000686};
Eric Andersencffd5022002-05-24 06:50:15 +0000687
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000688#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000689
Eric Andersen2bf658d2001-02-24 20:01:53 +0000690#if defined(__mips__)
691struct mips_hi16
692{
693 struct mips_hi16 *next;
694 Elf32_Addr *addr;
695 Elf32_Addr value;
696};
697#endif
698
Eric Andersenfe4208f2000-09-24 03:44:29 +0000699struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000700 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000701#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000702 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000703#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000704#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000705 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000706#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000707#if defined(__mips__)
708 struct mips_hi16 *mips_hi16_list;
709#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000710};
711
Eric Andersenfe4208f2000-09-24 03:44:29 +0000712struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000713 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000714#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000715#if defined(CONFIG_USE_PLT_LIST)
716 struct arch_list_entry *pltent;
717#else
718 struct arch_single_entry pltent;
719#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000720#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000721#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000722 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000723#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000724};
725
726
Eric Andersen9f16d612000-06-12 23:11:16 +0000727struct external_module {
728 const char *name;
729 ElfW(Addr) addr;
730 int used;
731 size_t nsyms;
732 struct new_module_symbol *syms;
733};
734
Eric Andersen044228d2001-07-17 01:12:36 +0000735static struct new_module_symbol *ksyms;
736static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000737
Eric Andersen044228d2001-07-17 01:12:36 +0000738static struct external_module *ext_modules;
739static int n_ext_modules;
740static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000741extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000742
Eric Andersen61f83052002-06-22 17:15:42 +0000743static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000744static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000745
Eric Andersenfe4208f2000-09-24 03:44:29 +0000746
Erik Andersen02104321999-12-17 18:57:34 +0000747
Eric Andersen9f16d612000-06-12 23:11:16 +0000748/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000749
Eric Andersen9f16d612000-06-12 23:11:16 +0000750
Eric Andersen14d35432001-05-14 17:07:32 +0000751static int check_module_name_match(const char *filename, struct stat *statbuf,
752 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000753{
Eric Andersen14d35432001-05-14 17:07:32 +0000754 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000755
Eric Andersen14d35432001-05-14 17:07:32 +0000756 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000757 return (FALSE);
758 else {
Matt Kraaic8227632001-11-12 16:57:27 +0000759 char *tmp, *tmp1 = xstrdup(filename);
Eric Andersen14d35432001-05-14 17:07:32 +0000760 tmp = get_last_path_component(tmp1);
761 if (strcmp(tmp, fullname) == 0) {
762 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000763 /* Stop searching if we find a match */
Eric Andersen61f83052002-06-22 17:15:42 +0000764 m_filename = xstrdup(filename);
Eric Andersen14d35432001-05-14 17:07:32 +0000765 return (TRUE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000766 }
Eric Andersen14d35432001-05-14 17:07:32 +0000767 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000768 }
Eric Andersen14d35432001-05-14 17:07:32 +0000769 return (FALSE);
Erik Andersend387d011999-12-21 02:55:11 +0000770}
771
Erik Andersen02104321999-12-17 18:57:34 +0000772
Eric Andersen9f16d612000-06-12 23:11:16 +0000773/*======================================================================*/
774
Eric Andersen044228d2001-07-17 01:12:36 +0000775static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000776{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000777 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000778 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000779
Eric Andersencffd5022002-05-24 06:50:15 +0000780 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000781
Eric Andersen9f16d612000-06-12 23:11:16 +0000782 return &f->root;
783}
784
Eric Andersen044228d2001-07-17 01:12:36 +0000785static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000786{
787 return xmalloc(sizeof(struct obj_section));
788}
789
Eric Andersen044228d2001-07-17 01:12:36 +0000790static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000791{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000792 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000793 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000794
Eric Andersencffd5022002-05-24 06:50:15 +0000795 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000796
Eric Andersen9f16d612000-06-12 23:11:16 +0000797 return &sym->root;
798}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000799
Eric Andersen044228d2001-07-17 01:12:36 +0000800static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000801arch_apply_relocation(struct obj_file *f,
802 struct obj_section *targsec,
803 struct obj_section *symsec,
804 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000805 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000806{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000807 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000808 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000809 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
810 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000811#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
812 struct arch_symbol *isym = (struct arch_symbol *) sym;
813#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000814#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000815 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000816#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000817#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000818 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000819 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000820#if defined(CONFIG_USE_PLT_LIST)
821 struct arch_list_entry *pe;
822#else
823 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000824#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000825#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000826
827 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000828
Eric Andersencffd5022002-05-24 06:50:15 +0000829
830#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +0000831 case R_ARM_NONE:
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 break;
833
Eric Andersen21adca72000-12-06 18:18:26 +0000834 case R_ARM_ABS32:
Eric Andersen9f16d612000-06-12 23:11:16 +0000835 *loc += v;
836 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000837
838 case R_ARM_GOT32:
839 goto bb_use_got;
Miles Baderae28b042002-04-01 09:34:25 +0000840
Eric Andersencffd5022002-05-24 06:50:15 +0000841 case R_ARM_GOTPC:
842 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
843 * (which is .got) similar to branch,
844 * but is full 32 bits relative */
845
846 assert(got);
847 *loc += got - dot;
848 break;
849
850 case R_ARM_PC24:
851 case R_ARM_PLT32:
852 goto bb_use_plt;
853
854 case R_ARM_GOTOFF: /* address relative to the got */
855 assert(got);
856 *loc += v - got;
857 break;
858
859#elif defined(__i386__)
860
861 case R_386_NONE:
862 break;
863
864 case R_386_32:
865 *loc += v;
866 break;
867
868 case R_386_PLT32:
869 case R_386_PC32:
870 *loc += v - dot;
871 break;
872
873 case R_386_GLOB_DAT:
874 case R_386_JMP_SLOT:
875 *loc = v;
876 break;
877
878 case R_386_RELATIVE:
879 *loc += f->baseaddr;
880 break;
881
882 case R_386_GOTPC:
883 assert(got != 0);
884 *loc += got - dot;
885 break;
886
887 case R_386_GOT32:
888 goto bb_use_got;
889
890 case R_386_GOTOFF:
891 assert(got != 0);
892 *loc += v - got;
893 break;
894
895#elif defined(__mc68000__)
896
897 case R_68K_NONE:
898 break;
899
900 case R_68K_32:
901 *loc += v;
902 break;
903
904 case R_68K_8:
905 if (v > 0xff) {
906 ret = obj_reloc_overflow;
907 }
Eric Andersen8ae319a2001-05-21 16:09:18 +0000908 *(char *)loc = v;
909 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000910
911 case R_68K_16:
912 if (v > 0xffff) {
913 ret = obj_reloc_overflow;
914 }
Eric Andersen8ae319a2001-05-21 16:09:18 +0000915 *(short *)loc = v;
916 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000917
Eric Andersencffd5022002-05-24 06:50:15 +0000918 case R_68K_PC8:
919 v -= dot;
920 if ((Elf32_Sword)v > 0x7f ||
921 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
922 ret = obj_reloc_overflow;
923 }
924 *(char *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000925 break;
926
Eric Andersencffd5022002-05-24 06:50:15 +0000927 case R_68K_PC16:
928 v -= dot;
929 if ((Elf32_Sword)v > 0x7fff ||
930 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
931 ret = obj_reloc_overflow;
932 }
933 *(short *)loc = v;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000934 break;
935
Eric Andersencffd5022002-05-24 06:50:15 +0000936 case R_68K_PC32:
937 *(int *)loc = v - dot;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000938 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000939
Eric Andersencffd5022002-05-24 06:50:15 +0000940 case R_68K_GLOB_DAT:
941 case R_68K_JMP_SLOT:
942 *loc = v;
943 break;
944
945 case R_68K_RELATIVE:
946 *(int *)loc += f->baseaddr;
947 break;
948
949 case R_68K_GOT32:
950 goto bb_use_got;
951
952 case R_68K_GOTOFF:
953 assert(got != 0);
954 *loc += v - got;
955 break;
956
957#elif defined(__mips__)
958
959 case R_MIPS_NONE:
960 break;
961
962 case R_MIPS_32:
963 *loc += v;
964 break;
965
Eric Andersen2bf658d2001-02-24 20:01:53 +0000966 case R_MIPS_26:
967 if (v % 4)
968 ret = obj_reloc_dangerous;
969 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
970 ret = obj_reloc_overflow;
971 *loc =
972 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
973 0x03ffffff);
974 break;
975
976 case R_MIPS_HI16:
977 {
978 struct mips_hi16 *n;
979
980 /* We cannot relocate this one now because we don't know the value
981 of the carry we need to add. Save the information, and let LO16
982 do the actual relocation. */
983 n = (struct mips_hi16 *) xmalloc(sizeof *n);
984 n->addr = loc;
985 n->value = v;
986 n->next = ifile->mips_hi16_list;
987 ifile->mips_hi16_list = n;
988 break;
989 }
990
991 case R_MIPS_LO16:
992 {
993 unsigned long insnlo = *loc;
994 Elf32_Addr val, vallo;
995
996 /* Sign extend the addend we extract from the lo insn. */
997 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
998
999 if (ifile->mips_hi16_list != NULL) {
1000 struct mips_hi16 *l;
1001
1002 l = ifile->mips_hi16_list;
1003 while (l != NULL) {
1004 struct mips_hi16 *next;
1005 unsigned long insn;
1006
1007 /* The value for the HI16 had best be the same. */
1008 assert(v == l->value);
1009
1010 /* Do the HI16 relocation. Note that we actually don't
1011 need to know anything about the LO16 itself, except where
1012 to find the low 16 bits of the addend needed by the LO16. */
1013 insn = *l->addr;
1014 val =
1015 ((insn & 0xffff) << 16) +
1016 vallo;
1017 val += v;
1018
1019 /* Account for the sign extension that will happen in the
1020 low bits. */
1021 val =
1022 ((val >> 16) +
1023 ((val & 0x8000) !=
1024 0)) & 0xffff;
1025
1026 insn = (insn & ~0xffff) | val;
1027 *l->addr = insn;
1028
1029 next = l->next;
1030 free(l);
1031 l = next;
1032 }
1033
1034 ifile->mips_hi16_list = NULL;
1035 }
1036
1037 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1038 val = v + vallo;
1039 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1040 *loc = insnlo;
1041 break;
1042 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001043
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001044#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001045
1046 case R_PPC_ADDR16_HA:
1047 *(unsigned short *)loc = (v + 0x8000) >> 16;
1048 break;
1049
1050 case R_PPC_ADDR16_HI:
1051 *(unsigned short *)loc = v >> 16;
1052 break;
1053
1054 case R_PPC_ADDR16_LO:
1055 *(unsigned short *)loc = v;
1056 break;
1057
1058 case R_PPC_REL24:
1059 goto bb_use_plt;
1060
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001061 case R_PPC_REL32:
1062 *loc = v - dot;
1063 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001064
1065 case R_PPC_ADDR32:
1066 *loc = v;
1067 break;
1068
1069#elif defined(__sh__)
1070
1071 case R_SH_NONE:
1072 break;
1073
1074 case R_SH_DIR32:
1075 *loc += v;
1076 break;
1077
1078 case R_SH_REL32:
1079 *loc += v - dot;
1080 break;
1081
1082 case R_SH_PLT32:
1083 *loc = v - dot;
1084 break;
1085
1086 case R_SH_GLOB_DAT:
1087 case R_SH_JMP_SLOT:
1088 *loc = v;
1089 break;
1090
1091 case R_SH_RELATIVE:
1092 *loc = f->baseaddr + rel->r_addend;
1093 break;
1094
1095 case R_SH_GOTPC:
1096 assert(got != 0);
1097 *loc = got - dot + rel->r_addend;
1098 break;
1099
1100 case R_SH_GOT32:
1101 goto bb_use_got;
1102
1103 case R_SH_GOTOFF:
1104 assert(got != 0);
1105 *loc = v - got;
1106 break;
1107
Eric Andersen21adca72000-12-06 18:18:26 +00001108#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001109
Eric Andersencffd5022002-05-24 06:50:15 +00001110 default:
1111 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1112 ret = obj_reloc_unhandled;
1113 break;
1114
1115#if defined (__v850e__)
1116 case R_V850_NONE:
1117 break;
1118
1119 case R_V850_32:
1120 /* We write two shorts instead of a long because even
1121 32-bit insns only need half-word alignment, but
1122 32-bit data needs to be long-word aligned. */
1123 v += ((unsigned short *)loc)[0];
1124 v += ((unsigned short *)loc)[1] << 16;
1125 ((unsigned short *)loc)[0] = v & 0xffff;
1126 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1127 break;
1128
1129 case R_V850_22_PCREL:
1130 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001131#endif
1132
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001133#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001134
Eric Andersencffd5022002-05-24 06:50:15 +00001135 bb_use_plt:
1136
Eric Andersen21adca72000-12-06 18:18:26 +00001137 /* find the plt entry and initialize it if necessary */
1138 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001139
Eric Andersencffd5022002-05-24 06:50:15 +00001140#if defined(CONFIG_USE_PLT_LIST)
1141 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1142 pe = pe->next;
1143 assert(pe != NULL);
1144#else
1145 pe = &isym->pltent;
1146#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001147
Eric Andersen21adca72000-12-06 18:18:26 +00001148 if (! pe->inited) {
1149 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001150
1151 /* generate some machine code */
1152
1153#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001154 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1155 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001156#endif
1157#if defined(__powerpc__)
1158 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1159 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1160 ip[2] = 0x7d6903a6; /* mtctr r11 */
1161 ip[3] = 0x4e800420; /* bctr */
1162#endif
Miles Baderae28b042002-04-01 09:34:25 +00001163#if defined (__v850e__)
1164 /* We have to trash a register, so we assume that any control
1165 transfer more than 21-bits away must be a function call
1166 (so we can use a call-clobbered register). */
1167 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1168 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
1169#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001170 pe->inited = 1;
1171 }
1172
1173 /* relative distance to target */
1174 v -= dot;
1175 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001176#if defined (__arm__) || defined (__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001177 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001178#elif defined (__v850e__)
1179 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
1180#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001181 /* go via the plt */
1182 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001183
1184#if defined (__v850e__)
1185 if (v & 1)
1186#else
Eric Andersen21adca72000-12-06 18:18:26 +00001187 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001188#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001189 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001190
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001191 /* merge the offset into the instruction. */
1192#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001193 /* Convert to words. */
1194 v >>= 2;
1195
Eric Andersen21adca72000-12-06 18:18:26 +00001196 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001197#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001198#if defined(__powerpc__)
1199 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
1200#endif
Miles Baderae28b042002-04-01 09:34:25 +00001201#if defined (__v850e__)
1202 /* We write two shorts instead of a long because even 32-bit insns
1203 only need half-word alignment, but the 32-bit data write needs
1204 to be long-word aligned. */
1205 ((unsigned short *)loc)[0] =
1206 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1207 | ((v >> 16) & 0x3f); /* offs high part */
1208 ((unsigned short *)loc)[1] =
1209 (v & 0xffff); /* offs low part */
1210#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001211 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001212#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001213
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001214#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001215 bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001216
Eric Andersen9f16d612000-06-12 23:11:16 +00001217 assert(isym != NULL);
Eric Andersen21adca72000-12-06 18:18:26 +00001218 /* needs an entry in the .got: set it, once */
Eric Andersencffd5022002-05-24 06:50:15 +00001219 if (!isym->gotent.inited) {
1220 isym->gotent.inited = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001221 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
Eric Andersen9f16d612000-06-12 23:11:16 +00001222 }
Eric Andersen21adca72000-12-06 18:18:26 +00001223 /* make the reloc with_respect_to_.got */
1224#if defined(__sh__)
1225 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001226#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen9f16d612000-06-12 23:11:16 +00001227 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001228#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001229 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001230
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001231#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001232 }
1233
1234 return ret;
1235}
1236
Eric Andersencffd5022002-05-24 06:50:15 +00001237
1238#if defined(CONFIG_USE_LIST)
1239
1240static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1241 int offset, int size)
1242{
1243 struct arch_list_entry *pe;
1244
1245 for (pe = *list; pe != NULL; pe = pe->next) {
1246 if (pe->addend == rel->r_addend) {
1247 break;
1248 }
1249 }
1250
1251 if (pe == NULL) {
1252 pe = xmalloc(sizeof(struct arch_list_entry));
1253 pe->next = *list;
1254 pe->addend = rel->r_addend;
1255 pe->offset = offset;
1256 pe->inited = 0;
1257 *list = pe;
1258 return size;
1259 }
1260 return 0;
1261}
1262
1263#endif
1264
1265#if defined(CONFIG_USE_SINGLE)
1266
1267static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1268 int offset, int size)
1269{
1270 if (single->allocated == 0) {
1271 single->allocated = 1;
1272 single->offset = offset;
1273 single->inited = 0;
1274 return size;
1275 }
1276 return 0;
1277}
1278
1279#endif
1280
1281#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1282
1283static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
1284 int offset, int size)
1285{
1286 struct obj_section *myrelsec = obj_find_section(f, name);
1287
1288 if (offset == 0) {
1289 offset += size;
1290 }
1291
1292 if (myrelsec) {
1293 obj_extend_section(myrelsec, offset);
1294 } else {
1295 myrelsec = obj_create_alloced_section(f, name,
1296 size, offset);
1297 assert(myrelsec);
1298 }
1299
1300 return myrelsec;
1301}
1302
1303#endif
1304
1305static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001306{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001307#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001308 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001309 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001310#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001311 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001312#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001313#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001314 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001315#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001316 struct obj_section *relsec, *symsec, *strsec;
1317 ElfW(RelM) *rel, *relend;
1318 ElfW(Sym) *symtab, *extsym;
1319 const char *strtab, *name;
1320 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001321
Eric Andersen21adca72000-12-06 18:18:26 +00001322 for (i = 0; i < f->header.e_shnum; ++i) {
1323 relsec = f->sections[i];
1324 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001325 continue;
1326
Eric Andersen21adca72000-12-06 18:18:26 +00001327 symsec = f->sections[relsec->header.sh_link];
1328 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001329
Eric Andersen21adca72000-12-06 18:18:26 +00001330 rel = (ElfW(RelM) *) relsec->contents;
1331 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1332 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001333 strtab = (const char *) strsec->contents;
1334
1335 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001336 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001337
Eric Andersencffd5022002-05-24 06:50:15 +00001338#if defined(CONFIG_USE_GOT_ENTRIES)
1339 got_allocate = 0;
1340#endif
1341#if defined(CONFIG_USE_PLT_ENTRIES)
1342 plt_allocate = 0;
1343#endif
1344
Eric Andersen9f16d612000-06-12 23:11:16 +00001345 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001346#if defined(__arm__)
Eric Andersen21adca72000-12-06 18:18:26 +00001347 case R_ARM_PC24:
1348 case R_ARM_PLT32:
Eric Andersencffd5022002-05-24 06:50:15 +00001349 plt_allocate = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001350 break;
1351
Eric Andersen21adca72000-12-06 18:18:26 +00001352 case R_ARM_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001353 case R_ARM_GOTPC:
1354 got_needed = 1;
1355 continue;
1356
1357 case R_ARM_GOT32:
1358 got_allocate = 1;
1359 break;
1360
Eric Andersen21adca72000-12-06 18:18:26 +00001361#elif defined(__i386__)
1362 case R_386_GOTPC:
1363 case R_386_GOTOFF:
Eric Andersencffd5022002-05-24 06:50:15 +00001364 got_needed = 1;
1365 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001366
Eric Andersencffd5022002-05-24 06:50:15 +00001367 case R_386_GOT32:
1368 got_allocate = 1;
1369 break;
1370
1371#elif defined(__powerpc__)
1372 case R_PPC_REL24:
1373 plt_allocate = 1;
1374 break;
1375
1376#elif defined(__mc68000__)
1377 case R_68K_GOT32:
1378 got_allocate = 1;
1379 break;
1380
1381 case R_68K_GOTOFF:
1382 got_needed = 1;
1383 continue;
1384
1385#elif defined(__sh__)
1386 case R_SH_GOT32:
1387 got_allocate = 1;
1388 break;
1389
1390 case R_SH_GOTPC:
1391 case R_SH_GOTOFF:
1392 got_needed = 1;
1393 continue;
1394
1395#elif defined (__v850e__)
1396 case R_V850_22_PCREL:
1397 plt_needed = 1;
1398 break;
1399
1400#endif
Eric Andersen21adca72000-12-06 18:18:26 +00001401 default:
1402 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001403 }
1404
Eric Andersen21adca72000-12-06 18:18:26 +00001405 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001406 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001407 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001408 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001409 }
1410 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001411#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001412 if (got_allocate) {
1413 got_offset += arch_single_init(
1414 rel, &intsym->gotent,
1415 got_offset, CONFIG_GOT_ENTRY_SIZE);
1416
1417 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001418 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001419#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001420#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001421 if (plt_allocate) {
1422#if defined(CONFIG_USE_PLT_LIST)
1423 plt_offset += arch_list_add(
1424 rel, &intsym->pltent,
1425 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1426#else
1427 plt_offset += arch_single_init(
1428 rel, &intsym->pltent,
1429 plt_offset, CONFIG_PLT_ENTRY_SIZE);
1430#endif
1431 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001432 }
1433#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001434 }
Miles Baderae28b042002-04-01 09:34:25 +00001435 }
Eric Andersen21adca72000-12-06 18:18:26 +00001436
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001437#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001438 if (got_needed) {
1439 ifile->got = arch_xsect_init(f, ".got", got_offset,
1440 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001441 }
Eric Andersen21adca72000-12-06 18:18:26 +00001442#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001443
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001444#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001445 if (plt_needed) {
1446 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
1447 CONFIG_PLT_ENTRY_SIZE);
1448 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001449#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001450
1451#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001452}
1453
Eric Andersen6d139642001-12-29 04:15:13 +00001454#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00001455static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001456{
1457 return 1;
1458}
Eric Andersen6d139642001-12-29 04:15:13 +00001459#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001460
1461/*======================================================================*/
1462
1463/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001464static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001465{
1466 unsigned long h = 0;
1467 unsigned long g;
1468 unsigned char ch;
1469
1470 while (n > 0) {
1471 ch = *name++;
1472 h = (h << 4) + ch;
1473 if ((g = (h & 0xf0000000)) != 0) {
1474 h ^= g >> 24;
1475 h &= ~g;
1476 }
1477 n--;
1478 }
1479 return h;
1480}
1481
Eric Andersen044228d2001-07-17 01:12:36 +00001482static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001483{
1484 return obj_elf_hash_n(name, strlen(name));
1485}
1486
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001487#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001488/* String comparison for non-co-versioned kernel and module. */
1489
1490static int ncv_strcmp(const char *a, const char *b)
1491{
1492 size_t alen = strlen(a), blen = strlen(b);
1493
1494 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1495 return strncmp(a, b, alen);
1496 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1497 return strncmp(a, b, blen);
1498 else
1499 return strcmp(a, b);
1500}
1501
1502/* String hashing for non-co-versioned kernel and module. Here
1503 we are simply forced to drop the crc from the hash. */
1504
1505static unsigned long ncv_symbol_hash(const char *str)
1506{
1507 size_t len = strlen(str);
1508 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1509 len -= 10;
1510 return obj_elf_hash_n(str, len);
1511}
1512
Eric Andersen044228d2001-07-17 01:12:36 +00001513static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001514obj_set_symbol_compare(struct obj_file *f,
1515 int (*cmp) (const char *, const char *),
1516 unsigned long (*hash) (const char *))
1517{
1518 if (cmp)
1519 f->symbol_cmp = cmp;
1520 if (hash) {
1521 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1522 int i;
1523
1524 f->symbol_hash = hash;
1525
1526 memcpy(tmptab, f->symtab, sizeof(tmptab));
1527 memset(f->symtab, 0, sizeof(f->symtab));
1528
1529 for (i = 0; i < HASH_BUCKETS; ++i)
1530 for (sym = tmptab[i]; sym; sym = next) {
1531 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1532 next = sym->next;
1533 sym->next = f->symtab[h];
1534 f->symtab[h] = sym;
1535 }
1536 }
1537}
1538
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001539#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001540
Eric Andersen044228d2001-07-17 01:12:36 +00001541static struct obj_symbol *
1542obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001543 unsigned long symidx, int info,
1544 int secidx, ElfW(Addr) value,
1545 unsigned long size)
1546{
1547 struct obj_symbol *sym;
1548 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1549 int n_type = ELFW(ST_TYPE) (info);
1550 int n_binding = ELFW(ST_BIND) (info);
1551
1552 for (sym = f->symtab[hash]; sym; sym = sym->next)
1553 if (f->symbol_cmp(sym->name, name) == 0) {
1554 int o_secidx = sym->secidx;
1555 int o_info = sym->info;
1556 int o_type = ELFW(ST_TYPE) (o_info);
1557 int o_binding = ELFW(ST_BIND) (o_info);
1558
1559 /* A redefinition! Is it legal? */
1560
1561 if (secidx == SHN_UNDEF)
1562 return sym;
1563 else if (o_secidx == SHN_UNDEF)
1564 goto found;
1565 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1566 /* Cope with local and global symbols of the same name
1567 in the same object file, as might have been created
1568 by ld -r. The only reason locals are now seen at this
1569 level at all is so that we can do semi-sensible things
1570 with parameters. */
1571
1572 struct obj_symbol *nsym, **p;
1573
1574 nsym = arch_new_symbol();
1575 nsym->next = sym->next;
1576 nsym->ksymidx = -1;
1577
1578 /* Excise the old (local) symbol from the hash chain. */
1579 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1580 continue;
1581 *p = sym = nsym;
1582 goto found;
1583 } else if (n_binding == STB_LOCAL) {
1584 /* Another symbol of the same name has already been defined.
1585 Just add this to the local table. */
1586 sym = arch_new_symbol();
1587 sym->next = NULL;
1588 sym->ksymidx = -1;
1589 f->local_symtab[symidx] = sym;
1590 goto found;
1591 } else if (n_binding == STB_WEAK)
1592 return sym;
1593 else if (o_binding == STB_WEAK)
1594 goto found;
1595 /* Don't unify COMMON symbols with object types the programmer
1596 doesn't expect. */
1597 else if (secidx == SHN_COMMON
1598 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
1599 return sym;
1600 else if (o_secidx == SHN_COMMON
1601 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
1602 goto found;
1603 else {
1604 /* Don't report an error if the symbol is coming from
1605 the kernel or some external module. */
1606 if (secidx <= SHN_HIRESERVE)
Matt Kraaidd19c692001-01-31 19:00:21 +00001607 error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001608 return sym;
1609 }
1610 }
1611
1612 /* Completely new symbol. */
1613 sym = arch_new_symbol();
1614 sym->next = f->symtab[hash];
1615 f->symtab[hash] = sym;
1616 sym->ksymidx = -1;
1617
Eric Andersen66ca9482001-06-28 21:36:06 +00001618 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1619 if (symidx >= f->local_symtab_size)
1620 error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
1621 name, (long) symidx, (long) f->local_symtab_size);
1622 else
1623 f->local_symtab[symidx] = sym;
1624 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001625
1626 found:
1627 sym->name = name;
1628 sym->value = value;
1629 sym->size = size;
1630 sym->secidx = secidx;
1631 sym->info = info;
1632
1633 return sym;
1634}
1635
Eric Andersen044228d2001-07-17 01:12:36 +00001636static struct obj_symbol *
1637obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001638{
1639 struct obj_symbol *sym;
1640 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1641
1642 for (sym = f->symtab[hash]; sym; sym = sym->next)
1643 if (f->symbol_cmp(sym->name, name) == 0)
1644 return sym;
1645
1646 return NULL;
1647}
1648
Eric Andersen044228d2001-07-17 01:12:36 +00001649static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001650 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1651{
1652 if (sym) {
1653 if (sym->secidx >= SHN_LORESERVE)
1654 return sym->value;
1655
1656 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1657 } else {
1658 /* As a special case, a NULL sym has value zero. */
1659 return 0;
1660 }
1661}
1662
Eric Andersen044228d2001-07-17 01:12:36 +00001663static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001664{
1665 int i, n = f->header.e_shnum;
1666
1667 for (i = 0; i < n; ++i)
1668 if (strcmp(f->sections[i]->name, name) == 0)
1669 return f->sections[i];
1670
1671 return NULL;
1672}
1673
1674static int obj_load_order_prio(struct obj_section *a)
1675{
1676 unsigned long af, ac;
1677
1678 af = a->header.sh_flags;
1679
1680 ac = 0;
1681 if (a->name[0] != '.' || strlen(a->name) != 10 ||
1682 strcmp(a->name + 5, ".init"))
1683 ac |= 32;
1684 if (af & SHF_ALLOC)
1685 ac |= 16;
1686 if (!(af & SHF_WRITE))
1687 ac |= 8;
1688 if (af & SHF_EXECINSTR)
1689 ac |= 4;
1690 if (a->header.sh_type != SHT_NOBITS)
1691 ac |= 2;
1692
1693 return ac;
1694}
1695
Eric Andersen044228d2001-07-17 01:12:36 +00001696static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001697obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1698{
1699 struct obj_section **p;
1700 int prio = obj_load_order_prio(sec);
1701 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1702 if (obj_load_order_prio(*p) < prio)
1703 break;
1704 sec->load_next = *p;
1705 *p = sec;
1706}
1707
Eric Andersen044228d2001-07-17 01:12:36 +00001708static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001709 const char *name,
1710 unsigned long align,
1711 unsigned long size)
1712{
1713 int newidx = f->header.e_shnum++;
1714 struct obj_section *sec;
1715
1716 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1717 f->sections[newidx] = sec = arch_new_section();
1718
1719 memset(sec, 0, sizeof(*sec));
1720 sec->header.sh_type = SHT_PROGBITS;
1721 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1722 sec->header.sh_size = size;
1723 sec->header.sh_addralign = align;
1724 sec->name = name;
1725 sec->idx = newidx;
1726 if (size)
1727 sec->contents = xmalloc(size);
1728
1729 obj_insert_section_load_order(f, sec);
1730
1731 return sec;
1732}
1733
Eric Andersen044228d2001-07-17 01:12:36 +00001734static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001735 const char *name,
1736 unsigned long align,
1737 unsigned long size)
1738{
1739 int newidx = f->header.e_shnum++;
1740 struct obj_section *sec;
1741
1742 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1743 f->sections[newidx] = sec = arch_new_section();
1744
1745 memset(sec, 0, sizeof(*sec));
1746 sec->header.sh_type = SHT_PROGBITS;
1747 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1748 sec->header.sh_size = size;
1749 sec->header.sh_addralign = align;
1750 sec->name = name;
1751 sec->idx = newidx;
1752 if (size)
1753 sec->contents = xmalloc(size);
1754
1755 sec->load_next = f->load_order;
1756 f->load_order = sec;
1757 if (f->load_order_search_start == &f->load_order)
1758 f->load_order_search_start = &sec->load_next;
1759
1760 return sec;
1761}
1762
Eric Andersen044228d2001-07-17 01:12:36 +00001763static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001764{
1765 unsigned long oldsize = sec->header.sh_size;
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001766 if (more) {
1767 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1768 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001769 return sec->contents + oldsize;
1770}
1771
1772
Eric Andersen9f16d612000-06-12 23:11:16 +00001773/* Conditionally add the symbols from the given symbol set to the
1774 new module. */
1775
1776static int
1777add_symbols_from(
1778 struct obj_file *f,
1779 int idx, struct new_module_symbol *syms, size_t nsyms)
1780{
1781 struct new_module_symbol *s;
1782 size_t i;
1783 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001784#ifdef SYMBOL_PREFIX
1785 char *name_buf = 0;
1786 size_t name_alloced_size = 0;
1787#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001788
1789 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001790 /* Only add symbols that are already marked external.
1791 If we override locals we may cause problems for
1792 argument initialization. We will also create a false
1793 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001794 struct obj_symbol *sym;
Miles Baderae28b042002-04-01 09:34:25 +00001795 char *name = (char *)s->name;
Eric Andersen9f16d612000-06-12 23:11:16 +00001796
Miles Baderae28b042002-04-01 09:34:25 +00001797#ifdef SYMBOL_PREFIX
1798 /* Prepend SYMBOL_PREFIX to the symbol's name (the
1799 kernel exports `C names', but module object files
1800 reference `linker names'). */
1801 size_t extra = sizeof SYMBOL_PREFIX;
1802 size_t name_size = strlen (name) + extra;
1803 if (name_size > name_alloced_size) {
1804 name_alloced_size = name_size * 2;
1805 name_buf = alloca (name_alloced_size);
1806 }
1807 strcpy (name_buf, SYMBOL_PREFIX);
1808 strcpy (name_buf + extra - 1, name);
1809 name = name_buf;
1810#endif /* SYMBOL_PREFIX */
1811
1812 sym = obj_find_symbol(f, name);
1813 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
1814#ifdef SYMBOL_PREFIX
1815 /* Put NAME_BUF into more permanent storage. */
1816 name = xmalloc (name_size);
1817 strcpy (name, name_buf);
1818#endif
1819 sym = obj_add_symbol(f, name, -1,
1820 ELFW(ST_INFO) (STB_GLOBAL,
1821 STT_NOTYPE),
1822 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00001823 /* Did our symbol just get installed? If so, mark the
1824 module as "used". */
1825 if (sym->secidx == idx)
1826 used = 1;
1827 }
1828 }
1829
1830 return used;
1831}
1832
1833static void add_kernel_symbols(struct obj_file *f)
1834{
1835 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00001836 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00001837
1838 /* Add module symbols first. */
1839
1840 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
1841 if (m->nsyms
1842 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
1843 m->nsyms)) m->used = 1, ++nused;
1844
1845 n_ext_modules_used = nused;
1846
1847 /* And finally the symbols from the kernel proper. */
1848
1849 if (nksyms)
1850 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
1851}
1852
1853static char *get_modinfo_value(struct obj_file *f, const char *key)
1854{
1855 struct obj_section *sec;
1856 char *p, *v, *n, *ep;
1857 size_t klen = strlen(key);
1858
1859 sec = obj_find_section(f, ".modinfo");
1860 if (sec == NULL)
1861 return NULL;
1862 p = sec->contents;
1863 ep = p + sec->header.sh_size;
1864 while (p < ep) {
1865 v = strchr(p, '=');
1866 n = strchr(p, '\0');
1867 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001868 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001869 return v + 1;
1870 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00001871 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00001872 return n;
1873 }
1874 p = n + 1;
1875 }
1876
1877 return NULL;
1878}
1879
1880
1881/*======================================================================*/
1882/* Functions relating to module loading in pre 2.1 kernels. */
1883
1884static int
1885old_process_module_arguments(struct obj_file *f, int argc, char **argv)
1886{
1887 while (argc > 0) {
1888 char *p, *q;
1889 struct obj_symbol *sym;
1890 int *loc;
1891
1892 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00001893 if ((q = strchr(p, '=')) == NULL) {
1894 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00001895 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00001896 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001897 *q++ = '\0';
1898
1899 sym = obj_find_symbol(f, p);
1900
1901 /* Also check that the parameter was not resolved from the kernel. */
1902 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00001903 error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001904 return 0;
1905 }
1906
1907 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
1908
1909 /* Do C quoting if we begin with a ". */
1910 if (*q == '"') {
1911 char *r, *str;
1912
1913 str = alloca(strlen(q));
1914 for (r = str, q++; *q != '"'; ++q, ++r) {
1915 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00001916 error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00001917 return 0;
1918 } else if (*q == '\\')
1919 switch (*++q) {
1920 case 'a':
1921 *r = '\a';
1922 break;
1923 case 'b':
1924 *r = '\b';
1925 break;
1926 case 'e':
1927 *r = '\033';
1928 break;
1929 case 'f':
1930 *r = '\f';
1931 break;
1932 case 'n':
1933 *r = '\n';
1934 break;
1935 case 'r':
1936 *r = '\r';
1937 break;
1938 case 't':
1939 *r = '\t';
1940 break;
1941
1942 case '0':
1943 case '1':
1944 case '2':
1945 case '3':
1946 case '4':
1947 case '5':
1948 case '6':
1949 case '7':
1950 {
1951 int c = *q - '0';
1952 if (q[1] >= '0' && q[1] <= '7') {
1953 c = (c * 8) + *++q - '0';
1954 if (q[1] >= '0' && q[1] <= '7')
1955 c = (c * 8) + *++q - '0';
1956 }
1957 *r = c;
1958 }
1959 break;
1960
1961 default:
1962 *r = *q;
1963 break;
1964 } else
1965 *r = *q;
1966 }
1967 *r = '\0';
1968 obj_string_patch(f, sym->secidx, sym->value, str);
1969 } else if (*q >= '0' && *q <= '9') {
1970 do
1971 *loc++ = strtoul(q, &q, 0);
1972 while (*q++ == ',');
1973 } else {
1974 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00001975 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00001976 char *r; /* To search for commas */
1977
1978 /* Break the string with comas */
1979 while ((r = strchr(q, ',')) != (char *) NULL) {
1980 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00001981 obj_string_patch(f, sym->secidx, myloc - contents, q);
1982 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00001983 q = r;
1984 }
1985
1986 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00001987 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00001988 }
1989
1990 argc--, argv++;
1991 }
1992
1993 return 1;
1994}
1995
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001996#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001997static int old_is_module_checksummed(struct obj_file *f)
1998{
1999 return obj_find_symbol(f, "Using_Versions") != NULL;
2000}
2001/* Get the module's kernel version in the canonical integer form. */
2002
2003static int
2004old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2005{
2006 struct obj_symbol *sym;
2007 char *p, *q;
2008 int a, b, c;
2009
2010 sym = obj_find_symbol(f, "kernel_version");
2011 if (sym == NULL)
2012 return -1;
2013
2014 p = f->sections[sym->secidx]->contents + sym->value;
Eric Andersen2d342152002-06-18 05:16:25 +00002015 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002016
2017 a = strtoul(p, &p, 10);
2018 if (*p != '.')
2019 return -1;
2020 b = strtoul(p + 1, &p, 10);
2021 if (*p != '.')
2022 return -1;
2023 c = strtoul(p + 1, &q, 10);
2024 if (p + 1 == q)
2025 return -1;
2026
2027 return a << 16 | b << 8 | c;
2028}
2029
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002030#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002031
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002032#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002033
2034/* Fetch all the symbols and divvy them up as appropriate for the modules. */
2035
Eric Andersen8c185f92000-09-22 00:38:07 +00002036static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002037{
2038 struct old_kernel_sym *ks, *k;
2039 struct new_module_symbol *s;
2040 struct external_module *mod;
2041 int nks, nms, nmod, i;
2042
2043 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00002044 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002045 if (nks)
2046 perror_msg("get_kernel_syms: %s", m_name);
2047 else
2048 error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00002049 return 0;
2050 }
2051
2052 ks = k = xmalloc(nks * sizeof(*ks));
2053
2054 if (get_kernel_syms(ks) != nks) {
2055 perror("inconsistency with get_kernel_syms -- is someone else "
2056 "playing with modules?");
2057 free(ks);
2058 return 0;
2059 }
2060
2061 /* Collect the module information. */
2062
2063 mod = NULL;
2064 nmod = -1;
2065
2066 while (k->name[0] == '#' && k->name[1]) {
2067 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00002068
2069 /* Find out how many symbols this module has. */
2070 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
2071 continue;
2072 nms = k2 - k - 1;
2073
2074 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
2075 mod[nmod].name = k->name + 1;
2076 mod[nmod].addr = k->value;
2077 mod[nmod].used = 0;
2078 mod[nmod].nsyms = nms;
2079 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2080
2081 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
2082 s->name = (unsigned long) k->name;
2083 s->value = k->value;
2084 }
2085
2086 k = k2;
2087 }
2088
2089 ext_modules = mod;
2090 n_ext_modules = nmod + 1;
2091
2092 /* Now collect the symbols for the kernel proper. */
2093
2094 if (k->name[0] == '#')
2095 ++k;
2096
2097 nksyms = nms = nks - (k - ks);
2098 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2099
2100 for (i = 0; i < nms; ++i, ++s, ++k) {
2101 s->name = (unsigned long) k->name;
2102 s->value = k->value;
2103 }
2104
2105 return 1;
2106}
2107
2108/* Return the kernel symbol checksum version, or zero if not used. */
2109
2110static int old_is_kernel_checksummed(void)
2111{
2112 /* Using_Versions is the first symbol. */
2113 if (nksyms > 0
2114 && strcmp((char *) ksyms[0].name,
2115 "Using_Versions") == 0) return ksyms[0].value;
2116 else
2117 return 0;
2118}
2119
2120
2121static int old_create_mod_use_count(struct obj_file *f)
2122{
2123 struct obj_section *sec;
2124
2125 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
2126 sizeof(long));
2127
2128 obj_add_symbol(f, "mod_use_count_", -1,
2129 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2130 sizeof(long));
2131
2132 return 1;
2133}
2134
2135static int
2136old_init_module(const char *m_name, struct obj_file *f,
2137 unsigned long m_size)
2138{
2139 char *image;
2140 struct old_mod_routines routines;
2141 struct old_symbol_table *symtab;
2142 int ret;
2143
2144 /* Create the symbol table */
2145 {
2146 int nsyms = 0, strsize = 0, total;
2147
2148 /* Size things first... */
2149 if (flag_export) {
2150 int i;
2151 for (i = 0; i < HASH_BUCKETS; ++i) {
2152 struct obj_symbol *sym;
2153 for (sym = f->symtab[i]; sym; sym = sym->next)
2154 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2155 && sym->secidx <= SHN_HIRESERVE)
2156 {
2157 sym->ksymidx = nsyms++;
2158 strsize += strlen(sym->name) + 1;
2159 }
2160 }
2161 }
2162
2163 total = (sizeof(struct old_symbol_table)
2164 + nsyms * sizeof(struct old_module_symbol)
2165 + n_ext_modules_used * sizeof(struct old_module_ref)
2166 + strsize);
2167 symtab = xmalloc(total);
2168 symtab->size = total;
2169 symtab->n_symbols = nsyms;
2170 symtab->n_refs = n_ext_modules_used;
2171
2172 if (flag_export && nsyms) {
2173 struct old_module_symbol *ksym;
2174 char *str;
2175 int i;
2176
2177 ksym = symtab->symbol;
2178 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
2179 + n_ext_modules_used * sizeof(struct old_module_ref));
2180
2181 for (i = 0; i < HASH_BUCKETS; ++i) {
2182 struct obj_symbol *sym;
2183 for (sym = f->symtab[i]; sym; sym = sym->next)
2184 if (sym->ksymidx >= 0) {
2185 ksym->addr = obj_symbol_final_value(f, sym);
2186 ksym->name =
2187 (unsigned long) str - (unsigned long) symtab;
2188
Matt Kraai70a78552001-01-04 02:00:17 +00002189 strcpy(str, sym->name);
2190 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002191 ksym++;
2192 }
2193 }
2194 }
2195
2196 if (n_ext_modules_used) {
2197 struct old_module_ref *ref;
2198 int i;
2199
2200 ref = (struct old_module_ref *)
2201 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2202
2203 for (i = 0; i < n_ext_modules; ++i)
2204 if (ext_modules[i].used)
2205 ref++->module = ext_modules[i].addr;
2206 }
2207 }
2208
2209 /* Fill in routines. */
2210
2211 routines.init =
Miles Baderae28b042002-04-01 09:34:25 +00002212 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002213 routines.cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002214 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002215
2216 /* Whew! All of the initialization is complete. Collect the final
2217 module image and give it to the kernel. */
2218
2219 image = xmalloc(m_size);
2220 obj_create_image(f, image);
2221
2222 /* image holds the complete relocated module, accounting correctly for
2223 mod_use_count. However the old module kernel support assume that
2224 it is receiving something which does not contain mod_use_count. */
2225 ret = old_sys_init_module(m_name, image + sizeof(long),
2226 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2227 : 0), &routines, symtab);
2228 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002229 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002230
2231 free(image);
2232 free(symtab);
2233
2234 return ret == 0;
2235}
2236
2237#else
2238
2239#define old_create_mod_use_count(x) TRUE
2240#define old_init_module(x, y, z) TRUE
2241
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002242#endif /* CONFIG_FEATURE_OLD_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002243
2244
2245
2246/*======================================================================*/
2247/* Functions relating to module loading after 2.1.18. */
2248
2249static int
2250new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2251{
2252 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002253 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002254 struct obj_symbol *sym;
2255 char *contents, *loc;
2256 int min, max, n;
2257
2258 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002259 if ((q = strchr(p, '=')) == NULL) {
2260 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002261 continue;
Eric Andersenef40aa82000-06-26 11:16:22 +00002262 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002263
2264 key = alloca(q - p + 6);
2265 memcpy(key, "parm_", 5);
2266 memcpy(key + 5, p, q - p);
2267 key[q - p + 5] = 0;
2268
2269 p = get_modinfo_value(f, key);
2270 key += 5;
2271 if (p == NULL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002272 error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002273 return 0;
2274 }
2275
Miles Baderae28b042002-04-01 09:34:25 +00002276#ifdef SYMBOL_PREFIX
2277 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2278 strcpy (sym_name, SYMBOL_PREFIX);
2279 strcat (sym_name, key);
2280#else
2281 sym_name = key;
2282#endif
2283 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002284
2285 /* Also check that the parameter was not resolved from the kernel. */
2286 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002287 error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002288 return 0;
2289 }
2290
2291 if (isdigit(*p)) {
2292 min = strtoul(p, &p, 10);
2293 if (*p == '-')
2294 max = strtoul(p + 1, &p, 10);
2295 else
2296 max = min;
2297 } else
2298 min = max = 1;
2299
2300 contents = f->sections[sym->secidx]->contents;
2301 loc = contents + sym->value;
2302 n = (*++q != '\0');
2303
2304 while (1) {
2305 if ((*p == 's') || (*p == 'c')) {
2306 char *str;
2307
2308 /* Do C quoting if we begin with a ", else slurp the lot. */
2309 if (*q == '"') {
2310 char *r;
2311
2312 str = alloca(strlen(q));
2313 for (r = str, q++; *q != '"'; ++q, ++r) {
2314 if (*q == '\0') {
Matt Kraaidd19c692001-01-31 19:00:21 +00002315 error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002316 key);
2317 return 0;
2318 } else if (*q == '\\')
2319 switch (*++q) {
2320 case 'a':
2321 *r = '\a';
2322 break;
2323 case 'b':
2324 *r = '\b';
2325 break;
2326 case 'e':
2327 *r = '\033';
2328 break;
2329 case 'f':
2330 *r = '\f';
2331 break;
2332 case 'n':
2333 *r = '\n';
2334 break;
2335 case 'r':
2336 *r = '\r';
2337 break;
2338 case 't':
2339 *r = '\t';
2340 break;
2341
2342 case '0':
2343 case '1':
2344 case '2':
2345 case '3':
2346 case '4':
2347 case '5':
2348 case '6':
2349 case '7':
2350 {
2351 int c = *q - '0';
2352 if (q[1] >= '0' && q[1] <= '7') {
2353 c = (c * 8) + *++q - '0';
2354 if (q[1] >= '0' && q[1] <= '7')
2355 c = (c * 8) + *++q - '0';
2356 }
2357 *r = c;
2358 }
2359 break;
2360
2361 default:
2362 *r = *q;
2363 break;
2364 } else
2365 *r = *q;
2366 }
2367 *r = '\0';
2368 ++q;
2369 } else {
2370 char *r;
2371
2372 /* In this case, the string is not quoted. We will break
2373 it using the coma (like for ints). If the user wants to
2374 include comas in a string, he just has to quote it */
2375
2376 /* Search the next coma */
2377 r = strchr(q, ',');
2378
2379 /* Found ? */
2380 if (r != (char *) NULL) {
2381 /* Recopy the current field */
2382 str = alloca(r - q + 1);
2383 memcpy(str, q, r - q);
2384
2385 /* I don't know if it is usefull, as the previous case
2386 doesn't null terminate the string ??? */
2387 str[r - q] = '\0';
2388
2389 /* Keep next fields */
2390 q = r;
2391 } else {
2392 /* last string */
2393 str = q;
2394 q = "";
2395 }
2396 }
2397
2398 if (*p == 's') {
2399 /* Normal string */
2400 obj_string_patch(f, sym->secidx, loc - contents, str);
2401 loc += tgt_sizeof_char_p;
2402 } else {
2403 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002404 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002405
2406 /* Get the size of each member */
2407 /* Probably we should do that outside the loop ? */
2408 if (!isdigit(*(p + 1))) {
Mark Whitleyf57c9442000-12-07 19:56:48 +00002409 error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002410 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002411 return 0;
2412 }
2413 charssize = strtoul(p + 1, (char **) NULL, 10);
2414
2415 /* Check length */
2416 if (strlen(str) >= charssize) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002417 error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002418 charssize - 1);
2419 return 0;
2420 }
2421
2422 /* Copy to location */
2423 strcpy((char *) loc, str);
2424 loc += charssize;
2425 }
2426 } else {
2427 long v = strtoul(q, &q, 0);
2428 switch (*p) {
2429 case 'b':
2430 *loc++ = v;
2431 break;
2432 case 'h':
2433 *(short *) loc = v;
2434 loc += tgt_sizeof_short;
2435 break;
2436 case 'i':
2437 *(int *) loc = v;
2438 loc += tgt_sizeof_int;
2439 break;
2440 case 'l':
2441 *(long *) loc = v;
2442 loc += tgt_sizeof_long;
2443 break;
2444
2445 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002446 error_msg("unknown parameter type '%c' for %s", *p, key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002447 return 0;
2448 }
2449 }
2450
2451 retry_end_of_value:
2452 switch (*q) {
2453 case '\0':
2454 goto end_of_arg;
2455
2456 case ' ':
2457 case '\t':
2458 case '\n':
2459 case '\r':
2460 ++q;
2461 goto retry_end_of_value;
2462
2463 case ',':
2464 if (++n > max) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002465 error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002466 return 0;
2467 }
2468 ++q;
2469 break;
2470
2471 default:
Matt Kraaidd19c692001-01-31 19:00:21 +00002472 error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002473 return 0;
2474 }
2475 }
2476
2477 end_of_arg:
2478 if (n < min) {
Matt Kraaidd19c692001-01-31 19:00:21 +00002479 error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002480 return 0;
2481 }
2482
2483 argc--, argv++;
2484 }
2485
2486 return 1;
2487}
2488
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002489#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002490static int new_is_module_checksummed(struct obj_file *f)
2491{
2492 const char *p = get_modinfo_value(f, "using_checksums");
2493 if (p)
2494 return atoi(p);
2495 else
2496 return 0;
2497}
2498
2499/* Get the module's kernel version in the canonical integer form. */
2500
2501static int
2502new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2503{
2504 char *p, *q;
2505 int a, b, c;
2506
2507 p = get_modinfo_value(f, "kernel_version");
2508 if (p == NULL)
2509 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002510 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002511
2512 a = strtoul(p, &p, 10);
2513 if (*p != '.')
2514 return -1;
2515 b = strtoul(p + 1, &p, 10);
2516 if (*p != '.')
2517 return -1;
2518 c = strtoul(p + 1, &q, 10);
2519 if (p + 1 == q)
2520 return -1;
2521
2522 return a << 16 | b << 8 | c;
2523}
2524
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002525#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002526
2527
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002528#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00002529
2530/* Fetch the loaded modules, and all currently exported symbols. */
2531
2532static int new_get_kernel_symbols(void)
2533{
2534 char *module_names, *mn;
2535 struct external_module *modules, *m;
2536 struct new_module_symbol *syms, *s;
2537 size_t ret, bufsize, nmod, nsyms, i, j;
2538
2539 /* Collect the loaded modules. */
2540
2541 module_names = xmalloc(bufsize = 256);
2542 retry_modules_load:
2543 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002544 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002545 module_names = xrealloc(module_names, bufsize = ret);
2546 goto retry_modules_load;
2547 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002548 perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002549 return 0;
2550 }
2551
2552 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002553
2554 /* Collect the modules' symbols. */
2555
Mark Whitley94fd4802001-03-12 23:08:34 +00002556 if (nmod){
2557 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2558 memset(modules, 0, nmod * sizeof(*modules));
2559 for (i = 0, mn = module_names, m = modules;
2560 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
2561 struct new_module_info info;
2562
2563 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2564 if (errno == ENOENT) {
2565 /* The module was removed out from underneath us. */
2566 continue;
2567 }
2568 perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002569 return 0;
2570 }
Mark Whitley94fd4802001-03-12 23:08:34 +00002571
2572 syms = xmalloc(bufsize = 1024);
2573 retry_mod_sym_load:
2574 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2575 switch (errno) {
2576 case ENOSPC:
2577 syms = xrealloc(syms, bufsize = ret);
2578 goto retry_mod_sym_load;
2579 case ENOENT:
2580 /* The module was removed out from underneath us. */
2581 continue;
2582 default:
2583 perror_msg("query_module: QM_SYMBOLS: %s", mn);
2584 return 0;
2585 }
2586 }
2587 nsyms = ret;
2588
2589 m->name = mn;
2590 m->addr = info.addr;
2591 m->nsyms = nsyms;
2592 m->syms = syms;
2593
2594 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2595 s->name += (unsigned long) syms;
2596 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002597 }
2598 }
2599
2600 /* Collect the kernel's symbols. */
2601
2602 syms = xmalloc(bufsize = 16 * 1024);
2603 retry_kern_sym_load:
2604 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002605 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002606 syms = xrealloc(syms, bufsize = ret);
2607 goto retry_kern_sym_load;
2608 }
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002609 perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002610 return 0;
2611 }
2612 nksyms = nsyms = ret;
2613 ksyms = syms;
2614
2615 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2616 s->name += (unsigned long) syms;
2617 }
2618 return 1;
2619}
2620
2621
2622/* Return the kernel symbol checksum version, or zero if not used. */
2623
2624static int new_is_kernel_checksummed(void)
2625{
2626 struct new_module_symbol *s;
2627 size_t i;
2628
2629 /* Using_Versions is not the first symbol, but it should be in there. */
2630
2631 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2632 if (strcmp((char *) s->name, "Using_Versions") == 0)
2633 return s->value;
2634
2635 return 0;
2636}
2637
2638
2639static int new_create_this_module(struct obj_file *f, const char *m_name)
2640{
2641 struct obj_section *sec;
2642
2643 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
2644 sizeof(struct new_module));
2645 memset(sec->contents, 0, sizeof(struct new_module));
2646
Miles Baderae28b042002-04-01 09:34:25 +00002647 obj_add_symbol(f, SPFX "__this_module", -1,
2648 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2649 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002650
2651 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
2652 m_name);
2653
2654 return 1;
2655}
2656
2657
2658static int new_create_module_ksymtab(struct obj_file *f)
2659{
2660 struct obj_section *sec;
2661 int i;
2662
2663 /* We must always add the module references. */
2664
2665 if (n_ext_modules_used) {
2666 struct new_module_ref *dep;
2667 struct obj_symbol *tm;
2668
2669 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
2670 (sizeof(struct new_module_ref)
2671 * n_ext_modules_used));
2672 if (!sec)
2673 return 0;
2674
Miles Baderae28b042002-04-01 09:34:25 +00002675 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002676 dep = (struct new_module_ref *) sec->contents;
2677 for (i = 0; i < n_ext_modules; ++i)
2678 if (ext_modules[i].used) {
2679 dep->dep = ext_modules[i].addr;
2680 obj_symbol_patch(f, sec->idx,
2681 (char *) &dep->ref - sec->contents, tm);
2682 dep->next_ref = 0;
2683 ++dep;
2684 }
2685 }
2686
2687 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2688 size_t nsyms;
2689 int *loaded;
2690
2691 sec =
2692 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
2693 0);
2694
2695 /* We don't want to export symbols residing in sections that
2696 aren't loaded. There are a number of these created so that
2697 we make sure certain module options don't appear twice. */
2698
2699 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2700 while (--i >= 0)
2701 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2702
2703 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2704 struct obj_symbol *sym;
2705 for (sym = f->symtab[i]; sym; sym = sym->next)
2706 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
2707 && sym->secidx <= SHN_HIRESERVE
2708 && (sym->secidx >= SHN_LORESERVE
2709 || loaded[sym->secidx])) {
2710 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2711
2712 obj_symbol_patch(f, sec->idx, ofs, sym);
2713 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
2714 sym->name);
2715
2716 nsyms++;
2717 }
2718 }
2719
2720 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2721 }
2722
2723 return 1;
2724}
2725
2726
2727static int
2728new_init_module(const char *m_name, struct obj_file *f,
2729 unsigned long m_size)
2730{
2731 struct new_module *module;
2732 struct obj_section *sec;
2733 void *image;
2734 int ret;
2735 tgt_long m_addr;
2736
2737 sec = obj_find_section(f, ".this");
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002738 if (!sec || !sec->contents) {
2739 perror_msg_and_die("corrupt module %s?",m_name);
2740 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002741 module = (struct new_module *) sec->contents;
2742 m_addr = sec->header.sh_addr;
2743
2744 module->size_of_struct = sizeof(*module);
2745 module->size = m_size;
2746 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2747
2748 sec = obj_find_section(f, "__ksymtab");
2749 if (sec && sec->header.sh_size) {
2750 module->syms = sec->header.sh_addr;
2751 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2752 }
2753
2754 if (n_ext_modules_used) {
2755 sec = obj_find_section(f, ".kmodtab");
2756 module->deps = sec->header.sh_addr;
2757 module->ndeps = n_ext_modules_used;
2758 }
2759
2760 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002761 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002762 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002763 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002764
2765 sec = obj_find_section(f, "__ex_table");
2766 if (sec) {
2767 module->ex_table_start = sec->header.sh_addr;
2768 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2769 }
2770
2771 sec = obj_find_section(f, ".text.init");
2772 if (sec) {
2773 module->runsize = sec->header.sh_addr - m_addr;
2774 }
2775 sec = obj_find_section(f, ".data.init");
2776 if (sec) {
2777 if (!module->runsize ||
2778 module->runsize > sec->header.sh_addr - m_addr)
2779 module->runsize = sec->header.sh_addr - m_addr;
2780 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002781 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2782 if (sec && sec->header.sh_size) {
2783 module->archdata_start = (void*)sec->header.sh_addr;
2784 module->archdata_end = module->archdata_start + sec->header.sh_size;
2785 }
2786 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2787 if (sec && sec->header.sh_size) {
2788 module->kallsyms_start = (void*)sec->header.sh_addr;
2789 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2790 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002791
2792 if (!arch_init_module(f, module))
2793 return 0;
2794
2795 /* Whew! All of the initialization is complete. Collect the final
2796 module image and give it to the kernel. */
2797
2798 image = xmalloc(m_size);
2799 obj_create_image(f, image);
2800
Eric Andersen64c8b172001-04-05 07:33:10 +00002801 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002802 if (ret)
Matt Kraai1fa1ade2000-12-18 03:57:16 +00002803 perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002804
2805 free(image);
2806
2807 return ret == 0;
2808}
2809
2810#else
2811
2812#define new_init_module(x, y, z) TRUE
2813#define new_create_this_module(x, y) 0
2814#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00002815#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00002816
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002817#endif /* CONFIG_FEATURE_NEW_MODULE_INTERFACE */
Eric Andersen9f16d612000-06-12 23:11:16 +00002818
2819
2820/*======================================================================*/
2821
Eric Andersen044228d2001-07-17 01:12:36 +00002822static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002823obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2824 const char *string)
2825{
2826 struct obj_string_patch *p;
2827 struct obj_section *strsec;
2828 size_t len = strlen(string) + 1;
2829 char *loc;
2830
2831 p = xmalloc(sizeof(*p));
2832 p->next = f->string_patches;
2833 p->reloc_secidx = secidx;
2834 p->reloc_offset = offset;
2835 f->string_patches = p;
2836
2837 strsec = obj_find_section(f, ".kstrtab");
2838 if (strsec == NULL) {
2839 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2840 p->string_offset = 0;
2841 loc = strsec->contents;
2842 } else {
2843 p->string_offset = strsec->header.sh_size;
2844 loc = obj_extend_section(strsec, len);
2845 }
2846 memcpy(loc, string, len);
2847
2848 return 1;
2849}
2850
Eric Andersen6d139642001-12-29 04:15:13 +00002851#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen044228d2001-07-17 01:12:36 +00002852static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002853obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2854 struct obj_symbol *sym)
2855{
2856 struct obj_symbol_patch *p;
2857
2858 p = xmalloc(sizeof(*p));
2859 p->next = f->symbol_patches;
2860 p->reloc_secidx = secidx;
2861 p->reloc_offset = offset;
2862 p->sym = sym;
2863 f->symbol_patches = p;
2864
2865 return 1;
2866}
Eric Andersen6d139642001-12-29 04:15:13 +00002867#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002868
Eric Andersen044228d2001-07-17 01:12:36 +00002869static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002870{
2871 unsigned long i;
2872 int ret = 1;
2873
2874 for (i = 0; i < HASH_BUCKETS; ++i) {
2875 struct obj_symbol *sym;
2876 for (sym = f->symtab[i]; sym; sym = sym->next)
2877 if (sym->secidx == SHN_UNDEF) {
2878 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
2879 sym->secidx = SHN_ABS;
2880 sym->value = 0;
2881 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00002882 if (!flag_quiet) {
2883 error_msg("unresolved symbol %s", sym->name);
2884 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002885 ret = 0;
2886 }
2887 }
2888 }
2889
2890 return ret;
2891}
2892
Eric Andersen044228d2001-07-17 01:12:36 +00002893static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002894{
2895 struct common_entry {
2896 struct common_entry *next;
2897 struct obj_symbol *sym;
2898 } *common_head = NULL;
2899
2900 unsigned long i;
2901
2902 for (i = 0; i < HASH_BUCKETS; ++i) {
2903 struct obj_symbol *sym;
2904 for (sym = f->symtab[i]; sym; sym = sym->next)
2905 if (sym->secidx == SHN_COMMON) {
2906 /* Collect all COMMON symbols and sort them by size so as to
2907 minimize space wasted by alignment requirements. */
2908 {
2909 struct common_entry **p, *n;
2910 for (p = &common_head; *p; p = &(*p)->next)
2911 if (sym->size <= (*p)->sym->size)
2912 break;
2913
2914 n = alloca(sizeof(*n));
2915 n->next = *p;
2916 n->sym = sym;
2917 *p = n;
2918 }
2919 }
2920 }
2921
2922 for (i = 1; i < f->local_symtab_size; ++i) {
2923 struct obj_symbol *sym = f->local_symtab[i];
2924 if (sym && sym->secidx == SHN_COMMON) {
2925 struct common_entry **p, *n;
2926 for (p = &common_head; *p; p = &(*p)->next)
2927 if (sym == (*p)->sym)
2928 break;
2929 else if (sym->size < (*p)->sym->size) {
2930 n = alloca(sizeof(*n));
2931 n->next = *p;
2932 n->sym = sym;
2933 *p = n;
2934 break;
2935 }
2936 }
2937 }
2938
2939 if (common_head) {
2940 /* Find the bss section. */
2941 for (i = 0; i < f->header.e_shnum; ++i)
2942 if (f->sections[i]->header.sh_type == SHT_NOBITS)
2943 break;
2944
2945 /* If for some reason there hadn't been one, create one. */
2946 if (i == f->header.e_shnum) {
2947 struct obj_section *sec;
2948
2949 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
2950 f->sections[i] = sec = arch_new_section();
2951 f->header.e_shnum = i + 1;
2952
2953 memset(sec, 0, sizeof(*sec));
2954 sec->header.sh_type = SHT_PROGBITS;
2955 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2956 sec->name = ".bss";
2957 sec->idx = i;
2958 }
2959
2960 /* Allocate the COMMONS. */
2961 {
2962 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
2963 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
2964 struct common_entry *c;
2965
2966 for (c = common_head; c; c = c->next) {
2967 ElfW(Addr) align = c->sym->value;
2968
2969 if (align > max_align)
2970 max_align = align;
2971 if (bss_size & (align - 1))
2972 bss_size = (bss_size | (align - 1)) + 1;
2973
2974 c->sym->secidx = i;
2975 c->sym->value = bss_size;
2976
2977 bss_size += c->sym->size;
2978 }
2979
2980 f->sections[i]->header.sh_size = bss_size;
2981 f->sections[i]->header.sh_addralign = max_align;
2982 }
2983 }
2984
2985 /* For the sake of patch relocation and parameter initialization,
2986 allocate zeroed data for NOBITS sections now. Note that after
2987 this we cannot assume NOBITS are really empty. */
2988 for (i = 0; i < f->header.e_shnum; ++i) {
2989 struct obj_section *s = f->sections[i];
2990 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00002991 if (s->header.sh_size != 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002992 s->contents = memset(xmalloc(s->header.sh_size),
2993 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00002994 else
2995 s->contents = NULL;
2996
Eric Andersen9f16d612000-06-12 23:11:16 +00002997 s->header.sh_type = SHT_PROGBITS;
2998 }
2999 }
3000}
3001
Eric Andersen044228d2001-07-17 01:12:36 +00003002static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003003{
3004 unsigned long dot = 0;
3005 struct obj_section *sec;
3006
3007 /* Finalize the positions of the sections relative to one another. */
3008
3009 for (sec = f->load_order; sec; sec = sec->load_next) {
3010 ElfW(Addr) align;
3011
3012 align = sec->header.sh_addralign;
3013 if (align && (dot & (align - 1)))
3014 dot = (dot | (align - 1)) + 1;
3015
3016 sec->header.sh_addr = dot;
3017 dot += sec->header.sh_size;
3018 }
3019
3020 return dot;
3021}
3022
Eric Andersen044228d2001-07-17 01:12:36 +00003023static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003024{
3025 int i, n = f->header.e_shnum;
3026 int ret = 1;
3027
3028 /* Finalize the addresses of the sections. */
3029
3030 f->baseaddr = base;
3031 for (i = 0; i < n; ++i)
3032 f->sections[i]->header.sh_addr += base;
3033
3034 /* And iterate over all of the relocations. */
3035
3036 for (i = 0; i < n; ++i) {
3037 struct obj_section *relsec, *symsec, *targsec, *strsec;
3038 ElfW(RelM) * rel, *relend;
3039 ElfW(Sym) * symtab;
3040 const char *strtab;
3041
3042 relsec = f->sections[i];
3043 if (relsec->header.sh_type != SHT_RELM)
3044 continue;
3045
3046 symsec = f->sections[relsec->header.sh_link];
3047 targsec = f->sections[relsec->header.sh_info];
3048 strsec = f->sections[symsec->header.sh_link];
3049
3050 rel = (ElfW(RelM) *) relsec->contents;
3051 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3052 symtab = (ElfW(Sym) *) symsec->contents;
3053 strtab = (const char *) strsec->contents;
3054
3055 for (; rel < relend; ++rel) {
3056 ElfW(Addr) value = 0;
3057 struct obj_symbol *intsym = NULL;
3058 unsigned long symndx;
3059 ElfW(Sym) * extsym = 0;
3060 const char *errmsg;
3061
3062 /* Attempt to find a value to use for this relocation. */
3063
3064 symndx = ELFW(R_SYM) (rel->r_info);
3065 if (symndx) {
3066 /* Note we've already checked for undefined symbols. */
3067
3068 extsym = &symtab[symndx];
3069 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3070 /* Local symbols we look up in the local table to be sure
3071 we get the one that is really intended. */
3072 intsym = f->local_symtab[symndx];
3073 } else {
3074 /* Others we look up in the hash table. */
3075 const char *name;
3076 if (extsym->st_name)
3077 name = strtab + extsym->st_name;
3078 else
3079 name = f->sections[extsym->st_shndx]->name;
3080 intsym = obj_find_symbol(f, name);
3081 }
3082
3083 value = obj_symbol_final_value(f, intsym);
3084 intsym->referenced = 1;
3085 }
3086#if SHT_RELM == SHT_RELA
3087#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3088 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3089 if (!extsym || !extsym->st_name ||
3090 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
3091#endif
3092 value += rel->r_addend;
3093#endif
3094
3095 /* Do it! */
3096 switch (arch_apply_relocation
3097 (f, targsec, symsec, intsym, rel, value)) {
3098 case obj_reloc_ok:
3099 break;
3100
3101 case obj_reloc_overflow:
3102 errmsg = "Relocation overflow";
3103 goto bad_reloc;
3104 case obj_reloc_dangerous:
3105 errmsg = "Dangerous relocation";
3106 goto bad_reloc;
3107 case obj_reloc_unhandled:
3108 errmsg = "Unhandled relocation";
3109 bad_reloc:
3110 if (extsym) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003111 error_msg("%s of type %ld for %s", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003112 (long) ELFW(R_TYPE) (rel->r_info),
3113 strtab + extsym->st_name);
3114 } else {
Matt Kraaidd19c692001-01-31 19:00:21 +00003115 error_msg("%s of type %ld", errmsg,
Eric Andersen9f16d612000-06-12 23:11:16 +00003116 (long) ELFW(R_TYPE) (rel->r_info));
3117 }
3118 ret = 0;
3119 break;
3120 }
3121 }
3122 }
3123
3124 /* Finally, take care of the patches. */
3125
3126 if (f->string_patches) {
3127 struct obj_string_patch *p;
3128 struct obj_section *strsec;
3129 ElfW(Addr) strsec_base;
3130 strsec = obj_find_section(f, ".kstrtab");
3131 strsec_base = strsec->header.sh_addr;
3132
3133 for (p = f->string_patches; p; p = p->next) {
3134 struct obj_section *targsec = f->sections[p->reloc_secidx];
3135 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3136 = strsec_base + p->string_offset;
3137 }
3138 }
3139
3140 if (f->symbol_patches) {
3141 struct obj_symbol_patch *p;
3142
3143 for (p = f->symbol_patches; p; p = p->next) {
3144 struct obj_section *targsec = f->sections[p->reloc_secidx];
3145 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3146 = obj_symbol_final_value(f, p->sym);
3147 }
3148 }
3149
3150 return ret;
3151}
3152
Eric Andersen044228d2001-07-17 01:12:36 +00003153static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003154{
3155 struct obj_section *sec;
3156 ElfW(Addr) base = f->baseaddr;
3157
3158 for (sec = f->load_order; sec; sec = sec->load_next) {
3159 char *secimg;
3160
Eric Andersen2bf658d2001-02-24 20:01:53 +00003161 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003162 continue;
3163
3164 secimg = image + (sec->header.sh_addr - base);
3165
3166 /* Note that we allocated data for NOBITS sections earlier. */
3167 memcpy(secimg, sec->contents, sec->header.sh_size);
3168 }
3169
3170 return 1;
3171}
3172
3173/*======================================================================*/
3174
Eric Andersen044228d2001-07-17 01:12:36 +00003175static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003176{
3177 struct obj_file *f;
3178 ElfW(Shdr) * section_headers;
3179 int shnum, i;
3180 char *shstrtab;
3181
3182 /* Read the file header. */
3183
3184 f = arch_new_file();
3185 memset(f, 0, sizeof(*f));
3186 f->symbol_cmp = strcmp;
3187 f->symbol_hash = obj_elf_hash;
3188 f->load_order_search_start = &f->load_order;
3189
3190 fseek(fp, 0, SEEK_SET);
3191 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003192 perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003193 return NULL;
3194 }
3195
3196 if (f->header.e_ident[EI_MAG0] != ELFMAG0
3197 || f->header.e_ident[EI_MAG1] != ELFMAG1
3198 || f->header.e_ident[EI_MAG2] != ELFMAG2
3199 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003200 error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003201 return NULL;
3202 }
3203 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
3204 || f->header.e_ident[EI_DATA] != ELFDATAM
3205 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3206 || !MATCH_MACHINE(f->header.e_machine)) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003207 error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003208 return NULL;
3209 }
3210 if (f->header.e_type != ET_REL) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003211 error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003212 return NULL;
3213 }
3214
3215 /* Read the section headers. */
3216
3217 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003218 error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003219 (unsigned long) f->header.e_shentsize,
3220 (unsigned long) sizeof(ElfW(Shdr)));
3221 return NULL;
3222 }
3223
3224 shnum = f->header.e_shnum;
3225 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3226 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3227
3228 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3229 fseek(fp, f->header.e_shoff, SEEK_SET);
3230 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003231 perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003232 return NULL;
3233 }
3234
3235 /* Read the section data. */
3236
3237 for (i = 0; i < shnum; ++i) {
3238 struct obj_section *sec;
3239
3240 f->sections[i] = sec = arch_new_section();
3241 memset(sec, 0, sizeof(*sec));
3242
3243 sec->header = section_headers[i];
3244 sec->idx = i;
3245
Eric Andersen2bf658d2001-02-24 20:01:53 +00003246 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003247 case SHT_NULL:
3248 case SHT_NOTE:
3249 case SHT_NOBITS:
3250 /* ignore */
3251 break;
3252
3253 case SHT_PROGBITS:
Eric Andersen8ae319a2001-05-21 16:09:18 +00003254#if LOADBITS
3255 if (!loadprogbits) {
3256 sec->contents = NULL;
3257 break;
3258 }
3259#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003260 case SHT_SYMTAB:
3261 case SHT_STRTAB:
3262 case SHT_RELM:
3263 if (sec->header.sh_size > 0) {
3264 sec->contents = xmalloc(sec->header.sh_size);
3265 fseek(fp, sec->header.sh_offset, SEEK_SET);
3266 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003267 perror_msg("error reading ELF section data");
Eric Andersen9f16d612000-06-12 23:11:16 +00003268 return NULL;
3269 }
3270 } else {
3271 sec->contents = NULL;
3272 }
3273 break;
3274
3275#if SHT_RELM == SHT_REL
3276 case SHT_RELA:
Matt Kraaidd19c692001-01-31 19:00:21 +00003277 error_msg("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003278 return NULL;
3279#else
3280 case SHT_REL:
Matt Kraaidd19c692001-01-31 19:00:21 +00003281 error_msg("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003282 return NULL;
3283#endif
3284
3285 default:
3286 if (sec->header.sh_type >= SHT_LOPROC) {
3287 /* Assume processor specific section types are debug
3288 info and can safely be ignored. If this is ever not
3289 the case (Hello MIPS?), don't put ifdefs here but
3290 create an arch_load_proc_section(). */
3291 break;
3292 }
3293
Matt Kraaidd19c692001-01-31 19:00:21 +00003294 error_msg("can't handle sections of type %ld",
Eric Andersen9f16d612000-06-12 23:11:16 +00003295 (long) sec->header.sh_type);
3296 return NULL;
3297 }
3298 }
3299
3300 /* Do what sort of interpretation as needed by each section. */
3301
3302 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3303
3304 for (i = 0; i < shnum; ++i) {
3305 struct obj_section *sec = f->sections[i];
3306 sec->name = shstrtab + sec->header.sh_name;
3307 }
3308
3309 for (i = 0; i < shnum; ++i) {
3310 struct obj_section *sec = f->sections[i];
3311
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003312 /* .modinfo should be contents only but gcc has no attribute for that.
3313 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3314 */
3315 if (strcmp(sec->name, ".modinfo") == 0)
3316 sec->header.sh_flags &= ~SHF_ALLOC;
3317
Eric Andersen9f16d612000-06-12 23:11:16 +00003318 if (sec->header.sh_flags & SHF_ALLOC)
3319 obj_insert_section_load_order(f, sec);
3320
3321 switch (sec->header.sh_type) {
3322 case SHT_SYMTAB:
3323 {
3324 unsigned long nsym, j;
3325 char *strtab;
3326 ElfW(Sym) * sym;
3327
3328 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003329 error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003330 (unsigned long) sec->header.sh_entsize,
3331 (unsigned long) sizeof(ElfW(Sym)));
3332 return NULL;
3333 }
3334
3335 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3336 strtab = f->sections[sec->header.sh_link]->contents;
3337 sym = (ElfW(Sym) *) sec->contents;
3338
3339 /* Allocate space for a table of local symbols. */
3340 j = f->local_symtab_size = sec->header.sh_info;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003341 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003342
3343 /* Insert all symbols into the hash table. */
3344 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3345 const char *name;
3346 if (sym->st_name)
3347 name = strtab + sym->st_name;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003348 else
Eric Andersen9f16d612000-06-12 23:11:16 +00003349 name = f->sections[sym->st_shndx]->name;
3350
3351 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3352 sym->st_value, sym->st_size);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003353 }
3354 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003355 break;
3356
3357 case SHT_RELM:
3358 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Matt Kraaidd19c692001-01-31 19:00:21 +00003359 error_msg("relocation entry size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003360 (unsigned long) sec->header.sh_entsize,
3361 (unsigned long) sizeof(ElfW(RelM)));
3362 return NULL;
3363 }
3364 break;
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003365 /* XXX Relocation code from modutils-2.3.19 is not here.
3366 * Why? That's about 20 lines of code from obj/obj_load.c,
3367 * which gets done in a second pass through the sections.
3368 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003369 }
3370 }
3371
3372 return f;
3373}
3374
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003375#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003376/*
3377 * load the unloaded sections directly into the memory allocated by
3378 * kernel for the module
3379 */
3380
Eric Andersenac5dbd12001-08-22 05:26:08 +00003381static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003382{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003383 ElfW(Addr) base = f->baseaddr;
3384 struct obj_section* sec;
3385
3386 for (sec = f->load_order; sec; sec = sec->load_next) {
3387
3388 /* section already loaded? */
3389 if (sec->contents != NULL)
3390 continue;
3391
3392 if (sec->header.sh_size == 0)
3393 continue;
3394
3395 sec->contents = imagebase + (sec->header.sh_addr - base);
3396 fseek(fp, sec->header.sh_offset, SEEK_SET);
3397 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Eric Andersenac5dbd12001-08-22 05:26:08 +00003398 error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003399 return 0;
3400 }
3401
3402 }
3403 return 1;
3404}
3405#endif
3406
Eric Andersen9f16d612000-06-12 23:11:16 +00003407static void hide_special_symbols(struct obj_file *f)
3408{
3409 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003410 SPFX "cleanup_module",
3411 SPFX "init_module",
3412 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003413 NULL
3414 };
3415
3416 struct obj_symbol *sym;
3417 const char *const *p;
3418
3419 for (p = specials; *p; ++p)
3420 if ((sym = obj_find_symbol(f, *p)) != NULL)
3421 sym->info =
3422 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3423}
3424
Eric Andersen71ae64b2002-10-10 04:20:21 +00003425#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003426static int obj_gpl_license(struct obj_file *f, const char **license)
3427{
3428 struct obj_section *sec;
3429 /* This list must match *exactly* the list of allowable licenses in
3430 * linux/include/linux/module.h. Checking for leading "GPL" will not
3431 * work, somebody will use "GPL sucks, this is proprietary".
3432 */
3433 static const char *gpl_licenses[] = {
3434 "GPL",
3435 "GPL v2",
3436 "GPL and additional rights",
3437 "Dual BSD/GPL",
3438 "Dual MPL/GPL",
3439 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003440
Eric Andersen166fa462002-09-16 05:30:24 +00003441 if ((sec = obj_find_section(f, ".modinfo"))) {
3442 const char *value, *ptr, *endptr;
3443 ptr = sec->contents;
3444 endptr = ptr + sec->header.sh_size;
3445 while (ptr < endptr) {
3446 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3447 int i;
3448 if (license)
3449 *license = value+1;
3450 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3451 if (strcmp(value+1, gpl_licenses[i]) == 0)
3452 return(0);
3453 }
3454 return(2);
3455 }
3456 if (strchr(ptr, '\0'))
3457 ptr = strchr(ptr, '\0') + 1;
3458 else
3459 ptr = endptr;
3460 }
3461 }
3462 return(1);
3463}
3464
3465#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3466#define TAINT_PROPRIETORY_MODULE (1<<0)
3467#define TAINT_FORCED_MODULE (1<<1)
3468#define TAINT_UNSAFE_SMP (1<<2)
3469#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3470
3471static void set_tainted(struct obj_file *f, int fd, char *m_name,
3472 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3473{
3474 char buf[80];
3475 int oldval;
3476 static int first = 1;
3477 if (fd < 0 && !kernel_has_tainted)
3478 return; /* New modutils on old kernel */
3479 printf("Warning: loading %s will taint the kernel: %s%s\n",
3480 m_name, text1, text2);
3481 if (first) {
3482 printf(" See %s for information about tainted modules\n", TAINT_URL);
3483 first = 0;
3484 }
3485 if (fd >= 0) {
3486 read(fd, buf, sizeof(buf)-1);
3487 buf[sizeof(buf)-1] = '\0';
3488 oldval = strtoul(buf, NULL, 10);
3489 sprintf(buf, "%d\n", oldval | taint);
3490 write(fd, buf, strlen(buf));
3491 }
3492}
3493
3494/* Check if loading this module will taint the kernel. */
3495static void check_tainted_module(struct obj_file *f, char *m_name)
3496{
3497 static const char tainted_file[] = TAINT_FILENAME;
3498 int fd, kernel_has_tainted;
3499 const char *ptr;
3500
3501 kernel_has_tainted = 1;
3502 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3503 if (errno == ENOENT)
3504 kernel_has_tainted = 0;
3505 else if (errno == EACCES)
3506 kernel_has_tainted = 1;
3507 else {
3508 perror(tainted_file);
3509 kernel_has_tainted = 0;
3510 }
3511 }
3512
3513 switch (obj_gpl_license(f, &ptr)) {
3514 case 0:
3515 break;
3516 case 1:
3517 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3518 break;
3519 case 2:
3520 /* The module has a non-GPL license so we pretend that the
3521 * kernel always has a taint flag to get a warning even on
3522 * kernels without the proc flag.
3523 */
3524 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3525 break;
3526 default:
3527 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3528 break;
3529 }
3530
3531 if (flag_force_load)
3532 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3533
3534 if (fd >= 0)
3535 close(fd);
3536}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003537#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3538#define check_tainted_module(x, y) do { } while(0);
3539#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003540
3541extern int insmod_main( int argc, char **argv)
3542{
Eric Andersena18aaf12001-01-24 19:07:09 +00003543 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00003544 int k_crcs;
3545 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003546 int len;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003547 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003548 unsigned long m_size;
3549 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003550 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003551 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003552 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003553 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003554 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003555#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003556 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003557 char m_strversion[STRVERSIONLEN];
3558 int m_version;
3559 int m_crcs;
3560#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003561#ifdef CONFIG_FEATURE_CLEAN_UP
3562 FILE *fp = 0;
3563#else
3564 FILE *fp;
3565#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003566
Erik Andersene49d5ec2000-02-08 19:58:47 +00003567 /* Parse any options */
Eric Andersenb493dec2002-07-02 19:14:23 +00003568 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0) {
Eric Andersena18aaf12001-01-24 19:07:09 +00003569 switch (opt) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003570 case 'f': /* force loading */
3571 flag_force_load = 1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003572 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003573 case 'k': /* module loaded by kerneld, auto-cleanable */
3574 flag_autoclean = 1;
3575 break;
Eric Andersenc088c582002-05-03 10:34:35 +00003576 case 's': /* log to syslog */
3577 /* log to syslog -- not supported */
3578 /* but kernel needs this for request_module(), */
3579 /* as this calls: modprobe -k -s -- <module> */
3580 /* so silently ignore this flag */
3581 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003582 case 'v': /* verbose output */
3583 flag_verbose = 1;
3584 break;
Eric Andersenb493dec2002-07-02 19:14:23 +00003585 case 'q': /* silent */
3586 flag_quiet = 1;
3587 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003588 case 'x': /* do not export externs */
3589 flag_export = 0;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003590 break;
Eric Andersen155c89b2001-01-25 04:11:06 +00003591 case 'o': /* name the output module */
Eric Andersen61f83052002-06-22 17:15:42 +00003592 if(m_name) /* Hmmm, duplicate "-o name". */
3593 free(m_name);
3594 m_name = xstrdup(optarg);
Eric Andersen155c89b2001-01-25 04:11:06 +00003595 break;
Eric Andersena18aaf12001-01-24 19:07:09 +00003596 case 'L': /* Stub warning */
3597 /* This is needed for compatibility with modprobe.
3598 * In theory, this does locking, but we don't do
3599 * that. So be careful and plan your life around not
3600 * loading the same module 50 times concurrently. */
3601 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003602 default:
Eric Andersen67991cf2001-02-14 21:23:06 +00003603 show_usage();
Erik Andersene49d5ec2000-02-08 19:58:47 +00003604 }
Erik Andersend387d011999-12-21 02:55:11 +00003605 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003606
3607 if (argv[optind] == NULL) {
Eric Andersen67991cf2001-02-14 21:23:06 +00003608 show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003609 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003610
Erik Andersene49d5ec2000-02-08 19:58:47 +00003611 /* Grab the module name */
Eric Andersen6fb4e482002-06-06 14:24:57 +00003612 tmp1 = xstrdup(argv[optind]);
3613 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003614 len = strlen(tmp);
3615
Eric Andersen6fb4e482002-06-06 14:24:57 +00003616 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
3617 len-=2;
3618 tmp[len] = '\0';
Eric Andersen155c89b2001-01-25 04:11:06 +00003619 }
Eric Andersen2d342152002-06-18 05:16:25 +00003620
Robert Griebl967c3d42002-07-21 17:33:27 +00003621 bb_asprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003622
Eric Andersen61f83052002-06-22 17:15:42 +00003623 if (!m_name) {
3624 m_name = tmp;
3625 } else {
3626 free(tmp1);
3627 tmp1 = 0; /* flag for free(m_name) before exit() */
3628 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003629
Eric Andersen14d35432001-05-14 17:07:32 +00003630 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00003631 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
3632 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00003633 struct utsname myuname;
3634
3635 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3636 * but do not error out yet if we fail to find it... */
3637 if (uname(&myuname) == 0) {
Robert Griebld378c312002-07-19 00:05:54 +00003638 char *module_dir;
3639 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003640 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003641
3642 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003643 /* Jump through hoops in case /lib/modules/`uname -r`
3644 * is a symlink. We do not want recursive_action to
3645 * follow symlinks, but we do want to follow the
3646 * /lib/modules/`uname -r` dir, So resolve it ourselves
3647 * if it is a link... */
Robert Griebld378c312002-07-19 00:05:54 +00003648 if (realpath (tmdn, real_module_dir) == NULL)
3649 module_dir = tmdn;
3650 else
3651 module_dir = real_module_dir;
3652 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen14d35432001-05-14 17:07:32 +00003653 check_module_name_match, 0, m_fullName);
Robert Griebld378c312002-07-19 00:05:54 +00003654 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00003655 }
3656
3657 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00003658 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00003659 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00003660 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00003661
3662 free(m_filename);
3663 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00003664 if (realpath (_PATH_MODULES, module_dir) == NULL)
3665 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00003666 /* No module found under /lib/modules/`uname -r`, this
3667 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00003668 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
3669 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00003670 {
Eric Andersen61f83052002-06-22 17:15:42 +00003671 if (m_filename == 0
Eric Andersen14d35432001-05-14 17:07:32 +00003672 || ((fp = fopen(m_filename, "r")) == NULL))
3673 {
3674 error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00003675 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00003676 }
3677 } else
3678 error_msg_and_die("%s: no module by that name found", m_fullName);
3679 }
3680 } else
Eric Andersen61f83052002-06-22 17:15:42 +00003681 m_filename = xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00003682
Eric Andersen14d35432001-05-14 17:07:32 +00003683 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00003684
Eric Andersen8ae319a2001-05-21 16:09:18 +00003685 if ((f = obj_load(fp, LOADBITS)) == NULL)
Matt Kraaia9819b22000-12-22 01:48:07 +00003686 perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00003687
Eric Andersen9f16d612000-06-12 23:11:16 +00003688 if (get_modinfo_value(f, "kernel_version") == NULL)
3689 m_has_modinfo = 0;
3690 else
3691 m_has_modinfo = 1;
3692
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003693#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003694 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00003695 if (!flag_quiet) {
3696 if (uname(&uts_info) < 0)
3697 uts_info.release[0] = '\0';
3698 if (m_has_modinfo) {
3699 m_version = new_get_module_version(f, m_strversion);
Eric Andersen9f16d612000-06-12 23:11:16 +00003700 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003701 m_version = old_get_module_version(f, m_strversion);
3702 if (m_version == -1) {
3703 error_msg("couldn't find the kernel version the module was "
3704 "compiled for");
3705 goto out;
3706 }
3707 }
3708
3709 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
3710 if (flag_force_load) {
3711 error_msg("Warning: kernel-module version mismatch\n"
3712 "\t%s was compiled for kernel version %s\n"
3713 "\twhile this kernel is version %s",
3714 m_filename, m_strversion, uts_info.release);
3715 } else {
3716 error_msg("kernel-module version mismatch\n"
3717 "\t%s was compiled for kernel version %s\n"
3718 "\twhile this kernel is version %s.",
3719 m_filename, m_strversion, uts_info.release);
3720 goto out;
3721 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003722 }
3723 }
3724 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003725#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003726
3727 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
3728
3729 if (k_new_syscalls) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003730#ifdef CONFIG_FEATURE_NEW_MODULE_INTERFACE
Eric Andersen9f16d612000-06-12 23:11:16 +00003731 if (!new_get_kernel_symbols())
3732 goto out;
3733 k_crcs = new_is_kernel_checksummed();
3734#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003735 error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003736 goto out;
3737#endif
3738 } else {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003739#ifdef CONFIG_FEATURE_OLD_MODULE_INTERFACE
Eric Andersen8c185f92000-09-22 00:38:07 +00003740 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00003741 goto out;
3742 k_crcs = old_is_kernel_checksummed();
3743#else
Matt Kraaidd19c692001-01-31 19:00:21 +00003744 error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00003745 goto out;
3746#endif
3747 }
3748
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003749#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00003750 if (m_has_modinfo)
3751 m_crcs = new_is_module_checksummed(f);
3752 else
3753 m_crcs = old_is_module_checksummed(f);
3754
3755 if (m_crcs != k_crcs)
3756 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003757#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00003758
Erik Andersene49d5ec2000-02-08 19:58:47 +00003759 /* Let the module know about the kernel symbols. */
3760 add_kernel_symbols(f);
3761
Eric Andersen9f16d612000-06-12 23:11:16 +00003762 /* Allocate common symbols, symbol tables, and string tables. */
3763
3764 if (k_new_syscalls
3765 ? !new_create_this_module(f, m_name)
3766 : !old_create_mod_use_count(f))
3767 {
3768 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003769 }
3770
Eric Andersen9f16d612000-06-12 23:11:16 +00003771 if (!obj_check_undefineds(f)) {
3772 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003773 }
3774 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00003775 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003776
Eric Andersen86f3d5b2001-01-24 23:59:50 +00003777 /* done with the module name, on to the optional var=value arguments */
3778 ++optind;
3779
Eric Andersen9f16d612000-06-12 23:11:16 +00003780 if (optind < argc) {
3781 if (m_has_modinfo
3782 ? !new_process_module_arguments(f, argc - optind, argv + optind)
3783 : !old_process_module_arguments(f, argc - optind, argv + optind))
3784 {
3785 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003786 }
3787 }
3788
Eric Andersen9f16d612000-06-12 23:11:16 +00003789 arch_create_got(f);
3790 hide_special_symbols(f);
3791
3792 if (k_new_syscalls)
3793 new_create_module_ksymtab(f);
3794
Erik Andersene49d5ec2000-02-08 19:58:47 +00003795 /* Find current size of the module */
3796 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00003797
3798
Erik Andersene49d5ec2000-02-08 19:58:47 +00003799 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00003800 if (m_addr == -1) switch (errno) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003801 case EEXIST:
Matt Kraaidd19c692001-01-31 19:00:21 +00003802 error_msg("A module named %s already exists", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003803 goto out;
3804 case ENOMEM:
Matt Kraaidd19c692001-01-31 19:00:21 +00003805 error_msg("Can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen9f16d612000-06-12 23:11:16 +00003806 m_size);
3807 goto out;
Erik Andersend387d011999-12-21 02:55:11 +00003808 default:
Matt Kraai1fa1ade2000-12-18 03:57:16 +00003809 perror_msg("create_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003810 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003811 }
Erik Andersend387d011999-12-21 02:55:11 +00003812
Eric Andersen8ae319a2001-05-21 16:09:18 +00003813#if !LOADBITS
3814 /*
3815 * the PROGBITS section was not loaded by the obj_load
3816 * now we can load them directly into the kernel memory
3817 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00003818 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00003819 delete_module(m_name);
3820 goto out;
3821 }
3822#endif
3823
Eric Andersen9f16d612000-06-12 23:11:16 +00003824 if (!obj_relocate(f, m_addr)) {
3825 delete_module(m_name);
3826 goto out;
3827 }
Erik Andersend387d011999-12-21 02:55:11 +00003828
Eric Andersen9f16d612000-06-12 23:11:16 +00003829 if (k_new_syscalls
3830 ? !new_init_module(m_name, f, m_size)
3831 : !old_init_module(m_name, f, m_size))
3832 {
3833 delete_module(m_name);
3834 goto out;
3835 }
3836
Matt Kraai3e856ce2000-12-01 02:55:13 +00003837 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00003838
3839out:
Eric Andersen61f83052002-06-22 17:15:42 +00003840#ifdef CONFIG_FEATURE_CLEAN_UP
3841 if(fp)
Erik Andersene49d5ec2000-02-08 19:58:47 +00003842 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00003843 if(tmp1) {
3844 free(tmp1);
3845 } else {
3846 free(m_name);
3847 }
3848 free(m_filename);
3849#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00003850 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00003851}