blob: 63ee9da713e0bc5d6b7c60f64d7ee99d2c1ea405 [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 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * This version of insmod supports x86, ARM, SH3/4/5, powerpc, m68k,
Miles Baderae28b042002-04-01 09:34:25 +00006 * MIPS, and v850e.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00008 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +00009 * and Ron Alder <alder@lineo.com>
10 *
Miles Bader75ce8d72002-04-01 14:25:51 +000011 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000012 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000013 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000014 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
15 *
16 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
17 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
18 * very minor changes required to also work with StrongArm and presumably
19 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000020 *
Eric Andersenbf833552003-08-13 19:56:33 +000021 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
22 * Integrated support for sh64 (SH-5), from preliminary modutils
23 * patches from Benedict Gaster <benedict.gaster@superh.com>.
24 * Currently limited to support for 32bit ABI.
25 *
Eric Andersencffd5022002-05-24 06:50:15 +000026 * Magnus Damm <damm@opensource.se> 22-May-2002.
27 * The plt and got code are now using the same structs.
28 * Added generic linked list code to fully support PowerPC.
29 * Replaced the mess in arch_apply_relocation() with architecture blocks.
30 * The arch_create_got() function got cleaned up with architecture blocks.
31 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
32 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000033 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000034 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000035 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
36 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000037 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000038 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000039 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
40 * based on modutils-2.4.2
41 * MIPS specific support for Elf loading and relocation.
42 * Copyright 1996, 1997 Linux International.
43 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
44 *
Eric Andersen9f16d612000-06-12 23:11:16 +000045 * Based almost entirely on the Linux modutils-2.3.11 implementation.
46 * Copyright 1996, 1997 Linux International.
47 * New implementation contributed by Richard Henderson <rth@tamu.edu>
48 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
49 * Restructured (and partly rewritten) by:
50 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000051 *
52 * This program is free software; you can redistribute it and/or modify
53 * it under the terms of the GNU General Public License as published by
54 * the Free Software Foundation; either version 2 of the License, or
55 * (at your option) any later version.
56 *
57 * This program is distributed in the hope that it will be useful,
58 * but WITHOUT ANY WARRANTY; without even the implied warranty of
59 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
60 * General Public License for more details.
61 *
62 * You should have received a copy of the GNU General Public License
63 * along with this program; if not, write to the Free Software
64 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65 *
66 */
67
Erik Andersen02104321999-12-17 18:57:34 +000068#include <stdlib.h>
69#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000070#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000071#include <errno.h>
72#include <unistd.h>
73#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000074#include <ctype.h>
75#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000076#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000077#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000078#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000079#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000080#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000081
Eric Andersene7047882003-12-11 01:42:13 +000082#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
83 !defined(CONFIG_FEATURE_2_2_MODULES) && \
84 !defined(CONFIG_FEATURE_2_6_MODULES)
85#define CONFIG_FEATURE_2_4_MODULES
86#endif
87
88#if !defined(CONFIG_FEATURE_2_4_MODULES) && !defined(CONFIG_FEATURE_2_2_MODULES)
89#define insmod_ng_main insmod_main
90#endif
91
92#if defined(CONFIG_FEATURE_2_4_MODULES) || defined(CONFIG_FEATURE_2_2_MODULES)
93
94#if defined(CONFIG_FEATURE_2_6_MODULES)
95extern int insmod_ng_main( int argc, char **argv);
96#endif
97
98#ifdef CONFIG_FEATURE_2_4_MODULES
99# undef CONFIG_FEATURE_2_2_MODULES
Eric Andersen64c8b172001-04-05 07:33:10 +0000100# define new_sys_init_module init_module
101#else
102# define old_sys_init_module init_module
103#endif
104
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000105#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000106#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +0000107#else
108#define LOADBITS 1
109#endif
110
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000111
112#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000113#define CONFIG_USE_PLT_ENTRIES
114#define CONFIG_PLT_ENTRY_SIZE 8
115#define CONFIG_USE_GOT_ENTRIES
116#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000117#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000118
Eric Andersencffd5022002-05-24 06:50:15 +0000119#define MATCH_MACHINE(x) (x == EM_ARM)
120#define SHT_RELM SHT_REL
121#define Elf32_RelM Elf32_Rel
122#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000123#endif
124
Eric Andersenbf77f612003-01-23 06:02:39 +0000125#if defined(__s390__)
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000126#define CONFIG_USE_PLT_ENTRIES
127#define CONFIG_PLT_ENTRY_SIZE 8
128#define CONFIG_USE_GOT_ENTRIES
129#define CONFIG_GOT_ENTRY_SIZE 8
130#define CONFIG_USE_SINGLE
Eric Andersenbf77f612003-01-23 06:02:39 +0000131
132#define MATCH_MACHINE(x) (x == EM_S390)
133#define SHT_RELM SHT_RELA
134#define Elf32_RelM Elf32_Rela
135#define ELFCLASSM ELFCLASS32
136#endif
137
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000138#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000139#define CONFIG_USE_GOT_ENTRIES
140#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000141#define CONFIG_USE_SINGLE
142
143#ifndef EM_486
144#define MATCH_MACHINE(x) (x == EM_386)
145#else
146#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
147#endif
148
149#define SHT_RELM SHT_REL
150#define Elf32_RelM Elf32_Rel
151#define ELFCLASSM ELFCLASS32
152#endif
153
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000154#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000155#define CONFIG_USE_GOT_ENTRIES
156#define CONFIG_GOT_ENTRY_SIZE 4
157#define CONFIG_USE_SINGLE
158
159#define MATCH_MACHINE(x) (x == EM_68K)
160#define SHT_RELM SHT_RELA
161#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000162#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000163#endif
164
Eric Andersen2bf658d2001-02-24 20:01:53 +0000165#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000166/* Account for ELF spec changes. */
167#ifndef EM_MIPS_RS3_LE
168#ifdef EM_MIPS_RS4_BE
169#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
170#else
171#define EM_MIPS_RS3_LE 10
172#endif
173#endif /* !EM_MIPS_RS3_LE */
174
175#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
176#define SHT_RELM SHT_REL
177#define Elf32_RelM Elf32_Rel
178#define ELFCLASSM ELFCLASS32
179#define ARCHDATAM "__dbe_table"
180#endif
181
182#if defined(__powerpc__)
183#define CONFIG_USE_PLT_ENTRIES
184#define CONFIG_PLT_ENTRY_SIZE 16
185#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000186#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000187#define CONFIG_USE_LIST
188
189#define MATCH_MACHINE(x) (x == EM_PPC)
190#define SHT_RELM SHT_RELA
191#define Elf32_RelM Elf32_Rela
192#define ELFCLASSM ELFCLASS32
193#define ARCHDATAM "__ftr_fixup"
194#endif
195
196#if defined(__sh__)
197#define CONFIG_USE_GOT_ENTRIES
198#define CONFIG_GOT_ENTRY_SIZE 4
199#define CONFIG_USE_SINGLE
200
201#define MATCH_MACHINE(x) (x == EM_SH)
202#define SHT_RELM SHT_RELA
203#define Elf32_RelM Elf32_Rela
204#define ELFCLASSM ELFCLASS32
205
Eric Andersenbf833552003-08-13 19:56:33 +0000206/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000207/* I'm not sure about big endian, so let's warn: */
208
Eric Andersenbf833552003-08-13 19:56:33 +0000209#if defined(__sh__) && defined(__BIG_ENDIAN__)
210#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000211#endif
212
213/* it may or may not work on the SH1/SH2... So let's error on those
214 also */
Eric Andersenbf833552003-08-13 19:56:33 +0000215#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && \
216 (defined(__sh__))
217#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000218#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000219#endif
220
Miles Baderae28b042002-04-01 09:34:25 +0000221#if defined (__v850e__)
222#define CONFIG_USE_PLT_ENTRIES
223#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000224#define CONFIG_USE_SINGLE
225
226#ifndef EM_CYGNUS_V850 /* grumble */
227#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000228#endif
229
Eric Andersencffd5022002-05-24 06:50:15 +0000230#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
231#define SHT_RELM SHT_RELA
232#define Elf32_RelM Elf32_Rela
233#define ELFCLASSM ELFCLASS32
234
235#define SYMBOL_PREFIX "_"
236#endif
237
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +0000238#if defined(__cris__)
239#ifndef EM_CRIS
240#define EM_CRIS 76
241#define R_CRIS_NONE 0
242#define R_CRIS_32 3
243#endif
244
245#define MATCH_MACHINE(x) (x == EM_CRIS)
246#define SHT_RELM SHT_RELA
247#define Elf32_RelM Elf32_Rela
248#define ELFCLASSM ELFCLASS32
249#endif
250
Eric Andersencffd5022002-05-24 06:50:15 +0000251#ifndef SHT_RELM
252#error Sorry, but insmod.c does not yet support this architecture...
253#endif
254
255
Eric Andersen9f16d612000-06-12 23:11:16 +0000256//----------------------------------------------------------------------------
257//--------modutils module.h, lines 45-242
258//----------------------------------------------------------------------------
259
260/* Definitions for the Linux module syscall interface.
261 Copyright 1996, 1997 Linux International.
262
263 Contributed by Richard Henderson <rth@tamu.edu>
264
265 This file is part of the Linux modutils.
266
267 This program is free software; you can redistribute it and/or modify it
268 under the terms of the GNU General Public License as published by the
269 Free Software Foundation; either version 2 of the License, or (at your
270 option) any later version.
271
272 This program is distributed in the hope that it will be useful, but
273 WITHOUT ANY WARRANTY; without even the implied warranty of
274 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
275 General Public License for more details.
276
277 You should have received a copy of the GNU General Public License
278 along with this program; if not, write to the Free Software Foundation,
279 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
280
281
282#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000283static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000284
Eric Andersenaff114c2004-04-14 17:51:38 +0000285#ident "$Id: insmod.c,v 1.117 2004/04/14 17:51:22 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000286
287/* This file contains the structures used by the 2.0 and 2.1 kernels.
288 We do not use the kernel headers directly because we do not wish
Eric Andersenaff114c2004-04-14 17:51:38 +0000289 to be dependent on a particular kernel version to compile insmod. */
Eric Andersen9f16d612000-06-12 23:11:16 +0000290
291
292/*======================================================================*/
293/* The structures used by Linux 2.0. */
294
295/* The symbol format used by get_kernel_syms(2). */
296struct old_kernel_sym
297{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000298 unsigned long value;
299 char name[60];
Eric Andersen9f16d612000-06-12 23:11:16 +0000300};
301
302struct old_module_ref
303{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000304 unsigned long module; /* kernel addresses */
305 unsigned long next;
Eric Andersen9f16d612000-06-12 23:11:16 +0000306};
307
308struct old_module_symbol
309{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000310 unsigned long addr;
311 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000312};
313
314struct old_symbol_table
315{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000316 int size; /* total, including string table!!! */
317 int n_symbols;
318 int n_refs;
319 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
320 struct old_module_ref ref[0]; /* actual size defined by n_refs */
Eric Andersen9f16d612000-06-12 23:11:16 +0000321};
322
323struct old_mod_routines
324{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000325 unsigned long init;
326 unsigned long cleanup;
Eric Andersen9f16d612000-06-12 23:11:16 +0000327};
328
329struct old_module
330{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000331 unsigned long next;
332 unsigned long ref; /* the list of modules that refer to me */
333 unsigned long symtab;
334 unsigned long name;
335 int size; /* size of module in pages */
336 unsigned long addr; /* address of module */
337 int state;
338 unsigned long cleanup; /* cleanup routine */
Eric Andersen9f16d612000-06-12 23:11:16 +0000339};
340
341/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000342static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000343
344int get_kernel_syms(struct old_kernel_sym *);
345int old_sys_init_module(const char *name, char *code, unsigned codesize,
346 struct old_mod_routines *, struct old_symbol_table *);
347
348/*======================================================================*/
349/* For sizeof() which are related to the module platform and not to the
350 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
351
352#define tgt_sizeof_char sizeof(char)
353#define tgt_sizeof_short sizeof(short)
354#define tgt_sizeof_int sizeof(int)
355#define tgt_sizeof_long sizeof(long)
356#define tgt_sizeof_char_p sizeof(char *)
357#define tgt_sizeof_void_p sizeof(void *)
358#define tgt_long long
359
360#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
361#undef tgt_sizeof_long
362#undef tgt_sizeof_char_p
363#undef tgt_sizeof_void_p
364#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000365static const int tgt_sizeof_long = 8;
366static const int tgt_sizeof_char_p = 8;
367static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000368#define tgt_long long long
369#endif
370
371/*======================================================================*/
372/* The structures used in Linux 2.1. */
373
374/* Note: new_module_symbol does not use tgt_long intentionally */
375struct new_module_symbol
376{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000377 unsigned long value;
378 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000379};
380
381struct new_module_persist;
382
383struct new_module_ref
384{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000385 unsigned tgt_long dep; /* kernel addresses */
386 unsigned tgt_long ref;
387 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000388};
389
390struct new_module
391{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned tgt_long size_of_struct; /* == sizeof(module) */
393 unsigned tgt_long next;
394 unsigned tgt_long name;
395 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000396
Eric Andersen3b1a7442003-12-24 20:30:45 +0000397 tgt_long usecount;
398 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000399
Eric Andersen3b1a7442003-12-24 20:30:45 +0000400 unsigned nsyms;
401 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000402
Eric Andersen3b1a7442003-12-24 20:30:45 +0000403 unsigned tgt_long syms;
404 unsigned tgt_long deps;
405 unsigned tgt_long refs;
406 unsigned tgt_long init;
407 unsigned tgt_long cleanup;
408 unsigned tgt_long ex_table_start;
409 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000410#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000411 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000412#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000413 /* Everything after here is extension. */
414 unsigned tgt_long persist_start;
415 unsigned tgt_long persist_end;
416 unsigned tgt_long can_unload;
417 unsigned tgt_long runsize;
Eric Andersene7047882003-12-11 01:42:13 +0000418#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen3b1a7442003-12-24 20:30:45 +0000419 const char *kallsyms_start; /* All symbols for kernel debugging */
420 const char *kallsyms_end;
421 const char *archdata_start; /* arch specific data for module */
422 const char *archdata_end;
423 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen8ae319a2001-05-21 16:09:18 +0000424#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000425};
426
Eric Andersencffd5022002-05-24 06:50:15 +0000427#ifdef ARCHDATAM
428#define ARCHDATA_SEC_NAME ARCHDATAM
429#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000430#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000431#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000432#define KALLSYMS_SEC_NAME "__kallsyms"
433
434
Eric Andersen9f16d612000-06-12 23:11:16 +0000435struct new_module_info
436{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000437 unsigned long addr;
438 unsigned long size;
439 unsigned long flags;
440 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000441};
442
443/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000444static const int NEW_MOD_RUNNING = 1;
445static const int NEW_MOD_DELETED = 2;
446static const int NEW_MOD_AUTOCLEAN = 4;
447static const int NEW_MOD_VISITED = 8;
448static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000449
Eric Andersen64c8b172001-04-05 07:33:10 +0000450int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000451int query_module(const char *name, int which, void *buf, size_t bufsize,
452 size_t *ret);
453
454/* Values for query_module's which. */
455
Mark Whitley59ab0252001-01-23 22:30:04 +0000456static const int QM_MODULES = 1;
457static const int QM_DEPS = 2;
458static const int QM_REFS = 3;
459static const int QM_SYMBOLS = 4;
460static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000461
462/*======================================================================*/
463/* The system calls unchanged between 2.0 and 2.1. */
464
465unsigned long create_module(const char *, size_t);
466int delete_module(const char *);
467
468
469#endif /* module.h */
470
471//----------------------------------------------------------------------------
472//--------end of modutils module.h
473//----------------------------------------------------------------------------
474
475
476
477//----------------------------------------------------------------------------
478//--------modutils obj.h, lines 253-462
479//----------------------------------------------------------------------------
480
481/* Elf object file loading and relocation routines.
482 Copyright 1996, 1997 Linux International.
483
484 Contributed by Richard Henderson <rth@tamu.edu>
485
486 This file is part of the Linux modutils.
487
488 This program is free software; you can redistribute it and/or modify it
489 under the terms of the GNU General Public License as published by the
490 Free Software Foundation; either version 2 of the License, or (at your
491 option) any later version.
492
493 This program is distributed in the hope that it will be useful, but
494 WITHOUT ANY WARRANTY; without even the implied warranty of
495 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
496 General Public License for more details.
497
498 You should have received a copy of the GNU General Public License
499 along with this program; if not, write to the Free Software Foundation,
500 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
501
502
503#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000504static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000505
Eric Andersenaff114c2004-04-14 17:51:38 +0000506#ident "$Id: insmod.c,v 1.117 2004/04/14 17:51:22 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000507
508/* The relocatable object is manipulated using elfin types. */
509
510#include <stdio.h>
511#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000512#include <endian.h>
513
514#if __BYTE_ORDER == __LITTLE_ENDIAN
515#define ELFDATAM ELFDATA2LSB
516#elif __BYTE_ORDER == __BIG_ENDIAN
517#define ELFDATAM ELFDATA2MSB
518#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000519
Eric Andersen9f16d612000-06-12 23:11:16 +0000520#ifndef ElfW
521# if ELFCLASSM == ELFCLASS32
522# define ElfW(x) Elf32_ ## x
523# define ELFW(x) ELF32_ ## x
524# else
525# define ElfW(x) Elf64_ ## x
526# define ELFW(x) ELF64_ ## x
527# endif
528#endif
529
Eric Andersen85e5e722003-07-22 08:56:55 +0000530/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000531#ifndef ELF32_ST_INFO
532# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
533#endif
534
535#ifndef ELF64_ST_INFO
536# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
537#endif
538
539struct obj_string_patch;
540struct obj_symbol_patch;
541
542struct obj_section
543{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000544 ElfW(Shdr) header;
545 const char *name;
546 char *contents;
547 struct obj_section *load_next;
548 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000549};
550
551struct obj_symbol
552{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000553 struct obj_symbol *next; /* hash table link */
554 const char *name;
555 unsigned long value;
556 unsigned long size;
557 int secidx; /* the defining section index/module */
558 int info;
559 int ksymidx; /* for export to the kernel symtab */
560 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000561};
562
563/* Hardcode the hash table size. We shouldn't be needing so many
564 symbols that we begin to degrade performance, and we get a big win
565 by giving the compiler a constant divisor. */
566
567#define HASH_BUCKETS 521
568
569struct obj_file
570{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000571 ElfW(Ehdr) header;
572 ElfW(Addr) baseaddr;
573 struct obj_section **sections;
574 struct obj_section *load_order;
575 struct obj_section **load_order_search_start;
576 struct obj_string_patch *string_patches;
577 struct obj_symbol_patch *symbol_patches;
578 int (*symbol_cmp)(const char *, const char *);
579 unsigned long (*symbol_hash)(const char *);
580 unsigned long local_symtab_size;
581 struct obj_symbol **local_symtab;
582 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000583};
584
585enum obj_reloc
586{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000587 obj_reloc_ok,
588 obj_reloc_overflow,
589 obj_reloc_dangerous,
590 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000591};
592
593struct obj_string_patch
594{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000595 struct obj_string_patch *next;
596 int reloc_secidx;
597 ElfW(Addr) reloc_offset;
598 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000599};
600
601struct obj_symbol_patch
602{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000603 struct obj_symbol_patch *next;
604 int reloc_secidx;
605 ElfW(Addr) reloc_offset;
606 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000607};
608
609
610/* Generic object manipulation routines. */
611
Eric Andersen044228d2001-07-17 01:12:36 +0000612static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000613
Eric Andersen044228d2001-07-17 01:12:36 +0000614static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000615
Eric Andersen044228d2001-07-17 01:12:36 +0000616static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000617 const char *name);
618
Eric Andersen044228d2001-07-17 01:12:36 +0000619static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000620 struct obj_symbol *sym);
621
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000622#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000623static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000624 int (*cmp)(const char *, const char *),
625 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000626#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000627
Eric Andersen044228d2001-07-17 01:12:36 +0000628static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000629 const char *name);
630
Eric Andersen044228d2001-07-17 01:12:36 +0000631static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000632 struct obj_section *sec);
633
Eric Andersen044228d2001-07-17 01:12:36 +0000634static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000635 const char *name,
636 unsigned long align,
637 unsigned long size);
638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000640 const char *name,
641 unsigned long align,
642 unsigned long size);
643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000645
Eric Andersen044228d2001-07-17 01:12:36 +0000646static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000647 const char *string);
648
Eric Andersene7047882003-12-11 01:42:13 +0000649#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +0000650static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000651 struct obj_symbol *sym);
Eric Andersen6d139642001-12-29 04:15:13 +0000652#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000653
Eric Andersen044228d2001-07-17 01:12:36 +0000654static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000655
Eric Andersen044228d2001-07-17 01:12:36 +0000656static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000661
Eric Andersen044228d2001-07-17 01:12:36 +0000662static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000663
Eric Andersen044228d2001-07-17 01:12:36 +0000664static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000665
666/* Architecture specific manipulation routines. */
667
Eric Andersen044228d2001-07-17 01:12:36 +0000668static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000669
Eric Andersen044228d2001-07-17 01:12:36 +0000670static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000671
Eric Andersen044228d2001-07-17 01:12:36 +0000672static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000673
Eric Andersen044228d2001-07-17 01:12:36 +0000674static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000675 struct obj_section *targsec,
676 struct obj_section *symsec,
677 struct obj_symbol *sym,
678 ElfW(RelM) *rel, ElfW(Addr) value);
679
Eric Andersencffd5022002-05-24 06:50:15 +0000680static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000681
Glenn L McGrath759515c2003-08-30 06:00:33 +0000682static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000683
Eric Andersene7047882003-12-11 01:42:13 +0000684#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +0000685static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen6d139642001-12-29 04:15:13 +0000686#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000687
688#endif /* obj.h */
689//----------------------------------------------------------------------------
690//--------end of modutils obj.h
691//----------------------------------------------------------------------------
692
693
Miles Baderae28b042002-04-01 09:34:25 +0000694/* SPFX is always a string, so it can be concatenated to string constants. */
695#ifdef SYMBOL_PREFIX
696#define SPFX SYMBOL_PREFIX
697#else
698#define SPFX ""
699#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000700
Erik Andersen02104321999-12-17 18:57:34 +0000701
Erik Andersend387d011999-12-21 02:55:11 +0000702#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000703static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000704
Eric Andersen9f16d612000-06-12 23:11:16 +0000705/*======================================================================*/
706
Eric Andersen044228d2001-07-17 01:12:36 +0000707static int flag_force_load = 0;
708static int flag_autoclean = 0;
709static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000710static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000711static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000712
713
714/*======================================================================*/
715
Eric Andersencffd5022002-05-24 06:50:15 +0000716#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000717
Eric Andersencffd5022002-05-24 06:50:15 +0000718struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000719{
Eric Andersencffd5022002-05-24 06:50:15 +0000720 struct arch_list_entry *next;
721 CONFIG_LIST_ARCHTYPE addend;
722 int offset;
723 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000724};
Eric Andersencffd5022002-05-24 06:50:15 +0000725
Eric Andersen21adca72000-12-06 18:18:26 +0000726#endif
727
Eric Andersencffd5022002-05-24 06:50:15 +0000728#if defined(CONFIG_USE_SINGLE)
729
730struct arch_single_entry
731{
Eric Andersen9f16d612000-06-12 23:11:16 +0000732 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000733 int inited : 1;
734 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000735};
Eric Andersencffd5022002-05-24 06:50:15 +0000736
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000737#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000738
Eric Andersen2bf658d2001-02-24 20:01:53 +0000739#if defined(__mips__)
740struct mips_hi16
741{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000742 struct mips_hi16 *next;
743 Elf32_Addr *addr;
744 Elf32_Addr value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000745};
746#endif
747
Eric Andersenfe4208f2000-09-24 03:44:29 +0000748struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000749 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000750#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000751 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000752#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000753#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000754 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000756#if defined(__mips__)
757 struct mips_hi16 *mips_hi16_list;
758#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000759};
760
Eric Andersenfe4208f2000-09-24 03:44:29 +0000761struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000762 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000763#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000764#if defined(CONFIG_USE_PLT_LIST)
765 struct arch_list_entry *pltent;
766#else
767 struct arch_single_entry pltent;
768#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000769#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000770#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000771 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000772#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000773};
774
775
Eric Andersen9f16d612000-06-12 23:11:16 +0000776struct external_module {
777 const char *name;
778 ElfW(Addr) addr;
779 int used;
780 size_t nsyms;
781 struct new_module_symbol *syms;
782};
783
Eric Andersen044228d2001-07-17 01:12:36 +0000784static struct new_module_symbol *ksyms;
785static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000786
Eric Andersen044228d2001-07-17 01:12:36 +0000787static struct external_module *ext_modules;
788static int n_ext_modules;
789static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000790extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000791
Eric Andersen61f83052002-06-22 17:15:42 +0000792static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000793static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000794
Eric Andersenfe4208f2000-09-24 03:44:29 +0000795
Erik Andersen02104321999-12-17 18:57:34 +0000796
Eric Andersen9f16d612000-06-12 23:11:16 +0000797/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000798
Eric Andersen9f16d612000-06-12 23:11:16 +0000799
Eric Andersen14d35432001-05-14 17:07:32 +0000800static int check_module_name_match(const char *filename, struct stat *statbuf,
801 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000802{
Eric Andersen14d35432001-05-14 17:07:32 +0000803 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000804
Eric Andersen14d35432001-05-14 17:07:32 +0000805 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000806 return (FALSE);
807 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000808 char *tmp, *tmp1 = bb_xstrdup(filename);
809 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000810 if (strcmp(tmp, fullname) == 0) {
811 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000812 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000813 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000814 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000815 }
Eric Andersen14d35432001-05-14 17:07:32 +0000816 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000817 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000818 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000819}
820
Erik Andersen02104321999-12-17 18:57:34 +0000821
Eric Andersen9f16d612000-06-12 23:11:16 +0000822/*======================================================================*/
823
Eric Andersen044228d2001-07-17 01:12:36 +0000824static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000825{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000826 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000827 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828
Eric Andersencffd5022002-05-24 06:50:15 +0000829 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 return &f->root;
832}
833
Eric Andersen044228d2001-07-17 01:12:36 +0000834static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000835{
836 return xmalloc(sizeof(struct obj_section));
837}
838
Eric Andersen044228d2001-07-17 01:12:36 +0000839static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000840{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000841 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000842 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000843
Eric Andersencffd5022002-05-24 06:50:15 +0000844 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000845
Eric Andersen9f16d612000-06-12 23:11:16 +0000846 return &sym->root;
847}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000848
Eric Andersen044228d2001-07-17 01:12:36 +0000849static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000850arch_apply_relocation(struct obj_file *f,
851 struct obj_section *targsec,
852 struct obj_section *symsec,
853 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000854 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000855{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000856 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000857 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000858 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
859 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000860#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
861 struct arch_symbol *isym = (struct arch_symbol *) sym;
862#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000863#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000864 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000865#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000866#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000867 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000868 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000869#if defined(CONFIG_USE_PLT_LIST)
870 struct arch_list_entry *pe;
871#else
872 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000873#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000874#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000875
876 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000877
Eric Andersencffd5022002-05-24 06:50:15 +0000878
879#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000880 case R_ARM_NONE:
881 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000882
Eric Andersen3b1a7442003-12-24 20:30:45 +0000883 case R_ARM_ABS32:
884 *loc += v;
885 break;
Miles Baderae28b042002-04-01 09:34:25 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_GOT32:
888 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000889
Eric Andersen3b1a7442003-12-24 20:30:45 +0000890 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000891 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
892 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000893 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 assert(got);
896 *loc += got - dot;
897 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000898
Eric Andersen3b1a7442003-12-24 20:30:45 +0000899 case R_ARM_PC24:
900 case R_ARM_PLT32:
901 goto bb_use_plt;
902
903 case R_ARM_GOTOFF: /* address relative to the got */
904 assert(got);
905 *loc += v - got;
906 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000907
Eric Andersenbf77f612003-01-23 06:02:39 +0000908#elif defined(__s390__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000909 case R_390_32:
910 *(unsigned int *) loc += v;
911 break;
912 case R_390_16:
913 *(unsigned short *) loc += v;
914 break;
915 case R_390_8:
916 *(unsigned char *) loc += v;
917 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000918
Eric Andersen3b1a7442003-12-24 20:30:45 +0000919 case R_390_PC32:
920 *(unsigned int *) loc += v - dot;
921 break;
922 case R_390_PC16DBL:
923 *(unsigned short *) loc += (v - dot) >> 1;
924 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000925 case R_390_PC16:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000926 *(unsigned short *) loc += v - dot;
927 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000928
Eric Andersen3b1a7442003-12-24 20:30:45 +0000929 case R_390_PLT32:
930 case R_390_PLT16DBL:
931 /* find the plt entry and initialize it. */
932 assert(isym != NULL);
933 pe = (struct arch_single_entry *) &isym->pltent;
934 assert(pe->allocated);
935 if (pe->inited == 0) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000936 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000937 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
938 ip[1] = 0x100607f1;
939 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
940 ip[2] = v - 2;
941 else
942 ip[2] = v;
943 pe->inited = 1;
944 }
Eric Andersenbf77f612003-01-23 06:02:39 +0000945
Eric Andersen3b1a7442003-12-24 20:30:45 +0000946 /* Insert relative distance to target. */
947 v = plt + pe->offset - dot;
948 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
949 *(unsigned int *) loc = (unsigned int) v;
950 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
951 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
952 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000953
Eric Andersen3b1a7442003-12-24 20:30:45 +0000954 case R_390_GLOB_DAT:
955 case R_390_JMP_SLOT:
956 *loc = v;
957 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000958
Eric Andersen3b1a7442003-12-24 20:30:45 +0000959 case R_390_RELATIVE:
960 *loc += f->baseaddr;
961 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000962
Eric Andersen3b1a7442003-12-24 20:30:45 +0000963 case R_390_GOTPC:
964 assert(got != 0);
965 *(unsigned long *) loc += got - dot;
966 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000967
Eric Andersen3b1a7442003-12-24 20:30:45 +0000968 case R_390_GOT12:
969 case R_390_GOT16:
970 case R_390_GOT32:
971 assert(isym != NULL);
972 assert(got != 0);
973 if (!isym->gotent.inited)
974 {
975 isym->gotent.inited = 1;
976 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
977 }
978 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
979 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
980 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
981 *(unsigned short *) loc += isym->gotent.offset;
982 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
983 *(unsigned int *) loc += isym->gotent.offset;
984 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000985
Eric Andersen951df202003-10-21 06:45:29 +0000986#ifndef R_390_GOTOFF32
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000987#define R_390_GOTOFF32 R_390_GOTOFF
Eric Andersen951df202003-10-21 06:45:29 +0000988#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000989 case R_390_GOTOFF32:
990 assert(got != 0);
991 *loc += v - got;
992 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000993
Eric Andersencffd5022002-05-24 06:50:15 +0000994#elif defined(__i386__)
995
Eric Andersen3b1a7442003-12-24 20:30:45 +0000996 case R_386_NONE:
997 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000998
Eric Andersen3b1a7442003-12-24 20:30:45 +0000999 case R_386_32:
1000 *loc += v;
1001 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001002
Eric Andersen3b1a7442003-12-24 20:30:45 +00001003 case R_386_PLT32:
1004 case R_386_PC32:
1005 *loc += v - dot;
1006 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001007
Eric Andersen3b1a7442003-12-24 20:30:45 +00001008 case R_386_GLOB_DAT:
1009 case R_386_JMP_SLOT:
1010 *loc = v;
1011 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001012
Eric Andersen3b1a7442003-12-24 20:30:45 +00001013 case R_386_RELATIVE:
1014 *loc += f->baseaddr;
1015 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001016
Eric Andersen3b1a7442003-12-24 20:30:45 +00001017 case R_386_GOTPC:
1018 assert(got != 0);
1019 *loc += got - dot;
1020 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001021
Eric Andersen3b1a7442003-12-24 20:30:45 +00001022 case R_386_GOT32:
1023 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001024
Eric Andersen3b1a7442003-12-24 20:30:45 +00001025 case R_386_GOTOFF:
1026 assert(got != 0);
1027 *loc += v - got;
1028 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001029
1030#elif defined(__mc68000__)
1031
Eric Andersen3b1a7442003-12-24 20:30:45 +00001032 case R_68K_NONE:
1033 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001034
Eric Andersen3b1a7442003-12-24 20:30:45 +00001035 case R_68K_32:
1036 *loc += v;
1037 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001038
Eric Andersen3b1a7442003-12-24 20:30:45 +00001039 case R_68K_8:
1040 if (v > 0xff) {
1041 ret = obj_reloc_overflow;
1042 }
1043 *(char *)loc = v;
1044 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001045
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_16:
1047 if (v > 0xffff) {
1048 ret = obj_reloc_overflow;
1049 }
1050 *(short *)loc = v;
1051 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_68K_PC8:
1054 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001055 if ((Elf32_Sword)v > 0x7f ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001056 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1057 ret = obj_reloc_overflow;
1058 }
1059 *(char *)loc = v;
1060 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001061
Eric Andersen3b1a7442003-12-24 20:30:45 +00001062 case R_68K_PC16:
1063 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001064 if ((Elf32_Sword)v > 0x7fff ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001065 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1066 ret = obj_reloc_overflow;
1067 }
1068 *(short *)loc = v;
1069 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001070
Eric Andersen3b1a7442003-12-24 20:30:45 +00001071 case R_68K_PC32:
1072 *(int *)loc = v - dot;
1073 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001074
Eric Andersen3b1a7442003-12-24 20:30:45 +00001075 case R_68K_GLOB_DAT:
1076 case R_68K_JMP_SLOT:
1077 *loc = v;
1078 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001079
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080 case R_68K_RELATIVE:
1081 *(int *)loc += f->baseaddr;
1082 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001083
Eric Andersen3b1a7442003-12-24 20:30:45 +00001084 case R_68K_GOT32:
1085 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001086
Eric Andersen16451a02004-03-19 12:16:18 +00001087#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001088 case R_68K_GOTOFF:
1089 assert(got != 0);
1090 *loc += v - got;
1091 break;
Eric Andersen16451a02004-03-19 12:16:18 +00001092#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001093
1094#elif defined(__mips__)
1095
Eric Andersen3b1a7442003-12-24 20:30:45 +00001096 case R_MIPS_NONE:
1097 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001098
Eric Andersen3b1a7442003-12-24 20:30:45 +00001099 case R_MIPS_32:
1100 *loc += v;
1101 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001102
Eric Andersen3b1a7442003-12-24 20:30:45 +00001103 case R_MIPS_26:
1104 if (v % 4)
1105 ret = obj_reloc_dangerous;
1106 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1107 ret = obj_reloc_overflow;
1108 *loc =
1109 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1110 0x03ffffff);
1111 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001112
Eric Andersen3b1a7442003-12-24 20:30:45 +00001113 case R_MIPS_HI16:
1114 {
1115 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001116
Eric Andersen3b1a7442003-12-24 20:30:45 +00001117 /* We cannot relocate this one now because we don't know the value
1118 of the carry we need to add. Save the information, and let LO16
1119 do the actual relocation. */
1120 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1121 n->addr = loc;
1122 n->value = v;
1123 n->next = ifile->mips_hi16_list;
1124 ifile->mips_hi16_list = n;
1125 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001126 }
1127
Eric Andersen3b1a7442003-12-24 20:30:45 +00001128 case R_MIPS_LO16:
1129 {
1130 unsigned long insnlo = *loc;
1131 Elf32_Addr val, vallo;
1132
1133 /* Sign extend the addend we extract from the lo insn. */
1134 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1135
1136 if (ifile->mips_hi16_list != NULL) {
1137 struct mips_hi16 *l;
1138
1139 l = ifile->mips_hi16_list;
1140 while (l != NULL) {
1141 struct mips_hi16 *next;
1142 unsigned long insn;
1143
1144 /* The value for the HI16 had best be the same. */
1145 assert(v == l->value);
1146
1147 /* Do the HI16 relocation. Note that we actually don't
1148 need to know anything about the LO16 itself, except where
1149 to find the low 16 bits of the addend needed by the LO16. */
1150 insn = *l->addr;
1151 val =
1152 ((insn & 0xffff) << 16) +
1153 vallo;
1154 val += v;
1155
1156 /* Account for the sign extension that will happen in the
1157 low bits. */
1158 val =
1159 ((val >> 16) +
1160 ((val & 0x8000) !=
1161 0)) & 0xffff;
1162
1163 insn = (insn & ~0xffff) | val;
1164 *l->addr = insn;
1165
1166 next = l->next;
1167 free(l);
1168 l = next;
1169 }
1170
1171 ifile->mips_hi16_list = NULL;
1172 }
1173
1174 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1175 val = v + vallo;
1176 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1177 *loc = insnlo;
1178 break;
1179 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001180
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001181#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001182
Eric Andersen3b1a7442003-12-24 20:30:45 +00001183 case R_PPC_ADDR16_HA:
1184 *(unsigned short *)loc = (v + 0x8000) >> 16;
1185 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001186
Eric Andersen3b1a7442003-12-24 20:30:45 +00001187 case R_PPC_ADDR16_HI:
1188 *(unsigned short *)loc = v >> 16;
1189 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001190
Eric Andersen3b1a7442003-12-24 20:30:45 +00001191 case R_PPC_ADDR16_LO:
1192 *(unsigned short *)loc = v;
1193 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001194
Eric Andersen3b1a7442003-12-24 20:30:45 +00001195 case R_PPC_REL24:
1196 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001197
Eric Andersen3b1a7442003-12-24 20:30:45 +00001198 case R_PPC_REL32:
1199 *loc = v - dot;
1200 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001201
Eric Andersen3b1a7442003-12-24 20:30:45 +00001202 case R_PPC_ADDR32:
1203 *loc = v;
1204 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001205
1206#elif defined(__sh__)
1207
Eric Andersen3b1a7442003-12-24 20:30:45 +00001208 case R_SH_NONE:
1209 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001210
Eric Andersen3b1a7442003-12-24 20:30:45 +00001211 case R_SH_DIR32:
1212 *loc += v;
1213 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001214
Eric Andersen3b1a7442003-12-24 20:30:45 +00001215 case R_SH_REL32:
1216 *loc += v - dot;
1217 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001218
Eric Andersen3b1a7442003-12-24 20:30:45 +00001219 case R_SH_PLT32:
1220 *loc = v - dot;
1221 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001222
Eric Andersen3b1a7442003-12-24 20:30:45 +00001223 case R_SH_GLOB_DAT:
1224 case R_SH_JMP_SLOT:
1225 *loc = v;
1226 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001227
Eric Andersen3b1a7442003-12-24 20:30:45 +00001228 case R_SH_RELATIVE:
1229 *loc = f->baseaddr + rel->r_addend;
1230 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001231
Eric Andersen3b1a7442003-12-24 20:30:45 +00001232 case R_SH_GOTPC:
1233 assert(got != 0);
1234 *loc = got - dot + rel->r_addend;
1235 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001236
Eric Andersen3b1a7442003-12-24 20:30:45 +00001237 case R_SH_GOT32:
1238 goto bb_use_got;
1239
1240 case R_SH_GOTOFF:
1241 assert(got != 0);
1242 *loc = v - got;
1243 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001244
Eric Andersenbf833552003-08-13 19:56:33 +00001245#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001246 case R_SH_IMM_MEDLOW16:
1247 case R_SH_IMM_LOW16:
1248 {
1249 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001250
Eric Andersen3b1a7442003-12-24 20:30:45 +00001251 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1252 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001253
Eric Andersen3b1a7442003-12-24 20:30:45 +00001254 /*
1255 * movi and shori have the format:
1256 *
1257 * | op | imm | reg | reserved |
1258 * 31..26 25..10 9.. 4 3 .. 0
1259 *
1260 * so we simply mask and or in imm.
1261 */
1262 word = *loc & ~0x3fffc00;
1263 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001264
Eric Andersen3b1a7442003-12-24 20:30:45 +00001265 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001266
Eric Andersen3b1a7442003-12-24 20:30:45 +00001267 break;
1268 }
Eric Andersenbf833552003-08-13 19:56:33 +00001269
Eric Andersen3b1a7442003-12-24 20:30:45 +00001270 case R_SH_IMM_MEDLOW16_PCREL:
1271 case R_SH_IMM_LOW16_PCREL:
1272 {
1273 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001274
Eric Andersen3b1a7442003-12-24 20:30:45 +00001275 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001276
Eric Andersen3b1a7442003-12-24 20:30:45 +00001277 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001278
Eric Andersen3b1a7442003-12-24 20:30:45 +00001279 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1280 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001281
Eric Andersen3b1a7442003-12-24 20:30:45 +00001282 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001283
Eric Andersen3b1a7442003-12-24 20:30:45 +00001284 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001285
Eric Andersen3b1a7442003-12-24 20:30:45 +00001286 break;
1287 }
Eric Andersenbf833552003-08-13 19:56:33 +00001288#endif /* __SH5__ */
1289#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001290
Eric Andersen3b1a7442003-12-24 20:30:45 +00001291 default:
1292 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1293 ret = obj_reloc_unhandled;
1294 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001295
1296#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001297 case R_V850_NONE:
1298 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001299
Eric Andersen3b1a7442003-12-24 20:30:45 +00001300 case R_V850_32:
1301 /* We write two shorts instead of a long because even
1302 32-bit insns only need half-word alignment, but
1303 32-bit data needs to be long-word aligned. */
1304 v += ((unsigned short *)loc)[0];
1305 v += ((unsigned short *)loc)[1] << 16;
1306 ((unsigned short *)loc)[0] = v & 0xffff;
1307 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1308 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001309
Eric Andersen3b1a7442003-12-24 20:30:45 +00001310 case R_V850_22_PCREL:
1311 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001312#endif
1313
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001314#if defined (__cris__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001315 case R_CRIS_NONE:
1316 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001317
Eric Andersen3b1a7442003-12-24 20:30:45 +00001318 case R_CRIS_32:
1319 /* CRIS keeps the relocation value in the r_addend field and
1320 * should not use whats in *loc at all
1321 */
1322 *loc = v;
1323 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001324#endif
1325
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001326#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001327
Eric Andersen3b1a7442003-12-24 20:30:45 +00001328bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001329
Eric Andersen3b1a7442003-12-24 20:30:45 +00001330 /* find the plt entry and initialize it if necessary */
1331 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001332
Eric Andersencffd5022002-05-24 06:50:15 +00001333#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001334 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1335 pe = pe->next;
1336 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001337#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001338 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001339#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001340
Eric Andersen3b1a7442003-12-24 20:30:45 +00001341 if (! pe->inited) {
1342 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001343
Eric Andersen3b1a7442003-12-24 20:30:45 +00001344 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001345
1346#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001347 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1348 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001349#endif
1350#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001351 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1352 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1353 ip[2] = 0x7d6903a6; /* mtctr r11 */
1354 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001355#endif
Miles Baderae28b042002-04-01 09:34:25 +00001356#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 /* We have to trash a register, so we assume that any control
1358 transfer more than 21-bits away must be a function call
1359 (so we can use a call-clobbered register). */
1360 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1361 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001362#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001363 pe->inited = 1;
1364 }
Eric Andersen21adca72000-12-06 18:18:26 +00001365
Eric Andersen3b1a7442003-12-24 20:30:45 +00001366 /* relative distance to target */
1367 v -= dot;
1368 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001369#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001370 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001371#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001372 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001373#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001374 /* go via the plt */
1375 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001376
1377#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001378 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001379#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001380 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001381#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001382 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001383
Eric Andersen3b1a7442003-12-24 20:30:45 +00001384 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001385#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001386 /* Convert to words. */
1387 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001388
Eric Andersen3b1a7442003-12-24 20:30:45 +00001389 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001390#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001391#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001392 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001393#endif
Miles Baderae28b042002-04-01 09:34:25 +00001394#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001395 /* We write two shorts instead of a long because even 32-bit insns
1396 only need half-word alignment, but the 32-bit data write needs
1397 to be long-word aligned. */
1398 ((unsigned short *)loc)[0] =
1399 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1400 | ((v >> 16) & 0x3f); /* offs high part */
1401 ((unsigned short *)loc)[1] =
1402 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001403#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001404 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001405#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001406
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001407#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001408bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001409
Eric Andersen3b1a7442003-12-24 20:30:45 +00001410 assert(isym != NULL);
1411 /* needs an entry in the .got: set it, once */
1412 if (!isym->gotent.inited) {
1413 isym->gotent.inited = 1;
1414 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1415 }
1416 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001417#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001418 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001419#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001420 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001421#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001422 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001423
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001424#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001425 }
1426
1427 return ret;
1428}
1429
Eric Andersencffd5022002-05-24 06:50:15 +00001430
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001431#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001432
1433static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1434 int offset, int size)
1435{
1436 struct arch_list_entry *pe;
1437
1438 for (pe = *list; pe != NULL; pe = pe->next) {
1439 if (pe->addend == rel->r_addend) {
1440 break;
1441 }
1442 }
1443
1444 if (pe == NULL) {
1445 pe = xmalloc(sizeof(struct arch_list_entry));
1446 pe->next = *list;
1447 pe->addend = rel->r_addend;
1448 pe->offset = offset;
1449 pe->inited = 0;
1450 *list = pe;
1451 return size;
1452 }
1453 return 0;
1454}
1455
1456#endif
1457
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001458#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001459
1460static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1461 int offset, int size)
1462{
1463 if (single->allocated == 0) {
1464 single->allocated = 1;
1465 single->offset = offset;
1466 single->inited = 0;
1467 return size;
1468 }
1469 return 0;
1470}
1471
1472#endif
1473
1474#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1475
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001476static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001477 int offset, int size)
1478{
1479 struct obj_section *myrelsec = obj_find_section(f, name);
1480
1481 if (offset == 0) {
1482 offset += size;
1483 }
1484
1485 if (myrelsec) {
1486 obj_extend_section(myrelsec, offset);
1487 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001488 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001490 assert(myrelsec);
1491 }
1492
1493 return myrelsec;
1494}
1495
1496#endif
1497
1498static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001499{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001500#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001501 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001502 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001503#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001504 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001505#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001506#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001507 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001508#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001509 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001510 ElfW(RelM) *rel, *relend;
1511 ElfW(Sym) *symtab, *extsym;
1512 const char *strtab, *name;
1513 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001514
Eric Andersen21adca72000-12-06 18:18:26 +00001515 for (i = 0; i < f->header.e_shnum; ++i) {
1516 relsec = f->sections[i];
1517 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001518 continue;
1519
Eric Andersen21adca72000-12-06 18:18:26 +00001520 symsec = f->sections[relsec->header.sh_link];
1521 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001522
Eric Andersen21adca72000-12-06 18:18:26 +00001523 rel = (ElfW(RelM) *) relsec->contents;
1524 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1525 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001526 strtab = (const char *) strsec->contents;
1527
1528 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001529 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001530
Eric Andersencffd5022002-05-24 06:50:15 +00001531#if defined(CONFIG_USE_GOT_ENTRIES)
1532 got_allocate = 0;
1533#endif
1534#if defined(CONFIG_USE_PLT_ENTRIES)
1535 plt_allocate = 0;
1536#endif
1537
Eric Andersen9f16d612000-06-12 23:11:16 +00001538 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001539#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001540 case R_ARM_PC24:
1541 case R_ARM_PLT32:
1542 plt_allocate = 1;
1543 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001544
Eric Andersen3b1a7442003-12-24 20:30:45 +00001545 case R_ARM_GOTOFF:
1546 case R_ARM_GOTPC:
1547 got_needed = 1;
1548 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001549
Eric Andersen3b1a7442003-12-24 20:30:45 +00001550 case R_ARM_GOT32:
1551 got_allocate = 1;
1552 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001553
Eric Andersen21adca72000-12-06 18:18:26 +00001554#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001555 case R_386_GOTPC:
1556 case R_386_GOTOFF:
1557 got_needed = 1;
1558 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001559
Eric Andersen3b1a7442003-12-24 20:30:45 +00001560 case R_386_GOT32:
1561 got_allocate = 1;
1562 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001563
1564#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001565 case R_PPC_REL24:
1566 plt_allocate = 1;
1567 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001568
1569#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001570 case R_68K_GOT32:
1571 got_allocate = 1;
1572 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001573
Eric Andersen16451a02004-03-19 12:16:18 +00001574#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001575 case R_68K_GOTOFF:
1576 got_needed = 1;
1577 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001578#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001579
1580#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001581 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001582 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001583 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001584
Eric Andersen3b1a7442003-12-24 20:30:45 +00001585 case R_SH_GOTPC:
1586 case R_SH_GOTOFF:
1587 got_needed = 1;
1588 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001589
1590#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001591 case R_V850_22_PCREL:
1592 plt_needed = 1;
1593 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001594
1595#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001596 default:
1597 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001598 }
1599
Eric Andersen21adca72000-12-06 18:18:26 +00001600 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001601 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001602 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001603 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001604 }
1605 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001606#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001607 if (got_allocate) {
1608 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001609 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001610 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001611
1612 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001613 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001614#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001615#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001616 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001617#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001618 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001619 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001620 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001621#else
1622 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001623 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001624 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001625#endif
1626 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001627 }
1628#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001629 }
Miles Baderae28b042002-04-01 09:34:25 +00001630 }
Eric Andersen21adca72000-12-06 18:18:26 +00001631
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001632#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001633 if (got_needed) {
1634 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001635 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001636 }
Eric Andersen21adca72000-12-06 18:18:26 +00001637#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001638
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001639#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001640 if (plt_needed) {
1641 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001643 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001644#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001645
1646#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001647}
1648
Eric Andersene7047882003-12-11 01:42:13 +00001649#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +00001650static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001651{
1652 return 1;
1653}
Eric Andersen6d139642001-12-29 04:15:13 +00001654#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001655
1656/*======================================================================*/
1657
1658/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001659static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001660{
1661 unsigned long h = 0;
1662 unsigned long g;
1663 unsigned char ch;
1664
1665 while (n > 0) {
1666 ch = *name++;
1667 h = (h << 4) + ch;
1668 if ((g = (h & 0xf0000000)) != 0) {
1669 h ^= g >> 24;
1670 h &= ~g;
1671 }
1672 n--;
1673 }
1674 return h;
1675}
1676
Eric Andersen044228d2001-07-17 01:12:36 +00001677static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001678{
1679 return obj_elf_hash_n(name, strlen(name));
1680}
1681
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001682#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001683/* String comparison for non-co-versioned kernel and module. */
1684
1685static int ncv_strcmp(const char *a, const char *b)
1686{
1687 size_t alen = strlen(a), blen = strlen(b);
1688
1689 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1690 return strncmp(a, b, alen);
1691 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1692 return strncmp(a, b, blen);
1693 else
1694 return strcmp(a, b);
1695}
1696
1697/* String hashing for non-co-versioned kernel and module. Here
1698 we are simply forced to drop the crc from the hash. */
1699
1700static unsigned long ncv_symbol_hash(const char *str)
1701{
1702 size_t len = strlen(str);
1703 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1704 len -= 10;
1705 return obj_elf_hash_n(str, len);
1706}
1707
Eric Andersen044228d2001-07-17 01:12:36 +00001708static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001709obj_set_symbol_compare(struct obj_file *f,
1710 int (*cmp) (const char *, const char *),
1711 unsigned long (*hash) (const char *))
1712{
1713 if (cmp)
1714 f->symbol_cmp = cmp;
1715 if (hash) {
1716 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1717 int i;
1718
1719 f->symbol_hash = hash;
1720
1721 memcpy(tmptab, f->symtab, sizeof(tmptab));
1722 memset(f->symtab, 0, sizeof(f->symtab));
1723
1724 for (i = 0; i < HASH_BUCKETS; ++i)
1725 for (sym = tmptab[i]; sym; sym = next) {
1726 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1727 next = sym->next;
1728 sym->next = f->symtab[h];
1729 f->symtab[h] = sym;
1730 }
1731 }
1732}
1733
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001734#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001735
Eric Andersen044228d2001-07-17 01:12:36 +00001736static struct obj_symbol *
1737obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001738 unsigned long symidx, int info,
1739 int secidx, ElfW(Addr) value,
1740 unsigned long size)
1741{
1742 struct obj_symbol *sym;
1743 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1744 int n_type = ELFW(ST_TYPE) (info);
1745 int n_binding = ELFW(ST_BIND) (info);
1746
1747 for (sym = f->symtab[hash]; sym; sym = sym->next)
1748 if (f->symbol_cmp(sym->name, name) == 0) {
1749 int o_secidx = sym->secidx;
1750 int o_info = sym->info;
1751 int o_type = ELFW(ST_TYPE) (o_info);
1752 int o_binding = ELFW(ST_BIND) (o_info);
1753
1754 /* A redefinition! Is it legal? */
1755
1756 if (secidx == SHN_UNDEF)
1757 return sym;
1758 else if (o_secidx == SHN_UNDEF)
1759 goto found;
1760 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1761 /* Cope with local and global symbols of the same name
1762 in the same object file, as might have been created
1763 by ld -r. The only reason locals are now seen at this
1764 level at all is so that we can do semi-sensible things
1765 with parameters. */
1766
1767 struct obj_symbol *nsym, **p;
1768
1769 nsym = arch_new_symbol();
1770 nsym->next = sym->next;
1771 nsym->ksymidx = -1;
1772
1773 /* Excise the old (local) symbol from the hash chain. */
1774 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1775 continue;
1776 *p = sym = nsym;
1777 goto found;
1778 } else if (n_binding == STB_LOCAL) {
1779 /* Another symbol of the same name has already been defined.
1780 Just add this to the local table. */
1781 sym = arch_new_symbol();
1782 sym->next = NULL;
1783 sym->ksymidx = -1;
1784 f->local_symtab[symidx] = sym;
1785 goto found;
1786 } else if (n_binding == STB_WEAK)
1787 return sym;
1788 else if (o_binding == STB_WEAK)
1789 goto found;
1790 /* Don't unify COMMON symbols with object types the programmer
1791 doesn't expect. */
1792 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001793 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001794 return sym;
1795 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001796 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001797 goto found;
1798 else {
1799 /* Don't report an error if the symbol is coming from
1800 the kernel or some external module. */
1801 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001802 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001803 return sym;
1804 }
1805 }
1806
1807 /* Completely new symbol. */
1808 sym = arch_new_symbol();
1809 sym->next = f->symtab[hash];
1810 f->symtab[hash] = sym;
1811 sym->ksymidx = -1;
1812
Eric Andersen66ca9482001-06-28 21:36:06 +00001813 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1814 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001815 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001816 name, (long) symidx, (long) f->local_symtab_size);
1817 else
1818 f->local_symtab[symidx] = sym;
1819 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001820
Eric Andersen3b1a7442003-12-24 20:30:45 +00001821found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001822 sym->name = name;
1823 sym->value = value;
1824 sym->size = size;
1825 sym->secidx = secidx;
1826 sym->info = info;
1827
1828 return sym;
1829}
1830
Eric Andersen044228d2001-07-17 01:12:36 +00001831static struct obj_symbol *
1832obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001833{
1834 struct obj_symbol *sym;
1835 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1836
1837 for (sym = f->symtab[hash]; sym; sym = sym->next)
1838 if (f->symbol_cmp(sym->name, name) == 0)
1839 return sym;
1840
1841 return NULL;
1842}
1843
Eric Andersen044228d2001-07-17 01:12:36 +00001844static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001845 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1846{
1847 if (sym) {
1848 if (sym->secidx >= SHN_LORESERVE)
1849 return sym->value;
1850
1851 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1852 } else {
1853 /* As a special case, a NULL sym has value zero. */
1854 return 0;
1855 }
1856}
1857
Eric Andersen044228d2001-07-17 01:12:36 +00001858static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001859{
1860 int i, n = f->header.e_shnum;
1861
1862 for (i = 0; i < n; ++i)
1863 if (strcmp(f->sections[i]->name, name) == 0)
1864 return f->sections[i];
1865
1866 return NULL;
1867}
1868
1869static int obj_load_order_prio(struct obj_section *a)
1870{
1871 unsigned long af, ac;
1872
1873 af = a->header.sh_flags;
1874
1875 ac = 0;
1876 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001877 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001878 ac |= 32;
1879 if (af & SHF_ALLOC)
1880 ac |= 16;
1881 if (!(af & SHF_WRITE))
1882 ac |= 8;
1883 if (af & SHF_EXECINSTR)
1884 ac |= 4;
1885 if (a->header.sh_type != SHT_NOBITS)
1886 ac |= 2;
1887
1888 return ac;
1889}
1890
Eric Andersen044228d2001-07-17 01:12:36 +00001891static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001892obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1893{
1894 struct obj_section **p;
1895 int prio = obj_load_order_prio(sec);
1896 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1897 if (obj_load_order_prio(*p) < prio)
1898 break;
1899 sec->load_next = *p;
1900 *p = sec;
1901}
1902
Eric Andersen044228d2001-07-17 01:12:36 +00001903static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001904 const char *name,
1905 unsigned long align,
1906 unsigned long size)
1907{
1908 int newidx = f->header.e_shnum++;
1909 struct obj_section *sec;
1910
1911 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1912 f->sections[newidx] = sec = arch_new_section();
1913
1914 memset(sec, 0, sizeof(*sec));
1915 sec->header.sh_type = SHT_PROGBITS;
1916 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1917 sec->header.sh_size = size;
1918 sec->header.sh_addralign = align;
1919 sec->name = name;
1920 sec->idx = newidx;
1921 if (size)
1922 sec->contents = xmalloc(size);
1923
1924 obj_insert_section_load_order(f, sec);
1925
1926 return sec;
1927}
1928
Eric Andersen044228d2001-07-17 01:12:36 +00001929static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001930 const char *name,
1931 unsigned long align,
1932 unsigned long size)
1933{
1934 int newidx = f->header.e_shnum++;
1935 struct obj_section *sec;
1936
1937 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1938 f->sections[newidx] = sec = arch_new_section();
1939
1940 memset(sec, 0, sizeof(*sec));
1941 sec->header.sh_type = SHT_PROGBITS;
1942 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1943 sec->header.sh_size = size;
1944 sec->header.sh_addralign = align;
1945 sec->name = name;
1946 sec->idx = newidx;
1947 if (size)
1948 sec->contents = xmalloc(size);
1949
1950 sec->load_next = f->load_order;
1951 f->load_order = sec;
1952 if (f->load_order_search_start == &f->load_order)
1953 f->load_order_search_start = &sec->load_next;
1954
1955 return sec;
1956}
1957
Eric Andersen044228d2001-07-17 01:12:36 +00001958static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00001959{
1960 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001961 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00001962 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
1963 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001964 return sec->contents + oldsize;
1965}
1966
1967
Eric Andersen9f16d612000-06-12 23:11:16 +00001968/* Conditionally add the symbols from the given symbol set to the
1969 new module. */
1970
1971static int
1972add_symbols_from(
1973 struct obj_file *f,
1974 int idx, struct new_module_symbol *syms, size_t nsyms)
1975{
1976 struct new_module_symbol *s;
1977 size_t i;
1978 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00001979#ifdef SYMBOL_PREFIX
1980 char *name_buf = 0;
1981 size_t name_alloced_size = 0;
1982#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001983#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
1984 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00001985
Glenn L McGrath759515c2003-08-30 06:00:33 +00001986 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00001987#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001988 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00001989 /* Only add symbols that are already marked external.
1990 If we override locals we may cause problems for
1991 argument initialization. We will also create a false
1992 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00001993 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00001994 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00001995
Glenn L McGrath759515c2003-08-30 06:00:33 +00001996 /* GPL licensed modules can use symbols exported with
1997 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
1998 * exported names. Non-GPL modules never see any GPLONLY_
1999 * symbols so they cannot fudge it by adding the prefix on
2000 * their references.
2001 */
2002 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002003#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002004 if (gpl)
2005 ((char *)s->name) += 8;
2006 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002007#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002008 continue;
2009 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002010 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002011
Miles Baderae28b042002-04-01 09:34:25 +00002012#ifdef SYMBOL_PREFIX
2013 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2014 kernel exports `C names', but module object files
2015 reference `linker names'). */
2016 size_t extra = sizeof SYMBOL_PREFIX;
2017 size_t name_size = strlen (name) + extra;
2018 if (name_size > name_alloced_size) {
2019 name_alloced_size = name_size * 2;
2020 name_buf = alloca (name_alloced_size);
2021 }
2022 strcpy (name_buf, SYMBOL_PREFIX);
2023 strcpy (name_buf + extra - 1, name);
2024 name = name_buf;
2025#endif /* SYMBOL_PREFIX */
2026
2027 sym = obj_find_symbol(f, name);
2028 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
2029#ifdef SYMBOL_PREFIX
2030 /* Put NAME_BUF into more permanent storage. */
2031 name = xmalloc (name_size);
2032 strcpy (name, name_buf);
2033#endif
2034 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002035 ELFW(ST_INFO) (STB_GLOBAL,
2036 STT_NOTYPE),
2037 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002038 /* Did our symbol just get installed? If so, mark the
2039 module as "used". */
2040 if (sym->secidx == idx)
2041 used = 1;
2042 }
2043 }
2044
2045 return used;
2046}
2047
2048static void add_kernel_symbols(struct obj_file *f)
2049{
2050 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002051 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002052
2053 /* Add module symbols first. */
2054
2055 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2056 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002057 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2058 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002059
2060 n_ext_modules_used = nused;
2061
2062 /* And finally the symbols from the kernel proper. */
2063
2064 if (nksyms)
2065 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2066}
2067
2068static char *get_modinfo_value(struct obj_file *f, const char *key)
2069{
2070 struct obj_section *sec;
2071 char *p, *v, *n, *ep;
2072 size_t klen = strlen(key);
2073
2074 sec = obj_find_section(f, ".modinfo");
2075 if (sec == NULL)
2076 return NULL;
2077 p = sec->contents;
2078 ep = p + sec->header.sh_size;
2079 while (p < ep) {
2080 v = strchr(p, '=');
2081 n = strchr(p, '\0');
2082 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002083 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002084 return v + 1;
2085 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002086 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002087 return n;
2088 }
2089 p = n + 1;
2090 }
2091
2092 return NULL;
2093}
2094
2095
2096/*======================================================================*/
2097/* Functions relating to module loading in pre 2.1 kernels. */
2098
2099static int
2100old_process_module_arguments(struct obj_file *f, int argc, char **argv)
2101{
2102 while (argc > 0) {
2103 char *p, *q;
2104 struct obj_symbol *sym;
2105 int *loc;
2106
2107 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002108 if ((q = strchr(p, '=')) == NULL) {
2109 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002110 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002111 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002112 *q++ = '\0';
2113
2114 sym = obj_find_symbol(f, p);
2115
2116 /* Also check that the parameter was not resolved from the kernel. */
2117 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002118 bb_error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002119 return 0;
2120 }
2121
2122 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
2123
2124 /* Do C quoting if we begin with a ". */
2125 if (*q == '"') {
2126 char *r, *str;
2127
2128 str = alloca(strlen(q));
2129 for (r = str, q++; *q != '"'; ++q, ++r) {
2130 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002131 bb_error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002132 return 0;
2133 } else if (*q == '\\')
2134 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002135 case 'a':
2136 *r = '\a';
2137 break;
2138 case 'b':
2139 *r = '\b';
2140 break;
2141 case 'e':
2142 *r = '\033';
2143 break;
2144 case 'f':
2145 *r = '\f';
2146 break;
2147 case 'n':
2148 *r = '\n';
2149 break;
2150 case 'r':
2151 *r = '\r';
2152 break;
2153 case 't':
2154 *r = '\t';
2155 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002156
Eric Andersen3b1a7442003-12-24 20:30:45 +00002157 case '0':
2158 case '1':
2159 case '2':
2160 case '3':
2161 case '4':
2162 case '5':
2163 case '6':
2164 case '7':
2165 {
2166 int c = *q - '0';
2167 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002168 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002169 if (q[1] >= '0' && q[1] <= '7')
2170 c = (c * 8) + *++q - '0';
2171 }
2172 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002173 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002174 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002175
Eric Andersen3b1a7442003-12-24 20:30:45 +00002176 default:
2177 *r = *q;
2178 break;
2179 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002180 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002181 }
2182 *r = '\0';
2183 obj_string_patch(f, sym->secidx, sym->value, str);
2184 } else if (*q >= '0' && *q <= '9') {
2185 do
2186 *loc++ = strtoul(q, &q, 0);
2187 while (*q++ == ',');
2188 } else {
2189 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00002190 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002191 char *r; /* To search for commas */
2192
2193 /* Break the string with comas */
2194 while ((r = strchr(q, ',')) != (char *) NULL) {
2195 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00002196 obj_string_patch(f, sym->secidx, myloc - contents, q);
2197 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00002198 q = r;
2199 }
2200
2201 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00002202 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00002203 }
2204
2205 argc--, argv++;
2206 }
2207
2208 return 1;
2209}
2210
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002211#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002212static int old_is_module_checksummed(struct obj_file *f)
2213{
2214 return obj_find_symbol(f, "Using_Versions") != NULL;
2215}
2216/* Get the module's kernel version in the canonical integer form. */
2217
2218static int
2219old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2220{
2221 struct obj_symbol *sym;
2222 char *p, *q;
2223 int a, b, c;
2224
2225 sym = obj_find_symbol(f, "kernel_version");
2226 if (sym == NULL)
2227 return -1;
2228
2229 p = f->sections[sym->secidx]->contents + sym->value;
Eric Andersen2d342152002-06-18 05:16:25 +00002230 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002231
2232 a = strtoul(p, &p, 10);
2233 if (*p != '.')
2234 return -1;
2235 b = strtoul(p + 1, &p, 10);
2236 if (*p != '.')
2237 return -1;
2238 c = strtoul(p + 1, &q, 10);
2239 if (p + 1 == q)
2240 return -1;
2241
2242 return a << 16 | b << 8 | c;
2243}
2244
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002245#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002246
Eric Andersene7047882003-12-11 01:42:13 +00002247#ifdef CONFIG_FEATURE_2_2_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00002248
2249/* Fetch all the symbols and divvy them up as appropriate for the modules. */
2250
Eric Andersen8c185f92000-09-22 00:38:07 +00002251static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002252{
2253 struct old_kernel_sym *ks, *k;
2254 struct new_module_symbol *s;
2255 struct external_module *mod;
2256 int nks, nms, nmod, i;
2257
2258 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00002259 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002260 if (nks)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002261 bb_perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002262 else
Manuel Novoa III cad53642003-03-19 09:13:01 +00002263 bb_error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00002264 return 0;
2265 }
2266
2267 ks = k = xmalloc(nks * sizeof(*ks));
2268
2269 if (get_kernel_syms(ks) != nks) {
2270 perror("inconsistency with get_kernel_syms -- is someone else "
Eric Andersen3b1a7442003-12-24 20:30:45 +00002271 "playing with modules?");
Eric Andersen9f16d612000-06-12 23:11:16 +00002272 free(ks);
2273 return 0;
2274 }
2275
2276 /* Collect the module information. */
2277
2278 mod = NULL;
2279 nmod = -1;
2280
2281 while (k->name[0] == '#' && k->name[1]) {
2282 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00002283
2284 /* Find out how many symbols this module has. */
2285 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
2286 continue;
2287 nms = k2 - k - 1;
2288
2289 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
2290 mod[nmod].name = k->name + 1;
2291 mod[nmod].addr = k->value;
2292 mod[nmod].used = 0;
2293 mod[nmod].nsyms = nms;
2294 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2295
2296 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
2297 s->name = (unsigned long) k->name;
2298 s->value = k->value;
2299 }
2300
2301 k = k2;
2302 }
2303
2304 ext_modules = mod;
2305 n_ext_modules = nmod + 1;
2306
2307 /* Now collect the symbols for the kernel proper. */
2308
2309 if (k->name[0] == '#')
2310 ++k;
2311
2312 nksyms = nms = nks - (k - ks);
2313 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2314
2315 for (i = 0; i < nms; ++i, ++s, ++k) {
2316 s->name = (unsigned long) k->name;
2317 s->value = k->value;
2318 }
2319
2320 return 1;
2321}
2322
2323/* Return the kernel symbol checksum version, or zero if not used. */
2324
2325static int old_is_kernel_checksummed(void)
2326{
2327 /* Using_Versions is the first symbol. */
2328 if (nksyms > 0
Eric Andersen3b1a7442003-12-24 20:30:45 +00002329 && strcmp((char *) ksyms[0].name,
2330 "Using_Versions") == 0) return ksyms[0].value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002331 else
2332 return 0;
2333}
2334
2335
2336static int old_create_mod_use_count(struct obj_file *f)
2337{
2338 struct obj_section *sec;
2339
2340 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002341 sizeof(long));
Eric Andersen9f16d612000-06-12 23:11:16 +00002342
2343 obj_add_symbol(f, "mod_use_count_", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002344 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2345 sizeof(long));
Eric Andersen9f16d612000-06-12 23:11:16 +00002346
2347 return 1;
2348}
2349
2350static int
2351old_init_module(const char *m_name, struct obj_file *f,
2352 unsigned long m_size)
2353{
2354 char *image;
2355 struct old_mod_routines routines;
2356 struct old_symbol_table *symtab;
2357 int ret;
2358
2359 /* Create the symbol table */
2360 {
2361 int nsyms = 0, strsize = 0, total;
2362
2363 /* Size things first... */
2364 if (flag_export) {
2365 int i;
2366 for (i = 0; i < HASH_BUCKETS; ++i) {
2367 struct obj_symbol *sym;
2368 for (sym = f->symtab[i]; sym; sym = sym->next)
2369 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002370 && sym->secidx <= SHN_HIRESERVE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002371 {
2372 sym->ksymidx = nsyms++;
2373 strsize += strlen(sym->name) + 1;
2374 }
2375 }
2376 }
2377
2378 total = (sizeof(struct old_symbol_table)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002379 + nsyms * sizeof(struct old_module_symbol)
2380 + n_ext_modules_used * sizeof(struct old_module_ref)
2381 + strsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002382 symtab = xmalloc(total);
2383 symtab->size = total;
2384 symtab->n_symbols = nsyms;
2385 symtab->n_refs = n_ext_modules_used;
2386
2387 if (flag_export && nsyms) {
2388 struct old_module_symbol *ksym;
2389 char *str;
2390 int i;
2391
2392 ksym = symtab->symbol;
2393 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002394 + n_ext_modules_used * sizeof(struct old_module_ref));
Eric Andersen9f16d612000-06-12 23:11:16 +00002395
2396 for (i = 0; i < HASH_BUCKETS; ++i) {
2397 struct obj_symbol *sym;
2398 for (sym = f->symtab[i]; sym; sym = sym->next)
2399 if (sym->ksymidx >= 0) {
2400 ksym->addr = obj_symbol_final_value(f, sym);
2401 ksym->name =
2402 (unsigned long) str - (unsigned long) symtab;
2403
Matt Kraai70a78552001-01-04 02:00:17 +00002404 strcpy(str, sym->name);
2405 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 ksym++;
2407 }
2408 }
2409 }
2410
2411 if (n_ext_modules_used) {
2412 struct old_module_ref *ref;
2413 int i;
2414
2415 ref = (struct old_module_ref *)
2416 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2417
2418 for (i = 0; i < n_ext_modules; ++i)
2419 if (ext_modules[i].used)
2420 ref++->module = ext_modules[i].addr;
2421 }
2422 }
2423
2424 /* Fill in routines. */
2425
2426 routines.init =
Miles Baderae28b042002-04-01 09:34:25 +00002427 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002428 routines.cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002429 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002430
2431 /* Whew! All of the initialization is complete. Collect the final
2432 module image and give it to the kernel. */
2433
2434 image = xmalloc(m_size);
2435 obj_create_image(f, image);
2436
2437 /* image holds the complete relocated module, accounting correctly for
2438 mod_use_count. However the old module kernel support assume that
2439 it is receiving something which does not contain mod_use_count. */
2440 ret = old_sys_init_module(m_name, image + sizeof(long),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002441 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2442 : 0), &routines, symtab);
Eric Andersen9f16d612000-06-12 23:11:16 +00002443 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002444 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002445
2446 free(image);
2447 free(symtab);
2448
2449 return ret == 0;
2450}
2451
2452#else
2453
2454#define old_create_mod_use_count(x) TRUE
2455#define old_init_module(x, y, z) TRUE
2456
Eric Andersene7047882003-12-11 01:42:13 +00002457#endif /* CONFIG_FEATURE_2_2_MODULES */
Eric Andersen9f16d612000-06-12 23:11:16 +00002458
2459
2460
2461/*======================================================================*/
2462/* Functions relating to module loading after 2.1.18. */
2463
2464static int
2465new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2466{
2467 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002468 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002469 struct obj_symbol *sym;
2470 char *contents, *loc;
2471 int min, max, n;
2472
2473 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002474 if ((q = strchr(p, '=')) == NULL) {
2475 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002476 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002477 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002478
2479 key = alloca(q - p + 6);
2480 memcpy(key, "parm_", 5);
2481 memcpy(key + 5, p, q - p);
2482 key[q - p + 5] = 0;
2483
2484 p = get_modinfo_value(f, key);
2485 key += 5;
2486 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002487 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002488 return 0;
2489 }
2490
Miles Baderae28b042002-04-01 09:34:25 +00002491#ifdef SYMBOL_PREFIX
2492 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2493 strcpy (sym_name, SYMBOL_PREFIX);
2494 strcat (sym_name, key);
2495#else
2496 sym_name = key;
2497#endif
2498 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002499
2500 /* Also check that the parameter was not resolved from the kernel. */
2501 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002502 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002503 return 0;
2504 }
2505
2506 if (isdigit(*p)) {
2507 min = strtoul(p, &p, 10);
2508 if (*p == '-')
2509 max = strtoul(p + 1, &p, 10);
2510 else
2511 max = min;
2512 } else
2513 min = max = 1;
2514
2515 contents = f->sections[sym->secidx]->contents;
2516 loc = contents + sym->value;
2517 n = (*++q != '\0');
2518
2519 while (1) {
2520 if ((*p == 's') || (*p == 'c')) {
2521 char *str;
2522
2523 /* Do C quoting if we begin with a ", else slurp the lot. */
2524 if (*q == '"') {
2525 char *r;
2526
2527 str = alloca(strlen(q));
2528 for (r = str, q++; *q != '"'; ++q, ++r) {
2529 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002530 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002531 key);
2532 return 0;
2533 } else if (*q == '\\')
2534 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002535 case 'a':
2536 *r = '\a';
2537 break;
2538 case 'b':
2539 *r = '\b';
2540 break;
2541 case 'e':
2542 *r = '\033';
2543 break;
2544 case 'f':
2545 *r = '\f';
2546 break;
2547 case 'n':
2548 *r = '\n';
2549 break;
2550 case 'r':
2551 *r = '\r';
2552 break;
2553 case 't':
2554 *r = '\t';
2555 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002556
Eric Andersen3b1a7442003-12-24 20:30:45 +00002557 case '0':
2558 case '1':
2559 case '2':
2560 case '3':
2561 case '4':
2562 case '5':
2563 case '6':
2564 case '7':
2565 {
2566 int c = *q - '0';
2567 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002568 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002569 if (q[1] >= '0' && q[1] <= '7')
2570 c = (c * 8) + *++q - '0';
2571 }
2572 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002573 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002574 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002575
Eric Andersen3b1a7442003-12-24 20:30:45 +00002576 default:
2577 *r = *q;
2578 break;
2579 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002580 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002581 }
2582 *r = '\0';
2583 ++q;
2584 } else {
2585 char *r;
2586
2587 /* In this case, the string is not quoted. We will break
2588 it using the coma (like for ints). If the user wants to
2589 include comas in a string, he just has to quote it */
2590
2591 /* Search the next coma */
2592 r = strchr(q, ',');
2593
2594 /* Found ? */
2595 if (r != (char *) NULL) {
2596 /* Recopy the current field */
2597 str = alloca(r - q + 1);
2598 memcpy(str, q, r - q);
2599
Eric Andersenaff114c2004-04-14 17:51:38 +00002600 /* I don't know if it is useful, as the previous case
2601 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002602 str[r - q] = '\0';
2603
2604 /* Keep next fields */
2605 q = r;
2606 } else {
2607 /* last string */
2608 str = q;
2609 q = "";
2610 }
2611 }
2612
2613 if (*p == 's') {
2614 /* Normal string */
2615 obj_string_patch(f, sym->secidx, loc - contents, str);
2616 loc += tgt_sizeof_char_p;
2617 } else {
2618 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002619 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002620
2621 /* Get the size of each member */
2622 /* Probably we should do that outside the loop ? */
2623 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002624 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002625 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002626 return 0;
2627 }
2628 charssize = strtoul(p + 1, (char **) NULL, 10);
2629
2630 /* Check length */
2631 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002632 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002633 charssize - 1);
2634 return 0;
2635 }
2636
2637 /* Copy to location */
2638 strcpy((char *) loc, str);
2639 loc += charssize;
2640 }
2641 } else {
2642 long v = strtoul(q, &q, 0);
2643 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002644 case 'b':
2645 *loc++ = v;
2646 break;
2647 case 'h':
2648 *(short *) loc = v;
2649 loc += tgt_sizeof_short;
2650 break;
2651 case 'i':
2652 *(int *) loc = v;
2653 loc += tgt_sizeof_int;
2654 break;
2655 case 'l':
2656 *(long *) loc = v;
2657 loc += tgt_sizeof_long;
2658 break;
2659
2660 default:
2661 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2662 return 0;
2663 }
2664 }
2665
2666retry_end_of_value:
2667 switch (*q) {
2668 case '\0':
2669 goto end_of_arg;
2670
2671 case ' ':
2672 case '\t':
2673 case '\n':
2674 case '\r':
2675 ++q;
2676 goto retry_end_of_value;
2677
2678 case ',':
2679 if (++n > max) {
2680 bb_error_msg("too many values for %s (max %d)", key, max);
2681 return 0;
2682 }
2683 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002684 break;
2685
2686 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002687 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002688 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002689 }
2690 }
2691
Eric Andersen3b1a7442003-12-24 20:30:45 +00002692end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002694 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002695 return 0;
2696 }
2697
2698 argc--, argv++;
2699 }
2700
2701 return 1;
2702}
2703
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002704#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002705static int new_is_module_checksummed(struct obj_file *f)
2706{
2707 const char *p = get_modinfo_value(f, "using_checksums");
2708 if (p)
2709 return atoi(p);
2710 else
2711 return 0;
2712}
2713
2714/* Get the module's kernel version in the canonical integer form. */
2715
2716static int
2717new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2718{
2719 char *p, *q;
2720 int a, b, c;
2721
2722 p = get_modinfo_value(f, "kernel_version");
2723 if (p == NULL)
2724 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002725 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002726
2727 a = strtoul(p, &p, 10);
2728 if (*p != '.')
2729 return -1;
2730 b = strtoul(p + 1, &p, 10);
2731 if (*p != '.')
2732 return -1;
2733 c = strtoul(p + 1, &q, 10);
2734 if (p + 1 == q)
2735 return -1;
2736
2737 return a << 16 | b << 8 | c;
2738}
2739
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002740#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002741
2742
Eric Andersene7047882003-12-11 01:42:13 +00002743#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00002744
2745/* Fetch the loaded modules, and all currently exported symbols. */
2746
2747static int new_get_kernel_symbols(void)
2748{
2749 char *module_names, *mn;
2750 struct external_module *modules, *m;
2751 struct new_module_symbol *syms, *s;
2752 size_t ret, bufsize, nmod, nsyms, i, j;
2753
2754 /* Collect the loaded modules. */
2755
2756 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002757retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002758 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002759 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002760 module_names = xrealloc(module_names, bufsize = ret);
2761 goto retry_modules_load;
2762 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002763 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002764 return 0;
2765 }
2766
2767 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002768
2769 /* Collect the modules' symbols. */
2770
Mark Whitley94fd4802001-03-12 23:08:34 +00002771 if (nmod){
2772 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2773 memset(modules, 0, nmod * sizeof(*modules));
2774 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002775 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002776 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002777
Mark Whitley94fd4802001-03-12 23:08:34 +00002778 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2779 if (errno == ENOENT) {
2780 /* The module was removed out from underneath us. */
2781 continue;
2782 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002783 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002784 return 0;
2785 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002786
Mark Whitley94fd4802001-03-12 23:08:34 +00002787 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002788retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002789 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2790 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002791 case ENOSPC:
2792 syms = xrealloc(syms, bufsize = ret);
2793 goto retry_mod_sym_load;
2794 case ENOENT:
2795 /* The module was removed out from underneath us. */
2796 continue;
2797 default:
2798 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2799 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002800 }
2801 }
2802 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002803
Mark Whitley94fd4802001-03-12 23:08:34 +00002804 m->name = mn;
2805 m->addr = info.addr;
2806 m->nsyms = nsyms;
2807 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002808
Mark Whitley94fd4802001-03-12 23:08:34 +00002809 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2810 s->name += (unsigned long) syms;
2811 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002812 }
2813 }
2814
2815 /* Collect the kernel's symbols. */
2816
2817 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002818retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002819 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002820 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002821 syms = xrealloc(syms, bufsize = ret);
2822 goto retry_kern_sym_load;
2823 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002824 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002825 return 0;
2826 }
2827 nksyms = nsyms = ret;
2828 ksyms = syms;
2829
2830 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2831 s->name += (unsigned long) syms;
2832 }
2833 return 1;
2834}
2835
2836
2837/* Return the kernel symbol checksum version, or zero if not used. */
2838
2839static int new_is_kernel_checksummed(void)
2840{
2841 struct new_module_symbol *s;
2842 size_t i;
2843
2844 /* Using_Versions is not the first symbol, but it should be in there. */
2845
2846 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2847 if (strcmp((char *) s->name, "Using_Versions") == 0)
2848 return s->value;
2849
2850 return 0;
2851}
2852
2853
2854static int new_create_this_module(struct obj_file *f, const char *m_name)
2855{
2856 struct obj_section *sec;
2857
2858 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002859 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002860 memset(sec->contents, 0, sizeof(struct new_module));
2861
Miles Baderae28b042002-04-01 09:34:25 +00002862 obj_add_symbol(f, SPFX "__this_module", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002863 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2864 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002865
2866 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002867 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002868
2869 return 1;
2870}
2871
Eric Andersen889dd202003-01-23 04:48:34 +00002872#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2873/* add an entry to the __ksymtab section, creating it if necessary */
2874static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2875{
2876 struct obj_section *sec;
2877 ElfW(Addr) ofs;
2878
2879 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2880 * If __ksymtab is defined but not marked alloc, x out the first character
2881 * (no obj_delete routine) and create a new __ksymtab with the correct
2882 * characteristics.
2883 */
2884 sec = obj_find_section(f, "__ksymtab");
2885 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2886 *((char *)(sec->name)) = 'x'; /* override const */
2887 sec = NULL;
2888 }
2889 if (!sec)
2890 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002891 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002892 if (!sec)
2893 return;
2894 sec->header.sh_flags |= SHF_ALLOC;
2895 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002896 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002897 ofs = sec->header.sh_size;
2898 obj_symbol_patch(f, sec->idx, ofs, sym);
2899 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2900 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2901}
2902#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002903
2904static int new_create_module_ksymtab(struct obj_file *f)
2905{
2906 struct obj_section *sec;
2907 int i;
2908
2909 /* We must always add the module references. */
2910
2911 if (n_ext_modules_used) {
2912 struct new_module_ref *dep;
2913 struct obj_symbol *tm;
2914
2915 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002916 (sizeof(struct new_module_ref)
2917 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002918 if (!sec)
2919 return 0;
2920
Miles Baderae28b042002-04-01 09:34:25 +00002921 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002922 dep = (struct new_module_ref *) sec->contents;
2923 for (i = 0; i < n_ext_modules; ++i)
2924 if (ext_modules[i].used) {
2925 dep->dep = ext_modules[i].addr;
2926 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002927 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002928 dep->next_ref = 0;
2929 ++dep;
2930 }
2931 }
2932
2933 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2934 size_t nsyms;
2935 int *loaded;
2936
2937 sec =
2938 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002939 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002940
2941 /* We don't want to export symbols residing in sections that
2942 aren't loaded. There are a number of these created so that
2943 we make sure certain module options don't appear twice. */
2944
2945 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2946 while (--i >= 0)
2947 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2948
2949 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2950 struct obj_symbol *sym;
2951 for (sym = f->symtab[i]; sym; sym = sym->next)
2952 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002953 && sym->secidx <= SHN_HIRESERVE
2954 && (sym->secidx >= SHN_LORESERVE
2955 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002956 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2957
2958 obj_symbol_patch(f, sec->idx, ofs, sym);
2959 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002960 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002961
2962 nsyms++;
2963 }
2964 }
2965
2966 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2967 }
2968
2969 return 1;
2970}
2971
2972
2973static int
2974new_init_module(const char *m_name, struct obj_file *f,
2975 unsigned long m_size)
2976{
2977 struct new_module *module;
2978 struct obj_section *sec;
2979 void *image;
2980 int ret;
2981 tgt_long m_addr;
2982
2983 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002984 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002985 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002986 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002987 module = (struct new_module *) sec->contents;
2988 m_addr = sec->header.sh_addr;
2989
2990 module->size_of_struct = sizeof(*module);
2991 module->size = m_size;
2992 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2993
2994 sec = obj_find_section(f, "__ksymtab");
2995 if (sec && sec->header.sh_size) {
2996 module->syms = sec->header.sh_addr;
2997 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2998 }
2999
3000 if (n_ext_modules_used) {
3001 sec = obj_find_section(f, ".kmodtab");
3002 module->deps = sec->header.sh_addr;
3003 module->ndeps = n_ext_modules_used;
3004 }
3005
3006 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00003007 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00003008 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00003009 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00003010
3011 sec = obj_find_section(f, "__ex_table");
3012 if (sec) {
3013 module->ex_table_start = sec->header.sh_addr;
3014 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
3015 }
3016
3017 sec = obj_find_section(f, ".text.init");
3018 if (sec) {
3019 module->runsize = sec->header.sh_addr - m_addr;
3020 }
3021 sec = obj_find_section(f, ".data.init");
3022 if (sec) {
3023 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00003024 module->runsize > sec->header.sh_addr - m_addr)
3025 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003026 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00003027 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
3028 if (sec && sec->header.sh_size) {
3029 module->archdata_start = (void*)sec->header.sh_addr;
3030 module->archdata_end = module->archdata_start + sec->header.sh_size;
3031 }
3032 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
3033 if (sec && sec->header.sh_size) {
3034 module->kallsyms_start = (void*)sec->header.sh_addr;
3035 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
3036 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003037
3038 if (!arch_init_module(f, module))
3039 return 0;
3040
3041 /* Whew! All of the initialization is complete. Collect the final
3042 module image and give it to the kernel. */
3043
3044 image = xmalloc(m_size);
3045 obj_create_image(f, image);
3046
Eric Andersen64c8b172001-04-05 07:33:10 +00003047 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00003048 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003049 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003050
3051 free(image);
3052
3053 return ret == 0;
3054}
3055
3056#else
3057
3058#define new_init_module(x, y, z) TRUE
3059#define new_create_this_module(x, y) 0
Eric Andersen889dd202003-01-23 04:48:34 +00003060#define new_add_ksymtab(x, y) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003061#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00003062#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003063
Eric Andersene7047882003-12-11 01:42:13 +00003064#endif /* CONFIG_FEATURE_2_4_MODULES */
Eric Andersen9f16d612000-06-12 23:11:16 +00003065
3066
3067/*======================================================================*/
3068
Eric Andersen044228d2001-07-17 01:12:36 +00003069static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003070obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3071 const char *string)
3072{
3073 struct obj_string_patch *p;
3074 struct obj_section *strsec;
3075 size_t len = strlen(string) + 1;
3076 char *loc;
3077
3078 p = xmalloc(sizeof(*p));
3079 p->next = f->string_patches;
3080 p->reloc_secidx = secidx;
3081 p->reloc_offset = offset;
3082 f->string_patches = p;
3083
3084 strsec = obj_find_section(f, ".kstrtab");
3085 if (strsec == NULL) {
3086 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3087 p->string_offset = 0;
3088 loc = strsec->contents;
3089 } else {
3090 p->string_offset = strsec->header.sh_size;
3091 loc = obj_extend_section(strsec, len);
3092 }
3093 memcpy(loc, string, len);
3094
3095 return 1;
3096}
3097
Eric Andersene7047882003-12-11 01:42:13 +00003098#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +00003099static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003100obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3101 struct obj_symbol *sym)
3102{
3103 struct obj_symbol_patch *p;
3104
3105 p = xmalloc(sizeof(*p));
3106 p->next = f->symbol_patches;
3107 p->reloc_secidx = secidx;
3108 p->reloc_offset = offset;
3109 p->sym = sym;
3110 f->symbol_patches = p;
3111
3112 return 1;
3113}
Eric Andersen6d139642001-12-29 04:15:13 +00003114#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003115
Eric Andersen044228d2001-07-17 01:12:36 +00003116static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003117{
3118 unsigned long i;
3119 int ret = 1;
3120
3121 for (i = 0; i < HASH_BUCKETS; ++i) {
3122 struct obj_symbol *sym;
3123 for (sym = f->symtab[i]; sym; sym = sym->next)
3124 if (sym->secidx == SHN_UNDEF) {
3125 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
3126 sym->secidx = SHN_ABS;
3127 sym->value = 0;
3128 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003129 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003130 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003131 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 ret = 0;
3133 }
3134 }
3135 }
3136
3137 return ret;
3138}
3139
Eric Andersen044228d2001-07-17 01:12:36 +00003140static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003141{
3142 struct common_entry {
3143 struct common_entry *next;
3144 struct obj_symbol *sym;
3145 } *common_head = NULL;
3146
3147 unsigned long i;
3148
3149 for (i = 0; i < HASH_BUCKETS; ++i) {
3150 struct obj_symbol *sym;
3151 for (sym = f->symtab[i]; sym; sym = sym->next)
3152 if (sym->secidx == SHN_COMMON) {
3153 /* Collect all COMMON symbols and sort them by size so as to
3154 minimize space wasted by alignment requirements. */
3155 {
3156 struct common_entry **p, *n;
3157 for (p = &common_head; *p; p = &(*p)->next)
3158 if (sym->size <= (*p)->sym->size)
3159 break;
3160
3161 n = alloca(sizeof(*n));
3162 n->next = *p;
3163 n->sym = sym;
3164 *p = n;
3165 }
3166 }
3167 }
3168
3169 for (i = 1; i < f->local_symtab_size; ++i) {
3170 struct obj_symbol *sym = f->local_symtab[i];
3171 if (sym && sym->secidx == SHN_COMMON) {
3172 struct common_entry **p, *n;
3173 for (p = &common_head; *p; p = &(*p)->next)
3174 if (sym == (*p)->sym)
3175 break;
3176 else if (sym->size < (*p)->sym->size) {
3177 n = alloca(sizeof(*n));
3178 n->next = *p;
3179 n->sym = sym;
3180 *p = n;
3181 break;
3182 }
3183 }
3184 }
3185
3186 if (common_head) {
3187 /* Find the bss section. */
3188 for (i = 0; i < f->header.e_shnum; ++i)
3189 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3190 break;
3191
3192 /* If for some reason there hadn't been one, create one. */
3193 if (i == f->header.e_shnum) {
3194 struct obj_section *sec;
3195
3196 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3197 f->sections[i] = sec = arch_new_section();
3198 f->header.e_shnum = i + 1;
3199
3200 memset(sec, 0, sizeof(*sec));
3201 sec->header.sh_type = SHT_PROGBITS;
3202 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3203 sec->name = ".bss";
3204 sec->idx = i;
3205 }
3206
3207 /* Allocate the COMMONS. */
3208 {
3209 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3210 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3211 struct common_entry *c;
3212
3213 for (c = common_head; c; c = c->next) {
3214 ElfW(Addr) align = c->sym->value;
3215
3216 if (align > max_align)
3217 max_align = align;
3218 if (bss_size & (align - 1))
3219 bss_size = (bss_size | (align - 1)) + 1;
3220
3221 c->sym->secidx = i;
3222 c->sym->value = bss_size;
3223
3224 bss_size += c->sym->size;
3225 }
3226
3227 f->sections[i]->header.sh_size = bss_size;
3228 f->sections[i]->header.sh_addralign = max_align;
3229 }
3230 }
3231
3232 /* For the sake of patch relocation and parameter initialization,
3233 allocate zeroed data for NOBITS sections now. Note that after
3234 this we cannot assume NOBITS are really empty. */
3235 for (i = 0; i < f->header.e_shnum; ++i) {
3236 struct obj_section *s = f->sections[i];
3237 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003238 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003239 s->contents = memset(xmalloc(s->header.sh_size),
3240 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003241 else
3242 s->contents = NULL;
3243
Eric Andersen9f16d612000-06-12 23:11:16 +00003244 s->header.sh_type = SHT_PROGBITS;
3245 }
3246 }
3247}
3248
Eric Andersen044228d2001-07-17 01:12:36 +00003249static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003250{
3251 unsigned long dot = 0;
3252 struct obj_section *sec;
3253
3254 /* Finalize the positions of the sections relative to one another. */
3255
3256 for (sec = f->load_order; sec; sec = sec->load_next) {
3257 ElfW(Addr) align;
3258
3259 align = sec->header.sh_addralign;
3260 if (align && (dot & (align - 1)))
3261 dot = (dot | (align - 1)) + 1;
3262
3263 sec->header.sh_addr = dot;
3264 dot += sec->header.sh_size;
3265 }
3266
3267 return dot;
3268}
3269
Eric Andersen044228d2001-07-17 01:12:36 +00003270static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003271{
3272 int i, n = f->header.e_shnum;
3273 int ret = 1;
3274
3275 /* Finalize the addresses of the sections. */
3276
3277 f->baseaddr = base;
3278 for (i = 0; i < n; ++i)
3279 f->sections[i]->header.sh_addr += base;
3280
3281 /* And iterate over all of the relocations. */
3282
3283 for (i = 0; i < n; ++i) {
3284 struct obj_section *relsec, *symsec, *targsec, *strsec;
3285 ElfW(RelM) * rel, *relend;
3286 ElfW(Sym) * symtab;
3287 const char *strtab;
3288
3289 relsec = f->sections[i];
3290 if (relsec->header.sh_type != SHT_RELM)
3291 continue;
3292
3293 symsec = f->sections[relsec->header.sh_link];
3294 targsec = f->sections[relsec->header.sh_info];
3295 strsec = f->sections[symsec->header.sh_link];
3296
3297 rel = (ElfW(RelM) *) relsec->contents;
3298 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3299 symtab = (ElfW(Sym) *) symsec->contents;
3300 strtab = (const char *) strsec->contents;
3301
3302 for (; rel < relend; ++rel) {
3303 ElfW(Addr) value = 0;
3304 struct obj_symbol *intsym = NULL;
3305 unsigned long symndx;
3306 ElfW(Sym) * extsym = 0;
3307 const char *errmsg;
3308
3309 /* Attempt to find a value to use for this relocation. */
3310
3311 symndx = ELFW(R_SYM) (rel->r_info);
3312 if (symndx) {
3313 /* Note we've already checked for undefined symbols. */
3314
3315 extsym = &symtab[symndx];
3316 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3317 /* Local symbols we look up in the local table to be sure
3318 we get the one that is really intended. */
3319 intsym = f->local_symtab[symndx];
3320 } else {
3321 /* Others we look up in the hash table. */
3322 const char *name;
3323 if (extsym->st_name)
3324 name = strtab + extsym->st_name;
3325 else
3326 name = f->sections[extsym->st_shndx]->name;
3327 intsym = obj_find_symbol(f, name);
3328 }
3329
3330 value = obj_symbol_final_value(f, intsym);
3331 intsym->referenced = 1;
3332 }
3333#if SHT_RELM == SHT_RELA
3334#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3335 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3336 if (!extsym || !extsym->st_name ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00003337 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003338#endif
3339 value += rel->r_addend;
3340#endif
3341
3342 /* Do it! */
3343 switch (arch_apply_relocation
3344 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003345 case obj_reloc_ok:
3346 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003347
Eric Andersen3b1a7442003-12-24 20:30:45 +00003348 case obj_reloc_overflow:
3349 errmsg = "Relocation overflow";
3350 goto bad_reloc;
3351 case obj_reloc_dangerous:
3352 errmsg = "Dangerous relocation";
3353 goto bad_reloc;
3354 case obj_reloc_unhandled:
3355 errmsg = "Unhandled relocation";
3356bad_reloc:
3357 if (extsym) {
3358 bb_error_msg("%s of type %ld for %s", errmsg,
3359 (long) ELFW(R_TYPE) (rel->r_info),
3360 strtab + extsym->st_name);
3361 } else {
3362 bb_error_msg("%s of type %ld", errmsg,
3363 (long) ELFW(R_TYPE) (rel->r_info));
3364 }
3365 ret = 0;
3366 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003367 }
3368 }
3369 }
3370
3371 /* Finally, take care of the patches. */
3372
3373 if (f->string_patches) {
3374 struct obj_string_patch *p;
3375 struct obj_section *strsec;
3376 ElfW(Addr) strsec_base;
3377 strsec = obj_find_section(f, ".kstrtab");
3378 strsec_base = strsec->header.sh_addr;
3379
3380 for (p = f->string_patches; p; p = p->next) {
3381 struct obj_section *targsec = f->sections[p->reloc_secidx];
3382 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3383 = strsec_base + p->string_offset;
3384 }
3385 }
3386
3387 if (f->symbol_patches) {
3388 struct obj_symbol_patch *p;
3389
3390 for (p = f->symbol_patches; p; p = p->next) {
3391 struct obj_section *targsec = f->sections[p->reloc_secidx];
3392 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3393 = obj_symbol_final_value(f, p->sym);
3394 }
3395 }
3396
3397 return ret;
3398}
3399
Eric Andersen044228d2001-07-17 01:12:36 +00003400static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003401{
3402 struct obj_section *sec;
3403 ElfW(Addr) base = f->baseaddr;
3404
3405 for (sec = f->load_order; sec; sec = sec->load_next) {
3406 char *secimg;
3407
Eric Andersen2bf658d2001-02-24 20:01:53 +00003408 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003409 continue;
3410
3411 secimg = image + (sec->header.sh_addr - base);
3412
3413 /* Note that we allocated data for NOBITS sections earlier. */
3414 memcpy(secimg, sec->contents, sec->header.sh_size);
3415 }
3416
3417 return 1;
3418}
3419
3420/*======================================================================*/
3421
Eric Andersen044228d2001-07-17 01:12:36 +00003422static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003423{
3424 struct obj_file *f;
3425 ElfW(Shdr) * section_headers;
3426 int shnum, i;
3427 char *shstrtab;
3428
3429 /* Read the file header. */
3430
3431 f = arch_new_file();
3432 memset(f, 0, sizeof(*f));
3433 f->symbol_cmp = strcmp;
3434 f->symbol_hash = obj_elf_hash;
3435 f->load_order_search_start = &f->load_order;
3436
3437 fseek(fp, 0, SEEK_SET);
3438 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003439 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003440 return NULL;
3441 }
3442
3443 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003444 || f->header.e_ident[EI_MAG1] != ELFMAG1
3445 || f->header.e_ident[EI_MAG2] != ELFMAG2
3446 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003447 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003448 return NULL;
3449 }
3450 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003451 || f->header.e_ident[EI_DATA] != ELFDATAM
3452 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3453 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003454 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003455 return NULL;
3456 }
3457 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003458 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003459 return NULL;
3460 }
3461
3462 /* Read the section headers. */
3463
3464 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003465 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003466 (unsigned long) f->header.e_shentsize,
3467 (unsigned long) sizeof(ElfW(Shdr)));
3468 return NULL;
3469 }
3470
3471 shnum = f->header.e_shnum;
3472 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3473 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3474
3475 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3476 fseek(fp, f->header.e_shoff, SEEK_SET);
3477 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003478 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003479 return NULL;
3480 }
3481
3482 /* Read the section data. */
3483
3484 for (i = 0; i < shnum; ++i) {
3485 struct obj_section *sec;
3486
3487 f->sections[i] = sec = arch_new_section();
3488 memset(sec, 0, sizeof(*sec));
3489
3490 sec->header = section_headers[i];
3491 sec->idx = i;
3492
Eric Andersen2bf658d2001-02-24 20:01:53 +00003493 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003494 case SHT_NULL:
3495 case SHT_NOTE:
3496 case SHT_NOBITS:
3497 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003498 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003499
3500 case SHT_PROGBITS:
3501#if LOADBITS
3502 if (!loadprogbits) {
3503 sec->contents = NULL;
3504 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003505 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003506#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003507 case SHT_SYMTAB:
3508 case SHT_STRTAB:
3509 case SHT_RELM:
3510 if (sec->header.sh_size > 0) {
3511 sec->contents = xmalloc(sec->header.sh_size);
3512 fseek(fp, sec->header.sh_offset, SEEK_SET);
3513 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3514 bb_perror_msg("error reading ELF section data");
3515 return NULL;
3516 }
3517 } else {
3518 sec->contents = NULL;
3519 }
3520 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003521
3522#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003523 case SHT_RELA:
3524 bb_error_msg("RELA relocations not supported on this architecture");
3525 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003526#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003527 case SHT_REL:
3528 bb_error_msg("REL relocations not supported on this architecture");
3529 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003530#endif
3531
Eric Andersen3b1a7442003-12-24 20:30:45 +00003532 default:
3533 if (sec->header.sh_type >= SHT_LOPROC) {
3534 /* Assume processor specific section types are debug
3535 info and can safely be ignored. If this is ever not
3536 the case (Hello MIPS?), don't put ifdefs here but
3537 create an arch_load_proc_section(). */
3538 break;
3539 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003540
Eric Andersen3b1a7442003-12-24 20:30:45 +00003541 bb_error_msg("can't handle sections of type %ld",
3542 (long) sec->header.sh_type);
3543 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003544 }
3545 }
3546
3547 /* Do what sort of interpretation as needed by each section. */
3548
3549 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3550
3551 for (i = 0; i < shnum; ++i) {
3552 struct obj_section *sec = f->sections[i];
3553 sec->name = shstrtab + sec->header.sh_name;
3554 }
3555
3556 for (i = 0; i < shnum; ++i) {
3557 struct obj_section *sec = f->sections[i];
3558
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003559 /* .modinfo should be contents only but gcc has no attribute for that.
3560 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3561 */
3562 if (strcmp(sec->name, ".modinfo") == 0)
3563 sec->header.sh_flags &= ~SHF_ALLOC;
3564
Eric Andersen9f16d612000-06-12 23:11:16 +00003565 if (sec->header.sh_flags & SHF_ALLOC)
3566 obj_insert_section_load_order(f, sec);
3567
3568 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003569 case SHT_SYMTAB:
3570 {
3571 unsigned long nsym, j;
3572 char *strtab;
3573 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003574
Eric Andersen3b1a7442003-12-24 20:30:45 +00003575 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3576 bb_error_msg("symbol size mismatch: %lu != %lu",
3577 (unsigned long) sec->header.sh_entsize,
3578 (unsigned long) sizeof(ElfW(Sym)));
3579 return NULL;
3580 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003581
Eric Andersen3b1a7442003-12-24 20:30:45 +00003582 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3583 strtab = f->sections[sec->header.sh_link]->contents;
3584 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003585
Eric Andersen3b1a7442003-12-24 20:30:45 +00003586 /* Allocate space for a table of local symbols. */
3587 j = f->local_symtab_size = sec->header.sh_info;
3588 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003589
Eric Andersen3b1a7442003-12-24 20:30:45 +00003590 /* Insert all symbols into the hash table. */
3591 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3592 ElfW(Addr) val = sym->st_value;
3593 const char *name;
3594 if (sym->st_name)
3595 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003596 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003597 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003598 else
3599 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003600
Eric Andersenbf833552003-08-13 19:56:33 +00003601#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003602 /*
3603 * For sh64 it is possible that the target of a branch
3604 * requires a mode switch (32 to 16 and back again).
3605 *
3606 * This is implied by the lsb being set in the target
3607 * address for SHmedia mode and clear for SHcompact.
3608 */
3609 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003610#endif
3611
Eric Andersen3b1a7442003-12-24 20:30:45 +00003612 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3613 val, sym->st_size);
3614 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003615 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003616 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003617
Eric Andersen3b1a7442003-12-24 20:30:45 +00003618 case SHT_RELM:
3619 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3620 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3621 (unsigned long) sec->header.sh_entsize,
3622 (unsigned long) sizeof(ElfW(RelM)));
3623 return NULL;
3624 }
3625 break;
3626 /* XXX Relocation code from modutils-2.3.19 is not here.
3627 * Why? That's about 20 lines of code from obj/obj_load.c,
3628 * which gets done in a second pass through the sections.
3629 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003630 }
3631 }
3632
3633 return f;
3634}
3635
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003636#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003637/*
3638 * load the unloaded sections directly into the memory allocated by
3639 * kernel for the module
3640 */
3641
Eric Andersenac5dbd12001-08-22 05:26:08 +00003642static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003643{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003644 ElfW(Addr) base = f->baseaddr;
3645 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003646
Eric Andersen8ae319a2001-05-21 16:09:18 +00003647 for (sec = f->load_order; sec; sec = sec->load_next) {
3648
3649 /* section already loaded? */
3650 if (sec->contents != NULL)
3651 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003652
Eric Andersen8ae319a2001-05-21 16:09:18 +00003653 if (sec->header.sh_size == 0)
3654 continue;
3655
3656 sec->contents = imagebase + (sec->header.sh_addr - base);
3657 fseek(fp, sec->header.sh_offset, SEEK_SET);
3658 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003659 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003660 return 0;
3661 }
3662
3663 }
3664 return 1;
3665}
3666#endif
3667
Eric Andersen9f16d612000-06-12 23:11:16 +00003668static void hide_special_symbols(struct obj_file *f)
3669{
3670 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003671 SPFX "cleanup_module",
3672 SPFX "init_module",
3673 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003674 NULL
3675 };
3676
3677 struct obj_symbol *sym;
3678 const char *const *p;
3679
3680 for (p = specials; *p; ++p)
3681 if ((sym = obj_find_symbol(f, *p)) != NULL)
3682 sym->info =
3683 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3684}
3685
Glenn L McGrath759515c2003-08-30 06:00:33 +00003686
Eric Andersen71ae64b2002-10-10 04:20:21 +00003687#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003688static int obj_gpl_license(struct obj_file *f, const char **license)
3689{
3690 struct obj_section *sec;
3691 /* This list must match *exactly* the list of allowable licenses in
3692 * linux/include/linux/module.h. Checking for leading "GPL" will not
3693 * work, somebody will use "GPL sucks, this is proprietary".
3694 */
3695 static const char *gpl_licenses[] = {
3696 "GPL",
3697 "GPL v2",
3698 "GPL and additional rights",
3699 "Dual BSD/GPL",
3700 "Dual MPL/GPL",
3701 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003702
Eric Andersen166fa462002-09-16 05:30:24 +00003703 if ((sec = obj_find_section(f, ".modinfo"))) {
3704 const char *value, *ptr, *endptr;
3705 ptr = sec->contents;
3706 endptr = ptr + sec->header.sh_size;
3707 while (ptr < endptr) {
3708 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3709 int i;
3710 if (license)
3711 *license = value+1;
3712 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3713 if (strcmp(value+1, gpl_licenses[i]) == 0)
3714 return(0);
3715 }
3716 return(2);
3717 }
3718 if (strchr(ptr, '\0'))
3719 ptr = strchr(ptr, '\0') + 1;
3720 else
3721 ptr = endptr;
3722 }
3723 }
3724 return(1);
3725}
3726
3727#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3728#define TAINT_PROPRIETORY_MODULE (1<<0)
3729#define TAINT_FORCED_MODULE (1<<1)
3730#define TAINT_UNSAFE_SMP (1<<2)
3731#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3732
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003733static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003734 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3735{
3736 char buf[80];
3737 int oldval;
3738 static int first = 1;
3739 if (fd < 0 && !kernel_has_tainted)
3740 return; /* New modutils on old kernel */
3741 printf("Warning: loading %s will taint the kernel: %s%s\n",
3742 m_name, text1, text2);
3743 if (first) {
3744 printf(" See %s for information about tainted modules\n", TAINT_URL);
3745 first = 0;
3746 }
3747 if (fd >= 0) {
3748 read(fd, buf, sizeof(buf)-1);
3749 buf[sizeof(buf)-1] = '\0';
3750 oldval = strtoul(buf, NULL, 10);
3751 sprintf(buf, "%d\n", oldval | taint);
3752 write(fd, buf, strlen(buf));
3753 }
3754}
3755
3756/* Check if loading this module will taint the kernel. */
3757static void check_tainted_module(struct obj_file *f, char *m_name)
3758{
3759 static const char tainted_file[] = TAINT_FILENAME;
3760 int fd, kernel_has_tainted;
3761 const char *ptr;
3762
3763 kernel_has_tainted = 1;
3764 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3765 if (errno == ENOENT)
3766 kernel_has_tainted = 0;
3767 else if (errno == EACCES)
3768 kernel_has_tainted = 1;
3769 else {
3770 perror(tainted_file);
3771 kernel_has_tainted = 0;
3772 }
3773 }
3774
3775 switch (obj_gpl_license(f, &ptr)) {
3776 case 0:
3777 break;
3778 case 1:
3779 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3780 break;
3781 case 2:
3782 /* The module has a non-GPL license so we pretend that the
3783 * kernel always has a taint flag to get a warning even on
3784 * kernels without the proc flag.
3785 */
3786 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3787 break;
3788 default:
3789 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3790 break;
3791 }
3792
3793 if (flag_force_load)
3794 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3795
3796 if (fd >= 0)
3797 close(fd);
3798}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003799#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3800#define check_tainted_module(x, y) do { } while(0);
3801#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003802
Eric Andersen889dd202003-01-23 04:48:34 +00003803#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3804/* add module source, timestamp, kernel version and a symbol for the
3805 * start of some sections. this info is used by ksymoops to do better
3806 * debugging.
3807 */
3808static int
3809get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3810{
3811#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen3b1a7442003-12-24 20:30:45 +00003812 if (get_modinfo_value(f, "kernel_version") == NULL)
3813 return old_get_module_version(f, str);
3814 else
3815 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003816#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003817 strncpy(str, "???", sizeof(str));
3818 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003819#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3820}
3821
3822/* add module source, timestamp, kernel version and a symbol for the
3823 * start of some sections. this info is used by ksymoops to do better
3824 * debugging.
3825 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003826static void
Eric Andersen889dd202003-01-23 04:48:34 +00003827add_ksymoops_symbols(struct obj_file *f, const char *filename,
3828 const char *m_name)
3829{
3830 static const char symprefix[] = "__insmod_";
3831 struct obj_section *sec;
3832 struct obj_symbol *sym;
3833 char *name, *absolute_filename;
3834 char str[STRVERSIONLEN], real[PATH_MAX];
3835 int i, l, lm_name, lfilename, use_ksymtab, version;
3836 struct stat statbuf;
3837
3838 static const char *section_names[] = {
3839 ".text",
3840 ".rodata",
3841 ".data",
3842 ".bss"
Eric Andersen3b1a7442003-12-24 20:30:45 +00003843 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003844 };
3845
3846 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003847 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003848 }
3849 else {
3850 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003851 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003852 errno = save_errno;
3853 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003854 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003855 }
3856
3857 lm_name = strlen(m_name);
3858 lfilename = strlen(absolute_filename);
3859
3860 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3861 * are not to be exported. otherwise leave ksymtab alone for now, the
3862 * "export all symbols" compatibility code will export these symbols later.
3863 */
3864 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3865
3866 if ((sec = obj_find_section(f, ".this"))) {
3867 /* tag the module header with the object name, last modified
3868 * timestamp and module version. worst case for module version
3869 * is 0xffffff, decimal 16777215. putting all three fields in
3870 * one symbol is less readable but saves kernel space.
3871 */
3872 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003873 lm_name+ /* module name */
3874 2+ /* "_O" */
3875 lfilename+ /* object filename */
3876 2+ /* "_M" */
3877 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3878 2+ /* "_V" */
3879 8+ /* version in dec */
3880 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003881 name = xmalloc(l);
3882 if (stat(absolute_filename, &statbuf) != 0)
3883 statbuf.st_mtime = 0;
3884 version = get_module_version(f, str); /* -1 if not found */
3885 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003886 symprefix, m_name, absolute_filename,
3887 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3888 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003889 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003890 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3891 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003892 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003893 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003894 }
3895 free(absolute_filename);
3896#ifdef _NOT_SUPPORTED_
3897 /* record where the persistent data is going, same address as previous symbol */
3898
3899 if (f->persist) {
3900 l = sizeof(symprefix)+ /* "__insmod_" */
3901 lm_name+ /* module name */
3902 2+ /* "_P" */
3903 strlen(f->persist)+ /* data store */
3904 1; /* nul */
3905 name = xmalloc(l);
3906 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003907 symprefix, m_name, f->persist);
Eric Andersen889dd202003-01-23 04:48:34 +00003908 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003909 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003910 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003911 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003912 }
3913#endif /* _NOT_SUPPORTED_ */
3914 /* tag the desired sections if size is non-zero */
3915
3916 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3917 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003918 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003919 l = sizeof(symprefix)+ /* "__insmod_" */
3920 lm_name+ /* module name */
3921 2+ /* "_S" */
3922 strlen(sec->name)+ /* section name */
3923 2+ /* "_L" */
3924 8+ /* length in dec */
3925 1; /* nul */
3926 name = xmalloc(l);
3927 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003928 symprefix, m_name, sec->name,
3929 (long)sec->header.sh_size);
Eric Andersen889dd202003-01-23 04:48:34 +00003930 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003931 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003932 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003933 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003934 }
3935 }
3936}
3937#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3938
Eric Andersenbe65c352003-01-23 04:57:35 +00003939#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3940static void print_load_map(struct obj_file *f)
3941{
3942 struct obj_symbol *sym;
3943 struct obj_symbol **all, **p;
3944 struct obj_section *sec;
3945 int i, nsyms, *loaded;
3946
3947 /* Report on the section layout. */
3948
3949 printf("Sections: Size %-*s Align\n",
3950 (int) (2 * sizeof(void *)), "Address");
3951
3952 for (sec = f->load_order; sec; sec = sec->load_next) {
3953 int a;
3954 unsigned long tmp;
3955
3956 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3957 tmp >>= 1;
3958 if (a == -1)
3959 a = 0;
3960
3961 printf("%-15s %08lx %0*lx 2**%d\n",
3962 sec->name,
3963 (long)sec->header.sh_size,
3964 (int) (2 * sizeof(void *)),
3965 (long)sec->header.sh_addr,
3966 a);
3967 }
3968#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3969 /* Quick reference which section indicies are loaded. */
3970
3971 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3972 while (--i >= 0)
3973 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3974
3975 /* Collect the symbols we'll be listing. */
3976
3977 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3978 for (sym = f->symtab[i]; sym; sym = sym->next)
3979 if (sym->secidx <= SHN_HIRESERVE
3980 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3981 ++nsyms;
3982
3983 all = alloca(nsyms * sizeof(struct obj_symbol *));
3984
3985 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3986 for (sym = f->symtab[i]; sym; sym = sym->next)
3987 if (sym->secidx <= SHN_HIRESERVE
3988 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3989 *p++ = sym;
3990
3991 /* And list them. */
3992 printf("\nSymbols:\n");
3993 for (p = all; p < all + nsyms; ++p) {
3994 char type = '?';
3995 unsigned long value;
3996
3997 sym = *p;
3998 if (sym->secidx == SHN_ABS) {
3999 type = 'A';
4000 value = sym->value;
4001 } else if (sym->secidx == SHN_UNDEF) {
4002 type = 'U';
4003 value = 0;
4004 } else {
4005 sec = f->sections[sym->secidx];
4006
4007 if (sec->header.sh_type == SHT_NOBITS)
4008 type = 'B';
4009 else if (sec->header.sh_flags & SHF_ALLOC) {
4010 if (sec->header.sh_flags & SHF_EXECINSTR)
4011 type = 'T';
4012 else if (sec->header.sh_flags & SHF_WRITE)
4013 type = 'D';
4014 else
4015 type = 'R';
4016 }
4017 value = sym->value + sec->header.sh_addr;
4018 }
4019
4020 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
4021 type = tolower(type);
4022
4023 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
4024 type, sym->name);
4025 }
4026#endif
4027}
4028
4029#endif
4030
Eric Andersen9f16d612000-06-12 23:11:16 +00004031extern int insmod_main( int argc, char **argv)
4032{
Eric Andersena18aaf12001-01-24 19:07:09 +00004033 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00004034 int k_crcs;
4035 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004036 int len;
Eric Andersen6fb4e482002-06-06 14:24:57 +00004037 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00004038 unsigned long m_size;
4039 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00004040 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00004041 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00004042 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00004043 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00004044 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004045#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00004046 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00004047 char m_strversion[STRVERSIONLEN];
4048 int m_version;
4049 int m_crcs;
4050#endif
Eric Andersen61f83052002-06-22 17:15:42 +00004051#ifdef CONFIG_FEATURE_CLEAN_UP
4052 FILE *fp = 0;
4053#else
4054 FILE *fp;
4055#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00004056#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4057 int flag_print_load_map = 0;
4058#endif
Eric Andersen03d80912003-12-19 21:04:19 +00004059 int k_version = 0;
4060 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00004061
Erik Andersene49d5ec2000-02-08 19:58:47 +00004062 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00004063#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004064 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004065#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004066 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004067#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004068 {
4069 switch (opt) {
4070 case 'f': /* force loading */
4071 flag_force_load = 1;
4072 break;
4073 case 'k': /* module loaded by kerneld, auto-cleanable */
4074 flag_autoclean = 1;
4075 break;
4076 case 's': /* log to syslog */
4077 /* log to syslog -- not supported */
4078 /* but kernel needs this for request_module(), */
4079 /* as this calls: modprobe -k -s -- <module> */
4080 /* so silently ignore this flag */
4081 break;
4082 case 'v': /* verbose output */
4083 flag_verbose = 1;
4084 break;
4085 case 'q': /* silent */
4086 flag_quiet = 1;
4087 break;
4088 case 'x': /* do not export externs */
4089 flag_export = 0;
4090 break;
4091 case 'o': /* name the output module */
4092 free(m_name);
4093 m_name = bb_xstrdup(optarg);
4094 break;
4095 case 'L': /* Stub warning */
4096 /* This is needed for compatibility with modprobe.
4097 * In theory, this does locking, but we don't do
4098 * that. So be careful and plan your life around not
4099 * loading the same module 50 times concurrently. */
4100 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004101#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004102 case 'm': /* print module load map */
4103 flag_print_load_map = 1;
4104 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004105#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004106 default:
4107 bb_show_usage();
4108 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004109 }
Eric Andersen03d80912003-12-19 21:04:19 +00004110
Eric Andersena18aaf12001-01-24 19:07:09 +00004111 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004112 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00004113 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004114
Erik Andersene49d5ec2000-02-08 19:58:47 +00004115 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00004116 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00004117 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004118 len = strlen(tmp);
4119
Eric Andersen03d80912003-12-19 21:04:19 +00004120 if (uname(&myuname) == 0) {
4121 if (myuname.release[0] == '2') {
4122 k_version = myuname.release[2] - '0';
4123 }
4124 }
4125
4126#if defined(CONFIG_FEATURE_2_6_MODULES)
4127 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004128 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004129 len-=3;
4130 tmp[len] = '\0';
4131 }
4132 else
4133#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004134 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4135 len-=2;
4136 tmp[len] = '\0';
4137 }
Eric Andersen2d342152002-06-18 05:16:25 +00004138
Eric Andersen03d80912003-12-19 21:04:19 +00004139
4140#if defined(CONFIG_FEATURE_2_6_MODULES)
4141 if (k_version > 4)
4142 bb_xasprintf(&m_fullName, "%s.ko", tmp);
4143 else
Eric Andersen03d80912003-12-19 21:04:19 +00004144#endif
Eric Andersen66e21fd2004-01-05 23:49:37 +00004145 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004146
Eric Andersen61f83052002-06-22 17:15:42 +00004147 if (!m_name) {
4148 m_name = tmp;
4149 } else {
4150 free(tmp1);
4151 tmp1 = 0; /* flag for free(m_name) before exit() */
4152 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004153
Eric Andersen14d35432001-05-14 17:07:32 +00004154 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004155 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4156 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004157 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4158 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004159 if (k_version) { /* uname succeedd */
4160 char *module_dir;
4161 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004162 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004163
Eric Andersen03d80912003-12-19 21:04:19 +00004164 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004165 /* Jump through hoops in case /lib/modules/`uname -r`
4166 * is a symlink. We do not want recursive_action to
4167 * follow symlinks, but we do want to follow the
4168 * /lib/modules/`uname -r` dir, So resolve it ourselves
4169 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004170 if (realpath (tmdn, real_module_dir) == NULL)
4171 module_dir = tmdn;
4172 else
4173 module_dir = real_module_dir;
4174 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004175 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004176 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004177 }
4178
4179 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004180 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004181 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004182 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004183
Eric Andersen03d80912003-12-19 21:04:19 +00004184 free(m_filename);
4185 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004186 if (realpath (_PATH_MODULES, module_dir) == NULL)
4187 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004188 /* No module found under /lib/modules/`uname -r`, this
4189 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004190 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004191 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004192 {
Eric Andersen61f83052002-06-22 17:15:42 +00004193 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004194 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004195 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004196 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004197 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004198 }
4199 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004200 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004201 }
Eric Andersen03d80912003-12-19 21:04:19 +00004202 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004203 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004204
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004205 if (!flag_quiet)
4206 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004207
Eric Andersene7047882003-12-11 01:42:13 +00004208#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004209 if (k_version > 4)
4210 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004211 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004212 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004213 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004214 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004215#endif
4216
Eric Andersen8ae319a2001-05-21 16:09:18 +00004217 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004218 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004219
Eric Andersen9f16d612000-06-12 23:11:16 +00004220 if (get_modinfo_value(f, "kernel_version") == NULL)
4221 m_has_modinfo = 0;
4222 else
4223 m_has_modinfo = 1;
4224
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004225#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004226 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004227 if (!flag_quiet) {
4228 if (uname(&uts_info) < 0)
4229 uts_info.release[0] = '\0';
4230 if (m_has_modinfo) {
4231 m_version = new_get_module_version(f, m_strversion);
Eric Andersen9f16d612000-06-12 23:11:16 +00004232 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00004233 m_version = old_get_module_version(f, m_strversion);
4234 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004235 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004236 "compiled for");
4237 goto out;
4238 }
4239 }
4240
4241 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4242 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004243 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004244 "\t%s was compiled for kernel version %s\n"
4245 "\twhile this kernel is version %s",
4246 m_filename, m_strversion, uts_info.release);
4247 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004248 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004249 "\t%s was compiled for kernel version %s\n"
4250 "\twhile this kernel is version %s.",
4251 m_filename, m_strversion, uts_info.release);
4252 goto out;
4253 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004254 }
4255 }
4256 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004257#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004258
4259 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
4260
4261 if (k_new_syscalls) {
Eric Andersene7047882003-12-11 01:42:13 +00004262#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00004263 if (!new_get_kernel_symbols())
4264 goto out;
4265 k_crcs = new_is_kernel_checksummed();
4266#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004267 bb_error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004268 goto out;
4269#endif
4270 } else {
Eric Andersene7047882003-12-11 01:42:13 +00004271#ifdef CONFIG_FEATURE_2_2_MODULES
Eric Andersen8c185f92000-09-22 00:38:07 +00004272 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004273 goto out;
4274 k_crcs = old_is_kernel_checksummed();
4275#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004276 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004277 goto out;
4278#endif
4279 }
4280
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004281#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004282 if (m_has_modinfo)
4283 m_crcs = new_is_module_checksummed(f);
4284 else
4285 m_crcs = old_is_module_checksummed(f);
4286
4287 if (m_crcs != k_crcs)
4288 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004289#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004290
Erik Andersene49d5ec2000-02-08 19:58:47 +00004291 /* Let the module know about the kernel symbols. */
4292 add_kernel_symbols(f);
4293
Eric Andersen9f16d612000-06-12 23:11:16 +00004294 /* Allocate common symbols, symbol tables, and string tables. */
4295
Eric Andersen03d80912003-12-19 21:04:19 +00004296 if (k_new_syscalls
Eric Andersen3b1a7442003-12-24 20:30:45 +00004297 ? !new_create_this_module(f, m_name)
4298 : !old_create_mod_use_count(f))
Eric Andersen9f16d612000-06-12 23:11:16 +00004299 {
4300 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004301 }
4302
Eric Andersen9f16d612000-06-12 23:11:16 +00004303 if (!obj_check_undefineds(f)) {
4304 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004305 }
4306 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004307 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004308
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004309 /* done with the module name, on to the optional var=value arguments */
4310 ++optind;
4311
Eric Andersen9f16d612000-06-12 23:11:16 +00004312 if (optind < argc) {
4313 if (m_has_modinfo
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314 ? !new_process_module_arguments(f, argc - optind, argv + optind)
4315 : !old_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004316 {
4317 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004318 }
4319 }
4320
Eric Andersen9f16d612000-06-12 23:11:16 +00004321 arch_create_got(f);
4322 hide_special_symbols(f);
4323
Eric Andersen889dd202003-01-23 04:48:34 +00004324#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4325 add_ksymoops_symbols(f, m_filename, m_name);
4326#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4327
Eric Andersen9f16d612000-06-12 23:11:16 +00004328 if (k_new_syscalls)
4329 new_create_module_ksymtab(f);
4330
Erik Andersene49d5ec2000-02-08 19:58:47 +00004331 /* Find current size of the module */
4332 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004333
4334
Erik Andersene49d5ec2000-02-08 19:58:47 +00004335 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004336 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004337 case EEXIST:
4338 bb_error_msg("A module named %s already exists", m_name);
4339 goto out;
4340 case ENOMEM:
4341 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4342 m_size);
4343 goto out;
4344 default:
4345 bb_perror_msg("create_module: %s", m_name);
4346 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004347 }
Erik Andersend387d011999-12-21 02:55:11 +00004348
Eric Andersen8ae319a2001-05-21 16:09:18 +00004349#if !LOADBITS
4350 /*
4351 * the PROGBITS section was not loaded by the obj_load
4352 * now we can load them directly into the kernel memory
4353 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004354 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004355 delete_module(m_name);
4356 goto out;
4357 }
Eric Andersen03d80912003-12-19 21:04:19 +00004358#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004359
Eric Andersen9f16d612000-06-12 23:11:16 +00004360 if (!obj_relocate(f, m_addr)) {
4361 delete_module(m_name);
4362 goto out;
4363 }
Erik Andersend387d011999-12-21 02:55:11 +00004364
Eric Andersen03d80912003-12-19 21:04:19 +00004365 if (k_new_syscalls
Eric Andersen3b1a7442003-12-24 20:30:45 +00004366 ? !new_init_module(m_name, f, m_size)
4367 : !old_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004368 {
4369 delete_module(m_name);
4370 goto out;
4371 }
4372
Eric Andersenbe65c352003-01-23 04:57:35 +00004373#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4374 if(flag_print_load_map)
4375 print_load_map(f);
4376#endif
4377
Matt Kraai3e856ce2000-12-01 02:55:13 +00004378 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004379
4380out:
Eric Andersen61f83052002-06-22 17:15:42 +00004381#ifdef CONFIG_FEATURE_CLEAN_UP
4382 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004383 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004384 if(tmp1) {
4385 free(tmp1);
4386 } else {
4387 free(m_name);
4388 }
4389 free(m_filename);
4390#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004391 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004392}
Eric Andersene7047882003-12-11 01:42:13 +00004393
4394
4395#endif
4396
4397
4398#ifdef CONFIG_FEATURE_2_6_MODULES
4399
4400#include <sys/mman.h>
4401#include <asm/unistd.h>
4402#include <sys/syscall.h>
4403
4404/* We use error numbers in a loose translation... */
4405static const char *moderror(int err)
4406{
4407 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004408 case ENOEXEC:
4409 return "Invalid module format";
4410 case ENOENT:
4411 return "Unknown symbol in module";
4412 case ESRCH:
4413 return "Module has wrong symbol version";
4414 case EINVAL:
4415 return "Invalid parameters";
4416 default:
4417 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004418 }
4419}
4420
4421extern int insmod_ng_main( int argc, char **argv)
4422{
4423 int i;
4424 int fd;
4425 long int ret;
4426 struct stat st;
4427 unsigned long len;
4428 void *map;
4429 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004430
Eric Andersene7047882003-12-11 01:42:13 +00004431 filename = argv[1];
4432 if (!filename) {
4433 bb_show_usage();
4434 return -1;
4435 }
4436
4437 /* Rest is options */
4438 for (i = 2; i < argc; i++) {
4439 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4440 /* Spaces handled by "" pairs, but no way of escaping quotes */
4441 if (strchr(argv[i], ' ')) {
4442 strcat(options, "\"");
4443 strcat(options, argv[i]);
4444 strcat(options, "\"");
4445 } else {
4446 strcat(options, argv[i]);
4447 }
4448 strcat(options, " ");
4449 }
4450
4451 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4452 bb_perror_msg_and_die("cannot open module `%s'", filename);
4453 }
4454
4455 fstat(fd, &st);
4456 len = st.st_size;
4457 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4458 if (map == MAP_FAILED) {
4459 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4460 }
4461
4462 ret = syscall(__NR_init_module, map, len, options);
4463 if (ret != 0) {
4464 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004465 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004466 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004467
Eric Andersene7047882003-12-11 01:42:13 +00004468 return 0;
4469}
4470
4471#endif