blob: d98341e7b4d7afffec6087dddc5b180c387b429c [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,
Eric Andersenee70fa52004-05-26 11:38:46 +00006 * MIPS, v850e, and H8/300.
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 Andersenee70fa52004-05-26 11:38:46 +000021 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
22 * added Renesas H8/300 support.
23 *
Eric Andersenbf833552003-08-13 19:56:33 +000024 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
25 * Integrated support for sh64 (SH-5), from preliminary modutils
26 * patches from Benedict Gaster <benedict.gaster@superh.com>.
27 * Currently limited to support for 32bit ABI.
28 *
Eric Andersencffd5022002-05-24 06:50:15 +000029 * Magnus Damm <damm@opensource.se> 22-May-2002.
30 * The plt and got code are now using the same structs.
31 * Added generic linked list code to fully support PowerPC.
32 * Replaced the mess in arch_apply_relocation() with architecture blocks.
33 * The arch_create_got() function got cleaned up with architecture blocks.
34 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
35 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000036 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000037 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000038 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
39 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000040 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000042 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
43 * based on modutils-2.4.2
44 * MIPS specific support for Elf loading and relocation.
45 * Copyright 1996, 1997 Linux International.
46 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
47 *
Eric Andersen9f16d612000-06-12 23:11:16 +000048 * Based almost entirely on the Linux modutils-2.3.11 implementation.
49 * Copyright 1996, 1997 Linux International.
50 * New implementation contributed by Richard Henderson <rth@tamu.edu>
51 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
52 * Restructured (and partly rewritten) by:
53 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000054 *
55 * This program is free software; you can redistribute it and/or modify
56 * it under the terms of the GNU General Public License as published by
57 * the Free Software Foundation; either version 2 of the License, or
58 * (at your option) any later version.
59 *
60 * This program is distributed in the hope that it will be useful,
61 * but WITHOUT ANY WARRANTY; without even the implied warranty of
62 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
63 * General Public License for more details.
64 *
65 * You should have received a copy of the GNU General Public License
66 * along with this program; if not, write to the Free Software
67 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
68 *
69 */
70
Erik Andersen02104321999-12-17 18:57:34 +000071#include <stdlib.h>
72#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000073#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000074#include <errno.h>
75#include <unistd.h>
76#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000077#include <ctype.h>
78#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000079#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000080#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000081#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000082#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000083#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000084
Eric Andersene7047882003-12-11 01:42:13 +000085#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
86 !defined(CONFIG_FEATURE_2_2_MODULES) && \
87 !defined(CONFIG_FEATURE_2_6_MODULES)
88#define CONFIG_FEATURE_2_4_MODULES
89#endif
90
91#if !defined(CONFIG_FEATURE_2_4_MODULES) && !defined(CONFIG_FEATURE_2_2_MODULES)
92#define insmod_ng_main insmod_main
93#endif
94
95#if defined(CONFIG_FEATURE_2_4_MODULES) || defined(CONFIG_FEATURE_2_2_MODULES)
96
97#if defined(CONFIG_FEATURE_2_6_MODULES)
98extern int insmod_ng_main( int argc, char **argv);
99#endif
100
101#ifdef CONFIG_FEATURE_2_4_MODULES
102# undef CONFIG_FEATURE_2_2_MODULES
Eric Andersen64c8b172001-04-05 07:33:10 +0000103# define new_sys_init_module init_module
104#else
105# define old_sys_init_module init_module
106#endif
107
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000108#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000109#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +0000110#else
111#define LOADBITS 1
112#endif
113
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000114
115#if defined(__arm__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000116#define CONFIG_USE_PLT_ENTRIES
117#define CONFIG_PLT_ENTRY_SIZE 8
118#define CONFIG_USE_GOT_ENTRIES
119#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000120#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000121
Eric Andersencffd5022002-05-24 06:50:15 +0000122#define MATCH_MACHINE(x) (x == EM_ARM)
123#define SHT_RELM SHT_REL
124#define Elf32_RelM Elf32_Rel
125#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000126#endif
127
Eric Andersenbf77f612003-01-23 06:02:39 +0000128#if defined(__s390__)
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000129#define CONFIG_USE_PLT_ENTRIES
130#define CONFIG_PLT_ENTRY_SIZE 8
131#define CONFIG_USE_GOT_ENTRIES
132#define CONFIG_GOT_ENTRY_SIZE 8
133#define CONFIG_USE_SINGLE
Eric Andersenbf77f612003-01-23 06:02:39 +0000134
135#define MATCH_MACHINE(x) (x == EM_S390)
136#define SHT_RELM SHT_RELA
137#define Elf32_RelM Elf32_Rela
138#define ELFCLASSM ELFCLASS32
139#endif
140
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000141#if defined(__i386__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000142#define CONFIG_USE_GOT_ENTRIES
143#define CONFIG_GOT_ENTRY_SIZE 4
Eric Andersencffd5022002-05-24 06:50:15 +0000144#define CONFIG_USE_SINGLE
145
146#ifndef EM_486
147#define MATCH_MACHINE(x) (x == EM_386)
148#else
149#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
150#endif
151
152#define SHT_RELM SHT_REL
153#define Elf32_RelM Elf32_Rel
154#define ELFCLASSM ELFCLASS32
155#endif
156
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000157#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000158#define CONFIG_USE_GOT_ENTRIES
159#define CONFIG_GOT_ENTRY_SIZE 4
160#define CONFIG_USE_SINGLE
161
162#define MATCH_MACHINE(x) (x == EM_68K)
163#define SHT_RELM SHT_RELA
164#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000165#define ELFCLASSM ELFCLASS32
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000166#endif
167
Eric Andersen2bf658d2001-02-24 20:01:53 +0000168#if defined(__mips__)
Eric Andersencffd5022002-05-24 06:50:15 +0000169/* Account for ELF spec changes. */
170#ifndef EM_MIPS_RS3_LE
171#ifdef EM_MIPS_RS4_BE
172#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
173#else
174#define EM_MIPS_RS3_LE 10
175#endif
176#endif /* !EM_MIPS_RS3_LE */
177
178#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
179#define SHT_RELM SHT_REL
180#define Elf32_RelM Elf32_Rel
181#define ELFCLASSM ELFCLASS32
182#define ARCHDATAM "__dbe_table"
183#endif
184
185#if defined(__powerpc__)
186#define CONFIG_USE_PLT_ENTRIES
187#define CONFIG_PLT_ENTRY_SIZE 16
188#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000189#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000190#define CONFIG_USE_LIST
191
192#define MATCH_MACHINE(x) (x == EM_PPC)
193#define SHT_RELM SHT_RELA
194#define Elf32_RelM Elf32_Rela
195#define ELFCLASSM ELFCLASS32
196#define ARCHDATAM "__ftr_fixup"
197#endif
198
199#if defined(__sh__)
200#define CONFIG_USE_GOT_ENTRIES
201#define CONFIG_GOT_ENTRY_SIZE 4
202#define CONFIG_USE_SINGLE
203
204#define MATCH_MACHINE(x) (x == EM_SH)
205#define SHT_RELM SHT_RELA
206#define Elf32_RelM Elf32_Rela
207#define ELFCLASSM ELFCLASS32
208
Eric Andersenbf833552003-08-13 19:56:33 +0000209/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000210/* I'm not sure about big endian, so let's warn: */
211
Eric Andersenbf833552003-08-13 19:56:33 +0000212#if defined(__sh__) && defined(__BIG_ENDIAN__)
213#error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000214#endif
215
216/* it may or may not work on the SH1/SH2... So let's error on those
217 also */
Eric Andersenbf833552003-08-13 19:56:33 +0000218#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && \
219 (defined(__sh__))
220#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000221#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000222#endif
223
Miles Baderae28b042002-04-01 09:34:25 +0000224#if defined (__v850e__)
225#define CONFIG_USE_PLT_ENTRIES
226#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000227#define CONFIG_USE_SINGLE
228
229#ifndef EM_CYGNUS_V850 /* grumble */
230#define EM_CYGNUS_V850 0x9080
Miles Baderae28b042002-04-01 09:34:25 +0000231#endif
232
Eric Andersencffd5022002-05-24 06:50:15 +0000233#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
234#define SHT_RELM SHT_RELA
235#define Elf32_RelM Elf32_Rela
236#define ELFCLASSM ELFCLASS32
237
238#define SYMBOL_PREFIX "_"
239#endif
240
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +0000241#if defined(__cris__)
242#ifndef EM_CRIS
243#define EM_CRIS 76
244#define R_CRIS_NONE 0
245#define R_CRIS_32 3
246#endif
247
248#define MATCH_MACHINE(x) (x == EM_CRIS)
249#define SHT_RELM SHT_RELA
250#define Elf32_RelM Elf32_Rela
251#define ELFCLASSM ELFCLASS32
252#endif
253
Eric Andersenee70fa52004-05-26 11:38:46 +0000254#if defined(__H8300H__) || defined(__H8300S__)
255#define CONFIG_USE_SINGLE
256
257#define MATCH_MACHINE(x) (x == EM_H8_300)
258#define SHT_RELM SHT_RELA
259#define Elf32_RelM Elf32_Rela
260
261#define ELFCLASSM ELFCLASS32
262#define SYMBOL_PREFIX "_"
263#endif
264
Eric Andersencffd5022002-05-24 06:50:15 +0000265#ifndef SHT_RELM
266#error Sorry, but insmod.c does not yet support this architecture...
267#endif
268
269
Eric Andersen9f16d612000-06-12 23:11:16 +0000270//----------------------------------------------------------------------------
271//--------modutils module.h, lines 45-242
272//----------------------------------------------------------------------------
273
274/* Definitions for the Linux module syscall interface.
275 Copyright 1996, 1997 Linux International.
276
277 Contributed by Richard Henderson <rth@tamu.edu>
278
279 This file is part of the Linux modutils.
280
281 This program is free software; you can redistribute it and/or modify it
282 under the terms of the GNU General Public License as published by the
283 Free Software Foundation; either version 2 of the License, or (at your
284 option) any later version.
285
286 This program is distributed in the hope that it will be useful, but
287 WITHOUT ANY WARRANTY; without even the implied warranty of
288 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
289 General Public License for more details.
290
291 You should have received a copy of the GNU General Public License
292 along with this program; if not, write to the Free Software Foundation,
293 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
294
295
296#ifndef MODUTILS_MODULE_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000297static const int MODUTILS_MODULE_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000298
Eric Andersena6f6a952004-05-26 12:06:38 +0000299#ident "$Id: insmod.c,v 1.119 2004/05/26 12:06:38 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000300
301/* This file contains the structures used by the 2.0 and 2.1 kernels.
302 We do not use the kernel headers directly because we do not wish
Eric Andersenaff114c2004-04-14 17:51:38 +0000303 to be dependent on a particular kernel version to compile insmod. */
Eric Andersen9f16d612000-06-12 23:11:16 +0000304
305
306/*======================================================================*/
307/* The structures used by Linux 2.0. */
308
309/* The symbol format used by get_kernel_syms(2). */
310struct old_kernel_sym
311{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000312 unsigned long value;
313 char name[60];
Eric Andersen9f16d612000-06-12 23:11:16 +0000314};
315
316struct old_module_ref
317{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000318 unsigned long module; /* kernel addresses */
319 unsigned long next;
Eric Andersen9f16d612000-06-12 23:11:16 +0000320};
321
322struct old_module_symbol
323{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000324 unsigned long addr;
325 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000326};
327
328struct old_symbol_table
329{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000330 int size; /* total, including string table!!! */
331 int n_symbols;
332 int n_refs;
333 struct old_module_symbol symbol[0]; /* actual size defined by n_symbols */
334 struct old_module_ref ref[0]; /* actual size defined by n_refs */
Eric Andersen9f16d612000-06-12 23:11:16 +0000335};
336
337struct old_mod_routines
338{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000339 unsigned long init;
340 unsigned long cleanup;
Eric Andersen9f16d612000-06-12 23:11:16 +0000341};
342
343struct old_module
344{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000345 unsigned long next;
346 unsigned long ref; /* the list of modules that refer to me */
347 unsigned long symtab;
348 unsigned long name;
349 int size; /* size of module in pages */
350 unsigned long addr; /* address of module */
351 int state;
352 unsigned long cleanup; /* cleanup routine */
Eric Andersen9f16d612000-06-12 23:11:16 +0000353};
354
355/* Sent to init_module(2) or'ed into the code size parameter. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000356static const int OLD_MOD_AUTOCLEAN = 0x40000000; /* big enough, but no sign problems... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000357
358int get_kernel_syms(struct old_kernel_sym *);
359int old_sys_init_module(const char *name, char *code, unsigned codesize,
360 struct old_mod_routines *, struct old_symbol_table *);
361
362/*======================================================================*/
363/* For sizeof() which are related to the module platform and not to the
364 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
365
366#define tgt_sizeof_char sizeof(char)
367#define tgt_sizeof_short sizeof(short)
368#define tgt_sizeof_int sizeof(int)
369#define tgt_sizeof_long sizeof(long)
370#define tgt_sizeof_char_p sizeof(char *)
371#define tgt_sizeof_void_p sizeof(void *)
372#define tgt_long long
373
374#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
375#undef tgt_sizeof_long
376#undef tgt_sizeof_char_p
377#undef tgt_sizeof_void_p
378#undef tgt_long
Mark Whitley59ab0252001-01-23 22:30:04 +0000379static const int tgt_sizeof_long = 8;
380static const int tgt_sizeof_char_p = 8;
381static const int tgt_sizeof_void_p = 8;
Eric Andersen9f16d612000-06-12 23:11:16 +0000382#define tgt_long long long
383#endif
384
385/*======================================================================*/
386/* The structures used in Linux 2.1. */
387
388/* Note: new_module_symbol does not use tgt_long intentionally */
389struct new_module_symbol
390{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000391 unsigned long value;
392 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000393};
394
395struct new_module_persist;
396
397struct new_module_ref
398{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000399 unsigned tgt_long dep; /* kernel addresses */
400 unsigned tgt_long ref;
401 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000402};
403
404struct new_module
405{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000406 unsigned tgt_long size_of_struct; /* == sizeof(module) */
407 unsigned tgt_long next;
408 unsigned tgt_long name;
409 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000410
Eric Andersen3b1a7442003-12-24 20:30:45 +0000411 tgt_long usecount;
412 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000413
Eric Andersen3b1a7442003-12-24 20:30:45 +0000414 unsigned nsyms;
415 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000416
Eric Andersen3b1a7442003-12-24 20:30:45 +0000417 unsigned tgt_long syms;
418 unsigned tgt_long deps;
419 unsigned tgt_long refs;
420 unsigned tgt_long init;
421 unsigned tgt_long cleanup;
422 unsigned tgt_long ex_table_start;
423 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000424#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000425 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000426#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000427 /* Everything after here is extension. */
428 unsigned tgt_long persist_start;
429 unsigned tgt_long persist_end;
430 unsigned tgt_long can_unload;
431 unsigned tgt_long runsize;
Eric Andersene7047882003-12-11 01:42:13 +0000432#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen3b1a7442003-12-24 20:30:45 +0000433 const char *kallsyms_start; /* All symbols for kernel debugging */
434 const char *kallsyms_end;
435 const char *archdata_start; /* arch specific data for module */
436 const char *archdata_end;
437 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen8ae319a2001-05-21 16:09:18 +0000438#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000439};
440
Eric Andersencffd5022002-05-24 06:50:15 +0000441#ifdef ARCHDATAM
442#define ARCHDATA_SEC_NAME ARCHDATAM
443#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000444#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000445#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000446#define KALLSYMS_SEC_NAME "__kallsyms"
447
448
Eric Andersen9f16d612000-06-12 23:11:16 +0000449struct new_module_info
450{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000451 unsigned long addr;
452 unsigned long size;
453 unsigned long flags;
454 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000455};
456
457/* Bits of module.flags. */
Mark Whitley59ab0252001-01-23 22:30:04 +0000458static const int NEW_MOD_RUNNING = 1;
459static const int NEW_MOD_DELETED = 2;
460static const int NEW_MOD_AUTOCLEAN = 4;
461static const int NEW_MOD_VISITED = 8;
462static const int NEW_MOD_USED_ONCE = 16;
Eric Andersen9f16d612000-06-12 23:11:16 +0000463
Eric Andersen64c8b172001-04-05 07:33:10 +0000464int new_sys_init_module(const char *name, const struct new_module *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000465int query_module(const char *name, int which, void *buf, size_t bufsize,
466 size_t *ret);
467
468/* Values for query_module's which. */
469
Mark Whitley59ab0252001-01-23 22:30:04 +0000470static const int QM_MODULES = 1;
471static const int QM_DEPS = 2;
472static const int QM_REFS = 3;
473static const int QM_SYMBOLS = 4;
474static const int QM_INFO = 5;
Eric Andersen9f16d612000-06-12 23:11:16 +0000475
476/*======================================================================*/
477/* The system calls unchanged between 2.0 and 2.1. */
478
479unsigned long create_module(const char *, size_t);
480int delete_module(const char *);
481
482
483#endif /* module.h */
484
485//----------------------------------------------------------------------------
486//--------end of modutils module.h
487//----------------------------------------------------------------------------
488
489
490
491//----------------------------------------------------------------------------
492//--------modutils obj.h, lines 253-462
493//----------------------------------------------------------------------------
494
495/* Elf object file loading and relocation routines.
496 Copyright 1996, 1997 Linux International.
497
498 Contributed by Richard Henderson <rth@tamu.edu>
499
500 This file is part of the Linux modutils.
501
502 This program is free software; you can redistribute it and/or modify it
503 under the terms of the GNU General Public License as published by the
504 Free Software Foundation; either version 2 of the License, or (at your
505 option) any later version.
506
507 This program is distributed in the hope that it will be useful, but
508 WITHOUT ANY WARRANTY; without even the implied warranty of
509 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
510 General Public License for more details.
511
512 You should have received a copy of the GNU General Public License
513 along with this program; if not, write to the Free Software Foundation,
514 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
515
516
517#ifndef MODUTILS_OBJ_H
Mark Whitley59ab0252001-01-23 22:30:04 +0000518static const int MODUTILS_OBJ_H = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000519
Eric Andersena6f6a952004-05-26 12:06:38 +0000520#ident "$Id: insmod.c,v 1.119 2004/05/26 12:06:38 andersen Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000521
522/* The relocatable object is manipulated using elfin types. */
523
524#include <stdio.h>
525#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000526#include <endian.h>
527
528#if __BYTE_ORDER == __LITTLE_ENDIAN
529#define ELFDATAM ELFDATA2LSB
530#elif __BYTE_ORDER == __BIG_ENDIAN
531#define ELFDATAM ELFDATA2MSB
532#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000533
Eric Andersen9f16d612000-06-12 23:11:16 +0000534#ifndef ElfW
535# if ELFCLASSM == ELFCLASS32
536# define ElfW(x) Elf32_ ## x
537# define ELFW(x) ELF32_ ## x
538# else
539# define ElfW(x) Elf64_ ## x
540# define ELFW(x) ELF64_ ## x
541# endif
542#endif
543
Eric Andersen85e5e722003-07-22 08:56:55 +0000544/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000545#ifndef ELF32_ST_INFO
546# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
547#endif
548
549#ifndef ELF64_ST_INFO
550# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
551#endif
552
553struct obj_string_patch;
554struct obj_symbol_patch;
555
556struct obj_section
557{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000558 ElfW(Shdr) header;
559 const char *name;
560 char *contents;
561 struct obj_section *load_next;
562 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000563};
564
565struct obj_symbol
566{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000567 struct obj_symbol *next; /* hash table link */
568 const char *name;
569 unsigned long value;
570 unsigned long size;
571 int secidx; /* the defining section index/module */
572 int info;
573 int ksymidx; /* for export to the kernel symtab */
574 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000575};
576
577/* Hardcode the hash table size. We shouldn't be needing so many
578 symbols that we begin to degrade performance, and we get a big win
579 by giving the compiler a constant divisor. */
580
581#define HASH_BUCKETS 521
582
583struct obj_file
584{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000585 ElfW(Ehdr) header;
586 ElfW(Addr) baseaddr;
587 struct obj_section **sections;
588 struct obj_section *load_order;
589 struct obj_section **load_order_search_start;
590 struct obj_string_patch *string_patches;
591 struct obj_symbol_patch *symbol_patches;
592 int (*symbol_cmp)(const char *, const char *);
593 unsigned long (*symbol_hash)(const char *);
594 unsigned long local_symtab_size;
595 struct obj_symbol **local_symtab;
596 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000597};
598
599enum obj_reloc
600{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000601 obj_reloc_ok,
602 obj_reloc_overflow,
603 obj_reloc_dangerous,
604 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000605};
606
607struct obj_string_patch
608{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000609 struct obj_string_patch *next;
610 int reloc_secidx;
611 ElfW(Addr) reloc_offset;
612 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000613};
614
615struct obj_symbol_patch
616{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000617 struct obj_symbol_patch *next;
618 int reloc_secidx;
619 ElfW(Addr) reloc_offset;
620 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000621};
622
623
624/* Generic object manipulation routines. */
625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000627
Eric Andersen044228d2001-07-17 01:12:36 +0000628static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000629
Eric Andersen044228d2001-07-17 01:12:36 +0000630static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000631 const char *name);
632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000634 struct obj_symbol *sym);
635
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000636#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000637static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000638 int (*cmp)(const char *, const char *),
639 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000640#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000641
Eric Andersen044228d2001-07-17 01:12:36 +0000642static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000643 const char *name);
644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000646 struct obj_section *sec);
647
Eric Andersen044228d2001-07-17 01:12:36 +0000648static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000649 const char *name,
650 unsigned long align,
651 unsigned long size);
652
Eric Andersen044228d2001-07-17 01:12:36 +0000653static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000654 const char *name,
655 unsigned long align,
656 unsigned long size);
657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000659
Eric Andersen044228d2001-07-17 01:12:36 +0000660static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000661 const char *string);
662
Eric Andersene7047882003-12-11 01:42:13 +0000663#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +0000664static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000665 struct obj_symbol *sym);
Eric Andersen6d139642001-12-29 04:15:13 +0000666#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000667
Eric Andersen044228d2001-07-17 01:12:36 +0000668static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000669
Eric Andersen044228d2001-07-17 01:12:36 +0000670static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000671
Eric Andersen044228d2001-07-17 01:12:36 +0000672static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000673
Eric Andersen044228d2001-07-17 01:12:36 +0000674static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000675
Eric Andersen044228d2001-07-17 01:12:36 +0000676static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000677
Eric Andersen044228d2001-07-17 01:12:36 +0000678static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000679
680/* Architecture specific manipulation routines. */
681
Eric Andersen044228d2001-07-17 01:12:36 +0000682static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000683
Eric Andersen044228d2001-07-17 01:12:36 +0000684static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000685
Eric Andersen044228d2001-07-17 01:12:36 +0000686static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000687
Eric Andersen044228d2001-07-17 01:12:36 +0000688static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000689 struct obj_section *targsec,
690 struct obj_section *symsec,
691 struct obj_symbol *sym,
692 ElfW(RelM) *rel, ElfW(Addr) value);
693
Eric Andersencffd5022002-05-24 06:50:15 +0000694static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000695
Glenn L McGrath759515c2003-08-30 06:00:33 +0000696static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000697
Eric Andersene7047882003-12-11 01:42:13 +0000698#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +0000699static int arch_init_module (struct obj_file *f, struct new_module *);
Eric Andersen6d139642001-12-29 04:15:13 +0000700#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000701
702#endif /* obj.h */
703//----------------------------------------------------------------------------
704//--------end of modutils obj.h
705//----------------------------------------------------------------------------
706
707
Miles Baderae28b042002-04-01 09:34:25 +0000708/* SPFX is always a string, so it can be concatenated to string constants. */
709#ifdef SYMBOL_PREFIX
710#define SPFX SYMBOL_PREFIX
711#else
712#define SPFX ""
713#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000714
Erik Andersen02104321999-12-17 18:57:34 +0000715
Erik Andersend387d011999-12-21 02:55:11 +0000716#define _PATH_MODULES "/lib/modules"
Mark Whitley59ab0252001-01-23 22:30:04 +0000717static const int STRVERSIONLEN = 32;
Erik Andersend387d011999-12-21 02:55:11 +0000718
Eric Andersen9f16d612000-06-12 23:11:16 +0000719/*======================================================================*/
720
Eric Andersen044228d2001-07-17 01:12:36 +0000721static int flag_force_load = 0;
722static int flag_autoclean = 0;
723static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000724static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000725static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000726
727
728/*======================================================================*/
729
Eric Andersencffd5022002-05-24 06:50:15 +0000730#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000731
Eric Andersencffd5022002-05-24 06:50:15 +0000732struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000733{
Eric Andersencffd5022002-05-24 06:50:15 +0000734 struct arch_list_entry *next;
735 CONFIG_LIST_ARCHTYPE addend;
736 int offset;
737 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000738};
Eric Andersencffd5022002-05-24 06:50:15 +0000739
Eric Andersen21adca72000-12-06 18:18:26 +0000740#endif
741
Eric Andersencffd5022002-05-24 06:50:15 +0000742#if defined(CONFIG_USE_SINGLE)
743
744struct arch_single_entry
745{
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000747 int inited : 1;
748 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000749};
Eric Andersencffd5022002-05-24 06:50:15 +0000750
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000751#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000752
Eric Andersen2bf658d2001-02-24 20:01:53 +0000753#if defined(__mips__)
754struct mips_hi16
755{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000756 struct mips_hi16 *next;
757 Elf32_Addr *addr;
758 Elf32_Addr value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000759};
760#endif
761
Eric Andersenfe4208f2000-09-24 03:44:29 +0000762struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000763 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000764#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000765 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000766#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000767#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000768 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000769#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000770#if defined(__mips__)
771 struct mips_hi16 *mips_hi16_list;
772#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000773};
774
Eric Andersenfe4208f2000-09-24 03:44:29 +0000775struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000776 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000777#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000778#if defined(CONFIG_USE_PLT_LIST)
779 struct arch_list_entry *pltent;
780#else
781 struct arch_single_entry pltent;
782#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000783#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000784#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000785 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000786#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000787};
788
789
Eric Andersen9f16d612000-06-12 23:11:16 +0000790struct external_module {
791 const char *name;
792 ElfW(Addr) addr;
793 int used;
794 size_t nsyms;
795 struct new_module_symbol *syms;
796};
797
Eric Andersen044228d2001-07-17 01:12:36 +0000798static struct new_module_symbol *ksyms;
799static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000800
Eric Andersen044228d2001-07-17 01:12:36 +0000801static struct external_module *ext_modules;
802static int n_ext_modules;
803static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000804extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000805
Eric Andersen61f83052002-06-22 17:15:42 +0000806static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000807static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000808
Eric Andersenfe4208f2000-09-24 03:44:29 +0000809
Erik Andersen02104321999-12-17 18:57:34 +0000810
Eric Andersen9f16d612000-06-12 23:11:16 +0000811/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000812
Eric Andersen9f16d612000-06-12 23:11:16 +0000813
Eric Andersen14d35432001-05-14 17:07:32 +0000814static int check_module_name_match(const char *filename, struct stat *statbuf,
815 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000816{
Eric Andersen14d35432001-05-14 17:07:32 +0000817 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000818
Eric Andersen14d35432001-05-14 17:07:32 +0000819 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000820 return (FALSE);
821 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000822 char *tmp, *tmp1 = bb_xstrdup(filename);
823 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000824 if (strcmp(tmp, fullname) == 0) {
825 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000826 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000827 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000828 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000829 }
Eric Andersen14d35432001-05-14 17:07:32 +0000830 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000831 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000832 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000833}
834
Erik Andersen02104321999-12-17 18:57:34 +0000835
Eric Andersen9f16d612000-06-12 23:11:16 +0000836/*======================================================================*/
837
Eric Andersen044228d2001-07-17 01:12:36 +0000838static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000839{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000840 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000841 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000842
Eric Andersencffd5022002-05-24 06:50:15 +0000843 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000844
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 return &f->root;
846}
847
Eric Andersen044228d2001-07-17 01:12:36 +0000848static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000849{
850 return xmalloc(sizeof(struct obj_section));
851}
852
Eric Andersen044228d2001-07-17 01:12:36 +0000853static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000854{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000855 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000856 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000857
Eric Andersencffd5022002-05-24 06:50:15 +0000858 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000859
Eric Andersen9f16d612000-06-12 23:11:16 +0000860 return &sym->root;
861}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000862
Eric Andersen044228d2001-07-17 01:12:36 +0000863static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000864arch_apply_relocation(struct obj_file *f,
865 struct obj_section *targsec,
866 struct obj_section *symsec,
867 struct obj_symbol *sym,
Eric Andersen21adca72000-12-06 18:18:26 +0000868 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000869{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000870 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000871 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000872 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
873 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000874#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
875 struct arch_symbol *isym = (struct arch_symbol *) sym;
876#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000877#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000878 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000879#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000880#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000881 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000882 unsigned long *ip;
Eric Andersencffd5022002-05-24 06:50:15 +0000883#if defined(CONFIG_USE_PLT_LIST)
884 struct arch_list_entry *pe;
885#else
886 struct arch_single_entry *pe;
Eric Andersen21adca72000-12-06 18:18:26 +0000887#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000888#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000889
890 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000891
Eric Andersencffd5022002-05-24 06:50:15 +0000892
893#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 case R_ARM_NONE:
895 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000896
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 case R_ARM_ABS32:
898 *loc += v;
899 break;
Miles Baderae28b042002-04-01 09:34:25 +0000900
Eric Andersen3b1a7442003-12-24 20:30:45 +0000901 case R_ARM_GOT32:
902 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000903
Eric Andersen3b1a7442003-12-24 20:30:45 +0000904 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000905 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
906 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000907 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000908
Eric Andersen3b1a7442003-12-24 20:30:45 +0000909 assert(got);
910 *loc += got - dot;
911 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000912
Eric Andersen3b1a7442003-12-24 20:30:45 +0000913 case R_ARM_PC24:
914 case R_ARM_PLT32:
915 goto bb_use_plt;
916
917 case R_ARM_GOTOFF: /* address relative to the got */
918 assert(got);
919 *loc += v - got;
920 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000921
Eric Andersenbf77f612003-01-23 06:02:39 +0000922#elif defined(__s390__)
Eric Andersen3b1a7442003-12-24 20:30:45 +0000923 case R_390_32:
924 *(unsigned int *) loc += v;
925 break;
926 case R_390_16:
927 *(unsigned short *) loc += v;
928 break;
929 case R_390_8:
930 *(unsigned char *) loc += v;
931 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000932
Eric Andersen3b1a7442003-12-24 20:30:45 +0000933 case R_390_PC32:
934 *(unsigned int *) loc += v - dot;
935 break;
936 case R_390_PC16DBL:
937 *(unsigned short *) loc += (v - dot) >> 1;
938 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000939 case R_390_PC16:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000940 *(unsigned short *) loc += v - dot;
941 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000942
Eric Andersen3b1a7442003-12-24 20:30:45 +0000943 case R_390_PLT32:
944 case R_390_PLT16DBL:
945 /* find the plt entry and initialize it. */
946 assert(isym != NULL);
947 pe = (struct arch_single_entry *) &isym->pltent;
948 assert(pe->allocated);
949 if (pe->inited == 0) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000950 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
952 ip[1] = 0x100607f1;
953 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
954 ip[2] = v - 2;
955 else
956 ip[2] = v;
957 pe->inited = 1;
958 }
Eric Andersenbf77f612003-01-23 06:02:39 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 /* Insert relative distance to target. */
961 v = plt + pe->offset - dot;
962 if (ELF32_R_TYPE(rel->r_info) == R_390_PLT32)
963 *(unsigned int *) loc = (unsigned int) v;
964 else if (ELF32_R_TYPE(rel->r_info) == R_390_PLT16DBL)
965 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
966 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000967
Eric Andersen3b1a7442003-12-24 20:30:45 +0000968 case R_390_GLOB_DAT:
969 case R_390_JMP_SLOT:
970 *loc = v;
971 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000972
Eric Andersen3b1a7442003-12-24 20:30:45 +0000973 case R_390_RELATIVE:
974 *loc += f->baseaddr;
975 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000976
Eric Andersen3b1a7442003-12-24 20:30:45 +0000977 case R_390_GOTPC:
978 assert(got != 0);
979 *(unsigned long *) loc += got - dot;
980 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000981
Eric Andersen3b1a7442003-12-24 20:30:45 +0000982 case R_390_GOT12:
983 case R_390_GOT16:
984 case R_390_GOT32:
985 assert(isym != NULL);
986 assert(got != 0);
987 if (!isym->gotent.inited)
988 {
989 isym->gotent.inited = 1;
990 *(Elf32_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
991 }
992 if (ELF32_R_TYPE(rel->r_info) == R_390_GOT12)
993 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
994 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT16)
995 *(unsigned short *) loc += isym->gotent.offset;
996 else if (ELF32_R_TYPE(rel->r_info) == R_390_GOT32)
997 *(unsigned int *) loc += isym->gotent.offset;
998 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000999
Eric Andersen951df202003-10-21 06:45:29 +00001000#ifndef R_390_GOTOFF32
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001001#define R_390_GOTOFF32 R_390_GOTOFF
Eric Andersen951df202003-10-21 06:45:29 +00001002#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001003 case R_390_GOTOFF32:
1004 assert(got != 0);
1005 *loc += v - got;
1006 break;
Eric Andersenbf77f612003-01-23 06:02:39 +00001007
Eric Andersencffd5022002-05-24 06:50:15 +00001008#elif defined(__i386__)
1009
Eric Andersen3b1a7442003-12-24 20:30:45 +00001010 case R_386_NONE:
1011 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001012
Eric Andersen3b1a7442003-12-24 20:30:45 +00001013 case R_386_32:
1014 *loc += v;
1015 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001016
Eric Andersen3b1a7442003-12-24 20:30:45 +00001017 case R_386_PLT32:
1018 case R_386_PC32:
1019 *loc += v - dot;
1020 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001021
Eric Andersen3b1a7442003-12-24 20:30:45 +00001022 case R_386_GLOB_DAT:
1023 case R_386_JMP_SLOT:
1024 *loc = v;
1025 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001026
Eric Andersen3b1a7442003-12-24 20:30:45 +00001027 case R_386_RELATIVE:
1028 *loc += f->baseaddr;
1029 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001030
Eric Andersen3b1a7442003-12-24 20:30:45 +00001031 case R_386_GOTPC:
1032 assert(got != 0);
1033 *loc += got - dot;
1034 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001035
Eric Andersen3b1a7442003-12-24 20:30:45 +00001036 case R_386_GOT32:
1037 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001038
Eric Andersen3b1a7442003-12-24 20:30:45 +00001039 case R_386_GOTOFF:
1040 assert(got != 0);
1041 *loc += v - got;
1042 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001043
1044#elif defined(__mc68000__)
1045
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_NONE:
1047 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001048
Eric Andersen3b1a7442003-12-24 20:30:45 +00001049 case R_68K_32:
1050 *loc += v;
1051 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_68K_8:
1054 if (v > 0xff) {
1055 ret = obj_reloc_overflow;
1056 }
1057 *(char *)loc = v;
1058 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001059
Eric Andersen3b1a7442003-12-24 20:30:45 +00001060 case R_68K_16:
1061 if (v > 0xffff) {
1062 ret = obj_reloc_overflow;
1063 }
1064 *(short *)loc = v;
1065 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001066
Eric Andersen3b1a7442003-12-24 20:30:45 +00001067 case R_68K_PC8:
1068 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001069 if ((Elf32_Sword)v > 0x7f ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001070 (Elf32_Sword)v < -(Elf32_Sword)0x80) {
1071 ret = obj_reloc_overflow;
1072 }
1073 *(char *)loc = v;
1074 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001075
Eric Andersen3b1a7442003-12-24 20:30:45 +00001076 case R_68K_PC16:
1077 v -= dot;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001078 if ((Elf32_Sword)v > 0x7fff ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001079 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1080 ret = obj_reloc_overflow;
1081 }
1082 *(short *)loc = v;
1083 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001084
Eric Andersen3b1a7442003-12-24 20:30:45 +00001085 case R_68K_PC32:
1086 *(int *)loc = v - dot;
1087 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001088
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089 case R_68K_GLOB_DAT:
1090 case R_68K_JMP_SLOT:
1091 *loc = v;
1092 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001093
Eric Andersen3b1a7442003-12-24 20:30:45 +00001094 case R_68K_RELATIVE:
1095 *(int *)loc += f->baseaddr;
1096 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001097
Eric Andersen3b1a7442003-12-24 20:30:45 +00001098 case R_68K_GOT32:
1099 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001100
Eric Andersen16451a02004-03-19 12:16:18 +00001101#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001102 case R_68K_GOTOFF:
1103 assert(got != 0);
1104 *loc += v - got;
1105 break;
Eric Andersen16451a02004-03-19 12:16:18 +00001106#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001107
1108#elif defined(__mips__)
1109
Eric Andersen3b1a7442003-12-24 20:30:45 +00001110 case R_MIPS_NONE:
1111 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001112
Eric Andersen3b1a7442003-12-24 20:30:45 +00001113 case R_MIPS_32:
1114 *loc += v;
1115 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001116
Eric Andersen3b1a7442003-12-24 20:30:45 +00001117 case R_MIPS_26:
1118 if (v % 4)
1119 ret = obj_reloc_dangerous;
1120 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1121 ret = obj_reloc_overflow;
1122 *loc =
1123 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1124 0x03ffffff);
1125 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001126
Eric Andersen3b1a7442003-12-24 20:30:45 +00001127 case R_MIPS_HI16:
1128 {
1129 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001130
Eric Andersen3b1a7442003-12-24 20:30:45 +00001131 /* We cannot relocate this one now because we don't know the value
1132 of the carry we need to add. Save the information, and let LO16
1133 do the actual relocation. */
1134 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1135 n->addr = loc;
1136 n->value = v;
1137 n->next = ifile->mips_hi16_list;
1138 ifile->mips_hi16_list = n;
1139 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001140 }
1141
Eric Andersen3b1a7442003-12-24 20:30:45 +00001142 case R_MIPS_LO16:
1143 {
1144 unsigned long insnlo = *loc;
1145 Elf32_Addr val, vallo;
1146
1147 /* Sign extend the addend we extract from the lo insn. */
1148 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1149
1150 if (ifile->mips_hi16_list != NULL) {
1151 struct mips_hi16 *l;
1152
1153 l = ifile->mips_hi16_list;
1154 while (l != NULL) {
1155 struct mips_hi16 *next;
1156 unsigned long insn;
1157
1158 /* The value for the HI16 had best be the same. */
1159 assert(v == l->value);
1160
1161 /* Do the HI16 relocation. Note that we actually don't
1162 need to know anything about the LO16 itself, except where
1163 to find the low 16 bits of the addend needed by the LO16. */
1164 insn = *l->addr;
1165 val =
1166 ((insn & 0xffff) << 16) +
1167 vallo;
1168 val += v;
1169
1170 /* Account for the sign extension that will happen in the
1171 low bits. */
1172 val =
1173 ((val >> 16) +
1174 ((val & 0x8000) !=
1175 0)) & 0xffff;
1176
1177 insn = (insn & ~0xffff) | val;
1178 *l->addr = insn;
1179
1180 next = l->next;
1181 free(l);
1182 l = next;
1183 }
1184
1185 ifile->mips_hi16_list = NULL;
1186 }
1187
1188 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1189 val = v + vallo;
1190 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1191 *loc = insnlo;
1192 break;
1193 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001194
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001195#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001196
Eric Andersen3b1a7442003-12-24 20:30:45 +00001197 case R_PPC_ADDR16_HA:
1198 *(unsigned short *)loc = (v + 0x8000) >> 16;
1199 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001200
Eric Andersen3b1a7442003-12-24 20:30:45 +00001201 case R_PPC_ADDR16_HI:
1202 *(unsigned short *)loc = v >> 16;
1203 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001204
Eric Andersen3b1a7442003-12-24 20:30:45 +00001205 case R_PPC_ADDR16_LO:
1206 *(unsigned short *)loc = v;
1207 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001208
Eric Andersen3b1a7442003-12-24 20:30:45 +00001209 case R_PPC_REL24:
1210 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001211
Eric Andersen3b1a7442003-12-24 20:30:45 +00001212 case R_PPC_REL32:
1213 *loc = v - dot;
1214 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001215
Eric Andersen3b1a7442003-12-24 20:30:45 +00001216 case R_PPC_ADDR32:
1217 *loc = v;
1218 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001219
1220#elif defined(__sh__)
1221
Eric Andersen3b1a7442003-12-24 20:30:45 +00001222 case R_SH_NONE:
1223 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001224
Eric Andersen3b1a7442003-12-24 20:30:45 +00001225 case R_SH_DIR32:
1226 *loc += v;
1227 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001228
Eric Andersen3b1a7442003-12-24 20:30:45 +00001229 case R_SH_REL32:
1230 *loc += v - dot;
1231 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001232
Eric Andersen3b1a7442003-12-24 20:30:45 +00001233 case R_SH_PLT32:
1234 *loc = v - dot;
1235 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001236
Eric Andersen3b1a7442003-12-24 20:30:45 +00001237 case R_SH_GLOB_DAT:
1238 case R_SH_JMP_SLOT:
1239 *loc = v;
1240 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001241
Eric Andersen3b1a7442003-12-24 20:30:45 +00001242 case R_SH_RELATIVE:
1243 *loc = f->baseaddr + rel->r_addend;
1244 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001245
Eric Andersen3b1a7442003-12-24 20:30:45 +00001246 case R_SH_GOTPC:
1247 assert(got != 0);
1248 *loc = got - dot + rel->r_addend;
1249 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001250
Eric Andersen3b1a7442003-12-24 20:30:45 +00001251 case R_SH_GOT32:
1252 goto bb_use_got;
1253
1254 case R_SH_GOTOFF:
1255 assert(got != 0);
1256 *loc = v - got;
1257 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001258
Eric Andersenbf833552003-08-13 19:56:33 +00001259#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001260 case R_SH_IMM_MEDLOW16:
1261 case R_SH_IMM_LOW16:
1262 {
1263 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001264
Eric Andersen3b1a7442003-12-24 20:30:45 +00001265 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
1266 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001267
Eric Andersen3b1a7442003-12-24 20:30:45 +00001268 /*
1269 * movi and shori have the format:
1270 *
1271 * | op | imm | reg | reserved |
1272 * 31..26 25..10 9.. 4 3 .. 0
1273 *
1274 * so we simply mask and or in imm.
1275 */
1276 word = *loc & ~0x3fffc00;
1277 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001278
Eric Andersen3b1a7442003-12-24 20:30:45 +00001279 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001280
Eric Andersen3b1a7442003-12-24 20:30:45 +00001281 break;
1282 }
Eric Andersenbf833552003-08-13 19:56:33 +00001283
Eric Andersen3b1a7442003-12-24 20:30:45 +00001284 case R_SH_IMM_MEDLOW16_PCREL:
1285 case R_SH_IMM_LOW16_PCREL:
1286 {
1287 Elf32_Addr word;
Eric Andersenbf833552003-08-13 19:56:33 +00001288
Eric Andersen3b1a7442003-12-24 20:30:45 +00001289 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001290
Eric Andersen3b1a7442003-12-24 20:30:45 +00001291 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001292
Eric Andersen3b1a7442003-12-24 20:30:45 +00001293 if (ELF32_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
1294 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001295
Eric Andersen3b1a7442003-12-24 20:30:45 +00001296 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001297
Eric Andersen3b1a7442003-12-24 20:30:45 +00001298 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001299
Eric Andersen3b1a7442003-12-24 20:30:45 +00001300 break;
1301 }
Eric Andersenbf833552003-08-13 19:56:33 +00001302#endif /* __SH5__ */
1303#endif /* __sh__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001304
Eric Andersen3b1a7442003-12-24 20:30:45 +00001305 default:
1306 printf("Warning: unhandled reloc %d\n",(int)ELF32_R_TYPE(rel->r_info));
1307 ret = obj_reloc_unhandled;
1308 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001309
1310#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001311 case R_V850_NONE:
1312 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001313
Eric Andersen3b1a7442003-12-24 20:30:45 +00001314 case R_V850_32:
1315 /* We write two shorts instead of a long because even
1316 32-bit insns only need half-word alignment, but
1317 32-bit data needs to be long-word aligned. */
1318 v += ((unsigned short *)loc)[0];
1319 v += ((unsigned short *)loc)[1] << 16;
1320 ((unsigned short *)loc)[0] = v & 0xffff;
1321 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1322 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001323
Eric Andersen3b1a7442003-12-24 20:30:45 +00001324 case R_V850_22_PCREL:
1325 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001326#endif
1327
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001328#if defined (__cris__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001329 case R_CRIS_NONE:
1330 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001331
Eric Andersen3b1a7442003-12-24 20:30:45 +00001332 case R_CRIS_32:
1333 /* CRIS keeps the relocation value in the r_addend field and
1334 * should not use whats in *loc at all
1335 */
1336 *loc = v;
1337 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001338#endif
1339
Eric Andersena6f6a952004-05-26 12:06:38 +00001340#if defined(__H8300H__) || defined(__H8300S__)
Eric Andersenee70fa52004-05-26 11:38:46 +00001341 case R_H8_DIR24R8:
1342 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
1343 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
1344 break;
1345 case R_H8_DIR24A8:
1346 *loc += v;
1347 break;
1348 case R_H8_DIR32:
1349 case R_H8_DIR32A16:
1350 *loc += v;
1351 break;
1352 case R_H8_PCREL16:
1353 v -= dot + 2;
1354 if ((Elf32_Sword)v > 0x7fff ||
1355 (Elf32_Sword)v < -(Elf32_Sword)0x8000)
1356 ret = obj_reloc_overflow;
1357 else
1358 *(unsigned short *)loc = v;
1359 break;
1360 case R_H8_PCREL8:
1361 v -= dot + 1;
1362 if ((Elf32_Sword)v > 0x7f ||
1363 (Elf32_Sword)v < -(Elf32_Sword)0x80)
1364 ret = obj_reloc_overflow;
1365 else
1366 *(unsigned char *)loc = v;
1367 break;
1368#endif
1369
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001370#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001371
Eric Andersen3b1a7442003-12-24 20:30:45 +00001372bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001373
Eric Andersen3b1a7442003-12-24 20:30:45 +00001374 /* find the plt entry and initialize it if necessary */
1375 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001376
Eric Andersencffd5022002-05-24 06:50:15 +00001377#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001378 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1379 pe = pe->next;
1380 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001381#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001382 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001383#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001384
Eric Andersen3b1a7442003-12-24 20:30:45 +00001385 if (! pe->inited) {
1386 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001387
Eric Andersen3b1a7442003-12-24 20:30:45 +00001388 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001389
1390#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001391 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1392 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001393#endif
1394#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001395 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
1396 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
1397 ip[2] = 0x7d6903a6; /* mtctr r11 */
1398 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001399#endif
Miles Baderae28b042002-04-01 09:34:25 +00001400#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001401 /* We have to trash a register, so we assume that any control
1402 transfer more than 21-bits away must be a function call
1403 (so we can use a call-clobbered register). */
1404 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1405 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001406#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001407 pe->inited = 1;
1408 }
Eric Andersen21adca72000-12-06 18:18:26 +00001409
Eric Andersen3b1a7442003-12-24 20:30:45 +00001410 /* relative distance to target */
1411 v -= dot;
1412 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001413#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001414 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001415#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001416 if ((Elf32_Sword)v > 0x1fffff || (Elf32_Sword)v < (Elf32_Sword)-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001417#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001418 /* go via the plt */
1419 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001420
1421#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001422 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001423#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001424 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001425#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001426 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001427
Eric Andersen3b1a7442003-12-24 20:30:45 +00001428 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001429#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001430 /* Convert to words. */
1431 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001432
Eric Andersen3b1a7442003-12-24 20:30:45 +00001433 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001434#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001435#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001436 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001437#endif
Miles Baderae28b042002-04-01 09:34:25 +00001438#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001439 /* We write two shorts instead of a long because even 32-bit insns
1440 only need half-word alignment, but the 32-bit data write needs
1441 to be long-word aligned. */
1442 ((unsigned short *)loc)[0] =
1443 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1444 | ((v >> 16) & 0x3f); /* offs high part */
1445 ((unsigned short *)loc)[1] =
1446 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001447#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001448 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001449#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001450
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001451#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001452bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001453
Eric Andersen3b1a7442003-12-24 20:30:45 +00001454 assert(isym != NULL);
1455 /* needs an entry in the .got: set it, once */
1456 if (!isym->gotent.inited) {
1457 isym->gotent.inited = 1;
1458 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1459 }
1460 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001461#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001463#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001464 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001465#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001467
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001468#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001469 }
1470
1471 return ret;
1472}
1473
Eric Andersencffd5022002-05-24 06:50:15 +00001474
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001475#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001476
1477static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1478 int offset, int size)
1479{
1480 struct arch_list_entry *pe;
1481
1482 for (pe = *list; pe != NULL; pe = pe->next) {
1483 if (pe->addend == rel->r_addend) {
1484 break;
1485 }
1486 }
1487
1488 if (pe == NULL) {
1489 pe = xmalloc(sizeof(struct arch_list_entry));
1490 pe->next = *list;
1491 pe->addend = rel->r_addend;
1492 pe->offset = offset;
1493 pe->inited = 0;
1494 *list = pe;
1495 return size;
1496 }
1497 return 0;
1498}
1499
1500#endif
1501
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001502#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001503
1504static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1505 int offset, int size)
1506{
1507 if (single->allocated == 0) {
1508 single->allocated = 1;
1509 single->offset = offset;
1510 single->inited = 0;
1511 return size;
1512 }
1513 return 0;
1514}
1515
1516#endif
1517
1518#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1519
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001520static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001521 int offset, int size)
1522{
1523 struct obj_section *myrelsec = obj_find_section(f, name);
1524
1525 if (offset == 0) {
1526 offset += size;
1527 }
1528
1529 if (myrelsec) {
1530 obj_extend_section(myrelsec, offset);
1531 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001532 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001533 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001534 assert(myrelsec);
1535 }
1536
1537 return myrelsec;
1538}
1539
1540#endif
1541
1542static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001543{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001544#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001545 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001546 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001547#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001548 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001549#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001550#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001551 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001552#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001553 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001554 ElfW(RelM) *rel, *relend;
1555 ElfW(Sym) *symtab, *extsym;
1556 const char *strtab, *name;
1557 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001558
Eric Andersen21adca72000-12-06 18:18:26 +00001559 for (i = 0; i < f->header.e_shnum; ++i) {
1560 relsec = f->sections[i];
1561 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001562 continue;
1563
Eric Andersen21adca72000-12-06 18:18:26 +00001564 symsec = f->sections[relsec->header.sh_link];
1565 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001566
Eric Andersen21adca72000-12-06 18:18:26 +00001567 rel = (ElfW(RelM) *) relsec->contents;
1568 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1569 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001570 strtab = (const char *) strsec->contents;
1571
1572 for (; rel < relend; ++rel) {
Eric Andersen21adca72000-12-06 18:18:26 +00001573 extsym = &symtab[ELF32_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001574
Eric Andersencffd5022002-05-24 06:50:15 +00001575#if defined(CONFIG_USE_GOT_ENTRIES)
1576 got_allocate = 0;
1577#endif
1578#if defined(CONFIG_USE_PLT_ENTRIES)
1579 plt_allocate = 0;
1580#endif
1581
Eric Andersen9f16d612000-06-12 23:11:16 +00001582 switch (ELF32_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001583#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001584 case R_ARM_PC24:
1585 case R_ARM_PLT32:
1586 plt_allocate = 1;
1587 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001588
Eric Andersen3b1a7442003-12-24 20:30:45 +00001589 case R_ARM_GOTOFF:
1590 case R_ARM_GOTPC:
1591 got_needed = 1;
1592 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001593
Eric Andersen3b1a7442003-12-24 20:30:45 +00001594 case R_ARM_GOT32:
1595 got_allocate = 1;
1596 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001597
Eric Andersen21adca72000-12-06 18:18:26 +00001598#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001599 case R_386_GOTPC:
1600 case R_386_GOTOFF:
1601 got_needed = 1;
1602 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001603
Eric Andersen3b1a7442003-12-24 20:30:45 +00001604 case R_386_GOT32:
1605 got_allocate = 1;
1606 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001607
1608#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001609 case R_PPC_REL24:
1610 plt_allocate = 1;
1611 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001612
1613#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001614 case R_68K_GOT32:
1615 got_allocate = 1;
1616 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001617
Eric Andersen16451a02004-03-19 12:16:18 +00001618#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001619 case R_68K_GOTOFF:
1620 got_needed = 1;
1621 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001622#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001623
1624#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001625 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001626 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001627 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001628
Eric Andersen3b1a7442003-12-24 20:30:45 +00001629 case R_SH_GOTPC:
1630 case R_SH_GOTOFF:
1631 got_needed = 1;
1632 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001633
1634#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001635 case R_V850_22_PCREL:
1636 plt_needed = 1;
1637 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001638
1639#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 default:
1641 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001642 }
1643
Eric Andersen21adca72000-12-06 18:18:26 +00001644 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001645 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001646 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001647 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001648 }
1649 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001650#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001651 if (got_allocate) {
1652 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001653 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001655
1656 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001657 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001658#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001659#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001660 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001661#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001662 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001663 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001664 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001665#else
1666 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001667 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001668 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001669#endif
1670 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001671 }
1672#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001673 }
Miles Baderae28b042002-04-01 09:34:25 +00001674 }
Eric Andersen21adca72000-12-06 18:18:26 +00001675
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001676#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001677 if (got_needed) {
1678 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001679 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001680 }
Eric Andersen21adca72000-12-06 18:18:26 +00001681#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001682
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001683#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001684 if (plt_needed) {
1685 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001687 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001688#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001689
1690#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001691}
1692
Eric Andersene7047882003-12-11 01:42:13 +00001693#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +00001694static int arch_init_module(struct obj_file *f, struct new_module *mod)
Eric Andersen9f16d612000-06-12 23:11:16 +00001695{
1696 return 1;
1697}
Eric Andersen6d139642001-12-29 04:15:13 +00001698#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001699
1700/*======================================================================*/
1701
1702/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001703static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001704{
1705 unsigned long h = 0;
1706 unsigned long g;
1707 unsigned char ch;
1708
1709 while (n > 0) {
1710 ch = *name++;
1711 h = (h << 4) + ch;
1712 if ((g = (h & 0xf0000000)) != 0) {
1713 h ^= g >> 24;
1714 h &= ~g;
1715 }
1716 n--;
1717 }
1718 return h;
1719}
1720
Eric Andersen044228d2001-07-17 01:12:36 +00001721static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001722{
1723 return obj_elf_hash_n(name, strlen(name));
1724}
1725
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001726#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001727/* String comparison for non-co-versioned kernel and module. */
1728
1729static int ncv_strcmp(const char *a, const char *b)
1730{
1731 size_t alen = strlen(a), blen = strlen(b);
1732
1733 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1734 return strncmp(a, b, alen);
1735 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1736 return strncmp(a, b, blen);
1737 else
1738 return strcmp(a, b);
1739}
1740
1741/* String hashing for non-co-versioned kernel and module. Here
1742 we are simply forced to drop the crc from the hash. */
1743
1744static unsigned long ncv_symbol_hash(const char *str)
1745{
1746 size_t len = strlen(str);
1747 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1748 len -= 10;
1749 return obj_elf_hash_n(str, len);
1750}
1751
Eric Andersen044228d2001-07-17 01:12:36 +00001752static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001753obj_set_symbol_compare(struct obj_file *f,
1754 int (*cmp) (const char *, const char *),
1755 unsigned long (*hash) (const char *))
1756{
1757 if (cmp)
1758 f->symbol_cmp = cmp;
1759 if (hash) {
1760 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1761 int i;
1762
1763 f->symbol_hash = hash;
1764
1765 memcpy(tmptab, f->symtab, sizeof(tmptab));
1766 memset(f->symtab, 0, sizeof(f->symtab));
1767
1768 for (i = 0; i < HASH_BUCKETS; ++i)
1769 for (sym = tmptab[i]; sym; sym = next) {
1770 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1771 next = sym->next;
1772 sym->next = f->symtab[h];
1773 f->symtab[h] = sym;
1774 }
1775 }
1776}
1777
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001778#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001779
Eric Andersen044228d2001-07-17 01:12:36 +00001780static struct obj_symbol *
1781obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001782 unsigned long symidx, int info,
1783 int secidx, ElfW(Addr) value,
1784 unsigned long size)
1785{
1786 struct obj_symbol *sym;
1787 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1788 int n_type = ELFW(ST_TYPE) (info);
1789 int n_binding = ELFW(ST_BIND) (info);
1790
1791 for (sym = f->symtab[hash]; sym; sym = sym->next)
1792 if (f->symbol_cmp(sym->name, name) == 0) {
1793 int o_secidx = sym->secidx;
1794 int o_info = sym->info;
1795 int o_type = ELFW(ST_TYPE) (o_info);
1796 int o_binding = ELFW(ST_BIND) (o_info);
1797
1798 /* A redefinition! Is it legal? */
1799
1800 if (secidx == SHN_UNDEF)
1801 return sym;
1802 else if (o_secidx == SHN_UNDEF)
1803 goto found;
1804 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
1805 /* Cope with local and global symbols of the same name
1806 in the same object file, as might have been created
1807 by ld -r. The only reason locals are now seen at this
1808 level at all is so that we can do semi-sensible things
1809 with parameters. */
1810
1811 struct obj_symbol *nsym, **p;
1812
1813 nsym = arch_new_symbol();
1814 nsym->next = sym->next;
1815 nsym->ksymidx = -1;
1816
1817 /* Excise the old (local) symbol from the hash chain. */
1818 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
1819 continue;
1820 *p = sym = nsym;
1821 goto found;
1822 } else if (n_binding == STB_LOCAL) {
1823 /* Another symbol of the same name has already been defined.
1824 Just add this to the local table. */
1825 sym = arch_new_symbol();
1826 sym->next = NULL;
1827 sym->ksymidx = -1;
1828 f->local_symtab[symidx] = sym;
1829 goto found;
1830 } else if (n_binding == STB_WEAK)
1831 return sym;
1832 else if (o_binding == STB_WEAK)
1833 goto found;
1834 /* Don't unify COMMON symbols with object types the programmer
1835 doesn't expect. */
1836 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001837 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001838 return sym;
1839 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00001840 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00001841 goto found;
1842 else {
1843 /* Don't report an error if the symbol is coming from
1844 the kernel or some external module. */
1845 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001846 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00001847 return sym;
1848 }
1849 }
1850
1851 /* Completely new symbol. */
1852 sym = arch_new_symbol();
1853 sym->next = f->symtab[hash];
1854 f->symtab[hash] = sym;
1855 sym->ksymidx = -1;
1856
Eric Andersen66ca9482001-06-28 21:36:06 +00001857 if (ELFW(ST_BIND)(info) == STB_LOCAL && symidx != -1) {
1858 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00001859 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00001860 name, (long) symidx, (long) f->local_symtab_size);
1861 else
1862 f->local_symtab[symidx] = sym;
1863 }
Eric Andersen9f16d612000-06-12 23:11:16 +00001864
Eric Andersen3b1a7442003-12-24 20:30:45 +00001865found:
Eric Andersen9f16d612000-06-12 23:11:16 +00001866 sym->name = name;
1867 sym->value = value;
1868 sym->size = size;
1869 sym->secidx = secidx;
1870 sym->info = info;
1871
1872 return sym;
1873}
1874
Eric Andersen044228d2001-07-17 01:12:36 +00001875static struct obj_symbol *
1876obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001877{
1878 struct obj_symbol *sym;
1879 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
1880
1881 for (sym = f->symtab[hash]; sym; sym = sym->next)
1882 if (f->symbol_cmp(sym->name, name) == 0)
1883 return sym;
1884
1885 return NULL;
1886}
1887
Eric Andersen044228d2001-07-17 01:12:36 +00001888static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00001889 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
1890{
1891 if (sym) {
1892 if (sym->secidx >= SHN_LORESERVE)
1893 return sym->value;
1894
1895 return sym->value + f->sections[sym->secidx]->header.sh_addr;
1896 } else {
1897 /* As a special case, a NULL sym has value zero. */
1898 return 0;
1899 }
1900}
1901
Eric Andersen044228d2001-07-17 01:12:36 +00001902static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001903{
1904 int i, n = f->header.e_shnum;
1905
1906 for (i = 0; i < n; ++i)
1907 if (strcmp(f->sections[i]->name, name) == 0)
1908 return f->sections[i];
1909
1910 return NULL;
1911}
1912
1913static int obj_load_order_prio(struct obj_section *a)
1914{
1915 unsigned long af, ac;
1916
1917 af = a->header.sh_flags;
1918
1919 ac = 0;
1920 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00001921 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00001922 ac |= 32;
1923 if (af & SHF_ALLOC)
1924 ac |= 16;
1925 if (!(af & SHF_WRITE))
1926 ac |= 8;
1927 if (af & SHF_EXECINSTR)
1928 ac |= 4;
1929 if (a->header.sh_type != SHT_NOBITS)
1930 ac |= 2;
1931
1932 return ac;
1933}
1934
Eric Andersen044228d2001-07-17 01:12:36 +00001935static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001936obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
1937{
1938 struct obj_section **p;
1939 int prio = obj_load_order_prio(sec);
1940 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
1941 if (obj_load_order_prio(*p) < prio)
1942 break;
1943 sec->load_next = *p;
1944 *p = sec;
1945}
1946
Eric Andersen044228d2001-07-17 01:12:36 +00001947static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001948 const char *name,
1949 unsigned long align,
1950 unsigned long size)
1951{
1952 int newidx = f->header.e_shnum++;
1953 struct obj_section *sec;
1954
1955 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1956 f->sections[newidx] = sec = arch_new_section();
1957
1958 memset(sec, 0, sizeof(*sec));
1959 sec->header.sh_type = SHT_PROGBITS;
1960 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1961 sec->header.sh_size = size;
1962 sec->header.sh_addralign = align;
1963 sec->name = name;
1964 sec->idx = newidx;
1965 if (size)
1966 sec->contents = xmalloc(size);
1967
1968 obj_insert_section_load_order(f, sec);
1969
1970 return sec;
1971}
1972
Eric Andersen044228d2001-07-17 01:12:36 +00001973static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00001974 const char *name,
1975 unsigned long align,
1976 unsigned long size)
1977{
1978 int newidx = f->header.e_shnum++;
1979 struct obj_section *sec;
1980
1981 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
1982 f->sections[newidx] = sec = arch_new_section();
1983
1984 memset(sec, 0, sizeof(*sec));
1985 sec->header.sh_type = SHT_PROGBITS;
1986 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
1987 sec->header.sh_size = size;
1988 sec->header.sh_addralign = align;
1989 sec->name = name;
1990 sec->idx = newidx;
1991 if (size)
1992 sec->contents = xmalloc(size);
1993
1994 sec->load_next = f->load_order;
1995 f->load_order = sec;
1996 if (f->load_order_search_start == &f->load_order)
1997 f->load_order_search_start = &sec->load_next;
1998
1999 return sec;
2000}
2001
Eric Andersen044228d2001-07-17 01:12:36 +00002002static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002003{
2004 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002005 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002006 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2007 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002008 return sec->contents + oldsize;
2009}
2010
2011
Eric Andersen9f16d612000-06-12 23:11:16 +00002012/* Conditionally add the symbols from the given symbol set to the
2013 new module. */
2014
2015static int
2016add_symbols_from(
2017 struct obj_file *f,
2018 int idx, struct new_module_symbol *syms, size_t nsyms)
2019{
2020 struct new_module_symbol *s;
2021 size_t i;
2022 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002023#ifdef SYMBOL_PREFIX
2024 char *name_buf = 0;
2025 size_t name_alloced_size = 0;
2026#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002027#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2028 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002029
Glenn L McGrath759515c2003-08-30 06:00:33 +00002030 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002031#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002032 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002033 /* Only add symbols that are already marked external.
2034 If we override locals we may cause problems for
2035 argument initialization. We will also create a false
2036 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002037 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002038 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002039
Glenn L McGrath759515c2003-08-30 06:00:33 +00002040 /* GPL licensed modules can use symbols exported with
2041 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2042 * exported names. Non-GPL modules never see any GPLONLY_
2043 * symbols so they cannot fudge it by adding the prefix on
2044 * their references.
2045 */
2046 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002047#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002048 if (gpl)
2049 ((char *)s->name) += 8;
2050 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002051#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002052 continue;
2053 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002054 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002055
Miles Baderae28b042002-04-01 09:34:25 +00002056#ifdef SYMBOL_PREFIX
2057 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2058 kernel exports `C names', but module object files
2059 reference `linker names'). */
2060 size_t extra = sizeof SYMBOL_PREFIX;
2061 size_t name_size = strlen (name) + extra;
2062 if (name_size > name_alloced_size) {
2063 name_alloced_size = name_size * 2;
2064 name_buf = alloca (name_alloced_size);
2065 }
2066 strcpy (name_buf, SYMBOL_PREFIX);
2067 strcpy (name_buf + extra - 1, name);
2068 name = name_buf;
2069#endif /* SYMBOL_PREFIX */
2070
2071 sym = obj_find_symbol(f, name);
2072 if (sym && !(ELFW(ST_BIND) (sym->info) == STB_LOCAL)) {
2073#ifdef SYMBOL_PREFIX
2074 /* Put NAME_BUF into more permanent storage. */
2075 name = xmalloc (name_size);
2076 strcpy (name, name_buf);
2077#endif
2078 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002079 ELFW(ST_INFO) (STB_GLOBAL,
2080 STT_NOTYPE),
2081 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002082 /* Did our symbol just get installed? If so, mark the
2083 module as "used". */
2084 if (sym->secidx == idx)
2085 used = 1;
2086 }
2087 }
2088
2089 return used;
2090}
2091
2092static void add_kernel_symbols(struct obj_file *f)
2093{
2094 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002095 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002096
2097 /* Add module symbols first. */
2098
2099 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2100 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002101 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2102 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002103
2104 n_ext_modules_used = nused;
2105
2106 /* And finally the symbols from the kernel proper. */
2107
2108 if (nksyms)
2109 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2110}
2111
2112static char *get_modinfo_value(struct obj_file *f, const char *key)
2113{
2114 struct obj_section *sec;
2115 char *p, *v, *n, *ep;
2116 size_t klen = strlen(key);
2117
2118 sec = obj_find_section(f, ".modinfo");
2119 if (sec == NULL)
2120 return NULL;
2121 p = sec->contents;
2122 ep = p + sec->header.sh_size;
2123 while (p < ep) {
2124 v = strchr(p, '=');
2125 n = strchr(p, '\0');
2126 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002127 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002128 return v + 1;
2129 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002130 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002131 return n;
2132 }
2133 p = n + 1;
2134 }
2135
2136 return NULL;
2137}
2138
2139
2140/*======================================================================*/
2141/* Functions relating to module loading in pre 2.1 kernels. */
2142
2143static int
2144old_process_module_arguments(struct obj_file *f, int argc, char **argv)
2145{
2146 while (argc > 0) {
2147 char *p, *q;
2148 struct obj_symbol *sym;
2149 int *loc;
2150
2151 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002152 if ((q = strchr(p, '=')) == NULL) {
2153 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002154 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002155 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002156 *q++ = '\0';
2157
2158 sym = obj_find_symbol(f, p);
2159
2160 /* Also check that the parameter was not resolved from the kernel. */
2161 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002162 bb_error_msg("symbol for parameter %s not found", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002163 return 0;
2164 }
2165
2166 loc = (int *) (f->sections[sym->secidx]->contents + sym->value);
2167
2168 /* Do C quoting if we begin with a ". */
2169 if (*q == '"') {
2170 char *r, *str;
2171
2172 str = alloca(strlen(q));
2173 for (r = str, q++; *q != '"'; ++q, ++r) {
2174 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002175 bb_error_msg("improperly terminated string argument for %s", p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002176 return 0;
2177 } else if (*q == '\\')
2178 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002179 case 'a':
2180 *r = '\a';
2181 break;
2182 case 'b':
2183 *r = '\b';
2184 break;
2185 case 'e':
2186 *r = '\033';
2187 break;
2188 case 'f':
2189 *r = '\f';
2190 break;
2191 case 'n':
2192 *r = '\n';
2193 break;
2194 case 'r':
2195 *r = '\r';
2196 break;
2197 case 't':
2198 *r = '\t';
2199 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002200
Eric Andersen3b1a7442003-12-24 20:30:45 +00002201 case '0':
2202 case '1':
2203 case '2':
2204 case '3':
2205 case '4':
2206 case '5':
2207 case '6':
2208 case '7':
2209 {
2210 int c = *q - '0';
2211 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002212 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002213 if (q[1] >= '0' && q[1] <= '7')
2214 c = (c * 8) + *++q - '0';
2215 }
2216 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002217 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002218 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002219
Eric Andersen3b1a7442003-12-24 20:30:45 +00002220 default:
2221 *r = *q;
2222 break;
2223 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002224 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002225 }
2226 *r = '\0';
2227 obj_string_patch(f, sym->secidx, sym->value, str);
2228 } else if (*q >= '0' && *q <= '9') {
2229 do
2230 *loc++ = strtoul(q, &q, 0);
2231 while (*q++ == ',');
2232 } else {
2233 char *contents = f->sections[sym->secidx]->contents;
Eric Andersene76c3b02001-04-05 03:14:39 +00002234 char *myloc = contents + sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002235 char *r; /* To search for commas */
2236
2237 /* Break the string with comas */
2238 while ((r = strchr(q, ',')) != (char *) NULL) {
2239 *r++ = '\0';
Eric Andersene76c3b02001-04-05 03:14:39 +00002240 obj_string_patch(f, sym->secidx, myloc - contents, q);
2241 myloc += sizeof(char *);
Eric Andersen9f16d612000-06-12 23:11:16 +00002242 q = r;
2243 }
2244
2245 /* last part */
Eric Andersene76c3b02001-04-05 03:14:39 +00002246 obj_string_patch(f, sym->secidx, myloc - contents, q);
Eric Andersen9f16d612000-06-12 23:11:16 +00002247 }
2248
2249 argc--, argv++;
2250 }
2251
2252 return 1;
2253}
2254
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002255#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002256static int old_is_module_checksummed(struct obj_file *f)
2257{
2258 return obj_find_symbol(f, "Using_Versions") != NULL;
2259}
2260/* Get the module's kernel version in the canonical integer form. */
2261
2262static int
2263old_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2264{
2265 struct obj_symbol *sym;
2266 char *p, *q;
2267 int a, b, c;
2268
2269 sym = obj_find_symbol(f, "kernel_version");
2270 if (sym == NULL)
2271 return -1;
2272
2273 p = f->sections[sym->secidx]->contents + sym->value;
Eric Andersen2d342152002-06-18 05:16:25 +00002274 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002275
2276 a = strtoul(p, &p, 10);
2277 if (*p != '.')
2278 return -1;
2279 b = strtoul(p + 1, &p, 10);
2280 if (*p != '.')
2281 return -1;
2282 c = strtoul(p + 1, &q, 10);
2283 if (p + 1 == q)
2284 return -1;
2285
2286 return a << 16 | b << 8 | c;
2287}
2288
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002289#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002290
Eric Andersene7047882003-12-11 01:42:13 +00002291#ifdef CONFIG_FEATURE_2_2_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00002292
2293/* Fetch all the symbols and divvy them up as appropriate for the modules. */
2294
Eric Andersen8c185f92000-09-22 00:38:07 +00002295static int old_get_kernel_symbols(const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002296{
2297 struct old_kernel_sym *ks, *k;
2298 struct new_module_symbol *s;
2299 struct external_module *mod;
2300 int nks, nms, nmod, i;
2301
2302 nks = get_kernel_syms(NULL);
Eric Andersenf2278152001-04-24 21:41:41 +00002303 if (nks <= 0) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002304 if (nks)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002305 bb_perror_msg("get_kernel_syms: %s", m_name);
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002306 else
Manuel Novoa III cad53642003-03-19 09:13:01 +00002307 bb_error_msg("No kernel symbols");
Eric Andersen9f16d612000-06-12 23:11:16 +00002308 return 0;
2309 }
2310
2311 ks = k = xmalloc(nks * sizeof(*ks));
2312
2313 if (get_kernel_syms(ks) != nks) {
2314 perror("inconsistency with get_kernel_syms -- is someone else "
Eric Andersen3b1a7442003-12-24 20:30:45 +00002315 "playing with modules?");
Eric Andersen9f16d612000-06-12 23:11:16 +00002316 free(ks);
2317 return 0;
2318 }
2319
2320 /* Collect the module information. */
2321
2322 mod = NULL;
2323 nmod = -1;
2324
2325 while (k->name[0] == '#' && k->name[1]) {
2326 struct old_kernel_sym *k2;
Eric Andersen9f16d612000-06-12 23:11:16 +00002327
2328 /* Find out how many symbols this module has. */
2329 for (k2 = k + 1; k2->name[0] != '#'; ++k2)
2330 continue;
2331 nms = k2 - k - 1;
2332
2333 mod = xrealloc(mod, (++nmod + 1) * sizeof(*mod));
2334 mod[nmod].name = k->name + 1;
2335 mod[nmod].addr = k->value;
2336 mod[nmod].used = 0;
2337 mod[nmod].nsyms = nms;
2338 mod[nmod].syms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2339
2340 for (i = 0, ++k; i < nms; ++i, ++s, ++k) {
2341 s->name = (unsigned long) k->name;
2342 s->value = k->value;
2343 }
2344
2345 k = k2;
2346 }
2347
2348 ext_modules = mod;
2349 n_ext_modules = nmod + 1;
2350
2351 /* Now collect the symbols for the kernel proper. */
2352
2353 if (k->name[0] == '#')
2354 ++k;
2355
2356 nksyms = nms = nks - (k - ks);
2357 ksyms = s = (nms ? xmalloc(nms * sizeof(*s)) : NULL);
2358
2359 for (i = 0; i < nms; ++i, ++s, ++k) {
2360 s->name = (unsigned long) k->name;
2361 s->value = k->value;
2362 }
2363
2364 return 1;
2365}
2366
2367/* Return the kernel symbol checksum version, or zero if not used. */
2368
2369static int old_is_kernel_checksummed(void)
2370{
2371 /* Using_Versions is the first symbol. */
2372 if (nksyms > 0
Eric Andersen3b1a7442003-12-24 20:30:45 +00002373 && strcmp((char *) ksyms[0].name,
2374 "Using_Versions") == 0) return ksyms[0].value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002375 else
2376 return 0;
2377}
2378
2379
2380static int old_create_mod_use_count(struct obj_file *f)
2381{
2382 struct obj_section *sec;
2383
2384 sec = obj_create_alloced_section_first(f, ".moduse", sizeof(long),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002385 sizeof(long));
Eric Andersen9f16d612000-06-12 23:11:16 +00002386
2387 obj_add_symbol(f, "mod_use_count_", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002388 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2389 sizeof(long));
Eric Andersen9f16d612000-06-12 23:11:16 +00002390
2391 return 1;
2392}
2393
2394static int
2395old_init_module(const char *m_name, struct obj_file *f,
2396 unsigned long m_size)
2397{
2398 char *image;
2399 struct old_mod_routines routines;
2400 struct old_symbol_table *symtab;
2401 int ret;
2402
2403 /* Create the symbol table */
2404 {
2405 int nsyms = 0, strsize = 0, total;
2406
2407 /* Size things first... */
2408 if (flag_export) {
2409 int i;
2410 for (i = 0; i < HASH_BUCKETS; ++i) {
2411 struct obj_symbol *sym;
2412 for (sym = f->symtab[i]; sym; sym = sym->next)
2413 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002414 && sym->secidx <= SHN_HIRESERVE)
Eric Andersen9f16d612000-06-12 23:11:16 +00002415 {
2416 sym->ksymidx = nsyms++;
2417 strsize += strlen(sym->name) + 1;
2418 }
2419 }
2420 }
2421
2422 total = (sizeof(struct old_symbol_table)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002423 + nsyms * sizeof(struct old_module_symbol)
2424 + n_ext_modules_used * sizeof(struct old_module_ref)
2425 + strsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002426 symtab = xmalloc(total);
2427 symtab->size = total;
2428 symtab->n_symbols = nsyms;
2429 symtab->n_refs = n_ext_modules_used;
2430
2431 if (flag_export && nsyms) {
2432 struct old_module_symbol *ksym;
2433 char *str;
2434 int i;
2435
2436 ksym = symtab->symbol;
2437 str = ((char *) ksym + nsyms * sizeof(struct old_module_symbol)
Eric Andersen3b1a7442003-12-24 20:30:45 +00002438 + n_ext_modules_used * sizeof(struct old_module_ref));
Eric Andersen9f16d612000-06-12 23:11:16 +00002439
2440 for (i = 0; i < HASH_BUCKETS; ++i) {
2441 struct obj_symbol *sym;
2442 for (sym = f->symtab[i]; sym; sym = sym->next)
2443 if (sym->ksymidx >= 0) {
2444 ksym->addr = obj_symbol_final_value(f, sym);
2445 ksym->name =
2446 (unsigned long) str - (unsigned long) symtab;
2447
Matt Kraai70a78552001-01-04 02:00:17 +00002448 strcpy(str, sym->name);
2449 str += strlen(sym->name) + 1;
Eric Andersen9f16d612000-06-12 23:11:16 +00002450 ksym++;
2451 }
2452 }
2453 }
2454
2455 if (n_ext_modules_used) {
2456 struct old_module_ref *ref;
2457 int i;
2458
2459 ref = (struct old_module_ref *)
2460 ((char *) symtab->symbol + nsyms * sizeof(struct old_module_symbol));
2461
2462 for (i = 0; i < n_ext_modules; ++i)
2463 if (ext_modules[i].used)
2464 ref++->module = ext_modules[i].addr;
2465 }
2466 }
2467
2468 /* Fill in routines. */
2469
2470 routines.init =
Miles Baderae28b042002-04-01 09:34:25 +00002471 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002472 routines.cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002473 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002474
2475 /* Whew! All of the initialization is complete. Collect the final
2476 module image and give it to the kernel. */
2477
2478 image = xmalloc(m_size);
2479 obj_create_image(f, image);
2480
2481 /* image holds the complete relocated module, accounting correctly for
2482 mod_use_count. However the old module kernel support assume that
2483 it is receiving something which does not contain mod_use_count. */
2484 ret = old_sys_init_module(m_name, image + sizeof(long),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002485 m_size | (flag_autoclean ? OLD_MOD_AUTOCLEAN
2486 : 0), &routines, symtab);
Eric Andersen9f16d612000-06-12 23:11:16 +00002487 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002488 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002489
2490 free(image);
2491 free(symtab);
2492
2493 return ret == 0;
2494}
2495
2496#else
2497
2498#define old_create_mod_use_count(x) TRUE
2499#define old_init_module(x, y, z) TRUE
2500
Eric Andersene7047882003-12-11 01:42:13 +00002501#endif /* CONFIG_FEATURE_2_2_MODULES */
Eric Andersen9f16d612000-06-12 23:11:16 +00002502
2503
2504
2505/*======================================================================*/
2506/* Functions relating to module loading after 2.1.18. */
2507
2508static int
2509new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2510{
2511 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002512 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002513 struct obj_symbol *sym;
2514 char *contents, *loc;
2515 int min, max, n;
2516
2517 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002518 if ((q = strchr(p, '=')) == NULL) {
2519 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002520 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002521 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002522
2523 key = alloca(q - p + 6);
2524 memcpy(key, "parm_", 5);
2525 memcpy(key + 5, p, q - p);
2526 key[q - p + 5] = 0;
2527
2528 p = get_modinfo_value(f, key);
2529 key += 5;
2530 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002531 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002532 return 0;
2533 }
2534
Miles Baderae28b042002-04-01 09:34:25 +00002535#ifdef SYMBOL_PREFIX
2536 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2537 strcpy (sym_name, SYMBOL_PREFIX);
2538 strcat (sym_name, key);
2539#else
2540 sym_name = key;
2541#endif
2542 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002543
2544 /* Also check that the parameter was not resolved from the kernel. */
2545 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002546 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002547 return 0;
2548 }
2549
2550 if (isdigit(*p)) {
2551 min = strtoul(p, &p, 10);
2552 if (*p == '-')
2553 max = strtoul(p + 1, &p, 10);
2554 else
2555 max = min;
2556 } else
2557 min = max = 1;
2558
2559 contents = f->sections[sym->secidx]->contents;
2560 loc = contents + sym->value;
2561 n = (*++q != '\0');
2562
2563 while (1) {
2564 if ((*p == 's') || (*p == 'c')) {
2565 char *str;
2566
2567 /* Do C quoting if we begin with a ", else slurp the lot. */
2568 if (*q == '"') {
2569 char *r;
2570
2571 str = alloca(strlen(q));
2572 for (r = str, q++; *q != '"'; ++q, ++r) {
2573 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002574 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002575 key);
2576 return 0;
2577 } else if (*q == '\\')
2578 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002579 case 'a':
2580 *r = '\a';
2581 break;
2582 case 'b':
2583 *r = '\b';
2584 break;
2585 case 'e':
2586 *r = '\033';
2587 break;
2588 case 'f':
2589 *r = '\f';
2590 break;
2591 case 'n':
2592 *r = '\n';
2593 break;
2594 case 'r':
2595 *r = '\r';
2596 break;
2597 case 't':
2598 *r = '\t';
2599 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002600
Eric Andersen3b1a7442003-12-24 20:30:45 +00002601 case '0':
2602 case '1':
2603 case '2':
2604 case '3':
2605 case '4':
2606 case '5':
2607 case '6':
2608 case '7':
2609 {
2610 int c = *q - '0';
2611 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002612 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002613 if (q[1] >= '0' && q[1] <= '7')
2614 c = (c * 8) + *++q - '0';
2615 }
2616 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002617 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002618 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002619
Eric Andersen3b1a7442003-12-24 20:30:45 +00002620 default:
2621 *r = *q;
2622 break;
2623 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002624 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002625 }
2626 *r = '\0';
2627 ++q;
2628 } else {
2629 char *r;
2630
2631 /* In this case, the string is not quoted. We will break
2632 it using the coma (like for ints). If the user wants to
2633 include comas in a string, he just has to quote it */
2634
2635 /* Search the next coma */
2636 r = strchr(q, ',');
2637
2638 /* Found ? */
2639 if (r != (char *) NULL) {
2640 /* Recopy the current field */
2641 str = alloca(r - q + 1);
2642 memcpy(str, q, r - q);
2643
Eric Andersenaff114c2004-04-14 17:51:38 +00002644 /* I don't know if it is useful, as the previous case
2645 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002646 str[r - q] = '\0';
2647
2648 /* Keep next fields */
2649 q = r;
2650 } else {
2651 /* last string */
2652 str = q;
2653 q = "";
2654 }
2655 }
2656
2657 if (*p == 's') {
2658 /* Normal string */
2659 obj_string_patch(f, sym->secidx, loc - contents, str);
2660 loc += tgt_sizeof_char_p;
2661 } else {
2662 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002663 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002664
2665 /* Get the size of each member */
2666 /* Probably we should do that outside the loop ? */
2667 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002668 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002669 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002670 return 0;
2671 }
2672 charssize = strtoul(p + 1, (char **) NULL, 10);
2673
2674 /* Check length */
2675 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002676 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002677 charssize - 1);
2678 return 0;
2679 }
2680
2681 /* Copy to location */
2682 strcpy((char *) loc, str);
2683 loc += charssize;
2684 }
2685 } else {
2686 long v = strtoul(q, &q, 0);
2687 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002688 case 'b':
2689 *loc++ = v;
2690 break;
2691 case 'h':
2692 *(short *) loc = v;
2693 loc += tgt_sizeof_short;
2694 break;
2695 case 'i':
2696 *(int *) loc = v;
2697 loc += tgt_sizeof_int;
2698 break;
2699 case 'l':
2700 *(long *) loc = v;
2701 loc += tgt_sizeof_long;
2702 break;
2703
2704 default:
2705 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2706 return 0;
2707 }
2708 }
2709
2710retry_end_of_value:
2711 switch (*q) {
2712 case '\0':
2713 goto end_of_arg;
2714
2715 case ' ':
2716 case '\t':
2717 case '\n':
2718 case '\r':
2719 ++q;
2720 goto retry_end_of_value;
2721
2722 case ',':
2723 if (++n > max) {
2724 bb_error_msg("too many values for %s (max %d)", key, max);
2725 return 0;
2726 }
2727 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002728 break;
2729
2730 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002731 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002732 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002733 }
2734 }
2735
Eric Andersen3b1a7442003-12-24 20:30:45 +00002736end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002737 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002738 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002739 return 0;
2740 }
2741
2742 argc--, argv++;
2743 }
2744
2745 return 1;
2746}
2747
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002748#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002749static int new_is_module_checksummed(struct obj_file *f)
2750{
2751 const char *p = get_modinfo_value(f, "using_checksums");
2752 if (p)
2753 return atoi(p);
2754 else
2755 return 0;
2756}
2757
2758/* Get the module's kernel version in the canonical integer form. */
2759
2760static int
2761new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2762{
2763 char *p, *q;
2764 int a, b, c;
2765
2766 p = get_modinfo_value(f, "kernel_version");
2767 if (p == NULL)
2768 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002769 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002770
2771 a = strtoul(p, &p, 10);
2772 if (*p != '.')
2773 return -1;
2774 b = strtoul(p + 1, &p, 10);
2775 if (*p != '.')
2776 return -1;
2777 c = strtoul(p + 1, &q, 10);
2778 if (p + 1 == q)
2779 return -1;
2780
2781 return a << 16 | b << 8 | c;
2782}
2783
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002784#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002785
2786
Eric Andersene7047882003-12-11 01:42:13 +00002787#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00002788
2789/* Fetch the loaded modules, and all currently exported symbols. */
2790
2791static int new_get_kernel_symbols(void)
2792{
2793 char *module_names, *mn;
2794 struct external_module *modules, *m;
2795 struct new_module_symbol *syms, *s;
2796 size_t ret, bufsize, nmod, nsyms, i, j;
2797
2798 /* Collect the loaded modules. */
2799
2800 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002801retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002802 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002803 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002804 module_names = xrealloc(module_names, bufsize = ret);
2805 goto retry_modules_load;
2806 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002807 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002808 return 0;
2809 }
2810
2811 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002812
2813 /* Collect the modules' symbols. */
2814
Mark Whitley94fd4802001-03-12 23:08:34 +00002815 if (nmod){
2816 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2817 memset(modules, 0, nmod * sizeof(*modules));
2818 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002819 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002820 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002821
Mark Whitley94fd4802001-03-12 23:08:34 +00002822 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2823 if (errno == ENOENT) {
2824 /* The module was removed out from underneath us. */
2825 continue;
2826 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002827 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002828 return 0;
2829 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002830
Mark Whitley94fd4802001-03-12 23:08:34 +00002831 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002832retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002833 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2834 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002835 case ENOSPC:
2836 syms = xrealloc(syms, bufsize = ret);
2837 goto retry_mod_sym_load;
2838 case ENOENT:
2839 /* The module was removed out from underneath us. */
2840 continue;
2841 default:
2842 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2843 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002844 }
2845 }
2846 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002847
Mark Whitley94fd4802001-03-12 23:08:34 +00002848 m->name = mn;
2849 m->addr = info.addr;
2850 m->nsyms = nsyms;
2851 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002852
Mark Whitley94fd4802001-03-12 23:08:34 +00002853 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2854 s->name += (unsigned long) syms;
2855 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002856 }
2857 }
2858
2859 /* Collect the kernel's symbols. */
2860
2861 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002862retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002863 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002864 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002865 syms = xrealloc(syms, bufsize = ret);
2866 goto retry_kern_sym_load;
2867 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002868 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002869 return 0;
2870 }
2871 nksyms = nsyms = ret;
2872 ksyms = syms;
2873
2874 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2875 s->name += (unsigned long) syms;
2876 }
2877 return 1;
2878}
2879
2880
2881/* Return the kernel symbol checksum version, or zero if not used. */
2882
2883static int new_is_kernel_checksummed(void)
2884{
2885 struct new_module_symbol *s;
2886 size_t i;
2887
2888 /* Using_Versions is not the first symbol, but it should be in there. */
2889
2890 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2891 if (strcmp((char *) s->name, "Using_Versions") == 0)
2892 return s->value;
2893
2894 return 0;
2895}
2896
2897
2898static int new_create_this_module(struct obj_file *f, const char *m_name)
2899{
2900 struct obj_section *sec;
2901
2902 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002903 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002904 memset(sec->contents, 0, sizeof(struct new_module));
2905
Miles Baderae28b042002-04-01 09:34:25 +00002906 obj_add_symbol(f, SPFX "__this_module", -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002907 ELFW(ST_INFO) (STB_LOCAL, STT_OBJECT), sec->idx, 0,
2908 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002909
2910 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002911 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002912
2913 return 1;
2914}
2915
Eric Andersen889dd202003-01-23 04:48:34 +00002916#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2917/* add an entry to the __ksymtab section, creating it if necessary */
2918static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2919{
2920 struct obj_section *sec;
2921 ElfW(Addr) ofs;
2922
2923 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2924 * If __ksymtab is defined but not marked alloc, x out the first character
2925 * (no obj_delete routine) and create a new __ksymtab with the correct
2926 * characteristics.
2927 */
2928 sec = obj_find_section(f, "__ksymtab");
2929 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2930 *((char *)(sec->name)) = 'x'; /* override const */
2931 sec = NULL;
2932 }
2933 if (!sec)
2934 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002935 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002936 if (!sec)
2937 return;
2938 sec->header.sh_flags |= SHF_ALLOC;
2939 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002940 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002941 ofs = sec->header.sh_size;
2942 obj_symbol_patch(f, sec->idx, ofs, sym);
2943 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2944 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2945}
2946#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002947
2948static int new_create_module_ksymtab(struct obj_file *f)
2949{
2950 struct obj_section *sec;
2951 int i;
2952
2953 /* We must always add the module references. */
2954
2955 if (n_ext_modules_used) {
2956 struct new_module_ref *dep;
2957 struct obj_symbol *tm;
2958
2959 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002960 (sizeof(struct new_module_ref)
2961 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002962 if (!sec)
2963 return 0;
2964
Miles Baderae28b042002-04-01 09:34:25 +00002965 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002966 dep = (struct new_module_ref *) sec->contents;
2967 for (i = 0; i < n_ext_modules; ++i)
2968 if (ext_modules[i].used) {
2969 dep->dep = ext_modules[i].addr;
2970 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002971 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002972 dep->next_ref = 0;
2973 ++dep;
2974 }
2975 }
2976
2977 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2978 size_t nsyms;
2979 int *loaded;
2980
2981 sec =
2982 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002983 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002984
2985 /* We don't want to export symbols residing in sections that
2986 aren't loaded. There are a number of these created so that
2987 we make sure certain module options don't appear twice. */
2988
2989 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2990 while (--i >= 0)
2991 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2992
2993 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2994 struct obj_symbol *sym;
2995 for (sym = f->symtab[i]; sym; sym = sym->next)
2996 if (ELFW(ST_BIND) (sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002997 && sym->secidx <= SHN_HIRESERVE
2998 && (sym->secidx >= SHN_LORESERVE
2999 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003000 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
3001
3002 obj_symbol_patch(f, sec->idx, ofs, sym);
3003 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003004 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003005
3006 nsyms++;
3007 }
3008 }
3009
3010 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
3011 }
3012
3013 return 1;
3014}
3015
3016
3017static int
3018new_init_module(const char *m_name, struct obj_file *f,
3019 unsigned long m_size)
3020{
3021 struct new_module *module;
3022 struct obj_section *sec;
3023 void *image;
3024 int ret;
3025 tgt_long m_addr;
3026
3027 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003028 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003029 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00003030 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003031 module = (struct new_module *) sec->contents;
3032 m_addr = sec->header.sh_addr;
3033
3034 module->size_of_struct = sizeof(*module);
3035 module->size = m_size;
3036 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
3037
3038 sec = obj_find_section(f, "__ksymtab");
3039 if (sec && sec->header.sh_size) {
3040 module->syms = sec->header.sh_addr;
3041 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
3042 }
3043
3044 if (n_ext_modules_used) {
3045 sec = obj_find_section(f, ".kmodtab");
3046 module->deps = sec->header.sh_addr;
3047 module->ndeps = n_ext_modules_used;
3048 }
3049
3050 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00003051 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00003052 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00003053 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00003054
3055 sec = obj_find_section(f, "__ex_table");
3056 if (sec) {
3057 module->ex_table_start = sec->header.sh_addr;
3058 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
3059 }
3060
3061 sec = obj_find_section(f, ".text.init");
3062 if (sec) {
3063 module->runsize = sec->header.sh_addr - m_addr;
3064 }
3065 sec = obj_find_section(f, ".data.init");
3066 if (sec) {
3067 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00003068 module->runsize > sec->header.sh_addr - m_addr)
3069 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003070 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00003071 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
3072 if (sec && sec->header.sh_size) {
3073 module->archdata_start = (void*)sec->header.sh_addr;
3074 module->archdata_end = module->archdata_start + sec->header.sh_size;
3075 }
3076 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
3077 if (sec && sec->header.sh_size) {
3078 module->kallsyms_start = (void*)sec->header.sh_addr;
3079 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
3080 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003081
3082 if (!arch_init_module(f, module))
3083 return 0;
3084
3085 /* Whew! All of the initialization is complete. Collect the final
3086 module image and give it to the kernel. */
3087
3088 image = xmalloc(m_size);
3089 obj_create_image(f, image);
3090
Eric Andersen64c8b172001-04-05 07:33:10 +00003091 ret = new_sys_init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00003092 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003093 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003094
3095 free(image);
3096
3097 return ret == 0;
3098}
3099
3100#else
3101
3102#define new_init_module(x, y, z) TRUE
3103#define new_create_this_module(x, y) 0
Eric Andersen889dd202003-01-23 04:48:34 +00003104#define new_add_ksymtab(x, y) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003105#define new_create_module_ksymtab(x)
Eric Andersen21adca72000-12-06 18:18:26 +00003106#define query_module(v, w, x, y, z) -1
Eric Andersen9f16d612000-06-12 23:11:16 +00003107
Eric Andersene7047882003-12-11 01:42:13 +00003108#endif /* CONFIG_FEATURE_2_4_MODULES */
Eric Andersen9f16d612000-06-12 23:11:16 +00003109
3110
3111/*======================================================================*/
3112
Eric Andersen044228d2001-07-17 01:12:36 +00003113static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003114obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3115 const char *string)
3116{
3117 struct obj_string_patch *p;
3118 struct obj_section *strsec;
3119 size_t len = strlen(string) + 1;
3120 char *loc;
3121
3122 p = xmalloc(sizeof(*p));
3123 p->next = f->string_patches;
3124 p->reloc_secidx = secidx;
3125 p->reloc_offset = offset;
3126 f->string_patches = p;
3127
3128 strsec = obj_find_section(f, ".kstrtab");
3129 if (strsec == NULL) {
3130 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3131 p->string_offset = 0;
3132 loc = strsec->contents;
3133 } else {
3134 p->string_offset = strsec->header.sh_size;
3135 loc = obj_extend_section(strsec, len);
3136 }
3137 memcpy(loc, string, len);
3138
3139 return 1;
3140}
3141
Eric Andersene7047882003-12-11 01:42:13 +00003142#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen044228d2001-07-17 01:12:36 +00003143static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003144obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3145 struct obj_symbol *sym)
3146{
3147 struct obj_symbol_patch *p;
3148
3149 p = xmalloc(sizeof(*p));
3150 p->next = f->symbol_patches;
3151 p->reloc_secidx = secidx;
3152 p->reloc_offset = offset;
3153 p->sym = sym;
3154 f->symbol_patches = p;
3155
3156 return 1;
3157}
Eric Andersen6d139642001-12-29 04:15:13 +00003158#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00003159
Eric Andersen044228d2001-07-17 01:12:36 +00003160static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003161{
3162 unsigned long i;
3163 int ret = 1;
3164
3165 for (i = 0; i < HASH_BUCKETS; ++i) {
3166 struct obj_symbol *sym;
3167 for (sym = f->symtab[i]; sym; sym = sym->next)
3168 if (sym->secidx == SHN_UNDEF) {
3169 if (ELFW(ST_BIND) (sym->info) == STB_WEAK) {
3170 sym->secidx = SHN_ABS;
3171 sym->value = 0;
3172 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003173 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003174 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003175 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003176 ret = 0;
3177 }
3178 }
3179 }
3180
3181 return ret;
3182}
3183
Eric Andersen044228d2001-07-17 01:12:36 +00003184static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003185{
3186 struct common_entry {
3187 struct common_entry *next;
3188 struct obj_symbol *sym;
3189 } *common_head = NULL;
3190
3191 unsigned long i;
3192
3193 for (i = 0; i < HASH_BUCKETS; ++i) {
3194 struct obj_symbol *sym;
3195 for (sym = f->symtab[i]; sym; sym = sym->next)
3196 if (sym->secidx == SHN_COMMON) {
3197 /* Collect all COMMON symbols and sort them by size so as to
3198 minimize space wasted by alignment requirements. */
3199 {
3200 struct common_entry **p, *n;
3201 for (p = &common_head; *p; p = &(*p)->next)
3202 if (sym->size <= (*p)->sym->size)
3203 break;
3204
3205 n = alloca(sizeof(*n));
3206 n->next = *p;
3207 n->sym = sym;
3208 *p = n;
3209 }
3210 }
3211 }
3212
3213 for (i = 1; i < f->local_symtab_size; ++i) {
3214 struct obj_symbol *sym = f->local_symtab[i];
3215 if (sym && sym->secidx == SHN_COMMON) {
3216 struct common_entry **p, *n;
3217 for (p = &common_head; *p; p = &(*p)->next)
3218 if (sym == (*p)->sym)
3219 break;
3220 else if (sym->size < (*p)->sym->size) {
3221 n = alloca(sizeof(*n));
3222 n->next = *p;
3223 n->sym = sym;
3224 *p = n;
3225 break;
3226 }
3227 }
3228 }
3229
3230 if (common_head) {
3231 /* Find the bss section. */
3232 for (i = 0; i < f->header.e_shnum; ++i)
3233 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3234 break;
3235
3236 /* If for some reason there hadn't been one, create one. */
3237 if (i == f->header.e_shnum) {
3238 struct obj_section *sec;
3239
3240 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3241 f->sections[i] = sec = arch_new_section();
3242 f->header.e_shnum = i + 1;
3243
3244 memset(sec, 0, sizeof(*sec));
3245 sec->header.sh_type = SHT_PROGBITS;
3246 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3247 sec->name = ".bss";
3248 sec->idx = i;
3249 }
3250
3251 /* Allocate the COMMONS. */
3252 {
3253 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3254 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3255 struct common_entry *c;
3256
3257 for (c = common_head; c; c = c->next) {
3258 ElfW(Addr) align = c->sym->value;
3259
3260 if (align > max_align)
3261 max_align = align;
3262 if (bss_size & (align - 1))
3263 bss_size = (bss_size | (align - 1)) + 1;
3264
3265 c->sym->secidx = i;
3266 c->sym->value = bss_size;
3267
3268 bss_size += c->sym->size;
3269 }
3270
3271 f->sections[i]->header.sh_size = bss_size;
3272 f->sections[i]->header.sh_addralign = max_align;
3273 }
3274 }
3275
3276 /* For the sake of patch relocation and parameter initialization,
3277 allocate zeroed data for NOBITS sections now. Note that after
3278 this we cannot assume NOBITS are really empty. */
3279 for (i = 0; i < f->header.e_shnum; ++i) {
3280 struct obj_section *s = f->sections[i];
3281 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003282 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003283 s->contents = memset(xmalloc(s->header.sh_size),
3284 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003285 else
3286 s->contents = NULL;
3287
Eric Andersen9f16d612000-06-12 23:11:16 +00003288 s->header.sh_type = SHT_PROGBITS;
3289 }
3290 }
3291}
3292
Eric Andersen044228d2001-07-17 01:12:36 +00003293static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003294{
3295 unsigned long dot = 0;
3296 struct obj_section *sec;
3297
3298 /* Finalize the positions of the sections relative to one another. */
3299
3300 for (sec = f->load_order; sec; sec = sec->load_next) {
3301 ElfW(Addr) align;
3302
3303 align = sec->header.sh_addralign;
3304 if (align && (dot & (align - 1)))
3305 dot = (dot | (align - 1)) + 1;
3306
3307 sec->header.sh_addr = dot;
3308 dot += sec->header.sh_size;
3309 }
3310
3311 return dot;
3312}
3313
Eric Andersen044228d2001-07-17 01:12:36 +00003314static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003315{
3316 int i, n = f->header.e_shnum;
3317 int ret = 1;
3318
3319 /* Finalize the addresses of the sections. */
3320
3321 f->baseaddr = base;
3322 for (i = 0; i < n; ++i)
3323 f->sections[i]->header.sh_addr += base;
3324
3325 /* And iterate over all of the relocations. */
3326
3327 for (i = 0; i < n; ++i) {
3328 struct obj_section *relsec, *symsec, *targsec, *strsec;
3329 ElfW(RelM) * rel, *relend;
3330 ElfW(Sym) * symtab;
3331 const char *strtab;
3332
3333 relsec = f->sections[i];
3334 if (relsec->header.sh_type != SHT_RELM)
3335 continue;
3336
3337 symsec = f->sections[relsec->header.sh_link];
3338 targsec = f->sections[relsec->header.sh_info];
3339 strsec = f->sections[symsec->header.sh_link];
3340
3341 rel = (ElfW(RelM) *) relsec->contents;
3342 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3343 symtab = (ElfW(Sym) *) symsec->contents;
3344 strtab = (const char *) strsec->contents;
3345
3346 for (; rel < relend; ++rel) {
3347 ElfW(Addr) value = 0;
3348 struct obj_symbol *intsym = NULL;
3349 unsigned long symndx;
3350 ElfW(Sym) * extsym = 0;
3351 const char *errmsg;
3352
3353 /* Attempt to find a value to use for this relocation. */
3354
3355 symndx = ELFW(R_SYM) (rel->r_info);
3356 if (symndx) {
3357 /* Note we've already checked for undefined symbols. */
3358
3359 extsym = &symtab[symndx];
3360 if (ELFW(ST_BIND) (extsym->st_info) == STB_LOCAL) {
3361 /* Local symbols we look up in the local table to be sure
3362 we get the one that is really intended. */
3363 intsym = f->local_symtab[symndx];
3364 } else {
3365 /* Others we look up in the hash table. */
3366 const char *name;
3367 if (extsym->st_name)
3368 name = strtab + extsym->st_name;
3369 else
3370 name = f->sections[extsym->st_shndx]->name;
3371 intsym = obj_find_symbol(f, name);
3372 }
3373
3374 value = obj_symbol_final_value(f, intsym);
3375 intsym->referenced = 1;
3376 }
3377#if SHT_RELM == SHT_RELA
3378#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3379 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3380 if (!extsym || !extsym->st_name ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00003381 ELFW(ST_BIND) (extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003382#endif
3383 value += rel->r_addend;
3384#endif
3385
3386 /* Do it! */
3387 switch (arch_apply_relocation
3388 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003389 case obj_reloc_ok:
3390 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003391
Eric Andersen3b1a7442003-12-24 20:30:45 +00003392 case obj_reloc_overflow:
3393 errmsg = "Relocation overflow";
3394 goto bad_reloc;
3395 case obj_reloc_dangerous:
3396 errmsg = "Dangerous relocation";
3397 goto bad_reloc;
3398 case obj_reloc_unhandled:
3399 errmsg = "Unhandled relocation";
3400bad_reloc:
3401 if (extsym) {
3402 bb_error_msg("%s of type %ld for %s", errmsg,
3403 (long) ELFW(R_TYPE) (rel->r_info),
3404 strtab + extsym->st_name);
3405 } else {
3406 bb_error_msg("%s of type %ld", errmsg,
3407 (long) ELFW(R_TYPE) (rel->r_info));
3408 }
3409 ret = 0;
3410 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003411 }
3412 }
3413 }
3414
3415 /* Finally, take care of the patches. */
3416
3417 if (f->string_patches) {
3418 struct obj_string_patch *p;
3419 struct obj_section *strsec;
3420 ElfW(Addr) strsec_base;
3421 strsec = obj_find_section(f, ".kstrtab");
3422 strsec_base = strsec->header.sh_addr;
3423
3424 for (p = f->string_patches; p; p = p->next) {
3425 struct obj_section *targsec = f->sections[p->reloc_secidx];
3426 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3427 = strsec_base + p->string_offset;
3428 }
3429 }
3430
3431 if (f->symbol_patches) {
3432 struct obj_symbol_patch *p;
3433
3434 for (p = f->symbol_patches; p; p = p->next) {
3435 struct obj_section *targsec = f->sections[p->reloc_secidx];
3436 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3437 = obj_symbol_final_value(f, p->sym);
3438 }
3439 }
3440
3441 return ret;
3442}
3443
Eric Andersen044228d2001-07-17 01:12:36 +00003444static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003445{
3446 struct obj_section *sec;
3447 ElfW(Addr) base = f->baseaddr;
3448
3449 for (sec = f->load_order; sec; sec = sec->load_next) {
3450 char *secimg;
3451
Eric Andersen2bf658d2001-02-24 20:01:53 +00003452 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003453 continue;
3454
3455 secimg = image + (sec->header.sh_addr - base);
3456
3457 /* Note that we allocated data for NOBITS sections earlier. */
3458 memcpy(secimg, sec->contents, sec->header.sh_size);
3459 }
3460
3461 return 1;
3462}
3463
3464/*======================================================================*/
3465
Eric Andersen044228d2001-07-17 01:12:36 +00003466static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003467{
3468 struct obj_file *f;
3469 ElfW(Shdr) * section_headers;
3470 int shnum, i;
3471 char *shstrtab;
3472
3473 /* Read the file header. */
3474
3475 f = arch_new_file();
3476 memset(f, 0, sizeof(*f));
3477 f->symbol_cmp = strcmp;
3478 f->symbol_hash = obj_elf_hash;
3479 f->load_order_search_start = &f->load_order;
3480
3481 fseek(fp, 0, SEEK_SET);
3482 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003483 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003484 return NULL;
3485 }
3486
3487 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003488 || f->header.e_ident[EI_MAG1] != ELFMAG1
3489 || f->header.e_ident[EI_MAG2] != ELFMAG2
3490 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003491 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003492 return NULL;
3493 }
3494 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Eric Andersen3b1a7442003-12-24 20:30:45 +00003495 || f->header.e_ident[EI_DATA] != ELFDATAM
3496 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3497 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003498 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003499 return NULL;
3500 }
3501 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003502 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003503 return NULL;
3504 }
3505
3506 /* Read the section headers. */
3507
3508 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003509 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003510 (unsigned long) f->header.e_shentsize,
3511 (unsigned long) sizeof(ElfW(Shdr)));
3512 return NULL;
3513 }
3514
3515 shnum = f->header.e_shnum;
3516 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3517 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3518
3519 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3520 fseek(fp, f->header.e_shoff, SEEK_SET);
3521 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003522 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003523 return NULL;
3524 }
3525
3526 /* Read the section data. */
3527
3528 for (i = 0; i < shnum; ++i) {
3529 struct obj_section *sec;
3530
3531 f->sections[i] = sec = arch_new_section();
3532 memset(sec, 0, sizeof(*sec));
3533
3534 sec->header = section_headers[i];
3535 sec->idx = i;
3536
Eric Andersen2bf658d2001-02-24 20:01:53 +00003537 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003538 case SHT_NULL:
3539 case SHT_NOTE:
3540 case SHT_NOBITS:
3541 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003542 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003543
3544 case SHT_PROGBITS:
3545#if LOADBITS
3546 if (!loadprogbits) {
3547 sec->contents = NULL;
3548 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003549 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003550#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003551 case SHT_SYMTAB:
3552 case SHT_STRTAB:
3553 case SHT_RELM:
3554 if (sec->header.sh_size > 0) {
3555 sec->contents = xmalloc(sec->header.sh_size);
3556 fseek(fp, sec->header.sh_offset, SEEK_SET);
3557 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3558 bb_perror_msg("error reading ELF section data");
3559 return NULL;
3560 }
3561 } else {
3562 sec->contents = NULL;
3563 }
3564 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003565
3566#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003567 case SHT_RELA:
3568 bb_error_msg("RELA relocations not supported on this architecture");
3569 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003570#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003571 case SHT_REL:
3572 bb_error_msg("REL relocations not supported on this architecture");
3573 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003574#endif
3575
Eric Andersen3b1a7442003-12-24 20:30:45 +00003576 default:
3577 if (sec->header.sh_type >= SHT_LOPROC) {
3578 /* Assume processor specific section types are debug
3579 info and can safely be ignored. If this is ever not
3580 the case (Hello MIPS?), don't put ifdefs here but
3581 create an arch_load_proc_section(). */
3582 break;
3583 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003584
Eric Andersen3b1a7442003-12-24 20:30:45 +00003585 bb_error_msg("can't handle sections of type %ld",
3586 (long) sec->header.sh_type);
3587 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003588 }
3589 }
3590
3591 /* Do what sort of interpretation as needed by each section. */
3592
3593 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3594
3595 for (i = 0; i < shnum; ++i) {
3596 struct obj_section *sec = f->sections[i];
3597 sec->name = shstrtab + sec->header.sh_name;
3598 }
3599
3600 for (i = 0; i < shnum; ++i) {
3601 struct obj_section *sec = f->sections[i];
3602
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003603 /* .modinfo should be contents only but gcc has no attribute for that.
3604 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3605 */
3606 if (strcmp(sec->name, ".modinfo") == 0)
3607 sec->header.sh_flags &= ~SHF_ALLOC;
3608
Eric Andersen9f16d612000-06-12 23:11:16 +00003609 if (sec->header.sh_flags & SHF_ALLOC)
3610 obj_insert_section_load_order(f, sec);
3611
3612 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003613 case SHT_SYMTAB:
3614 {
3615 unsigned long nsym, j;
3616 char *strtab;
3617 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003618
Eric Andersen3b1a7442003-12-24 20:30:45 +00003619 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3620 bb_error_msg("symbol size mismatch: %lu != %lu",
3621 (unsigned long) sec->header.sh_entsize,
3622 (unsigned long) sizeof(ElfW(Sym)));
3623 return NULL;
3624 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003625
Eric Andersen3b1a7442003-12-24 20:30:45 +00003626 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3627 strtab = f->sections[sec->header.sh_link]->contents;
3628 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003629
Eric Andersen3b1a7442003-12-24 20:30:45 +00003630 /* Allocate space for a table of local symbols. */
3631 j = f->local_symtab_size = sec->header.sh_info;
3632 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003633
Eric Andersen3b1a7442003-12-24 20:30:45 +00003634 /* Insert all symbols into the hash table. */
3635 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3636 ElfW(Addr) val = sym->st_value;
3637 const char *name;
3638 if (sym->st_name)
3639 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003640 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003641 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003642 else
3643 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003644
Eric Andersenbf833552003-08-13 19:56:33 +00003645#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003646 /*
3647 * For sh64 it is possible that the target of a branch
3648 * requires a mode switch (32 to 16 and back again).
3649 *
3650 * This is implied by the lsb being set in the target
3651 * address for SHmedia mode and clear for SHcompact.
3652 */
3653 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003654#endif
3655
Eric Andersen3b1a7442003-12-24 20:30:45 +00003656 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3657 val, sym->st_size);
3658 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003659 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003660 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003661
Eric Andersen3b1a7442003-12-24 20:30:45 +00003662 case SHT_RELM:
3663 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3664 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3665 (unsigned long) sec->header.sh_entsize,
3666 (unsigned long) sizeof(ElfW(RelM)));
3667 return NULL;
3668 }
3669 break;
3670 /* XXX Relocation code from modutils-2.3.19 is not here.
3671 * Why? That's about 20 lines of code from obj/obj_load.c,
3672 * which gets done in a second pass through the sections.
3673 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003674 }
3675 }
3676
3677 return f;
3678}
3679
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003680#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003681/*
3682 * load the unloaded sections directly into the memory allocated by
3683 * kernel for the module
3684 */
3685
Eric Andersenac5dbd12001-08-22 05:26:08 +00003686static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003687{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003688 ElfW(Addr) base = f->baseaddr;
3689 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003690
Eric Andersen8ae319a2001-05-21 16:09:18 +00003691 for (sec = f->load_order; sec; sec = sec->load_next) {
3692
3693 /* section already loaded? */
3694 if (sec->contents != NULL)
3695 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003696
Eric Andersen8ae319a2001-05-21 16:09:18 +00003697 if (sec->header.sh_size == 0)
3698 continue;
3699
3700 sec->contents = imagebase + (sec->header.sh_addr - base);
3701 fseek(fp, sec->header.sh_offset, SEEK_SET);
3702 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003703 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003704 return 0;
3705 }
3706
3707 }
3708 return 1;
3709}
3710#endif
3711
Eric Andersen9f16d612000-06-12 23:11:16 +00003712static void hide_special_symbols(struct obj_file *f)
3713{
3714 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003715 SPFX "cleanup_module",
3716 SPFX "init_module",
3717 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003718 NULL
3719 };
3720
3721 struct obj_symbol *sym;
3722 const char *const *p;
3723
3724 for (p = specials; *p; ++p)
3725 if ((sym = obj_find_symbol(f, *p)) != NULL)
3726 sym->info =
3727 ELFW(ST_INFO) (STB_LOCAL, ELFW(ST_TYPE) (sym->info));
3728}
3729
Glenn L McGrath759515c2003-08-30 06:00:33 +00003730
Eric Andersen71ae64b2002-10-10 04:20:21 +00003731#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003732static int obj_gpl_license(struct obj_file *f, const char **license)
3733{
3734 struct obj_section *sec;
3735 /* This list must match *exactly* the list of allowable licenses in
3736 * linux/include/linux/module.h. Checking for leading "GPL" will not
3737 * work, somebody will use "GPL sucks, this is proprietary".
3738 */
3739 static const char *gpl_licenses[] = {
3740 "GPL",
3741 "GPL v2",
3742 "GPL and additional rights",
3743 "Dual BSD/GPL",
3744 "Dual MPL/GPL",
3745 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003746
Eric Andersen166fa462002-09-16 05:30:24 +00003747 if ((sec = obj_find_section(f, ".modinfo"))) {
3748 const char *value, *ptr, *endptr;
3749 ptr = sec->contents;
3750 endptr = ptr + sec->header.sh_size;
3751 while (ptr < endptr) {
3752 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3753 int i;
3754 if (license)
3755 *license = value+1;
3756 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3757 if (strcmp(value+1, gpl_licenses[i]) == 0)
3758 return(0);
3759 }
3760 return(2);
3761 }
3762 if (strchr(ptr, '\0'))
3763 ptr = strchr(ptr, '\0') + 1;
3764 else
3765 ptr = endptr;
3766 }
3767 }
3768 return(1);
3769}
3770
3771#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3772#define TAINT_PROPRIETORY_MODULE (1<<0)
3773#define TAINT_FORCED_MODULE (1<<1)
3774#define TAINT_UNSAFE_SMP (1<<2)
3775#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
3776
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003777static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003778 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3779{
3780 char buf[80];
3781 int oldval;
3782 static int first = 1;
3783 if (fd < 0 && !kernel_has_tainted)
3784 return; /* New modutils on old kernel */
3785 printf("Warning: loading %s will taint the kernel: %s%s\n",
3786 m_name, text1, text2);
3787 if (first) {
3788 printf(" See %s for information about tainted modules\n", TAINT_URL);
3789 first = 0;
3790 }
3791 if (fd >= 0) {
3792 read(fd, buf, sizeof(buf)-1);
3793 buf[sizeof(buf)-1] = '\0';
3794 oldval = strtoul(buf, NULL, 10);
3795 sprintf(buf, "%d\n", oldval | taint);
3796 write(fd, buf, strlen(buf));
3797 }
3798}
3799
3800/* Check if loading this module will taint the kernel. */
3801static void check_tainted_module(struct obj_file *f, char *m_name)
3802{
3803 static const char tainted_file[] = TAINT_FILENAME;
3804 int fd, kernel_has_tainted;
3805 const char *ptr;
3806
3807 kernel_has_tainted = 1;
3808 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3809 if (errno == ENOENT)
3810 kernel_has_tainted = 0;
3811 else if (errno == EACCES)
3812 kernel_has_tainted = 1;
3813 else {
3814 perror(tainted_file);
3815 kernel_has_tainted = 0;
3816 }
3817 }
3818
3819 switch (obj_gpl_license(f, &ptr)) {
3820 case 0:
3821 break;
3822 case 1:
3823 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3824 break;
3825 case 2:
3826 /* The module has a non-GPL license so we pretend that the
3827 * kernel always has a taint flag to get a warning even on
3828 * kernels without the proc flag.
3829 */
3830 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3831 break;
3832 default:
3833 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3834 break;
3835 }
3836
3837 if (flag_force_load)
3838 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3839
3840 if (fd >= 0)
3841 close(fd);
3842}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003843#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3844#define check_tainted_module(x, y) do { } while(0);
3845#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003846
Eric Andersen889dd202003-01-23 04:48:34 +00003847#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3848/* add module source, timestamp, kernel version and a symbol for the
3849 * start of some sections. this info is used by ksymoops to do better
3850 * debugging.
3851 */
3852static int
3853get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3854{
3855#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen3b1a7442003-12-24 20:30:45 +00003856 if (get_modinfo_value(f, "kernel_version") == NULL)
3857 return old_get_module_version(f, str);
3858 else
3859 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003860#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003861 strncpy(str, "???", sizeof(str));
3862 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003863#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3864}
3865
3866/* add module source, timestamp, kernel version and a symbol for the
3867 * start of some sections. this info is used by ksymoops to do better
3868 * debugging.
3869 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003870static void
Eric Andersen889dd202003-01-23 04:48:34 +00003871add_ksymoops_symbols(struct obj_file *f, const char *filename,
3872 const char *m_name)
3873{
3874 static const char symprefix[] = "__insmod_";
3875 struct obj_section *sec;
3876 struct obj_symbol *sym;
3877 char *name, *absolute_filename;
3878 char str[STRVERSIONLEN], real[PATH_MAX];
3879 int i, l, lm_name, lfilename, use_ksymtab, version;
3880 struct stat statbuf;
3881
3882 static const char *section_names[] = {
3883 ".text",
3884 ".rodata",
3885 ".data",
3886 ".bss"
Eric Andersen3b1a7442003-12-24 20:30:45 +00003887 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003888 };
3889
3890 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003891 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003892 }
3893 else {
3894 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003895 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003896 errno = save_errno;
3897 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003898 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003899 }
3900
3901 lm_name = strlen(m_name);
3902 lfilename = strlen(absolute_filename);
3903
3904 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3905 * are not to be exported. otherwise leave ksymtab alone for now, the
3906 * "export all symbols" compatibility code will export these symbols later.
3907 */
3908 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3909
3910 if ((sec = obj_find_section(f, ".this"))) {
3911 /* tag the module header with the object name, last modified
3912 * timestamp and module version. worst case for module version
3913 * is 0xffffff, decimal 16777215. putting all three fields in
3914 * one symbol is less readable but saves kernel space.
3915 */
3916 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003917 lm_name+ /* module name */
3918 2+ /* "_O" */
3919 lfilename+ /* object filename */
3920 2+ /* "_M" */
3921 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3922 2+ /* "_V" */
3923 8+ /* version in dec */
3924 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003925 name = xmalloc(l);
3926 if (stat(absolute_filename, &statbuf) != 0)
3927 statbuf.st_mtime = 0;
3928 version = get_module_version(f, str); /* -1 if not found */
3929 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003930 symprefix, m_name, absolute_filename,
3931 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3932 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003933 sym = obj_add_symbol(f, name, -1,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003934 ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
3935 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003936 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003937 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003938 }
3939 free(absolute_filename);
3940#ifdef _NOT_SUPPORTED_
3941 /* record where the persistent data is going, same address as previous symbol */
3942
3943 if (f->persist) {
3944 l = sizeof(symprefix)+ /* "__insmod_" */
3945 lm_name+ /* module name */
3946 2+ /* "_P" */
3947 strlen(f->persist)+ /* data store */
3948 1; /* nul */
3949 name = xmalloc(l);
3950 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003951 symprefix, m_name, f->persist);
Eric Andersen889dd202003-01-23 04:48:34 +00003952 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003953 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003954 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003955 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003956 }
3957#endif /* _NOT_SUPPORTED_ */
3958 /* tag the desired sections if size is non-zero */
3959
3960 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3961 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003962 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003963 l = sizeof(symprefix)+ /* "__insmod_" */
3964 lm_name+ /* module name */
3965 2+ /* "_S" */
3966 strlen(sec->name)+ /* section name */
3967 2+ /* "_L" */
3968 8+ /* length in dec */
3969 1; /* nul */
3970 name = xmalloc(l);
3971 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003972 symprefix, m_name, sec->name,
3973 (long)sec->header.sh_size);
Eric Andersen889dd202003-01-23 04:48:34 +00003974 sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003975 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003976 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003977 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003978 }
3979 }
3980}
3981#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3982
Eric Andersenbe65c352003-01-23 04:57:35 +00003983#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3984static void print_load_map(struct obj_file *f)
3985{
3986 struct obj_symbol *sym;
3987 struct obj_symbol **all, **p;
3988 struct obj_section *sec;
3989 int i, nsyms, *loaded;
3990
3991 /* Report on the section layout. */
3992
3993 printf("Sections: Size %-*s Align\n",
3994 (int) (2 * sizeof(void *)), "Address");
3995
3996 for (sec = f->load_order; sec; sec = sec->load_next) {
3997 int a;
3998 unsigned long tmp;
3999
4000 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
4001 tmp >>= 1;
4002 if (a == -1)
4003 a = 0;
4004
4005 printf("%-15s %08lx %0*lx 2**%d\n",
4006 sec->name,
4007 (long)sec->header.sh_size,
4008 (int) (2 * sizeof(void *)),
4009 (long)sec->header.sh_addr,
4010 a);
4011 }
4012#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
4013 /* Quick reference which section indicies are loaded. */
4014
4015 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
4016 while (--i >= 0)
4017 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
4018
4019 /* Collect the symbols we'll be listing. */
4020
4021 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
4022 for (sym = f->symtab[i]; sym; sym = sym->next)
4023 if (sym->secidx <= SHN_HIRESERVE
4024 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
4025 ++nsyms;
4026
4027 all = alloca(nsyms * sizeof(struct obj_symbol *));
4028
4029 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
4030 for (sym = f->symtab[i]; sym; sym = sym->next)
4031 if (sym->secidx <= SHN_HIRESERVE
4032 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
4033 *p++ = sym;
4034
4035 /* And list them. */
4036 printf("\nSymbols:\n");
4037 for (p = all; p < all + nsyms; ++p) {
4038 char type = '?';
4039 unsigned long value;
4040
4041 sym = *p;
4042 if (sym->secidx == SHN_ABS) {
4043 type = 'A';
4044 value = sym->value;
4045 } else if (sym->secidx == SHN_UNDEF) {
4046 type = 'U';
4047 value = 0;
4048 } else {
4049 sec = f->sections[sym->secidx];
4050
4051 if (sec->header.sh_type == SHT_NOBITS)
4052 type = 'B';
4053 else if (sec->header.sh_flags & SHF_ALLOC) {
4054 if (sec->header.sh_flags & SHF_EXECINSTR)
4055 type = 'T';
4056 else if (sec->header.sh_flags & SHF_WRITE)
4057 type = 'D';
4058 else
4059 type = 'R';
4060 }
4061 value = sym->value + sec->header.sh_addr;
4062 }
4063
4064 if (ELFW(ST_BIND) (sym->info) == STB_LOCAL)
4065 type = tolower(type);
4066
4067 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
4068 type, sym->name);
4069 }
4070#endif
4071}
4072
4073#endif
4074
Eric Andersen9f16d612000-06-12 23:11:16 +00004075extern int insmod_main( int argc, char **argv)
4076{
Eric Andersena18aaf12001-01-24 19:07:09 +00004077 int opt;
Eric Andersen9f16d612000-06-12 23:11:16 +00004078 int k_crcs;
4079 int k_new_syscalls;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004080 int len;
Eric Andersen6fb4e482002-06-06 14:24:57 +00004081 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00004082 unsigned long m_size;
4083 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00004084 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00004085 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00004086 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00004087 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00004088 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004089#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00004090 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00004091 char m_strversion[STRVERSIONLEN];
4092 int m_version;
4093 int m_crcs;
4094#endif
Eric Andersen61f83052002-06-22 17:15:42 +00004095#ifdef CONFIG_FEATURE_CLEAN_UP
4096 FILE *fp = 0;
4097#else
4098 FILE *fp;
4099#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00004100#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4101 int flag_print_load_map = 0;
4102#endif
Eric Andersen03d80912003-12-19 21:04:19 +00004103 int k_version = 0;
4104 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00004105
Erik Andersene49d5ec2000-02-08 19:58:47 +00004106 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00004107#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004108 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004109#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004110 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004111#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004112 {
4113 switch (opt) {
4114 case 'f': /* force loading */
4115 flag_force_load = 1;
4116 break;
4117 case 'k': /* module loaded by kerneld, auto-cleanable */
4118 flag_autoclean = 1;
4119 break;
4120 case 's': /* log to syslog */
4121 /* log to syslog -- not supported */
4122 /* but kernel needs this for request_module(), */
4123 /* as this calls: modprobe -k -s -- <module> */
4124 /* so silently ignore this flag */
4125 break;
4126 case 'v': /* verbose output */
4127 flag_verbose = 1;
4128 break;
4129 case 'q': /* silent */
4130 flag_quiet = 1;
4131 break;
4132 case 'x': /* do not export externs */
4133 flag_export = 0;
4134 break;
4135 case 'o': /* name the output module */
4136 free(m_name);
4137 m_name = bb_xstrdup(optarg);
4138 break;
4139 case 'L': /* Stub warning */
4140 /* This is needed for compatibility with modprobe.
4141 * In theory, this does locking, but we don't do
4142 * that. So be careful and plan your life around not
4143 * loading the same module 50 times concurrently. */
4144 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004145#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004146 case 'm': /* print module load map */
4147 flag_print_load_map = 1;
4148 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004149#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004150 default:
4151 bb_show_usage();
4152 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004153 }
Eric Andersen03d80912003-12-19 21:04:19 +00004154
Eric Andersena18aaf12001-01-24 19:07:09 +00004155 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004156 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00004157 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004158
Erik Andersene49d5ec2000-02-08 19:58:47 +00004159 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00004160 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00004161 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004162 len = strlen(tmp);
4163
Eric Andersen03d80912003-12-19 21:04:19 +00004164 if (uname(&myuname) == 0) {
4165 if (myuname.release[0] == '2') {
4166 k_version = myuname.release[2] - '0';
4167 }
4168 }
4169
4170#if defined(CONFIG_FEATURE_2_6_MODULES)
4171 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004172 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004173 len-=3;
4174 tmp[len] = '\0';
4175 }
4176 else
4177#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004178 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4179 len-=2;
4180 tmp[len] = '\0';
4181 }
Eric Andersen2d342152002-06-18 05:16:25 +00004182
Eric Andersen03d80912003-12-19 21:04:19 +00004183
4184#if defined(CONFIG_FEATURE_2_6_MODULES)
4185 if (k_version > 4)
4186 bb_xasprintf(&m_fullName, "%s.ko", tmp);
4187 else
Eric Andersen03d80912003-12-19 21:04:19 +00004188#endif
Eric Andersen66e21fd2004-01-05 23:49:37 +00004189 bb_xasprintf(&m_fullName, "%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004190
Eric Andersen61f83052002-06-22 17:15:42 +00004191 if (!m_name) {
4192 m_name = tmp;
4193 } else {
4194 free(tmp1);
4195 tmp1 = 0; /* flag for free(m_name) before exit() */
4196 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004197
Eric Andersen14d35432001-05-14 17:07:32 +00004198 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004199 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4200 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004201 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4202 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004203 if (k_version) { /* uname succeedd */
4204 char *module_dir;
4205 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004206 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004207
Eric Andersen03d80912003-12-19 21:04:19 +00004208 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004209 /* Jump through hoops in case /lib/modules/`uname -r`
4210 * is a symlink. We do not want recursive_action to
4211 * follow symlinks, but we do want to follow the
4212 * /lib/modules/`uname -r` dir, So resolve it ourselves
4213 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004214 if (realpath (tmdn, real_module_dir) == NULL)
4215 module_dir = tmdn;
4216 else
4217 module_dir = real_module_dir;
4218 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004219 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004220 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004221 }
4222
4223 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004224 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004225 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004226 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004227
Eric Andersen03d80912003-12-19 21:04:19 +00004228 free(m_filename);
4229 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004230 if (realpath (_PATH_MODULES, module_dir) == NULL)
4231 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004232 /* No module found under /lib/modules/`uname -r`, this
4233 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004234 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004235 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004236 {
Eric Andersen61f83052002-06-22 17:15:42 +00004237 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004238 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004239 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004240 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004241 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004242 }
4243 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004244 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004245 }
Eric Andersen03d80912003-12-19 21:04:19 +00004246 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004247 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004248
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004249 if (!flag_quiet)
4250 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004251
Eric Andersene7047882003-12-11 01:42:13 +00004252#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004253 if (k_version > 4)
4254 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004255 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004256 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004257 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004258 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004259#endif
4260
Eric Andersen8ae319a2001-05-21 16:09:18 +00004261 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004262 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004263
Eric Andersen9f16d612000-06-12 23:11:16 +00004264 if (get_modinfo_value(f, "kernel_version") == NULL)
4265 m_has_modinfo = 0;
4266 else
4267 m_has_modinfo = 1;
4268
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004269#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004270 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004271 if (!flag_quiet) {
4272 if (uname(&uts_info) < 0)
4273 uts_info.release[0] = '\0';
4274 if (m_has_modinfo) {
4275 m_version = new_get_module_version(f, m_strversion);
Eric Andersen9f16d612000-06-12 23:11:16 +00004276 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00004277 m_version = old_get_module_version(f, m_strversion);
4278 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004279 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004280 "compiled for");
4281 goto out;
4282 }
4283 }
4284
4285 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4286 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004287 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004288 "\t%s was compiled for kernel version %s\n"
4289 "\twhile this kernel is version %s",
4290 m_filename, m_strversion, uts_info.release);
4291 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004292 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004293 "\t%s was compiled for kernel version %s\n"
4294 "\twhile this kernel is version %s.",
4295 m_filename, m_strversion, uts_info.release);
4296 goto out;
4297 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004298 }
4299 }
4300 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004301#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004302
4303 k_new_syscalls = !query_module(NULL, 0, NULL, 0, NULL);
4304
4305 if (k_new_syscalls) {
Eric Andersene7047882003-12-11 01:42:13 +00004306#ifdef CONFIG_FEATURE_2_4_MODULES
Eric Andersen9f16d612000-06-12 23:11:16 +00004307 if (!new_get_kernel_symbols())
4308 goto out;
4309 k_crcs = new_is_kernel_checksummed();
4310#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004311 bb_error_msg("Not configured to support new kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004312 goto out;
4313#endif
4314 } else {
Eric Andersene7047882003-12-11 01:42:13 +00004315#ifdef CONFIG_FEATURE_2_2_MODULES
Eric Andersen8c185f92000-09-22 00:38:07 +00004316 if (!old_get_kernel_symbols(m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004317 goto out;
4318 k_crcs = old_is_kernel_checksummed();
4319#else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004320 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004321 goto out;
4322#endif
4323 }
4324
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004325#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004326 if (m_has_modinfo)
4327 m_crcs = new_is_module_checksummed(f);
4328 else
4329 m_crcs = old_is_module_checksummed(f);
4330
4331 if (m_crcs != k_crcs)
4332 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004333#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004334
Erik Andersene49d5ec2000-02-08 19:58:47 +00004335 /* Let the module know about the kernel symbols. */
4336 add_kernel_symbols(f);
4337
Eric Andersen9f16d612000-06-12 23:11:16 +00004338 /* Allocate common symbols, symbol tables, and string tables. */
4339
Eric Andersen03d80912003-12-19 21:04:19 +00004340 if (k_new_syscalls
Eric Andersen3b1a7442003-12-24 20:30:45 +00004341 ? !new_create_this_module(f, m_name)
4342 : !old_create_mod_use_count(f))
Eric Andersen9f16d612000-06-12 23:11:16 +00004343 {
4344 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004345 }
4346
Eric Andersen9f16d612000-06-12 23:11:16 +00004347 if (!obj_check_undefineds(f)) {
4348 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004349 }
4350 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004351 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004352
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004353 /* done with the module name, on to the optional var=value arguments */
4354 ++optind;
4355
Eric Andersen9f16d612000-06-12 23:11:16 +00004356 if (optind < argc) {
4357 if (m_has_modinfo
Eric Andersen3b1a7442003-12-24 20:30:45 +00004358 ? !new_process_module_arguments(f, argc - optind, argv + optind)
4359 : !old_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004360 {
4361 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004362 }
4363 }
4364
Eric Andersen9f16d612000-06-12 23:11:16 +00004365 arch_create_got(f);
4366 hide_special_symbols(f);
4367
Eric Andersen889dd202003-01-23 04:48:34 +00004368#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4369 add_ksymoops_symbols(f, m_filename, m_name);
4370#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4371
Eric Andersen9f16d612000-06-12 23:11:16 +00004372 if (k_new_syscalls)
4373 new_create_module_ksymtab(f);
4374
Erik Andersene49d5ec2000-02-08 19:58:47 +00004375 /* Find current size of the module */
4376 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004377
4378
Erik Andersene49d5ec2000-02-08 19:58:47 +00004379 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004380 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004381 case EEXIST:
4382 bb_error_msg("A module named %s already exists", m_name);
4383 goto out;
4384 case ENOMEM:
4385 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4386 m_size);
4387 goto out;
4388 default:
4389 bb_perror_msg("create_module: %s", m_name);
4390 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004391 }
Erik Andersend387d011999-12-21 02:55:11 +00004392
Eric Andersen8ae319a2001-05-21 16:09:18 +00004393#if !LOADBITS
4394 /*
4395 * the PROGBITS section was not loaded by the obj_load
4396 * now we can load them directly into the kernel memory
4397 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004398 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004399 delete_module(m_name);
4400 goto out;
4401 }
Eric Andersen03d80912003-12-19 21:04:19 +00004402#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004403
Eric Andersen9f16d612000-06-12 23:11:16 +00004404 if (!obj_relocate(f, m_addr)) {
4405 delete_module(m_name);
4406 goto out;
4407 }
Erik Andersend387d011999-12-21 02:55:11 +00004408
Eric Andersen03d80912003-12-19 21:04:19 +00004409 if (k_new_syscalls
Eric Andersen3b1a7442003-12-24 20:30:45 +00004410 ? !new_init_module(m_name, f, m_size)
4411 : !old_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004412 {
4413 delete_module(m_name);
4414 goto out;
4415 }
4416
Eric Andersenbe65c352003-01-23 04:57:35 +00004417#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4418 if(flag_print_load_map)
4419 print_load_map(f);
4420#endif
4421
Matt Kraai3e856ce2000-12-01 02:55:13 +00004422 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004423
4424out:
Eric Andersen61f83052002-06-22 17:15:42 +00004425#ifdef CONFIG_FEATURE_CLEAN_UP
4426 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004427 fclose(fp);
Eric Andersen61f83052002-06-22 17:15:42 +00004428 if(tmp1) {
4429 free(tmp1);
4430 } else {
4431 free(m_name);
4432 }
4433 free(m_filename);
4434#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004435 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004436}
Eric Andersene7047882003-12-11 01:42:13 +00004437
4438
4439#endif
4440
4441
4442#ifdef CONFIG_FEATURE_2_6_MODULES
4443
4444#include <sys/mman.h>
4445#include <asm/unistd.h>
4446#include <sys/syscall.h>
4447
4448/* We use error numbers in a loose translation... */
4449static const char *moderror(int err)
4450{
4451 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004452 case ENOEXEC:
4453 return "Invalid module format";
4454 case ENOENT:
4455 return "Unknown symbol in module";
4456 case ESRCH:
4457 return "Module has wrong symbol version";
4458 case EINVAL:
4459 return "Invalid parameters";
4460 default:
4461 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004462 }
4463}
4464
4465extern int insmod_ng_main( int argc, char **argv)
4466{
4467 int i;
4468 int fd;
4469 long int ret;
4470 struct stat st;
4471 unsigned long len;
4472 void *map;
4473 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004474
Eric Andersene7047882003-12-11 01:42:13 +00004475 filename = argv[1];
4476 if (!filename) {
4477 bb_show_usage();
4478 return -1;
4479 }
4480
4481 /* Rest is options */
4482 for (i = 2; i < argc; i++) {
4483 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4484 /* Spaces handled by "" pairs, but no way of escaping quotes */
4485 if (strchr(argv[i], ' ')) {
4486 strcat(options, "\"");
4487 strcat(options, argv[i]);
4488 strcat(options, "\"");
4489 } else {
4490 strcat(options, argv[i]);
4491 }
4492 strcat(options, " ");
4493 }
4494
4495 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4496 bb_perror_msg_and_die("cannot open module `%s'", filename);
4497 }
4498
4499 fstat(fd, &st);
4500 len = st.st_size;
4501 map = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
4502 if (map == MAP_FAILED) {
4503 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4504 }
4505
4506 ret = syscall(__NR_init_module, map, len, options);
4507 if (ret != 0) {
4508 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004509 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004510 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004511
Eric Andersene7047882003-12-11 01:42:13 +00004512 return 0;
4513}
4514
4515#endif