blob: 7b715b9c3f0b93efde92881d30a4376e0f729a4a [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 Andersen45a05132004-09-02 23:03:25 +00005 * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
6 * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
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 *
Eric Andersena4d27d22004-08-19 19:17:30 +000011 * Rodney Radford <rradford@mindspring.com> 17-Aug-2004.
12 * Added x86_64 support.
13 *
Miles Bader75ce8d72002-04-01 14:25:51 +000014 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000015 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000017 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
18 *
19 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
20 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
21 * very minor changes required to also work with StrongArm and presumably
22 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000023 *
Eric Andersenee70fa52004-05-26 11:38:46 +000024 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
25 * added Renesas H8/300 support.
26 *
Eric Andersenbf833552003-08-13 19:56:33 +000027 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
28 * Integrated support for sh64 (SH-5), from preliminary modutils
29 * patches from Benedict Gaster <benedict.gaster@superh.com>.
30 * Currently limited to support for 32bit ABI.
31 *
Eric Andersencffd5022002-05-24 06:50:15 +000032 * Magnus Damm <damm@opensource.se> 22-May-2002.
33 * The plt and got code are now using the same structs.
34 * Added generic linked list code to fully support PowerPC.
35 * Replaced the mess in arch_apply_relocation() with architecture blocks.
36 * The arch_create_got() function got cleaned up with architecture blocks.
37 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
38 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000040 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
42 * I've only tested the code on mpc8xx platforms in big-endian mode.
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000043 * Did some cleanup and added USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000044 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000045 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
46 * based on modutils-2.4.2
47 * MIPS specific support for Elf loading and relocation.
48 * Copyright 1996, 1997 Linux International.
49 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
50 *
Eric Andersen9f16d612000-06-12 23:11:16 +000051 * Based almost entirely on the Linux modutils-2.3.11 implementation.
52 * Copyright 1996, 1997 Linux International.
53 * New implementation contributed by Richard Henderson <rth@tamu.edu>
54 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
55 * Restructured (and partly rewritten) by:
56 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000057 *
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +000058 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Erik Andersen02104321999-12-17 18:57:34 +000059 */
60
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +000061#include "busybox.h"
Rob Landley519d7df2006-08-09 20:56:23 +000062#include <libgen.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000065#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
66#define ENABLE_FEATURE_2_4_MODULES 1
Eric Andersene7047882003-12-11 01:42:13 +000067#endif
68
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000069#if !ENABLE_FEATURE_2_4_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000070#define insmod_ng_main insmod_main
71#endif
72
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000073#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000074extern int insmod_ng_main( int argc, char **argv);
75#endif
76
Eric Andersencb3b9b12004-06-22 11:50:52 +000077
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000078#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000079
Eric Andersen64c8b172001-04-05 07:33:10 +000080
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000081#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000082#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000083#else
84#define LOADBITS 1
85#endif
86
Eric Andersen90fe7fe2001-02-20 20:47:08 +000087
Mike Frysinger63654c12004-12-26 09:13:32 +000088/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000089#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000090#define MATCH_MACHINE(x) (x == EM_ALPHA)
91#define SHT_RELM SHT_RELA
92#define Elf64_RelM Elf64_Rela
93#define ELFCLASSM ELFCLASS64
94#endif
95
Eric Andersen45a05132004-09-02 23:03:25 +000096/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000097#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000098#define MATCH_MACHINE(x) (x == EM_ARM)
99#define SHT_RELM SHT_REL
100#define Elf32_RelM Elf32_Rel
101#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000102#define USE_PLT_ENTRIES
103#define PLT_ENTRY_SIZE 8
104#define USE_GOT_ENTRIES
105#define GOT_ENTRY_SIZE 8
106#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000107#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000108
Mike Frysingerb306cb72006-06-06 06:15:52 +0000109/* blackfin */
110#if defined(BFIN)
111#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
112#define SHT_RELM SHT_RELA
113#define Elf32_RelM Elf32_Rela
114#define ELFCLASSM ELFCLASS32
115#endif
116
Eric Andersen45a05132004-09-02 23:03:25 +0000117/* CRIS */
118#if defined(__cris__)
119#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000120#define SHT_RELM SHT_RELA
121#define Elf32_RelM Elf32_Rela
122#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000123#ifndef EM_CRIS
124#define EM_CRIS 76
125#define R_CRIS_NONE 0
126#define R_CRIS_32 3
127#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000128#endif
129
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000130/* H8/300 */
131#if defined(__H8300H__) || defined(__H8300S__)
132#define MATCH_MACHINE(x) (x == EM_H8_300)
133#define SHT_RELM SHT_RELA
134#define Elf32_RelM Elf32_Rela
135#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000136#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000137#define SYMBOL_PREFIX "_"
138#endif
139
Mike Frysinger63654c12004-12-26 09:13:32 +0000140/* PA-RISC / HP-PA */
141#if defined(__hppa__)
142#define MATCH_MACHINE(x) (x == EM_PARISC)
143#define SHT_RELM SHT_RELA
144#if defined(__LP64__)
145#define Elf64_RelM Elf64_Rela
146#define ELFCLASSM ELFCLASS64
147#else
148#define Elf32_RelM Elf32_Rela
149#define ELFCLASSM ELFCLASS32
150#endif
151#endif
152
Eric Andersen45a05132004-09-02 23:03:25 +0000153/* x86 */
154#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000155#ifndef EM_486
156#define MATCH_MACHINE(x) (x == EM_386)
157#else
158#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
159#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000160#define SHT_RELM SHT_REL
161#define Elf32_RelM Elf32_Rel
162#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000163#define USE_GOT_ENTRIES
164#define GOT_ENTRY_SIZE 4
165#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000166#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000167
Eric Andersen45a05132004-09-02 23:03:25 +0000168/* IA64, aka Itanium */
169#if defined(__ia64__)
170#define MATCH_MACHINE(x) (x == EM_IA_64)
171#define SHT_RELM SHT_RELA
172#define Elf64_RelM Elf64_Rela
173#define ELFCLASSM ELFCLASS64
174#endif
175
176/* m68k */
177#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000178#define MATCH_MACHINE(x) (x == EM_68K)
179#define SHT_RELM SHT_RELA
180#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000181#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000182#define USE_GOT_ENTRIES
183#define GOT_ENTRY_SIZE 4
184#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000185#endif
186
Mike Frysingerb306cb72006-06-06 06:15:52 +0000187/* Microblaze */
188#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000189#define USE_SINGLE
Mike Frysingerb306cb72006-06-06 06:15:52 +0000190#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
191#define SHT_RELM SHT_RELA
192#define Elf32_RelM Elf32_Rela
193#define ELFCLASSM ELFCLASS32
194#endif
195
Eric Andersen45a05132004-09-02 23:03:25 +0000196/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000197#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000198#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
199#define SHT_RELM SHT_REL
200#define Elf32_RelM Elf32_Rel
201#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000202/* Account for ELF spec changes. */
203#ifndef EM_MIPS_RS3_LE
204#ifdef EM_MIPS_RS4_BE
205#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
206#else
207#define EM_MIPS_RS3_LE 10
208#endif
209#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000210#define ARCHDATAM "__dbe_table"
211#endif
212
Mike Frysingerf982d862006-01-04 00:11:26 +0000213/* Nios II */
214#if defined(__nios2__)
215#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
216#define SHT_RELM SHT_RELA
217#define Elf32_RelM Elf32_Rela
218#define ELFCLASSM ELFCLASS32
219#endif
220
Eric Andersen45a05132004-09-02 23:03:25 +0000221/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000222#if defined(__powerpc64__)
223#define MATCH_MACHINE(x) (x == EM_PPC64)
224#define SHT_RELM SHT_RELA
225#define Elf64_RelM Elf64_Rela
226#define ELFCLASSM ELFCLASS64
227#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000228#define MATCH_MACHINE(x) (x == EM_PPC)
229#define SHT_RELM SHT_RELA
230#define Elf32_RelM Elf32_Rela
231#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000232#define USE_PLT_ENTRIES
233#define PLT_ENTRY_SIZE 16
234#define USE_PLT_LIST
235#define LIST_ARCHTYPE ElfW(Addr)
236#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000237#define ARCHDATAM "__ftr_fixup"
238#endif
239
Eric Andersen45a05132004-09-02 23:03:25 +0000240/* S390 */
241#if defined(__s390__)
242#define MATCH_MACHINE(x) (x == EM_S390)
243#define SHT_RELM SHT_RELA
244#define Elf32_RelM Elf32_Rela
245#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000246#define USE_PLT_ENTRIES
247#define PLT_ENTRY_SIZE 8
248#define USE_GOT_ENTRIES
249#define GOT_ENTRY_SIZE 8
250#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000251#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000252
Eric Andersen45a05132004-09-02 23:03:25 +0000253/* SuperH */
254#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000255#define MATCH_MACHINE(x) (x == EM_SH)
256#define SHT_RELM SHT_RELA
257#define Elf32_RelM Elf32_Rela
258#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000259#define USE_GOT_ENTRIES
260#define GOT_ENTRY_SIZE 4
261#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000262/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000263/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000264#if defined(__sh__) && BB_BIG_ENDIAN
265# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000266#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000267/* it may or may not work on the SH1/SH2... Error on those also */
268#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000269#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000270#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000271#endif
272
Eric Andersen45a05132004-09-02 23:03:25 +0000273/* Sparc */
274#if defined(__sparc__)
275#define MATCH_MACHINE(x) (x == EM_SPARC)
276#define SHT_RELM SHT_RELA
277#define Elf32_RelM Elf32_Rela
278#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000279#endif
280
Eric Andersen45a05132004-09-02 23:03:25 +0000281/* v850e */
282#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000283#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
284#define SHT_RELM SHT_RELA
285#define Elf32_RelM Elf32_Rela
286#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000287#define USE_PLT_ENTRIES
288#define PLT_ENTRY_SIZE 8
289#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000290#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000291#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000292#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000293#define SYMBOL_PREFIX "_"
294#endif
295
Eric Andersen45a05132004-09-02 23:03:25 +0000296/* X86_64 */
297#if defined(__x86_64__)
298#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000299#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000300#define USE_GOT_ENTRIES
301#define GOT_ENTRY_SIZE 8
302#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000303#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000304#define ELFCLASSM ELFCLASS64
305#endif
306
Eric Andersencffd5022002-05-24 06:50:15 +0000307#ifndef SHT_RELM
308#error Sorry, but insmod.c does not yet support this architecture...
309#endif
310
311
Eric Andersen9f16d612000-06-12 23:11:16 +0000312//----------------------------------------------------------------------------
313//--------modutils module.h, lines 45-242
314//----------------------------------------------------------------------------
315
316/* Definitions for the Linux module syscall interface.
317 Copyright 1996, 1997 Linux International.
318
319 Contributed by Richard Henderson <rth@tamu.edu>
320
321 This file is part of the Linux modutils.
322
323 This program is free software; you can redistribute it and/or modify it
324 under the terms of the GNU General Public License as published by the
325 Free Software Foundation; either version 2 of the License, or (at your
326 option) any later version.
327
328 This program is distributed in the hope that it will be useful, but
329 WITHOUT ANY WARRANTY; without even the implied warranty of
330 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
331 General Public License for more details.
332
333 You should have received a copy of the GNU General Public License
334 along with this program; if not, write to the Free Software Foundation,
335 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
336
337
338#ifndef MODUTILS_MODULE_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000339/* Why? static const int MODUTILS_MODULE_H = 1;*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000340
Eric Andersen9f16d612000-06-12 23:11:16 +0000341/*======================================================================*/
342/* For sizeof() which are related to the module platform and not to the
343 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
344
345#define tgt_sizeof_char sizeof(char)
346#define tgt_sizeof_short sizeof(short)
347#define tgt_sizeof_int sizeof(int)
348#define tgt_sizeof_long sizeof(long)
349#define tgt_sizeof_char_p sizeof(char *)
350#define tgt_sizeof_void_p sizeof(void *)
351#define tgt_long long
352
353#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
354#undef tgt_sizeof_long
355#undef tgt_sizeof_char_p
356#undef tgt_sizeof_void_p
357#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000358enum {
359 tgt_sizeof_long = 8,
360 tgt_sizeof_char_p = 8,
361 tgt_sizeof_void_p = 8
362};
Eric Andersen9f16d612000-06-12 23:11:16 +0000363#define tgt_long long long
364#endif
365
366/*======================================================================*/
367/* The structures used in Linux 2.1. */
368
369/* Note: new_module_symbol does not use tgt_long intentionally */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000370struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000371 unsigned long value;
372 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000373};
374
375struct new_module_persist;
376
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000377struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000378 unsigned tgt_long dep; /* kernel addresses */
379 unsigned tgt_long ref;
380 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000381};
382
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000383struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000384 unsigned tgt_long size_of_struct; /* == sizeof(module) */
385 unsigned tgt_long next;
386 unsigned tgt_long name;
387 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000388
Eric Andersen3b1a7442003-12-24 20:30:45 +0000389 tgt_long usecount;
390 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000391
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned nsyms;
393 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000394
Eric Andersen3b1a7442003-12-24 20:30:45 +0000395 unsigned tgt_long syms;
396 unsigned tgt_long deps;
397 unsigned tgt_long refs;
398 unsigned tgt_long init;
399 unsigned tgt_long cleanup;
400 unsigned tgt_long ex_table_start;
401 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000402#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000403 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 /* Everything after here is extension. */
406 unsigned tgt_long persist_start;
407 unsigned tgt_long persist_end;
408 unsigned tgt_long can_unload;
409 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000410 const char *kallsyms_start; /* All symbols for kernel debugging */
411 const char *kallsyms_end;
412 const char *archdata_start; /* arch specific data for module */
413 const char *archdata_end;
414 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000415};
416
Eric Andersencffd5022002-05-24 06:50:15 +0000417#ifdef ARCHDATAM
418#define ARCHDATA_SEC_NAME ARCHDATAM
419#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000420#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000421#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000422#define KALLSYMS_SEC_NAME "__kallsyms"
423
424
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000425struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000426 unsigned long addr;
427 unsigned long size;
428 unsigned long flags;
429 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000430};
431
432/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000433enum {
434 NEW_MOD_RUNNING = 1,
435 NEW_MOD_DELETED = 2,
436 NEW_MOD_AUTOCLEAN = 4,
437 NEW_MOD_VISITED = 8,
438 NEW_MOD_USED_ONCE = 16
439};
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersencb3b9b12004-06-22 11:50:52 +0000441int init_module(const char *name, const struct new_module *);
442int query_module(const char *name, int which, void *buf,
443 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000444
445/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000446enum {
447 QM_MODULES = 1,
448 QM_DEPS = 2,
449 QM_REFS = 3,
450 QM_SYMBOLS = 4,
451 QM_INFO = 5
452};
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
454/*======================================================================*/
455/* The system calls unchanged between 2.0 and 2.1. */
456
457unsigned long create_module(const char *, size_t);
458int delete_module(const char *);
459
460
461#endif /* module.h */
462
463//----------------------------------------------------------------------------
464//--------end of modutils module.h
465//----------------------------------------------------------------------------
466
467
468
469//----------------------------------------------------------------------------
470//--------modutils obj.h, lines 253-462
471//----------------------------------------------------------------------------
472
473/* Elf object file loading and relocation routines.
474 Copyright 1996, 1997 Linux International.
475
476 Contributed by Richard Henderson <rth@tamu.edu>
477
478 This file is part of the Linux modutils.
479
480 This program is free software; you can redistribute it and/or modify it
481 under the terms of the GNU General Public License as published by the
482 Free Software Foundation; either version 2 of the License, or (at your
483 option) any later version.
484
485 This program is distributed in the hope that it will be useful, but
486 WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 General Public License for more details.
489
490 You should have received a copy of the GNU General Public License
491 along with this program; if not, write to the Free Software Foundation,
492 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
493
494
495#ifndef MODUTILS_OBJ_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000496/* Why? static const int MODUTILS_OBJ_H = 1; */
Eric Andersen9f16d612000-06-12 23:11:16 +0000497
Eric Andersen9f16d612000-06-12 23:11:16 +0000498/* The relocatable object is manipulated using elfin types. */
499
500#include <stdio.h>
501#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000502#include <endian.h>
503
Eric Andersen9f16d612000-06-12 23:11:16 +0000504#ifndef ElfW
505# if ELFCLASSM == ELFCLASS32
506# define ElfW(x) Elf32_ ## x
507# define ELFW(x) ELF32_ ## x
508# else
509# define ElfW(x) Elf64_ ## x
510# define ELFW(x) ELF64_ ## x
511# endif
512#endif
513
Eric Andersen85e5e722003-07-22 08:56:55 +0000514/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000515#ifndef ELF32_ST_INFO
516# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
517#endif
518
519#ifndef ELF64_ST_INFO
520# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
521#endif
522
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000523#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
524#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
525#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
526#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
527#define ELF_R_SYM(val) ELFW(R_SYM)(val)
528
Eric Andersen9f16d612000-06-12 23:11:16 +0000529struct obj_string_patch;
530struct obj_symbol_patch;
531
532struct obj_section
533{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000534 ElfW(Shdr) header;
535 const char *name;
536 char *contents;
537 struct obj_section *load_next;
538 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000539};
540
541struct obj_symbol
542{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000543 struct obj_symbol *next; /* hash table link */
544 const char *name;
545 unsigned long value;
546 unsigned long size;
547 int secidx; /* the defining section index/module */
548 int info;
549 int ksymidx; /* for export to the kernel symtab */
550 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000551};
552
553/* Hardcode the hash table size. We shouldn't be needing so many
554 symbols that we begin to degrade performance, and we get a big win
555 by giving the compiler a constant divisor. */
556
557#define HASH_BUCKETS 521
558
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000559struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000560 ElfW(Ehdr) header;
561 ElfW(Addr) baseaddr;
562 struct obj_section **sections;
563 struct obj_section *load_order;
564 struct obj_section **load_order_search_start;
565 struct obj_string_patch *string_patches;
566 struct obj_symbol_patch *symbol_patches;
567 int (*symbol_cmp)(const char *, const char *);
568 unsigned long (*symbol_hash)(const char *);
569 unsigned long local_symtab_size;
570 struct obj_symbol **local_symtab;
571 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000572};
573
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000574enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000575 obj_reloc_ok,
576 obj_reloc_overflow,
577 obj_reloc_dangerous,
578 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000579};
580
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000581struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000582 struct obj_string_patch *next;
583 int reloc_secidx;
584 ElfW(Addr) reloc_offset;
585 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000586};
587
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000588struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000589 struct obj_symbol_patch *next;
590 int reloc_secidx;
591 ElfW(Addr) reloc_offset;
592 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000593};
594
595
596/* Generic object manipulation routines. */
597
Eric Andersen044228d2001-07-17 01:12:36 +0000598static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000599
Eric Andersen044228d2001-07-17 01:12:36 +0000600static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000601
Eric Andersen044228d2001-07-17 01:12:36 +0000602static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000603 const char *name);
604
Eric Andersen044228d2001-07-17 01:12:36 +0000605static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000606 struct obj_symbol *sym);
607
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000608#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000609static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000610 int (*cmp)(const char *, const char *),
611 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000612#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000613
Eric Andersen044228d2001-07-17 01:12:36 +0000614static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000615 const char *name);
616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000618 struct obj_section *sec);
619
Eric Andersen044228d2001-07-17 01:12:36 +0000620static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000621 const char *name,
622 unsigned long align,
623 unsigned long size);
624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000626 const char *name,
627 unsigned long align,
628 unsigned long size);
629
Eric Andersen044228d2001-07-17 01:12:36 +0000630static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000631
Eric Andersen044228d2001-07-17 01:12:36 +0000632static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000633 const char *string);
634
Eric Andersen044228d2001-07-17 01:12:36 +0000635static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000636 struct obj_symbol *sym);
637
Eric Andersen044228d2001-07-17 01:12:36 +0000638static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000639
Eric Andersen044228d2001-07-17 01:12:36 +0000640static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000641
Eric Andersen044228d2001-07-17 01:12:36 +0000642static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000645
Eric Andersen044228d2001-07-17 01:12:36 +0000646static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000647
Eric Andersen044228d2001-07-17 01:12:36 +0000648static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000649
650/* Architecture specific manipulation routines. */
651
Eric Andersen044228d2001-07-17 01:12:36 +0000652static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000653
Eric Andersen044228d2001-07-17 01:12:36 +0000654static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000655
Eric Andersen044228d2001-07-17 01:12:36 +0000656static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000659 struct obj_section *targsec,
660 struct obj_section *symsec,
661 struct obj_symbol *sym,
662 ElfW(RelM) *rel, ElfW(Addr) value);
663
Eric Andersencffd5022002-05-24 06:50:15 +0000664static void arch_create_got (struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000665#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000666static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000667#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000668#endif /* obj.h */
669//----------------------------------------------------------------------------
670//--------end of modutils obj.h
671//----------------------------------------------------------------------------
672
673
Miles Baderae28b042002-04-01 09:34:25 +0000674/* SPFX is always a string, so it can be concatenated to string constants. */
675#ifdef SYMBOL_PREFIX
676#define SPFX SYMBOL_PREFIX
677#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000678#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000679#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000680
Erik Andersen02104321999-12-17 18:57:34 +0000681
Erik Andersend387d011999-12-21 02:55:11 +0000682#define _PATH_MODULES "/lib/modules"
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000683enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000684
Eric Andersen9f16d612000-06-12 23:11:16 +0000685/*======================================================================*/
686
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000687#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
688enum {
689 OPT_s = 0x1, // -s /* log to syslog */
690 /* Not supported but kernel needs this for request_module(),
691 as this calls: modprobe -k -s -- <module>
692 so silently ignore this flag */
693 OPT_L = 0x2, // -L /* Stub warning */
694 /* Compatibility with modprobe.
695 In theory, this does locking, but we don't do
696 that. So be careful and plan your life around not
697 loading the same module 50 times concurrently. */
698 OPT_o = 0x4, // -o /* name the output module */
699 OPT_f = 0x8, // -f /* force loading */
700 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
701 OPT_v = 0x20, // -v /* verbose output */
702 OPT_q = 0x40, // -q /* silent */
703 OPT_x = 0x80, // -x /* do not export externs */
704 OPT_m = 0x100, // -m /* print module load map */
705};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000706#define flag_force_load (option_mask32 & OPT_f)
707#define flag_autoclean (option_mask32 & OPT_k)
708#define flag_verbose (option_mask32 & OPT_v)
709#define flag_quiet (option_mask32 & OPT_q)
710#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000711#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000712#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000713#else
714#define flag_print_load_map 0
715#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000716
717/*======================================================================*/
718
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000719#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000720
Eric Andersencffd5022002-05-24 06:50:15 +0000721struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000722{
Eric Andersencffd5022002-05-24 06:50:15 +0000723 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000724 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000725 int offset;
726 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000727};
Eric Andersencffd5022002-05-24 06:50:15 +0000728
Eric Andersen21adca72000-12-06 18:18:26 +0000729#endif
730
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000731#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000732
733struct arch_single_entry
734{
Eric Andersen9f16d612000-06-12 23:11:16 +0000735 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000736 int inited : 1;
737 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000738};
Eric Andersencffd5022002-05-24 06:50:15 +0000739
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000740#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000741
Eric Andersen2bf658d2001-02-24 20:01:53 +0000742#if defined(__mips__)
743struct mips_hi16
744{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000745 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000746 ElfW(Addr) *addr;
747 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000748};
749#endif
750
Eric Andersenfe4208f2000-09-24 03:44:29 +0000751struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000752 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000753#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000754 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000755#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000756#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000757 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000758#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000759#if defined(__mips__)
760 struct mips_hi16 *mips_hi16_list;
761#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000762};
763
Eric Andersenfe4208f2000-09-24 03:44:29 +0000764struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000765 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000766#if defined(USE_PLT_ENTRIES)
767#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000768 struct arch_list_entry *pltent;
769#else
770 struct arch_single_entry pltent;
771#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000772#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000773#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000774 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000775#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000776};
777
778
Eric Andersen9f16d612000-06-12 23:11:16 +0000779struct external_module {
780 const char *name;
781 ElfW(Addr) addr;
782 int used;
783 size_t nsyms;
784 struct new_module_symbol *syms;
785};
786
Eric Andersen044228d2001-07-17 01:12:36 +0000787static struct new_module_symbol *ksyms;
788static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000789
Eric Andersen044228d2001-07-17 01:12:36 +0000790static struct external_module *ext_modules;
791static int n_ext_modules;
792static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000793extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000794
Eric Andersen61f83052002-06-22 17:15:42 +0000795static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000796static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000797
Eric Andersenfe4208f2000-09-24 03:44:29 +0000798
Eric Andersen9f16d612000-06-12 23:11:16 +0000799/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000800
Eric Andersen9f16d612000-06-12 23:11:16 +0000801
Eric Andersen14d35432001-05-14 17:07:32 +0000802static int check_module_name_match(const char *filename, struct stat *statbuf,
Denis Vlasenko8c35d652006-10-27 23:42:25 +0000803 void *userdata, int depth)
Eric Andersen9f16d612000-06-12 23:11:16 +0000804{
Eric Andersen14d35432001-05-14 17:07:32 +0000805 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000806
Eric Andersen14d35432001-05-14 17:07:32 +0000807 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000808 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000809 else {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000810 char *tmp, *tmp1 = xstrdup(filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000811 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000812 if (strcmp(tmp, fullname) == 0) {
813 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000814 /* Stop searching if we find a match */
Rob Landleyd921b2e2006-08-03 15:41:12 +0000815 m_filename = xstrdup(filename);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000816 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000817 }
Eric Andersen14d35432001-05-14 17:07:32 +0000818 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000819 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000820 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000821}
822
Erik Andersen02104321999-12-17 18:57:34 +0000823
Eric Andersen9f16d612000-06-12 23:11:16 +0000824/*======================================================================*/
825
Eric Andersen044228d2001-07-17 01:12:36 +0000826static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000827{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000828 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000829 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830
Eric Andersencffd5022002-05-24 06:50:15 +0000831 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000832
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 return &f->root;
834}
835
Eric Andersen044228d2001-07-17 01:12:36 +0000836static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000837{
838 return xmalloc(sizeof(struct obj_section));
839}
840
Eric Andersen044228d2001-07-17 01:12:36 +0000841static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000842{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000843 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000844 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000845
Eric Andersencffd5022002-05-24 06:50:15 +0000846 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000847
Eric Andersen9f16d612000-06-12 23:11:16 +0000848 return &sym->root;
849}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000850
Eric Andersen044228d2001-07-17 01:12:36 +0000851static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000852arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000853 struct obj_section *targsec,
854 struct obj_section *symsec,
855 struct obj_symbol *sym,
856 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000857{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000858 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000859 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000860 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
861 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000862#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000863 struct arch_symbol *isym = (struct arch_symbol *) sym;
864#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000865#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000866#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000867 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000868#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000869#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000870#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000871 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000872 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000873# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000874 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000875# else
Eric Andersencffd5022002-05-24 06:50:15 +0000876 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000877# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000878#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000879
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000880 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000881
Eric Andersencffd5022002-05-24 06:50:15 +0000882#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000883
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 case R_ARM_NONE:
885 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_ABS32:
888 *loc += v;
889 break;
Miles Baderae28b042002-04-01 09:34:25 +0000890
Eric Andersen3b1a7442003-12-24 20:30:45 +0000891 case R_ARM_GOT32:
892 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000893
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000895 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
896 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000898
Eric Andersen3b1a7442003-12-24 20:30:45 +0000899 *loc += got - dot;
900 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000901
Eric Andersen3b1a7442003-12-24 20:30:45 +0000902 case R_ARM_PC24:
903 case R_ARM_PLT32:
904 goto bb_use_plt;
905
906 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000907 *loc += v - got;
908 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000909
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000910#elif defined(__cris__)
911
912 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000913 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000914
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915 case R_CRIS_32:
916 /* CRIS keeps the relocation value in the r_addend field and
917 * should not use whats in *loc at all
918 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000919 *loc = v;
920 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000921
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000922#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000923
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000924 case R_H8_DIR24R8:
925 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
926 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000927 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000928 case R_H8_DIR24A8:
929 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000930 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000931 case R_H8_DIR32:
932 case R_H8_DIR32A16:
933 *loc += v;
934 break;
935 case R_H8_PCREL16:
936 v -= dot + 2;
937 if ((ElfW(Sword))v > 0x7fff ||
938 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
939 ret = obj_reloc_overflow;
940 else
941 *(unsigned short *)loc = v;
942 break;
943 case R_H8_PCREL8:
944 v -= dot + 1;
945 if ((ElfW(Sword))v > 0x7f ||
946 (ElfW(Sword))v < -(ElfW(Sword))0x80)
947 ret = obj_reloc_overflow;
948 else
949 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000950 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000951
Eric Andersencffd5022002-05-24 06:50:15 +0000952#elif defined(__i386__)
953
Eric Andersen3b1a7442003-12-24 20:30:45 +0000954 case R_386_NONE:
955 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000956
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 case R_386_32:
958 *loc += v;
959 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000960
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 case R_386_PLT32:
962 case R_386_PC32:
963 *loc += v - dot;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GLOB_DAT:
967 case R_386_JMP_SLOT:
968 *loc = v;
969 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000970
Eric Andersen3b1a7442003-12-24 20:30:45 +0000971 case R_386_RELATIVE:
972 *loc += f->baseaddr;
973 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000974
Eric Andersen3b1a7442003-12-24 20:30:45 +0000975 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000976 *loc += got - dot;
977 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000978
Eric Andersen3b1a7442003-12-24 20:30:45 +0000979 case R_386_GOT32:
980 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000981
Eric Andersen3b1a7442003-12-24 20:30:45 +0000982 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 *loc += v - got;
984 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000985
Mike Frysinger280dae72006-06-06 06:30:32 +0000986#elif defined (__microblaze__)
987 case R_MICROBLAZE_NONE:
988 case R_MICROBLAZE_64_NONE:
989 case R_MICROBLAZE_32_SYM_OP_SYM:
990 case R_MICROBLAZE_32_PCREL:
991 break;
992
993 case R_MICROBLAZE_64_PCREL: {
994 /* dot is the address of the current instruction.
995 * v is the target symbol address.
996 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000997 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000998 * of this instruction.
999 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
1000 */
1001
1002 /* Get split offset stored in code */
1003 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
1004 (loc[1] & 0xFFFF);
1005
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001006 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +00001007 * because dot points to the IMM insn, but branch
1008 * is computed relative to the branch instruction itself.
1009 */
1010 temp += v - dot - 4;
1011
1012 /* Store back into code */
1013 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1014 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1015
1016 break;
1017 }
1018
1019 case R_MICROBLAZE_32:
1020 *loc += v;
1021 break;
1022
1023 case R_MICROBLAZE_64: {
1024 /* Get split pointer stored in code */
1025 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1026 (loc[1] & 0xFFFF);
1027
1028 /* Add reloc offset */
1029 temp1+=v;
1030
1031 /* Store back into code */
1032 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1033 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1034
1035 break;
1036 }
1037
1038 case R_MICROBLAZE_32_PCREL_LO:
1039 case R_MICROBLAZE_32_LO:
1040 case R_MICROBLAZE_SRO32:
1041 case R_MICROBLAZE_SRW32:
1042 ret = obj_reloc_unhandled;
1043 break;
1044
Eric Andersencffd5022002-05-24 06:50:15 +00001045#elif defined(__mc68000__)
1046
Eric Andersen3b1a7442003-12-24 20:30:45 +00001047 case R_68K_NONE:
1048 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001049
Eric Andersen3b1a7442003-12-24 20:30:45 +00001050 case R_68K_32:
1051 *loc += v;
1052 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001053
Eric Andersen3b1a7442003-12-24 20:30:45 +00001054 case R_68K_8:
1055 if (v > 0xff) {
1056 ret = obj_reloc_overflow;
1057 }
1058 *(char *)loc = v;
1059 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001060
Eric Andersen3b1a7442003-12-24 20:30:45 +00001061 case R_68K_16:
1062 if (v > 0xffff) {
1063 ret = obj_reloc_overflow;
1064 }
1065 *(short *)loc = v;
1066 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001067
Eric Andersen3b1a7442003-12-24 20:30:45 +00001068 case R_68K_PC8:
1069 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001070 if ((ElfW(Sword))v > 0x7f ||
1071 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001072 ret = obj_reloc_overflow;
1073 }
1074 *(char *)loc = v;
1075 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001076
Eric Andersen3b1a7442003-12-24 20:30:45 +00001077 case R_68K_PC16:
1078 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001079 if ((ElfW(Sword))v > 0x7fff ||
1080 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001081 ret = obj_reloc_overflow;
1082 }
1083 *(short *)loc = v;
1084 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_68K_PC32:
1087 *(int *)loc = v - dot;
1088 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001089
Eric Andersen3b1a7442003-12-24 20:30:45 +00001090 case R_68K_GLOB_DAT:
1091 case R_68K_JMP_SLOT:
1092 *loc = v;
1093 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001094
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095 case R_68K_RELATIVE:
1096 *(int *)loc += f->baseaddr;
1097 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001098
Eric Andersen3b1a7442003-12-24 20:30:45 +00001099 case R_68K_GOT32:
1100 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001101
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001102# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001103 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 *loc += v - got;
1105 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +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;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001145 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001146
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
Eric Andersen3b1a7442003-12-24 20:30:45 +00001158 /* Do the HI16 relocation. Note that we actually don't
1159 need to know anything about the LO16 itself, except where
1160 to find the low 16 bits of the addend needed by the LO16. */
1161 insn = *l->addr;
1162 val =
1163 ((insn & 0xffff) << 16) +
1164 vallo;
1165 val += v;
1166
1167 /* Account for the sign extension that will happen in the
1168 low bits. */
1169 val =
1170 ((val >> 16) +
1171 ((val & 0x8000) !=
1172 0)) & 0xffff;
1173
1174 insn = (insn & ~0xffff) | val;
1175 *l->addr = insn;
1176
1177 next = l->next;
1178 free(l);
1179 l = next;
1180 }
1181
1182 ifile->mips_hi16_list = NULL;
1183 }
1184
1185 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1186 val = v + vallo;
1187 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1188 *loc = insnlo;
1189 break;
1190 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001191
Mike Frysingerf982d862006-01-04 00:11:26 +00001192#elif defined(__nios2__)
1193
1194 case R_NIOS2_NONE:
1195 break;
1196
1197 case R_NIOS2_BFD_RELOC_32:
1198 *loc += v;
1199 break;
1200
1201 case R_NIOS2_BFD_RELOC_16:
1202 if (v > 0xffff) {
1203 ret = obj_reloc_overflow;
1204 }
1205 *(short *)loc = v;
1206 break;
1207
1208 case R_NIOS2_BFD_RELOC_8:
1209 if (v > 0xff) {
1210 ret = obj_reloc_overflow;
1211 }
1212 *(char *)loc = v;
1213 break;
1214
1215 case R_NIOS2_S16:
1216 {
1217 Elf32_Addr word;
1218
1219 if ((Elf32_Sword)v > 0x7fff ||
1220 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1221 ret = obj_reloc_overflow;
1222 }
1223
1224 word = *loc;
1225 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1226 (word & 0x3f);
1227 }
1228 break;
1229
1230 case R_NIOS2_U16:
1231 {
1232 Elf32_Addr word;
1233
1234 if (v > 0xffff) {
1235 ret = obj_reloc_overflow;
1236 }
1237
1238 word = *loc;
1239 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1240 (word & 0x3f);
1241 }
1242 break;
1243
1244 case R_NIOS2_PCREL16:
1245 {
1246 Elf32_Addr word;
1247
1248 v -= dot + 4;
1249 if ((Elf32_Sword)v > 0x7fff ||
1250 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1251 ret = obj_reloc_overflow;
1252 }
1253
1254 word = *loc;
1255 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1256 }
1257 break;
1258
1259 case R_NIOS2_GPREL:
1260 {
1261 Elf32_Addr word, gp;
1262 /* get _gp */
1263 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1264 v-=gp;
1265 if ((Elf32_Sword)v > 0x7fff ||
1266 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1267 ret = obj_reloc_overflow;
1268 }
1269
1270 word = *loc;
1271 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1272 }
1273 break;
1274
1275 case R_NIOS2_CALL26:
1276 if (v & 3)
1277 ret = obj_reloc_dangerous;
1278 if ((v >> 28) != (dot >> 28))
1279 ret = obj_reloc_overflow;
1280 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1281 break;
1282
1283 case R_NIOS2_IMM5:
1284 {
1285 Elf32_Addr word;
1286
1287 if (v > 0x1f) {
1288 ret = obj_reloc_overflow;
1289 }
1290
1291 word = *loc & ~0x7c0;
1292 *loc = word | ((v & 0x1f) << 6);
1293 }
1294 break;
1295
1296 case R_NIOS2_IMM6:
1297 {
1298 Elf32_Addr word;
1299
1300 if (v > 0x3f) {
1301 ret = obj_reloc_overflow;
1302 }
1303
1304 word = *loc & ~0xfc0;
1305 *loc = word | ((v & 0x3f) << 6);
1306 }
1307 break;
1308
1309 case R_NIOS2_IMM8:
1310 {
1311 Elf32_Addr word;
1312
1313 if (v > 0xff) {
1314 ret = obj_reloc_overflow;
1315 }
1316
1317 word = *loc & ~0x3fc0;
1318 *loc = word | ((v & 0xff) << 6);
1319 }
1320 break;
1321
1322 case R_NIOS2_HI16:
1323 {
1324 Elf32_Addr word;
1325
1326 word = *loc;
1327 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1328 (word & 0x3f);
1329 }
1330 break;
1331
1332 case R_NIOS2_LO16:
1333 {
1334 Elf32_Addr word;
1335
1336 word = *loc;
1337 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1338 (word & 0x3f);
1339 }
1340 break;
1341
1342 case R_NIOS2_HIADJ16:
1343 {
1344 Elf32_Addr word1, word2;
1345
1346 word1 = *loc;
1347 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1348 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1349 (word1 & 0x3f);
1350 }
1351 break;
1352
Mike Frysingerebee0e72006-02-18 06:14:31 +00001353#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001354 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001355
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001356#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001357
Eric Andersen3b1a7442003-12-24 20:30:45 +00001358 case R_PPC_ADDR16_HA:
1359 *(unsigned short *)loc = (v + 0x8000) >> 16;
1360 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001361
Eric Andersen3b1a7442003-12-24 20:30:45 +00001362 case R_PPC_ADDR16_HI:
1363 *(unsigned short *)loc = v >> 16;
1364 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001365
Eric Andersen3b1a7442003-12-24 20:30:45 +00001366 case R_PPC_ADDR16_LO:
1367 *(unsigned short *)loc = v;
1368 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001369
Eric Andersen3b1a7442003-12-24 20:30:45 +00001370 case R_PPC_REL24:
1371 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001372
Eric Andersen3b1a7442003-12-24 20:30:45 +00001373 case R_PPC_REL32:
1374 *loc = v - dot;
1375 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001376
Eric Andersen3b1a7442003-12-24 20:30:45 +00001377 case R_PPC_ADDR32:
1378 *loc = v;
1379 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001380
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001381#elif defined(__s390__)
1382
1383 case R_390_32:
1384 *(unsigned int *) loc += v;
1385 break;
1386 case R_390_16:
1387 *(unsigned short *) loc += v;
1388 break;
1389 case R_390_8:
1390 *(unsigned char *) loc += v;
1391 break;
1392
1393 case R_390_PC32:
1394 *(unsigned int *) loc += v - dot;
1395 break;
1396 case R_390_PC16DBL:
1397 *(unsigned short *) loc += (v - dot) >> 1;
1398 break;
1399 case R_390_PC16:
1400 *(unsigned short *) loc += v - dot;
1401 break;
1402
1403 case R_390_PLT32:
1404 case R_390_PLT16DBL:
1405 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001406 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001407 if (pe->inited == 0) {
1408 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1409 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1410 ip[1] = 0x100607f1;
1411 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1412 ip[2] = v - 2;
1413 else
1414 ip[2] = v;
1415 pe->inited = 1;
1416 }
1417
1418 /* Insert relative distance to target. */
1419 v = plt + pe->offset - dot;
1420 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1421 *(unsigned int *) loc = (unsigned int) v;
1422 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1423 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1424 break;
1425
1426 case R_390_GLOB_DAT:
1427 case R_390_JMP_SLOT:
1428 *loc = v;
1429 break;
1430
1431 case R_390_RELATIVE:
1432 *loc += f->baseaddr;
1433 break;
1434
1435 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001436 *(unsigned long *) loc += got - dot;
1437 break;
1438
1439 case R_390_GOT12:
1440 case R_390_GOT16:
1441 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001442 if (!isym->gotent.inited)
1443 {
1444 isym->gotent.inited = 1;
1445 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1446 }
1447 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1448 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1449 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1450 *(unsigned short *) loc += isym->gotent.offset;
1451 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1452 *(unsigned int *) loc += isym->gotent.offset;
1453 break;
1454
1455# ifndef R_390_GOTOFF32
1456# define R_390_GOTOFF32 R_390_GOTOFF
1457# endif
1458 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001459 *loc += v - got;
1460 break;
1461
Eric Andersencffd5022002-05-24 06:50:15 +00001462#elif defined(__sh__)
1463
Eric Andersen3b1a7442003-12-24 20:30:45 +00001464 case R_SH_NONE:
1465 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001466
Eric Andersen3b1a7442003-12-24 20:30:45 +00001467 case R_SH_DIR32:
1468 *loc += v;
1469 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001470
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 case R_SH_REL32:
1472 *loc += v - dot;
1473 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001474
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 case R_SH_PLT32:
1476 *loc = v - dot;
1477 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 case R_SH_GLOB_DAT:
1480 case R_SH_JMP_SLOT:
1481 *loc = v;
1482 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001483
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 case R_SH_RELATIVE:
1485 *loc = f->baseaddr + rel->r_addend;
1486 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001487
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 *loc = got - dot + rel->r_addend;
1490 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001491
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492 case R_SH_GOT32:
1493 goto bb_use_got;
1494
1495 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001496 *loc = v - got;
1497 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001498
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001499# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001500 case R_SH_IMM_MEDLOW16:
1501 case R_SH_IMM_LOW16:
1502 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001503 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001504
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001505 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001507
Eric Andersen3b1a7442003-12-24 20:30:45 +00001508 /*
1509 * movi and shori have the format:
1510 *
1511 * | op | imm | reg | reserved |
1512 * 31..26 25..10 9.. 4 3 .. 0
1513 *
1514 * so we simply mask and or in imm.
1515 */
1516 word = *loc & ~0x3fffc00;
1517 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001518
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001520
Eric Andersen3b1a7442003-12-24 20:30:45 +00001521 break;
1522 }
Eric Andersenbf833552003-08-13 19:56:33 +00001523
Eric Andersen3b1a7442003-12-24 20:30:45 +00001524 case R_SH_IMM_MEDLOW16_PCREL:
1525 case R_SH_IMM_LOW16_PCREL:
1526 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001527 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001528
Eric Andersen3b1a7442003-12-24 20:30:45 +00001529 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001530
Eric Andersen3b1a7442003-12-24 20:30:45 +00001531 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001532
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001533 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001534 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001535
Eric Andersen3b1a7442003-12-24 20:30:45 +00001536 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001537
Eric Andersen3b1a7442003-12-24 20:30:45 +00001538 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001539
Eric Andersen3b1a7442003-12-24 20:30:45 +00001540 break;
1541 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001542# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001543
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001544#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001545
Eric Andersen3b1a7442003-12-24 20:30:45 +00001546 case R_V850_NONE:
1547 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001548
Eric Andersen3b1a7442003-12-24 20:30:45 +00001549 case R_V850_32:
1550 /* We write two shorts instead of a long because even
1551 32-bit insns only need half-word alignment, but
1552 32-bit data needs to be long-word aligned. */
1553 v += ((unsigned short *)loc)[0];
1554 v += ((unsigned short *)loc)[1] << 16;
1555 ((unsigned short *)loc)[0] = v & 0xffff;
1556 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1557 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001558
Eric Andersen3b1a7442003-12-24 20:30:45 +00001559 case R_V850_22_PCREL:
1560 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001561
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001562#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001563
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001564 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001565 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001566
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001567 case R_X86_64_64:
1568 *loc += v;
1569 break;
1570
1571 case R_X86_64_32:
1572 *(unsigned int *) loc += v;
1573 if (v > 0xffffffff)
1574 {
1575 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1576 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1577 }
1578 break;
1579
1580 case R_X86_64_32S:
1581 *(signed int *) loc += v;
1582 break;
1583
1584 case R_X86_64_16:
1585 *(unsigned short *) loc += v;
1586 break;
1587
1588 case R_X86_64_8:
1589 *(unsigned char *) loc += v;
1590 break;
1591
1592 case R_X86_64_PC32:
1593 *(unsigned int *) loc += v - dot;
1594 break;
1595
1596 case R_X86_64_PC16:
1597 *(unsigned short *) loc += v - dot;
1598 break;
1599
1600 case R_X86_64_PC8:
1601 *(unsigned char *) loc += v - dot;
1602 break;
1603
1604 case R_X86_64_GLOB_DAT:
1605 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001606 *loc = v;
1607 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001608
1609 case R_X86_64_RELATIVE:
1610 *loc += f->baseaddr;
1611 break;
1612
1613 case R_X86_64_GOT32:
1614 case R_X86_64_GOTPCREL:
1615 goto bb_use_got;
1616# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001617 if (!isym->gotent.reloc_done)
1618 {
1619 isym->gotent.reloc_done = 1;
1620 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1621 }
1622 /* XXX are these really correct? */
1623 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1624 *(unsigned int *) loc += v + isym->gotent.offset;
1625 else
1626 *loc += isym->gotent.offset;
1627 break;
1628# endif
1629
Mike Frysingerf982d862006-01-04 00:11:26 +00001630#else
1631# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001632#endif
1633
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001634 default:
1635 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1636 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001637 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001638
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001639#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001640
Eric Andersen3b1a7442003-12-24 20:30:45 +00001641bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001642
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001644
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001645#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1647 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001648#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001650#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001651
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 if (! pe->inited) {
1653 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001654
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001656
1657#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1659 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001660#endif
1661#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001662 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001663 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001664 ip[2] = 0x7d6903a6; /* mtctr r11 */
1665 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001666#endif
Miles Baderae28b042002-04-01 09:34:25 +00001667#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001668 /* We have to trash a register, so we assume that any control
1669 transfer more than 21-bits away must be a function call
1670 (so we can use a call-clobbered register). */
1671 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1672 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001673#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674 pe->inited = 1;
1675 }
Eric Andersen21adca72000-12-06 18:18:26 +00001676
Eric Andersen3b1a7442003-12-24 20:30:45 +00001677 /* relative distance to target */
1678 v -= dot;
1679 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001680#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001681 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001682#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001683 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001684#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001685 /* go via the plt */
1686 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001687
1688#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001689 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001690#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001691 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001692#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001693 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001694
Eric Andersen3b1a7442003-12-24 20:30:45 +00001695 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001696#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001697 /* Convert to words. */
1698 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001699
Eric Andersen3b1a7442003-12-24 20:30:45 +00001700 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001701#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001702#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001703 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001704#endif
Miles Baderae28b042002-04-01 09:34:25 +00001705#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001706 /* We write two shorts instead of a long because even 32-bit insns
1707 only need half-word alignment, but the 32-bit data write needs
1708 to be long-word aligned. */
1709 ((unsigned short *)loc)[0] =
1710 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1711 | ((v >> 16) & 0x3f); /* offs high part */
1712 ((unsigned short *)loc)[1] =
1713 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001714#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001715 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001716#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001717
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001718#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001719bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001720
Eric Andersen3b1a7442003-12-24 20:30:45 +00001721 /* needs an entry in the .got: set it, once */
1722 if (!isym->gotent.inited) {
1723 isym->gotent.inited = 1;
1724 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1725 }
1726 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001727#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001728 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001729#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001730 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001731#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001732 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001733
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001734#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001735 }
1736
1737 return ret;
1738}
1739
Eric Andersencffd5022002-05-24 06:50:15 +00001740
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001741#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001742
1743static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1744 int offset, int size)
1745{
1746 struct arch_list_entry *pe;
1747
1748 for (pe = *list; pe != NULL; pe = pe->next) {
1749 if (pe->addend == rel->r_addend) {
1750 break;
1751 }
1752 }
1753
1754 if (pe == NULL) {
1755 pe = xmalloc(sizeof(struct arch_list_entry));
1756 pe->next = *list;
1757 pe->addend = rel->r_addend;
1758 pe->offset = offset;
1759 pe->inited = 0;
1760 *list = pe;
1761 return size;
1762 }
1763 return 0;
1764}
1765
1766#endif
1767
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001768#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001769
1770static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1771 int offset, int size)
1772{
1773 if (single->allocated == 0) {
1774 single->allocated = 1;
1775 single->offset = offset;
1776 single->inited = 0;
1777 return size;
1778 }
1779 return 0;
1780}
1781
1782#endif
1783
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001784#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001785
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001786static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001787 int offset, int size)
1788{
1789 struct obj_section *myrelsec = obj_find_section(f, name);
1790
1791 if (offset == 0) {
1792 offset += size;
1793 }
1794
1795 if (myrelsec) {
1796 obj_extend_section(myrelsec, offset);
1797 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001798 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001799 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001800 }
1801
1802 return myrelsec;
1803}
1804
1805#endif
1806
1807static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001808{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001809#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001810 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001811 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001812#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001813 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001814#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001815#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001816 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001817#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001818 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001819 ElfW(RelM) *rel, *relend;
1820 ElfW(Sym) *symtab, *extsym;
1821 const char *strtab, *name;
1822 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001823
Eric Andersen21adca72000-12-06 18:18:26 +00001824 for (i = 0; i < f->header.e_shnum; ++i) {
1825 relsec = f->sections[i];
1826 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001827 continue;
1828
Eric Andersen21adca72000-12-06 18:18:26 +00001829 symsec = f->sections[relsec->header.sh_link];
1830 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001831
Eric Andersen21adca72000-12-06 18:18:26 +00001832 rel = (ElfW(RelM) *) relsec->contents;
1833 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1834 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001835 strtab = (const char *) strsec->contents;
1836
1837 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001838 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001839
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001840#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001841 got_allocate = 0;
1842#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001843#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001844 plt_allocate = 0;
1845#endif
1846
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001847 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001848#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001849 case R_ARM_PC24:
1850 case R_ARM_PLT32:
1851 plt_allocate = 1;
1852 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001853
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001854 case R_ARM_GOTOFF:
1855 case R_ARM_GOTPC:
1856 got_needed = 1;
1857 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001858
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001859 case R_ARM_GOT32:
1860 got_allocate = 1;
1861 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001862
Eric Andersen21adca72000-12-06 18:18:26 +00001863#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001864 case R_386_GOTPC:
1865 case R_386_GOTOFF:
1866 got_needed = 1;
1867 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001868
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001869 case R_386_GOT32:
1870 got_allocate = 1;
1871 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001872
1873#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001874 case R_PPC_REL24:
1875 plt_allocate = 1;
1876 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001877
1878#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001879 case R_68K_GOT32:
1880 got_allocate = 1;
1881 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001882
Eric Andersen16451a02004-03-19 12:16:18 +00001883#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001884 case R_68K_GOTOFF:
1885 got_needed = 1;
1886 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001887#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001888
1889#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001890 case R_SH_GOT32:
1891 got_allocate = 1;
1892 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001893
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001894 case R_SH_GOTPC:
1895 case R_SH_GOTOFF:
1896 got_needed = 1;
1897 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001898
1899#elif defined (__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001900 case R_V850_22_PCREL:
1901 plt_needed = 1;
1902 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001903
1904#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001905 default:
1906 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001907 }
1908
Eric Andersen21adca72000-12-06 18:18:26 +00001909 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001910 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001911 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001912 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001913 }
1914 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001915#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001916 if (got_allocate) {
1917 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001918 rel, &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001919 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001920
1921 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001922 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001923#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001924#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001925 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001926#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001927 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001928 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001929 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001930#else
1931 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001932 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001933 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001934#endif
1935 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001936 }
1937#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001938 }
Miles Baderae28b042002-04-01 09:34:25 +00001939 }
Eric Andersen21adca72000-12-06 18:18:26 +00001940
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001941#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001942 if (got_needed) {
1943 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001944 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001945 }
Eric Andersen21adca72000-12-06 18:18:26 +00001946#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001947
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001948#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001949 if (plt_needed) {
1950 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001951 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001952 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001953#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001954
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001955#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001956}
1957
Eric Andersen9f16d612000-06-12 23:11:16 +00001958/*======================================================================*/
1959
1960/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001961static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001962{
1963 unsigned long h = 0;
1964 unsigned long g;
1965 unsigned char ch;
1966
1967 while (n > 0) {
1968 ch = *name++;
1969 h = (h << 4) + ch;
1970 if ((g = (h & 0xf0000000)) != 0) {
1971 h ^= g >> 24;
1972 h &= ~g;
1973 }
1974 n--;
1975 }
1976 return h;
1977}
1978
Eric Andersen044228d2001-07-17 01:12:36 +00001979static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001980{
1981 return obj_elf_hash_n(name, strlen(name));
1982}
1983
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001984#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001985/* String comparison for non-co-versioned kernel and module. */
1986
1987static int ncv_strcmp(const char *a, const char *b)
1988{
1989 size_t alen = strlen(a), blen = strlen(b);
1990
1991 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1992 return strncmp(a, b, alen);
1993 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1994 return strncmp(a, b, blen);
1995 else
1996 return strcmp(a, b);
1997}
1998
1999/* String hashing for non-co-versioned kernel and module. Here
2000 we are simply forced to drop the crc from the hash. */
2001
2002static unsigned long ncv_symbol_hash(const char *str)
2003{
2004 size_t len = strlen(str);
2005 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2006 len -= 10;
2007 return obj_elf_hash_n(str, len);
2008}
2009
Eric Andersen044228d2001-07-17 01:12:36 +00002010static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002011obj_set_symbol_compare(struct obj_file *f,
2012 int (*cmp) (const char *, const char *),
2013 unsigned long (*hash) (const char *))
2014{
2015 if (cmp)
2016 f->symbol_cmp = cmp;
2017 if (hash) {
2018 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2019 int i;
2020
2021 f->symbol_hash = hash;
2022
2023 memcpy(tmptab, f->symtab, sizeof(tmptab));
2024 memset(f->symtab, 0, sizeof(f->symtab));
2025
2026 for (i = 0; i < HASH_BUCKETS; ++i)
2027 for (sym = tmptab[i]; sym; sym = next) {
2028 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2029 next = sym->next;
2030 sym->next = f->symtab[h];
2031 f->symtab[h] = sym;
2032 }
2033 }
2034}
2035
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002036#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002037
Eric Andersen044228d2001-07-17 01:12:36 +00002038static struct obj_symbol *
2039obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002040 unsigned long symidx, int info,
2041 int secidx, ElfW(Addr) value,
2042 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002043{
2044 struct obj_symbol *sym;
2045 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002046 int n_type = ELF_ST_TYPE(info);
2047 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002048
2049 for (sym = f->symtab[hash]; sym; sym = sym->next)
2050 if (f->symbol_cmp(sym->name, name) == 0) {
2051 int o_secidx = sym->secidx;
2052 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002053 int o_type = ELF_ST_TYPE(o_info);
2054 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002055
2056 /* A redefinition! Is it legal? */
2057
2058 if (secidx == SHN_UNDEF)
2059 return sym;
2060 else if (o_secidx == SHN_UNDEF)
2061 goto found;
2062 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2063 /* Cope with local and global symbols of the same name
2064 in the same object file, as might have been created
2065 by ld -r. The only reason locals are now seen at this
2066 level at all is so that we can do semi-sensible things
2067 with parameters. */
2068
2069 struct obj_symbol *nsym, **p;
2070
2071 nsym = arch_new_symbol();
2072 nsym->next = sym->next;
2073 nsym->ksymidx = -1;
2074
2075 /* Excise the old (local) symbol from the hash chain. */
2076 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2077 continue;
2078 *p = sym = nsym;
2079 goto found;
2080 } else if (n_binding == STB_LOCAL) {
2081 /* Another symbol of the same name has already been defined.
2082 Just add this to the local table. */
2083 sym = arch_new_symbol();
2084 sym->next = NULL;
2085 sym->ksymidx = -1;
2086 f->local_symtab[symidx] = sym;
2087 goto found;
2088 } else if (n_binding == STB_WEAK)
2089 return sym;
2090 else if (o_binding == STB_WEAK)
2091 goto found;
2092 /* Don't unify COMMON symbols with object types the programmer
2093 doesn't expect. */
2094 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002095 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002096 return sym;
2097 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002098 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002099 goto found;
2100 else {
2101 /* Don't report an error if the symbol is coming from
2102 the kernel or some external module. */
2103 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002104 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002105 return sym;
2106 }
2107 }
2108
2109 /* Completely new symbol. */
2110 sym = arch_new_symbol();
2111 sym->next = f->symtab[hash];
2112 f->symtab[hash] = sym;
2113 sym->ksymidx = -1;
2114
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002115 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002116 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002117 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002118 name, (long) symidx, (long) f->local_symtab_size);
2119 else
2120 f->local_symtab[symidx] = sym;
2121 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002122
Eric Andersen3b1a7442003-12-24 20:30:45 +00002123found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002124 sym->name = name;
2125 sym->value = value;
2126 sym->size = size;
2127 sym->secidx = secidx;
2128 sym->info = info;
2129
2130 return sym;
2131}
2132
Eric Andersen044228d2001-07-17 01:12:36 +00002133static struct obj_symbol *
2134obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002135{
2136 struct obj_symbol *sym;
2137 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2138
2139 for (sym = f->symtab[hash]; sym; sym = sym->next)
2140 if (f->symbol_cmp(sym->name, name) == 0)
2141 return sym;
2142
2143 return NULL;
2144}
2145
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002146static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002147{
2148 if (sym) {
2149 if (sym->secidx >= SHN_LORESERVE)
2150 return sym->value;
2151
2152 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2153 } else {
2154 /* As a special case, a NULL sym has value zero. */
2155 return 0;
2156 }
2157}
2158
Eric Andersen044228d2001-07-17 01:12:36 +00002159static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002160{
2161 int i, n = f->header.e_shnum;
2162
2163 for (i = 0; i < n; ++i)
2164 if (strcmp(f->sections[i]->name, name) == 0)
2165 return f->sections[i];
2166
2167 return NULL;
2168}
2169
2170static int obj_load_order_prio(struct obj_section *a)
2171{
2172 unsigned long af, ac;
2173
2174 af = a->header.sh_flags;
2175
2176 ac = 0;
2177 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002178 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002179 ac |= 32;
2180 if (af & SHF_ALLOC)
2181 ac |= 16;
2182 if (!(af & SHF_WRITE))
2183 ac |= 8;
2184 if (af & SHF_EXECINSTR)
2185 ac |= 4;
2186 if (a->header.sh_type != SHT_NOBITS)
2187 ac |= 2;
2188
2189 return ac;
2190}
2191
Eric Andersen044228d2001-07-17 01:12:36 +00002192static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002193obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2194{
2195 struct obj_section **p;
2196 int prio = obj_load_order_prio(sec);
2197 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2198 if (obj_load_order_prio(*p) < prio)
2199 break;
2200 sec->load_next = *p;
2201 *p = sec;
2202}
2203
Eric Andersen044228d2001-07-17 01:12:36 +00002204static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002205 const char *name,
2206 unsigned long align,
2207 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002208{
2209 int newidx = f->header.e_shnum++;
2210 struct obj_section *sec;
2211
2212 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2213 f->sections[newidx] = sec = arch_new_section();
2214
2215 memset(sec, 0, sizeof(*sec));
2216 sec->header.sh_type = SHT_PROGBITS;
2217 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2218 sec->header.sh_size = size;
2219 sec->header.sh_addralign = align;
2220 sec->name = name;
2221 sec->idx = newidx;
2222 if (size)
2223 sec->contents = xmalloc(size);
2224
2225 obj_insert_section_load_order(f, sec);
2226
2227 return sec;
2228}
2229
Eric Andersen044228d2001-07-17 01:12:36 +00002230static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002231 const char *name,
2232 unsigned long align,
2233 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002234{
2235 int newidx = f->header.e_shnum++;
2236 struct obj_section *sec;
2237
2238 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2239 f->sections[newidx] = sec = arch_new_section();
2240
2241 memset(sec, 0, sizeof(*sec));
2242 sec->header.sh_type = SHT_PROGBITS;
2243 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2244 sec->header.sh_size = size;
2245 sec->header.sh_addralign = align;
2246 sec->name = name;
2247 sec->idx = newidx;
2248 if (size)
2249 sec->contents = xmalloc(size);
2250
2251 sec->load_next = f->load_order;
2252 f->load_order = sec;
2253 if (f->load_order_search_start == &f->load_order)
2254 f->load_order_search_start = &sec->load_next;
2255
2256 return sec;
2257}
2258
Eric Andersen044228d2001-07-17 01:12:36 +00002259static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002260{
2261 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002262 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002263 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2264 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002265 return sec->contents + oldsize;
2266}
2267
2268
Eric Andersen9f16d612000-06-12 23:11:16 +00002269/* Conditionally add the symbols from the given symbol set to the
2270 new module. */
2271
2272static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002273add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002274 int idx, struct new_module_symbol *syms, size_t nsyms)
2275{
2276 struct new_module_symbol *s;
2277 size_t i;
2278 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002279#ifdef SYMBOL_PREFIX
2280 char *name_buf = 0;
2281 size_t name_alloced_size = 0;
2282#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002283#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002284 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002285
Glenn L McGrath759515c2003-08-30 06:00:33 +00002286 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002287#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002288 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002289 /* Only add symbols that are already marked external.
2290 If we override locals we may cause problems for
2291 argument initialization. We will also create a false
2292 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002293 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002294 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002295
Glenn L McGrath759515c2003-08-30 06:00:33 +00002296 /* GPL licensed modules can use symbols exported with
2297 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2298 * exported names. Non-GPL modules never see any GPLONLY_
2299 * symbols so they cannot fudge it by adding the prefix on
2300 * their references.
2301 */
2302 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002303#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002304 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002305 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002306 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002307#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002308 continue;
2309 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002310 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002311
Miles Baderae28b042002-04-01 09:34:25 +00002312#ifdef SYMBOL_PREFIX
2313 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2314 kernel exports `C names', but module object files
2315 reference `linker names'). */
2316 size_t extra = sizeof SYMBOL_PREFIX;
2317 size_t name_size = strlen (name) + extra;
2318 if (name_size > name_alloced_size) {
2319 name_alloced_size = name_size * 2;
2320 name_buf = alloca (name_alloced_size);
2321 }
2322 strcpy (name_buf, SYMBOL_PREFIX);
2323 strcpy (name_buf + extra - 1, name);
2324 name = name_buf;
2325#endif /* SYMBOL_PREFIX */
2326
2327 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002328 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002329#ifdef SYMBOL_PREFIX
2330 /* Put NAME_BUF into more permanent storage. */
2331 name = xmalloc (name_size);
2332 strcpy (name, name_buf);
2333#endif
2334 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002335 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002336 STT_NOTYPE),
2337 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002338 /* Did our symbol just get installed? If so, mark the
2339 module as "used". */
2340 if (sym->secidx == idx)
2341 used = 1;
2342 }
2343 }
2344
2345 return used;
2346}
2347
2348static void add_kernel_symbols(struct obj_file *f)
2349{
2350 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002351 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002352
2353 /* Add module symbols first. */
2354
2355 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2356 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002357 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2358 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002359
2360 n_ext_modules_used = nused;
2361
2362 /* And finally the symbols from the kernel proper. */
2363
2364 if (nksyms)
2365 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2366}
2367
2368static char *get_modinfo_value(struct obj_file *f, const char *key)
2369{
2370 struct obj_section *sec;
2371 char *p, *v, *n, *ep;
2372 size_t klen = strlen(key);
2373
2374 sec = obj_find_section(f, ".modinfo");
2375 if (sec == NULL)
2376 return NULL;
2377 p = sec->contents;
2378 ep = p + sec->header.sh_size;
2379 while (p < ep) {
2380 v = strchr(p, '=');
2381 n = strchr(p, '\0');
2382 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002383 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002384 return v + 1;
2385 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002386 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002387 return n;
2388 }
2389 p = n + 1;
2390 }
2391
2392 return NULL;
2393}
2394
2395
2396/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002397/* Functions relating to module loading after 2.1.18. */
2398
2399static int
2400new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2401{
2402 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002403 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002404 struct obj_symbol *sym;
2405 char *contents, *loc;
2406 int min, max, n;
2407
2408 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002409 if ((q = strchr(p, '=')) == NULL) {
2410 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002411 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002412 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002413
2414 key = alloca(q - p + 6);
2415 memcpy(key, "parm_", 5);
2416 memcpy(key + 5, p, q - p);
2417 key[q - p + 5] = 0;
2418
2419 p = get_modinfo_value(f, key);
2420 key += 5;
2421 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002422 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002423 return 0;
2424 }
2425
Miles Baderae28b042002-04-01 09:34:25 +00002426#ifdef SYMBOL_PREFIX
2427 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2428 strcpy (sym_name, SYMBOL_PREFIX);
2429 strcat (sym_name, key);
2430#else
2431 sym_name = key;
2432#endif
2433 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002434
2435 /* Also check that the parameter was not resolved from the kernel. */
2436 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002437 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002438 return 0;
2439 }
2440
2441 if (isdigit(*p)) {
2442 min = strtoul(p, &p, 10);
2443 if (*p == '-')
2444 max = strtoul(p + 1, &p, 10);
2445 else
2446 max = min;
2447 } else
2448 min = max = 1;
2449
2450 contents = f->sections[sym->secidx]->contents;
2451 loc = contents + sym->value;
2452 n = (*++q != '\0');
2453
2454 while (1) {
2455 if ((*p == 's') || (*p == 'c')) {
2456 char *str;
2457
2458 /* Do C quoting if we begin with a ", else slurp the lot. */
2459 if (*q == '"') {
2460 char *r;
2461
2462 str = alloca(strlen(q));
2463 for (r = str, q++; *q != '"'; ++q, ++r) {
2464 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002465 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002466 key);
2467 return 0;
2468 } else if (*q == '\\')
2469 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002470 case 'a':
2471 *r = '\a';
2472 break;
2473 case 'b':
2474 *r = '\b';
2475 break;
2476 case 'e':
2477 *r = '\033';
2478 break;
2479 case 'f':
2480 *r = '\f';
2481 break;
2482 case 'n':
2483 *r = '\n';
2484 break;
2485 case 'r':
2486 *r = '\r';
2487 break;
2488 case 't':
2489 *r = '\t';
2490 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002491
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002492 case '0':
2493 case '1':
2494 case '2':
2495 case '3':
2496 case '4':
2497 case '5':
2498 case '6':
2499 case '7':
2500 {
2501 int c = *q - '0';
2502 if (q[1] >= '0' && q[1] <= '7') {
2503 c = (c * 8) + *++q - '0';
2504 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002505 c = (c * 8) + *++q - '0';
2506 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002507 *r = c;
2508 }
2509 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002510
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002511 default:
2512 *r = *q;
2513 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002514 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002515 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002516 }
2517 *r = '\0';
2518 ++q;
2519 } else {
2520 char *r;
2521
2522 /* In this case, the string is not quoted. We will break
2523 it using the coma (like for ints). If the user wants to
2524 include comas in a string, he just has to quote it */
2525
2526 /* Search the next coma */
2527 r = strchr(q, ',');
2528
2529 /* Found ? */
2530 if (r != (char *) NULL) {
2531 /* Recopy the current field */
2532 str = alloca(r - q + 1);
2533 memcpy(str, q, r - q);
2534
Eric Andersenaff114c2004-04-14 17:51:38 +00002535 /* I don't know if it is useful, as the previous case
2536 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002537 str[r - q] = '\0';
2538
2539 /* Keep next fields */
2540 q = r;
2541 } else {
2542 /* last string */
2543 str = q;
2544 q = "";
2545 }
2546 }
2547
2548 if (*p == 's') {
2549 /* Normal string */
2550 obj_string_patch(f, sym->secidx, loc - contents, str);
2551 loc += tgt_sizeof_char_p;
2552 } else {
2553 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002554 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002555
2556 /* Get the size of each member */
2557 /* Probably we should do that outside the loop ? */
2558 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002559 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002560 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002561 return 0;
2562 }
2563 charssize = strtoul(p + 1, (char **) NULL, 10);
2564
2565 /* Check length */
2566 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002567 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002568 charssize - 1);
2569 return 0;
2570 }
2571
2572 /* Copy to location */
2573 strcpy((char *) loc, str);
2574 loc += charssize;
2575 }
2576 } else {
2577 long v = strtoul(q, &q, 0);
2578 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002579 case 'b':
2580 *loc++ = v;
2581 break;
2582 case 'h':
2583 *(short *) loc = v;
2584 loc += tgt_sizeof_short;
2585 break;
2586 case 'i':
2587 *(int *) loc = v;
2588 loc += tgt_sizeof_int;
2589 break;
2590 case 'l':
2591 *(long *) loc = v;
2592 loc += tgt_sizeof_long;
2593 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002594
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002595 default:
2596 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2597 return 0;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002598 }
2599 }
2600
2601retry_end_of_value:
2602 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002603 case '\0':
2604 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002605
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002606 case ' ':
2607 case '\t':
2608 case '\n':
2609 case '\r':
2610 ++q;
2611 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002612
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002613 case ',':
2614 if (++n > max) {
2615 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002616 return 0;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002617 }
2618 ++q;
2619 break;
2620
2621 default:
2622 bb_error_msg("invalid argument syntax for %s", key);
2623 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002624 }
2625 }
2626
Eric Andersen3b1a7442003-12-24 20:30:45 +00002627end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002628 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002629 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002630 return 0;
2631 }
2632
2633 argc--, argv++;
2634 }
2635
2636 return 1;
2637}
2638
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002639#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002640static int new_is_module_checksummed(struct obj_file *f)
2641{
2642 const char *p = get_modinfo_value(f, "using_checksums");
2643 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002644 return xatoi(p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002645 else
2646 return 0;
2647}
2648
2649/* Get the module's kernel version in the canonical integer form. */
2650
2651static int
2652new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2653{
2654 char *p, *q;
2655 int a, b, c;
2656
2657 p = get_modinfo_value(f, "kernel_version");
2658 if (p == NULL)
2659 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002660 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002661
2662 a = strtoul(p, &p, 10);
2663 if (*p != '.')
2664 return -1;
2665 b = strtoul(p + 1, &p, 10);
2666 if (*p != '.')
2667 return -1;
2668 c = strtoul(p + 1, &q, 10);
2669 if (p + 1 == q)
2670 return -1;
2671
2672 return a << 16 | b << 8 | c;
2673}
2674
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002675#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002676
2677
Eric Andersen9f16d612000-06-12 23:11:16 +00002678/* Fetch the loaded modules, and all currently exported symbols. */
2679
2680static int new_get_kernel_symbols(void)
2681{
2682 char *module_names, *mn;
2683 struct external_module *modules, *m;
2684 struct new_module_symbol *syms, *s;
2685 size_t ret, bufsize, nmod, nsyms, i, j;
2686
2687 /* Collect the loaded modules. */
2688
2689 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002690retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002691 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002692 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 module_names = xrealloc(module_names, bufsize = ret);
2694 goto retry_modules_load;
2695 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002696 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002697 return 0;
2698 }
2699
2700 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002701
2702 /* Collect the modules' symbols. */
2703
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002704 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002705 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2706 memset(modules, 0, nmod * sizeof(*modules));
2707 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002708 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002709 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002710
Mark Whitley94fd4802001-03-12 23:08:34 +00002711 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2712 if (errno == ENOENT) {
2713 /* The module was removed out from underneath us. */
2714 continue;
2715 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002716 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002717 return 0;
2718 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002719
Mark Whitley94fd4802001-03-12 23:08:34 +00002720 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002721retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002722 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2723 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002724 case ENOSPC:
2725 syms = xrealloc(syms, bufsize = ret);
2726 goto retry_mod_sym_load;
2727 case ENOENT:
2728 /* The module was removed out from underneath us. */
2729 continue;
2730 default:
2731 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2732 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002733 }
2734 }
2735 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002736
Mark Whitley94fd4802001-03-12 23:08:34 +00002737 m->name = mn;
2738 m->addr = info.addr;
2739 m->nsyms = nsyms;
2740 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002741
Mark Whitley94fd4802001-03-12 23:08:34 +00002742 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2743 s->name += (unsigned long) syms;
2744 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002745 }
2746 }
2747
2748 /* Collect the kernel's symbols. */
2749
2750 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002751retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002752 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002753 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002754 syms = xrealloc(syms, bufsize = ret);
2755 goto retry_kern_sym_load;
2756 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002757 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002758 return 0;
2759 }
2760 nksyms = nsyms = ret;
2761 ksyms = syms;
2762
2763 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2764 s->name += (unsigned long) syms;
2765 }
2766 return 1;
2767}
2768
2769
2770/* Return the kernel symbol checksum version, or zero if not used. */
2771
2772static int new_is_kernel_checksummed(void)
2773{
2774 struct new_module_symbol *s;
2775 size_t i;
2776
2777 /* Using_Versions is not the first symbol, but it should be in there. */
2778
2779 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2780 if (strcmp((char *) s->name, "Using_Versions") == 0)
2781 return s->value;
2782
2783 return 0;
2784}
2785
2786
2787static int new_create_this_module(struct obj_file *f, const char *m_name)
2788{
2789 struct obj_section *sec;
2790
2791 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002792 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002793 memset(sec->contents, 0, sizeof(struct new_module));
2794
Miles Baderae28b042002-04-01 09:34:25 +00002795 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002796 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002797 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002798
2799 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002800 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002801
2802 return 1;
2803}
2804
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002805#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002806/* add an entry to the __ksymtab section, creating it if necessary */
2807static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2808{
2809 struct obj_section *sec;
2810 ElfW(Addr) ofs;
2811
2812 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2813 * If __ksymtab is defined but not marked alloc, x out the first character
2814 * (no obj_delete routine) and create a new __ksymtab with the correct
2815 * characteristics.
2816 */
2817 sec = obj_find_section(f, "__ksymtab");
2818 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2819 *((char *)(sec->name)) = 'x'; /* override const */
2820 sec = NULL;
2821 }
2822 if (!sec)
2823 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002824 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002825 if (!sec)
2826 return;
2827 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002828 /* Empty section might be byte-aligned */
2829 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002830 ofs = sec->header.sh_size;
2831 obj_symbol_patch(f, sec->idx, ofs, sym);
2832 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2833 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2834}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002835#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002836
2837static int new_create_module_ksymtab(struct obj_file *f)
2838{
2839 struct obj_section *sec;
2840 int i;
2841
2842 /* We must always add the module references. */
2843
2844 if (n_ext_modules_used) {
2845 struct new_module_ref *dep;
2846 struct obj_symbol *tm;
2847
2848 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002849 (sizeof(struct new_module_ref)
2850 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002851 if (!sec)
2852 return 0;
2853
Miles Baderae28b042002-04-01 09:34:25 +00002854 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002855 dep = (struct new_module_ref *) sec->contents;
2856 for (i = 0; i < n_ext_modules; ++i)
2857 if (ext_modules[i].used) {
2858 dep->dep = ext_modules[i].addr;
2859 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002860 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002861 dep->next_ref = 0;
2862 ++dep;
2863 }
2864 }
2865
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002866 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002867 size_t nsyms;
2868 int *loaded;
2869
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002870 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002871
2872 /* We don't want to export symbols residing in sections that
2873 aren't loaded. There are a number of these created so that
2874 we make sure certain module options don't appear twice. */
2875
2876 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2877 while (--i >= 0)
2878 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2879
2880 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2881 struct obj_symbol *sym;
2882 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002883 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002884 && sym->secidx <= SHN_HIRESERVE
2885 && (sym->secidx >= SHN_LORESERVE
2886 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002887 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2888
2889 obj_symbol_patch(f, sec->idx, ofs, sym);
2890 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002891 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002892
2893 nsyms++;
2894 }
2895 }
2896
2897 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2898 }
2899
2900 return 1;
2901}
2902
2903
2904static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002905new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002906{
2907 struct new_module *module;
2908 struct obj_section *sec;
2909 void *image;
2910 int ret;
2911 tgt_long m_addr;
2912
2913 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002914 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002915 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002916 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002917 module = (struct new_module *) sec->contents;
2918 m_addr = sec->header.sh_addr;
2919
2920 module->size_of_struct = sizeof(*module);
2921 module->size = m_size;
2922 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2923
2924 sec = obj_find_section(f, "__ksymtab");
2925 if (sec && sec->header.sh_size) {
2926 module->syms = sec->header.sh_addr;
2927 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2928 }
2929
2930 if (n_ext_modules_used) {
2931 sec = obj_find_section(f, ".kmodtab");
2932 module->deps = sec->header.sh_addr;
2933 module->ndeps = n_ext_modules_used;
2934 }
2935
2936 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002937 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002938 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002939 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002940
2941 sec = obj_find_section(f, "__ex_table");
2942 if (sec) {
2943 module->ex_table_start = sec->header.sh_addr;
2944 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2945 }
2946
2947 sec = obj_find_section(f, ".text.init");
2948 if (sec) {
2949 module->runsize = sec->header.sh_addr - m_addr;
2950 }
2951 sec = obj_find_section(f, ".data.init");
2952 if (sec) {
2953 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002954 module->runsize > sec->header.sh_addr - m_addr)
2955 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002956 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002957 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2958 if (sec && sec->header.sh_size) {
2959 module->archdata_start = (void*)sec->header.sh_addr;
2960 module->archdata_end = module->archdata_start + sec->header.sh_size;
2961 }
2962 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2963 if (sec && sec->header.sh_size) {
2964 module->kallsyms_start = (void*)sec->header.sh_addr;
2965 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2966 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002967
Eric Andersen9f16d612000-06-12 23:11:16 +00002968 /* Whew! All of the initialization is complete. Collect the final
2969 module image and give it to the kernel. */
2970
2971 image = xmalloc(m_size);
2972 obj_create_image(f, image);
2973
Eric Andersencb3b9b12004-06-22 11:50:52 +00002974 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002975 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002976 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002977
2978 free(image);
2979
2980 return ret == 0;
2981}
2982
Eric Andersen9f16d612000-06-12 23:11:16 +00002983
2984/*======================================================================*/
2985
Eric Andersen044228d2001-07-17 01:12:36 +00002986static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002987obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2988 const char *string)
2989{
2990 struct obj_string_patch *p;
2991 struct obj_section *strsec;
2992 size_t len = strlen(string) + 1;
2993 char *loc;
2994
2995 p = xmalloc(sizeof(*p));
2996 p->next = f->string_patches;
2997 p->reloc_secidx = secidx;
2998 p->reloc_offset = offset;
2999 f->string_patches = p;
3000
3001 strsec = obj_find_section(f, ".kstrtab");
3002 if (strsec == NULL) {
3003 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3004 p->string_offset = 0;
3005 loc = strsec->contents;
3006 } else {
3007 p->string_offset = strsec->header.sh_size;
3008 loc = obj_extend_section(strsec, len);
3009 }
3010 memcpy(loc, string, len);
3011
3012 return 1;
3013}
3014
Eric Andersen044228d2001-07-17 01:12:36 +00003015static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003016obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3017 struct obj_symbol *sym)
3018{
3019 struct obj_symbol_patch *p;
3020
3021 p = xmalloc(sizeof(*p));
3022 p->next = f->symbol_patches;
3023 p->reloc_secidx = secidx;
3024 p->reloc_offset = offset;
3025 p->sym = sym;
3026 f->symbol_patches = p;
3027
3028 return 1;
3029}
3030
Eric Andersen044228d2001-07-17 01:12:36 +00003031static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003032{
3033 unsigned long i;
3034 int ret = 1;
3035
3036 for (i = 0; i < HASH_BUCKETS; ++i) {
3037 struct obj_symbol *sym;
3038 for (sym = f->symtab[i]; sym; sym = sym->next)
3039 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003040 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003041 sym->secidx = SHN_ABS;
3042 sym->value = 0;
3043 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003044 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003045 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003046 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003047 ret = 0;
3048 }
3049 }
3050 }
3051
3052 return ret;
3053}
3054
Eric Andersen044228d2001-07-17 01:12:36 +00003055static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003056{
3057 struct common_entry {
3058 struct common_entry *next;
3059 struct obj_symbol *sym;
3060 } *common_head = NULL;
3061
3062 unsigned long i;
3063
3064 for (i = 0; i < HASH_BUCKETS; ++i) {
3065 struct obj_symbol *sym;
3066 for (sym = f->symtab[i]; sym; sym = sym->next)
3067 if (sym->secidx == SHN_COMMON) {
3068 /* Collect all COMMON symbols and sort them by size so as to
3069 minimize space wasted by alignment requirements. */
3070 {
3071 struct common_entry **p, *n;
3072 for (p = &common_head; *p; p = &(*p)->next)
3073 if (sym->size <= (*p)->sym->size)
3074 break;
3075
3076 n = alloca(sizeof(*n));
3077 n->next = *p;
3078 n->sym = sym;
3079 *p = n;
3080 }
3081 }
3082 }
3083
3084 for (i = 1; i < f->local_symtab_size; ++i) {
3085 struct obj_symbol *sym = f->local_symtab[i];
3086 if (sym && sym->secidx == SHN_COMMON) {
3087 struct common_entry **p, *n;
3088 for (p = &common_head; *p; p = &(*p)->next)
3089 if (sym == (*p)->sym)
3090 break;
3091 else if (sym->size < (*p)->sym->size) {
3092 n = alloca(sizeof(*n));
3093 n->next = *p;
3094 n->sym = sym;
3095 *p = n;
3096 break;
3097 }
3098 }
3099 }
3100
3101 if (common_head) {
3102 /* Find the bss section. */
3103 for (i = 0; i < f->header.e_shnum; ++i)
3104 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3105 break;
3106
3107 /* If for some reason there hadn't been one, create one. */
3108 if (i == f->header.e_shnum) {
3109 struct obj_section *sec;
3110
3111 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3112 f->sections[i] = sec = arch_new_section();
3113 f->header.e_shnum = i + 1;
3114
3115 memset(sec, 0, sizeof(*sec));
3116 sec->header.sh_type = SHT_PROGBITS;
3117 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3118 sec->name = ".bss";
3119 sec->idx = i;
3120 }
3121
3122 /* Allocate the COMMONS. */
3123 {
3124 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3125 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3126 struct common_entry *c;
3127
3128 for (c = common_head; c; c = c->next) {
3129 ElfW(Addr) align = c->sym->value;
3130
3131 if (align > max_align)
3132 max_align = align;
3133 if (bss_size & (align - 1))
3134 bss_size = (bss_size | (align - 1)) + 1;
3135
3136 c->sym->secidx = i;
3137 c->sym->value = bss_size;
3138
3139 bss_size += c->sym->size;
3140 }
3141
3142 f->sections[i]->header.sh_size = bss_size;
3143 f->sections[i]->header.sh_addralign = max_align;
3144 }
3145 }
3146
3147 /* For the sake of patch relocation and parameter initialization,
3148 allocate zeroed data for NOBITS sections now. Note that after
3149 this we cannot assume NOBITS are really empty. */
3150 for (i = 0; i < f->header.e_shnum; ++i) {
3151 struct obj_section *s = f->sections[i];
3152 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003153 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003154 s->contents = memset(xmalloc(s->header.sh_size),
3155 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003156 else
3157 s->contents = NULL;
3158
Eric Andersen9f16d612000-06-12 23:11:16 +00003159 s->header.sh_type = SHT_PROGBITS;
3160 }
3161 }
3162}
3163
Eric Andersen044228d2001-07-17 01:12:36 +00003164static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003165{
3166 unsigned long dot = 0;
3167 struct obj_section *sec;
3168
3169 /* Finalize the positions of the sections relative to one another. */
3170
3171 for (sec = f->load_order; sec; sec = sec->load_next) {
3172 ElfW(Addr) align;
3173
3174 align = sec->header.sh_addralign;
3175 if (align && (dot & (align - 1)))
3176 dot = (dot | (align - 1)) + 1;
3177
3178 sec->header.sh_addr = dot;
3179 dot += sec->header.sh_size;
3180 }
3181
3182 return dot;
3183}
3184
Eric Andersen044228d2001-07-17 01:12:36 +00003185static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003186{
3187 int i, n = f->header.e_shnum;
3188 int ret = 1;
3189
3190 /* Finalize the addresses of the sections. */
3191
3192 f->baseaddr = base;
3193 for (i = 0; i < n; ++i)
3194 f->sections[i]->header.sh_addr += base;
3195
3196 /* And iterate over all of the relocations. */
3197
3198 for (i = 0; i < n; ++i) {
3199 struct obj_section *relsec, *symsec, *targsec, *strsec;
3200 ElfW(RelM) * rel, *relend;
3201 ElfW(Sym) * symtab;
3202 const char *strtab;
3203
3204 relsec = f->sections[i];
3205 if (relsec->header.sh_type != SHT_RELM)
3206 continue;
3207
3208 symsec = f->sections[relsec->header.sh_link];
3209 targsec = f->sections[relsec->header.sh_info];
3210 strsec = f->sections[symsec->header.sh_link];
3211
3212 rel = (ElfW(RelM) *) relsec->contents;
3213 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3214 symtab = (ElfW(Sym) *) symsec->contents;
3215 strtab = (const char *) strsec->contents;
3216
3217 for (; rel < relend; ++rel) {
3218 ElfW(Addr) value = 0;
3219 struct obj_symbol *intsym = NULL;
3220 unsigned long symndx;
3221 ElfW(Sym) * extsym = 0;
3222 const char *errmsg;
3223
3224 /* Attempt to find a value to use for this relocation. */
3225
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003226 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003227 if (symndx) {
3228 /* Note we've already checked for undefined symbols. */
3229
3230 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003231 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003232 /* Local symbols we look up in the local table to be sure
3233 we get the one that is really intended. */
3234 intsym = f->local_symtab[symndx];
3235 } else {
3236 /* Others we look up in the hash table. */
3237 const char *name;
3238 if (extsym->st_name)
3239 name = strtab + extsym->st_name;
3240 else
3241 name = f->sections[extsym->st_shndx]->name;
3242 intsym = obj_find_symbol(f, name);
3243 }
3244
3245 value = obj_symbol_final_value(f, intsym);
3246 intsym->referenced = 1;
3247 }
3248#if SHT_RELM == SHT_RELA
3249#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3250 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3251 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003252 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003253#endif
3254 value += rel->r_addend;
3255#endif
3256
3257 /* Do it! */
3258 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003259 (f, targsec, symsec, intsym, rel, value)
3260 ) {
3261 case obj_reloc_ok:
3262 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003263
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003264 case obj_reloc_overflow:
3265 errmsg = "Relocation overflow";
3266 goto bad_reloc;
3267 case obj_reloc_dangerous:
3268 errmsg = "Dangerous relocation";
3269 goto bad_reloc;
3270 case obj_reloc_unhandled:
3271 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003272bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003273 if (extsym) {
3274 bb_error_msg("%s of type %ld for %s", errmsg,
3275 (long) ELF_R_TYPE(rel->r_info),
3276 strtab + extsym->st_name);
3277 } else {
3278 bb_error_msg("%s of type %ld", errmsg,
3279 (long) ELF_R_TYPE(rel->r_info));
3280 }
3281 ret = 0;
3282 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003283 }
3284 }
3285 }
3286
3287 /* Finally, take care of the patches. */
3288
3289 if (f->string_patches) {
3290 struct obj_string_patch *p;
3291 struct obj_section *strsec;
3292 ElfW(Addr) strsec_base;
3293 strsec = obj_find_section(f, ".kstrtab");
3294 strsec_base = strsec->header.sh_addr;
3295
3296 for (p = f->string_patches; p; p = p->next) {
3297 struct obj_section *targsec = f->sections[p->reloc_secidx];
3298 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3299 = strsec_base + p->string_offset;
3300 }
3301 }
3302
3303 if (f->symbol_patches) {
3304 struct obj_symbol_patch *p;
3305
3306 for (p = f->symbol_patches; p; p = p->next) {
3307 struct obj_section *targsec = f->sections[p->reloc_secidx];
3308 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3309 = obj_symbol_final_value(f, p->sym);
3310 }
3311 }
3312
3313 return ret;
3314}
3315
Eric Andersen044228d2001-07-17 01:12:36 +00003316static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003317{
3318 struct obj_section *sec;
3319 ElfW(Addr) base = f->baseaddr;
3320
3321 for (sec = f->load_order; sec; sec = sec->load_next) {
3322 char *secimg;
3323
Eric Andersen2bf658d2001-02-24 20:01:53 +00003324 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003325 continue;
3326
3327 secimg = image + (sec->header.sh_addr - base);
3328
3329 /* Note that we allocated data for NOBITS sections earlier. */
3330 memcpy(secimg, sec->contents, sec->header.sh_size);
3331 }
3332
3333 return 1;
3334}
3335
3336/*======================================================================*/
3337
Eric Andersen044228d2001-07-17 01:12:36 +00003338static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003339{
3340 struct obj_file *f;
3341 ElfW(Shdr) * section_headers;
3342 int shnum, i;
3343 char *shstrtab;
3344
3345 /* Read the file header. */
3346
3347 f = arch_new_file();
3348 memset(f, 0, sizeof(*f));
3349 f->symbol_cmp = strcmp;
3350 f->symbol_hash = obj_elf_hash;
3351 f->load_order_search_start = &f->load_order;
3352
3353 fseek(fp, 0, SEEK_SET);
3354 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003355 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003356 return NULL;
3357 }
3358
3359 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003360 || f->header.e_ident[EI_MAG1] != ELFMAG1
3361 || f->header.e_ident[EI_MAG2] != ELFMAG2
3362 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003363 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003364 return NULL;
3365 }
3366 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003367 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003368 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003369 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3370 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003371 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003372 return NULL;
3373 }
3374 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003375 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003376 return NULL;
3377 }
3378
3379 /* Read the section headers. */
3380
3381 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003382 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003383 (unsigned long) f->header.e_shentsize,
3384 (unsigned long) sizeof(ElfW(Shdr)));
3385 return NULL;
3386 }
3387
3388 shnum = f->header.e_shnum;
3389 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3390 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3391
3392 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3393 fseek(fp, f->header.e_shoff, SEEK_SET);
3394 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003395 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 return NULL;
3397 }
3398
3399 /* Read the section data. */
3400
3401 for (i = 0; i < shnum; ++i) {
3402 struct obj_section *sec;
3403
3404 f->sections[i] = sec = arch_new_section();
3405 memset(sec, 0, sizeof(*sec));
3406
3407 sec->header = section_headers[i];
3408 sec->idx = i;
3409
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003410 if(sec->header.sh_size) {
3411 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003412 case SHT_NULL:
3413 case SHT_NOTE:
3414 case SHT_NOBITS:
3415 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003416 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003417
3418 case SHT_PROGBITS:
3419#if LOADBITS
3420 if (!loadprogbits) {
3421 sec->contents = NULL;
3422 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003423 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003424#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003425 case SHT_SYMTAB:
3426 case SHT_STRTAB:
3427 case SHT_RELM:
3428 if (sec->header.sh_size > 0) {
3429 sec->contents = xmalloc(sec->header.sh_size);
3430 fseek(fp, sec->header.sh_offset, SEEK_SET);
3431 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3432 bb_perror_msg("error reading ELF section data");
3433 return NULL;
3434 }
3435 } else {
3436 sec->contents = NULL;
3437 }
3438 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003439
3440#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003441 case SHT_RELA:
3442 bb_error_msg("RELA relocations not supported on this architecture");
3443 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003444#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003445 case SHT_REL:
3446 bb_error_msg("REL relocations not supported on this architecture");
3447 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003448#endif
3449
Eric Andersen3b1a7442003-12-24 20:30:45 +00003450 default:
3451 if (sec->header.sh_type >= SHT_LOPROC) {
3452 /* Assume processor specific section types are debug
3453 info and can safely be ignored. If this is ever not
3454 the case (Hello MIPS?), don't put ifdefs here but
3455 create an arch_load_proc_section(). */
3456 break;
3457 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003458
Eric Andersen3b1a7442003-12-24 20:30:45 +00003459 bb_error_msg("can't handle sections of type %ld",
3460 (long) sec->header.sh_type);
3461 return NULL;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003462 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003463 }
3464 }
3465
3466 /* Do what sort of interpretation as needed by each section. */
3467
3468 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3469
3470 for (i = 0; i < shnum; ++i) {
3471 struct obj_section *sec = f->sections[i];
3472 sec->name = shstrtab + sec->header.sh_name;
3473 }
3474
3475 for (i = 0; i < shnum; ++i) {
3476 struct obj_section *sec = f->sections[i];
3477
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003478 /* .modinfo should be contents only but gcc has no attribute for that.
3479 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3480 */
3481 if (strcmp(sec->name, ".modinfo") == 0)
3482 sec->header.sh_flags &= ~SHF_ALLOC;
3483
Eric Andersen9f16d612000-06-12 23:11:16 +00003484 if (sec->header.sh_flags & SHF_ALLOC)
3485 obj_insert_section_load_order(f, sec);
3486
3487 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003488 case SHT_SYMTAB:
3489 {
3490 unsigned long nsym, j;
3491 char *strtab;
3492 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003493
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003494 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3495 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003496 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003497 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003498 return NULL;
3499 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003500
3501 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3502 strtab = f->sections[sec->header.sh_link]->contents;
3503 sym = (ElfW(Sym) *) sec->contents;
3504
3505 /* Allocate space for a table of local symbols. */
3506 j = f->local_symtab_size = sec->header.sh_info;
3507 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3508
3509 /* Insert all symbols into the hash table. */
3510 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3511 ElfW(Addr) val = sym->st_value;
3512 const char *name;
3513 if (sym->st_name)
3514 name = strtab + sym->st_name;
3515 else if (sym->st_shndx < shnum)
3516 name = f->sections[sym->st_shndx]->name;
3517 else
3518 continue;
3519#if defined(__SH5__)
3520 /*
3521 * For sh64 it is possible that the target of a branch
3522 * requires a mode switch (32 to 16 and back again).
3523 *
3524 * This is implied by the lsb being set in the target
3525 * address for SHmedia mode and clear for SHcompact.
3526 */
3527 val |= sym->st_other & 4;
3528#endif
3529
3530 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3531 val, sym->st_size);
3532 }
3533 }
3534 break;
3535
3536 case SHT_RELM:
3537 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3538 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3539 (unsigned long) sec->header.sh_entsize,
3540 (unsigned long) sizeof(ElfW(RelM)));
3541 return NULL;
3542 }
3543 break;
3544 /* XXX Relocation code from modutils-2.3.19 is not here.
3545 * Why? That's about 20 lines of code from obj/obj_load.c,
3546 * which gets done in a second pass through the sections.
3547 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003548 }
3549 }
3550
3551 return f;
3552}
3553
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003554#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003555/*
3556 * load the unloaded sections directly into the memory allocated by
3557 * kernel for the module
3558 */
3559
Eric Andersenac5dbd12001-08-22 05:26:08 +00003560static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003561{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003562 ElfW(Addr) base = f->baseaddr;
3563 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003564
Eric Andersen8ae319a2001-05-21 16:09:18 +00003565 for (sec = f->load_order; sec; sec = sec->load_next) {
3566
3567 /* section already loaded? */
3568 if (sec->contents != NULL)
3569 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003570
Eric Andersen8ae319a2001-05-21 16:09:18 +00003571 if (sec->header.sh_size == 0)
3572 continue;
3573
3574 sec->contents = imagebase + (sec->header.sh_addr - base);
3575 fseek(fp, sec->header.sh_offset, SEEK_SET);
3576 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003577 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003578 return 0;
3579 }
3580
3581 }
3582 return 1;
3583}
3584#endif
3585
Eric Andersen9f16d612000-06-12 23:11:16 +00003586static void hide_special_symbols(struct obj_file *f)
3587{
3588 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003589 SPFX "cleanup_module",
3590 SPFX "init_module",
3591 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003592 NULL
3593 };
3594
3595 struct obj_symbol *sym;
3596 const char *const *p;
3597
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003598 for (p = specials; *p; ++p) {
3599 sym = obj_find_symbol(f, *p);
3600 if (sym != NULL)
3601 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3602 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003603}
3604
Glenn L McGrath759515c2003-08-30 06:00:33 +00003605
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003606#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003607static int obj_gpl_license(struct obj_file *f, const char **license)
3608{
3609 struct obj_section *sec;
3610 /* This list must match *exactly* the list of allowable licenses in
3611 * linux/include/linux/module.h. Checking for leading "GPL" will not
3612 * work, somebody will use "GPL sucks, this is proprietary".
3613 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003614 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003615 "GPL",
3616 "GPL v2",
3617 "GPL and additional rights",
3618 "Dual BSD/GPL",
3619 "Dual MPL/GPL",
3620 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003621
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003622 sec = obj_find_section(f, ".modinfo");
3623 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003624 const char *value, *ptr, *endptr;
3625 ptr = sec->contents;
3626 endptr = ptr + sec->header.sh_size;
3627 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003628 value = strchr(ptr, '=');
3629 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003630 int i;
3631 if (license)
3632 *license = value+1;
3633 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3634 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003635 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003636 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003637 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003638 }
3639 if (strchr(ptr, '\0'))
3640 ptr = strchr(ptr, '\0') + 1;
3641 else
3642 ptr = endptr;
3643 }
3644 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003645 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003646}
3647
3648#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3649#define TAINT_PROPRIETORY_MODULE (1<<0)
3650#define TAINT_FORCED_MODULE (1<<1)
3651#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003652#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003653
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003654static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003655 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3656{
3657 char buf[80];
3658 int oldval;
3659 static int first = 1;
3660 if (fd < 0 && !kernel_has_tainted)
3661 return; /* New modutils on old kernel */
3662 printf("Warning: loading %s will taint the kernel: %s%s\n",
3663 m_name, text1, text2);
3664 if (first) {
3665 printf(" See %s for information about tainted modules\n", TAINT_URL);
3666 first = 0;
3667 }
3668 if (fd >= 0) {
3669 read(fd, buf, sizeof(buf)-1);
3670 buf[sizeof(buf)-1] = '\0';
3671 oldval = strtoul(buf, NULL, 10);
3672 sprintf(buf, "%d\n", oldval | taint);
3673 write(fd, buf, strlen(buf));
3674 }
3675}
3676
3677/* Check if loading this module will taint the kernel. */
3678static void check_tainted_module(struct obj_file *f, char *m_name)
3679{
3680 static const char tainted_file[] = TAINT_FILENAME;
3681 int fd, kernel_has_tainted;
3682 const char *ptr;
3683
3684 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003685 fd = open(tainted_file, O_RDWR);
3686 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003687 if (errno == ENOENT)
3688 kernel_has_tainted = 0;
3689 else if (errno == EACCES)
3690 kernel_has_tainted = 1;
3691 else {
3692 perror(tainted_file);
3693 kernel_has_tainted = 0;
3694 }
3695 }
3696
3697 switch (obj_gpl_license(f, &ptr)) {
3698 case 0:
3699 break;
3700 case 1:
3701 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3702 break;
3703 case 2:
3704 /* The module has a non-GPL license so we pretend that the
3705 * kernel always has a taint flag to get a warning even on
3706 * kernels without the proc flag.
3707 */
3708 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3709 break;
3710 default:
3711 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3712 break;
3713 }
3714
3715 if (flag_force_load)
3716 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3717
3718 if (fd >= 0)
3719 close(fd);
3720}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003721#else /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen71ae64b2002-10-10 04:20:21 +00003722#define check_tainted_module(x, y) do { } while(0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003723#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003724
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003725#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003726/* add module source, timestamp, kernel version and a symbol for the
3727 * start of some sections. this info is used by ksymoops to do better
3728 * debugging.
3729 */
3730static int
3731get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3732{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003733#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003734 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003735#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003736 strncpy(str, "???", sizeof(str));
3737 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003738#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003739}
3740
3741/* add module source, timestamp, kernel version and a symbol for the
3742 * start of some sections. this info is used by ksymoops to do better
3743 * debugging.
3744 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003745static void
Eric Andersen889dd202003-01-23 04:48:34 +00003746add_ksymoops_symbols(struct obj_file *f, const char *filename,
3747 const char *m_name)
3748{
3749 static const char symprefix[] = "__insmod_";
3750 struct obj_section *sec;
3751 struct obj_symbol *sym;
3752 char *name, *absolute_filename;
3753 char str[STRVERSIONLEN], real[PATH_MAX];
3754 int i, l, lm_name, lfilename, use_ksymtab, version;
3755 struct stat statbuf;
3756
3757 static const char *section_names[] = {
3758 ".text",
3759 ".rodata",
3760 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003761 ".bss",
3762 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003763 };
3764
3765 if (realpath(filename, real)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +00003766 absolute_filename = xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003767 }
3768 else {
3769 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003770 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003771 errno = save_errno;
3772 perror("");
Rob Landleyd921b2e2006-08-03 15:41:12 +00003773 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003774 }
3775
3776 lm_name = strlen(m_name);
3777 lfilename = strlen(absolute_filename);
3778
3779 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3780 * are not to be exported. otherwise leave ksymtab alone for now, the
3781 * "export all symbols" compatibility code will export these symbols later.
3782 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003783 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003784
3785 if ((sec = obj_find_section(f, ".this"))) {
3786 /* tag the module header with the object name, last modified
3787 * timestamp and module version. worst case for module version
3788 * is 0xffffff, decimal 16777215. putting all three fields in
3789 * one symbol is less readable but saves kernel space.
3790 */
3791 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003792 lm_name+ /* module name */
3793 2+ /* "_O" */
3794 lfilename+ /* object filename */
3795 2+ /* "_M" */
3796 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3797 2+ /* "_V" */
3798 8+ /* version in dec */
3799 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003800 name = xmalloc(l);
3801 if (stat(absolute_filename, &statbuf) != 0)
3802 statbuf.st_mtime = 0;
3803 version = get_module_version(f, str); /* -1 if not found */
3804 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003805 symprefix, m_name, absolute_filename,
3806 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3807 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003808 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003809 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003810 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003811 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003812 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003813 }
3814 free(absolute_filename);
3815#ifdef _NOT_SUPPORTED_
3816 /* record where the persistent data is going, same address as previous symbol */
3817
3818 if (f->persist) {
3819 l = sizeof(symprefix)+ /* "__insmod_" */
3820 lm_name+ /* module name */
3821 2+ /* "_P" */
3822 strlen(f->persist)+ /* data store */
3823 1; /* nul */
3824 name = xmalloc(l);
3825 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003826 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003827 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003828 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003829 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003830 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003831 }
3832#endif /* _NOT_SUPPORTED_ */
3833 /* tag the desired sections if size is non-zero */
3834
3835 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3836 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003837 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003838 l = sizeof(symprefix)+ /* "__insmod_" */
3839 lm_name+ /* module name */
3840 2+ /* "_S" */
3841 strlen(sec->name)+ /* section name */
3842 2+ /* "_L" */
3843 8+ /* length in dec */
3844 1; /* nul */
3845 name = xmalloc(l);
3846 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003847 symprefix, m_name, sec->name,
3848 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003849 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003850 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003851 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003852 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003853 }
3854 }
3855}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003856#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003857
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003858#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003859static void print_load_map(struct obj_file *f)
3860{
3861 struct obj_symbol *sym;
3862 struct obj_symbol **all, **p;
3863 struct obj_section *sec;
3864 int i, nsyms, *loaded;
3865
3866 /* Report on the section layout. */
3867
3868 printf("Sections: Size %-*s Align\n",
3869 (int) (2 * sizeof(void *)), "Address");
3870
3871 for (sec = f->load_order; sec; sec = sec->load_next) {
3872 int a;
3873 unsigned long tmp;
3874
3875 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3876 tmp >>= 1;
3877 if (a == -1)
3878 a = 0;
3879
3880 printf("%-15s %08lx %0*lx 2**%d\n",
3881 sec->name,
3882 (long)sec->header.sh_size,
3883 (int) (2 * sizeof(void *)),
3884 (long)sec->header.sh_addr,
3885 a);
3886 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003887#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003888 /* Quick reference which section indicies are loaded. */
3889
3890 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3891 while (--i >= 0)
3892 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3893
3894 /* Collect the symbols we'll be listing. */
3895
3896 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3897 for (sym = f->symtab[i]; sym; sym = sym->next)
3898 if (sym->secidx <= SHN_HIRESERVE
3899 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3900 ++nsyms;
3901
3902 all = alloca(nsyms * sizeof(struct obj_symbol *));
3903
3904 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3905 for (sym = f->symtab[i]; sym; sym = sym->next)
3906 if (sym->secidx <= SHN_HIRESERVE
3907 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3908 *p++ = sym;
3909
3910 /* And list them. */
3911 printf("\nSymbols:\n");
3912 for (p = all; p < all + nsyms; ++p) {
3913 char type = '?';
3914 unsigned long value;
3915
3916 sym = *p;
3917 if (sym->secidx == SHN_ABS) {
3918 type = 'A';
3919 value = sym->value;
3920 } else if (sym->secidx == SHN_UNDEF) {
3921 type = 'U';
3922 value = 0;
3923 } else {
3924 sec = f->sections[sym->secidx];
3925
3926 if (sec->header.sh_type == SHT_NOBITS)
3927 type = 'B';
3928 else if (sec->header.sh_flags & SHF_ALLOC) {
3929 if (sec->header.sh_flags & SHF_EXECINSTR)
3930 type = 'T';
3931 else if (sec->header.sh_flags & SHF_WRITE)
3932 type = 'D';
3933 else
3934 type = 'R';
3935 }
3936 value = sym->value + sec->header.sh_addr;
3937 }
3938
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003939 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003940 type = tolower(type);
3941
3942 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3943 type, sym->name);
3944 }
3945#endif
3946}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003947#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003948void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003949#endif
3950
Rob Landleydfba7412006-03-06 20:47:33 +00003951int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003952{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003953 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003954 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003955 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003956 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003957 unsigned long m_size;
3958 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003959 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003960 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003961 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003962 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003963 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003964#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003965 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003966 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003967 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003968#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003969#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00003970 FILE *fp = 0;
3971#else
3972 FILE *fp;
3973#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003974 int k_version = 0;
3975 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003976
Erik Andersene49d5ec2000-02-08 19:58:47 +00003977 /* Parse any options */
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003978 getopt32(argc, argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003979 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003980 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003981 free(m_name);
3982 m_name = xstrdup(opt_o);
3983 }
Eric Andersen03d80912003-12-19 21:04:19 +00003984
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003985 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003986 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003987 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003988
Erik Andersene49d5ec2000-02-08 19:58:47 +00003989 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003990 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003991 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003992 len = strlen(tmp);
3993
Eric Andersen03d80912003-12-19 21:04:19 +00003994 if (uname(&myuname) == 0) {
3995 if (myuname.release[0] == '2') {
3996 k_version = myuname.release[2] - '0';
3997 }
3998 }
3999
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004000#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004001 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
4002 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
4003 ) {
4004 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00004005 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004006 } else
Eric Andersen03d80912003-12-19 21:04:19 +00004007#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004008 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004009 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004010 tmp[len] = '\0';
4011 }
Eric Andersen2d342152002-06-18 05:16:25 +00004012
Eric Andersen03d80912003-12-19 21:04:19 +00004013
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004014#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004015 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00004016 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004017 else
Eric Andersen03d80912003-12-19 21:04:19 +00004018#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00004019 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004020
Eric Andersen61f83052002-06-22 17:15:42 +00004021 if (!m_name) {
4022 m_name = tmp;
4023 } else {
4024 free(tmp1);
4025 tmp1 = 0; /* flag for free(m_name) before exit() */
4026 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004027
Eric Andersen14d35432001-05-14 17:07:32 +00004028 /* Get a filedesc for the module. Check we we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004029 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
4030 || (fp = fopen(arg1, "r")) == NULL
4031 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00004032 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4033 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004034 if (k_version) { /* uname succeedd */
4035 char *module_dir;
4036 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004037 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004038
Eric Andersen03d80912003-12-19 21:04:19 +00004039 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004040 /* Jump through hoops in case /lib/modules/`uname -r`
4041 * is a symlink. We do not want recursive_action to
4042 * follow symlinks, but we do want to follow the
4043 * /lib/modules/`uname -r` dir, So resolve it ourselves
4044 * if it is a link... */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004045 if (realpath(tmdn, real_module_dir) == NULL)
Eric Andersen03d80912003-12-19 21:04:19 +00004046 module_dir = tmdn;
4047 else
4048 module_dir = real_module_dir;
4049 recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004050 check_module_name_match, 0, m_fullName, 0);
Eric Andersen03d80912003-12-19 21:04:19 +00004051 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004052 }
4053
4054 /* Check if we have found anything yet */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004055 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004056 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004057
Eric Andersen03d80912003-12-19 21:04:19 +00004058 free(m_filename);
4059 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004060 if (realpath (_PATH_MODULES, module_dir) == NULL)
4061 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004062 /* No module found under /lib/modules/`uname -r`, this
4063 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004064 if (!recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004065 check_module_name_match, 0, m_fullName, 0)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004066 ) {
Eric Andersen61f83052002-06-22 17:15:42 +00004067 if (m_filename == 0
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004068 || ((fp = fopen(m_filename, "r")) == NULL)
4069 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004070 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004071 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004072 }
4073 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004074 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004075 }
Eric Andersen03d80912003-12-19 21:04:19 +00004076 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004077 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004078
Rob Landley999af202005-12-11 20:14:12 +00004079 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004080 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004081
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004082#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004083 if (k_version > 4) {
4084 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004085 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004086 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004087 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004088#endif
4089
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004090 f = obj_load(fp, LOADBITS);
4091 if (f == NULL)
4092 bb_perror_msg_and_die("cannot load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004093
Eric Andersen9f16d612000-06-12 23:11:16 +00004094 if (get_modinfo_value(f, "kernel_version") == NULL)
4095 m_has_modinfo = 0;
4096 else
4097 m_has_modinfo = 1;
4098
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004099#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004100 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004101 if (!flag_quiet) {
4102 if (uname(&uts_info) < 0)
4103 uts_info.release[0] = '\0';
4104 if (m_has_modinfo) {
4105 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004106 if (m_version == -1) {
Denis Vlasenkoa9595882006-09-29 21:30:43 +00004107 bb_error_msg("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004108 "compiled for");
4109 goto out;
4110 }
4111 }
4112
4113 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4114 if (flag_force_load) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004115 bb_error_msg("warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004116 "\t%s was compiled for kernel version %s\n"
4117 "\twhile this kernel is version %s",
4118 m_filename, m_strversion, uts_info.release);
4119 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004120 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004121 "\t%s was compiled for kernel version %s\n"
4122 "\twhile this kernel is version %s.",
4123 m_filename, m_strversion, uts_info.release);
4124 goto out;
4125 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004126 }
4127 }
4128 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004129#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004130
Eric Andersencb3b9b12004-06-22 11:50:52 +00004131 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004132 if (!new_get_kernel_symbols())
4133 goto out;
4134 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004135 } else {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004136 bb_error_msg("not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 }
4139
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004140#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004141 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004142 if (m_has_modinfo)
4143 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004144
4145 if (m_crcs != k_crcs)
4146 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004147#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004148
Erik Andersene49d5ec2000-02-08 19:58:47 +00004149 /* Let the module know about the kernel symbols. */
4150 add_kernel_symbols(f);
4151
Eric Andersen9f16d612000-06-12 23:11:16 +00004152 /* Allocate common symbols, symbol tables, and string tables. */
4153
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004154 if (!new_create_this_module(f, m_name)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004155 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004156 }
4157
Eric Andersen9f16d612000-06-12 23:11:16 +00004158 if (!obj_check_undefineds(f)) {
4159 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004160 }
4161 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004162 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004163
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004164 /* done with the module name, on to the optional var=value arguments */
4165 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004166 if (optind < argc) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004167 if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004168 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004169 }
4170 }
4171
Eric Andersen9f16d612000-06-12 23:11:16 +00004172 arch_create_got(f);
4173 hide_special_symbols(f);
4174
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004175#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004176 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004177#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004178
Eric Andersencb3b9b12004-06-22 11:50:52 +00004179 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004180
Erik Andersene49d5ec2000-02-08 19:58:47 +00004181 /* Find current size of the module */
4182 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004183
4184
Erik Andersene49d5ec2000-02-08 19:58:47 +00004185 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004186 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004187 case EEXIST:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004188 bb_error_msg("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004189 goto out;
4190 case ENOMEM:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004191 bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004192 m_size);
4193 goto out;
4194 default:
4195 bb_perror_msg("create_module: %s", m_name);
4196 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004197 }
Erik Andersend387d011999-12-21 02:55:11 +00004198
Eric Andersen8ae319a2001-05-21 16:09:18 +00004199#if !LOADBITS
4200 /*
4201 * the PROGBITS section was not loaded by the obj_load
4202 * now we can load them directly into the kernel memory
4203 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004204 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004205 delete_module(m_name);
4206 goto out;
4207 }
Eric Andersen03d80912003-12-19 21:04:19 +00004208#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004209
Eric Andersen9f16d612000-06-12 23:11:16 +00004210 if (!obj_relocate(f, m_addr)) {
4211 delete_module(m_name);
4212 goto out;
4213 }
Erik Andersend387d011999-12-21 02:55:11 +00004214
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004215 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004216 delete_module(m_name);
4217 goto out;
4218 }
4219
Eric Andersenbe65c352003-01-23 04:57:35 +00004220 if(flag_print_load_map)
4221 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004222
Matt Kraai3e856ce2000-12-01 02:55:13 +00004223 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004224
4225out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004226#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00004227 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004228 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004229 free(tmp1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004230 if(!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004231 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004232 free(m_filename);
4233#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004234 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004235}
Eric Andersene7047882003-12-11 01:42:13 +00004236
4237
4238#endif
4239
4240
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004241#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004242
4243#include <sys/mman.h>
4244#include <asm/unistd.h>
4245#include <sys/syscall.h>
4246
4247/* We use error numbers in a loose translation... */
4248static const char *moderror(int err)
4249{
4250 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004251 case ENOEXEC:
4252 return "Invalid module format";
4253 case ENOENT:
4254 return "Unknown symbol in module";
4255 case ESRCH:
4256 return "Module has wrong symbol version";
4257 case EINVAL:
4258 return "Invalid parameters";
4259 default:
4260 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004261 }
4262}
4263
Denis Vlasenko92297942006-11-21 11:58:14 +00004264int insmod_ng_main(int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004265{
Denis Vlasenko92297942006-11-21 11:58:14 +00004266 long ret;
4267 size_t len;
Eric Andersene7047882003-12-11 01:42:13 +00004268 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004269 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004270
Denis Vlasenko92297942006-11-21 11:58:14 +00004271 filename = *++argv;
4272 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004273 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004274
4275 /* Rest is options */
Denis Vlasenko92297942006-11-21 11:58:14 +00004276 options = xstrdup("");
4277 while (*++argv) {
4278 int optlen = strlen(options);
4279 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004280 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenko92297942006-11-21 11:58:14 +00004281 sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004282 }
4283
Denis Vlasenko92297942006-11-21 11:58:14 +00004284#if 0
4285 /* Any special reason why mmap? It isn't performace critical... */
4286 int fd;
4287 struct stat st;
4288 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004289 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004290 fstat(fd, &st);
4291 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004292 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004293 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004294 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004295 }
4296
Denis Vlasenko92297942006-11-21 11:58:14 +00004297 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4298 if (map == NULL) {
4299 map = xmalloc(len);
4300 xread(fd, map, len);
4301 }
4302#else
4303 len = MAXINT(ssize_t);
4304 map = xmalloc_open_read_close(filename, &len);
4305#endif
4306
Eric Andersene7047882003-12-11 01:42:13 +00004307 ret = syscall(__NR_init_module, map, len, options);
4308 if (ret != 0) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004309 bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004310 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004311 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004312
Eric Andersene7047882003-12-11 01:42:13 +00004313 return 0;
4314}
4315
4316#endif