blob: 09e7d6811306d8edb7270cde8e38a8ddd5cb08ce [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
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000061#include "libbb.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
Denis Vlasenko3bba5452006-12-30 17:57:03 +000066#undef ENABLE_FEATURE_2_4_MODULES
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000067#define ENABLE_FEATURE_2_4_MODULES 1
Eric Andersene7047882003-12-11 01:42:13 +000068#endif
69
Denis Vlasenkob68979a2007-11-02 23:31:10 +000070/*
71 * Big piece of 2.4-specific code
72 */
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000073#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000074
Denis Vlasenkob68979a2007-11-02 23:31:10 +000075#if ENABLE_FEATURE_2_6_MODULES
76static int insmod_ng_main(int argc, char **argv);
77#endif
Eric Andersen64c8b172001-04-05 07:33:10 +000078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000079#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000080#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000081#else
82#define LOADBITS 1
83#endif
84
Mike Frysinger63654c12004-12-26 09:13:32 +000085/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000086#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000087#define MATCH_MACHINE(x) (x == EM_ALPHA)
88#define SHT_RELM SHT_RELA
89#define Elf64_RelM Elf64_Rela
90#define ELFCLASSM ELFCLASS64
91#endif
92
Eric Andersen45a05132004-09-02 23:03:25 +000093/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000094#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000095#define MATCH_MACHINE(x) (x == EM_ARM)
96#define SHT_RELM SHT_REL
97#define Elf32_RelM Elf32_Rel
98#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000099#define USE_PLT_ENTRIES
100#define PLT_ENTRY_SIZE 8
101#define USE_GOT_ENTRIES
102#define GOT_ENTRY_SIZE 8
103#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000104#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000105
Mike Frysingerb306cb72006-06-06 06:15:52 +0000106/* blackfin */
107#if defined(BFIN)
108#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
109#define SHT_RELM SHT_RELA
110#define Elf32_RelM Elf32_Rela
111#define ELFCLASSM ELFCLASS32
112#endif
113
Eric Andersen45a05132004-09-02 23:03:25 +0000114/* CRIS */
115#if defined(__cris__)
116#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000117#define SHT_RELM SHT_RELA
118#define Elf32_RelM Elf32_Rela
119#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000120#ifndef EM_CRIS
121#define EM_CRIS 76
122#define R_CRIS_NONE 0
123#define R_CRIS_32 3
124#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000125#endif
126
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000127/* H8/300 */
128#if defined(__H8300H__) || defined(__H8300S__)
129#define MATCH_MACHINE(x) (x == EM_H8_300)
130#define SHT_RELM SHT_RELA
131#define Elf32_RelM Elf32_Rela
132#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000133#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000134#define SYMBOL_PREFIX "_"
135#endif
136
Mike Frysinger63654c12004-12-26 09:13:32 +0000137/* PA-RISC / HP-PA */
138#if defined(__hppa__)
139#define MATCH_MACHINE(x) (x == EM_PARISC)
140#define SHT_RELM SHT_RELA
141#if defined(__LP64__)
142#define Elf64_RelM Elf64_Rela
143#define ELFCLASSM ELFCLASS64
144#else
145#define Elf32_RelM Elf32_Rela
146#define ELFCLASSM ELFCLASS32
147#endif
148#endif
149
Eric Andersen45a05132004-09-02 23:03:25 +0000150/* x86 */
151#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000152#ifndef EM_486
153#define MATCH_MACHINE(x) (x == EM_386)
154#else
155#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
156#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000157#define SHT_RELM SHT_REL
158#define Elf32_RelM Elf32_Rel
159#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000160#define USE_GOT_ENTRIES
161#define GOT_ENTRY_SIZE 4
162#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000163#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000164
Eric Andersen45a05132004-09-02 23:03:25 +0000165/* IA64, aka Itanium */
166#if defined(__ia64__)
167#define MATCH_MACHINE(x) (x == EM_IA_64)
168#define SHT_RELM SHT_RELA
169#define Elf64_RelM Elf64_Rela
170#define ELFCLASSM ELFCLASS64
171#endif
172
173/* m68k */
174#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000175#define MATCH_MACHINE(x) (x == EM_68K)
176#define SHT_RELM SHT_RELA
177#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000178#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000179#define USE_GOT_ENTRIES
180#define GOT_ENTRY_SIZE 4
181#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000182#endif
183
Mike Frysingerb306cb72006-06-06 06:15:52 +0000184/* Microblaze */
185#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000186#define USE_SINGLE
Denis Vlasenko2794c9b2008-05-17 02:47:55 +0000187#include <linux/elf-em.h>
Mike Frysingerb306cb72006-06-06 06:15:52 +0000188#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
189#define SHT_RELM SHT_RELA
190#define Elf32_RelM Elf32_Rela
191#define ELFCLASSM ELFCLASS32
192#endif
193
Eric Andersen45a05132004-09-02 23:03:25 +0000194/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000195#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000196#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
197#define SHT_RELM SHT_REL
198#define Elf32_RelM Elf32_Rel
199#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000200/* Account for ELF spec changes. */
201#ifndef EM_MIPS_RS3_LE
202#ifdef EM_MIPS_RS4_BE
203#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
204#else
205#define EM_MIPS_RS3_LE 10
206#endif
207#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000208#define ARCHDATAM "__dbe_table"
209#endif
210
Mike Frysingerf982d862006-01-04 00:11:26 +0000211/* Nios II */
212#if defined(__nios2__)
213#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
214#define SHT_RELM SHT_RELA
215#define Elf32_RelM Elf32_Rela
216#define ELFCLASSM ELFCLASS32
217#endif
218
Eric Andersen45a05132004-09-02 23:03:25 +0000219/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000220#if defined(__powerpc64__)
221#define MATCH_MACHINE(x) (x == EM_PPC64)
222#define SHT_RELM SHT_RELA
223#define Elf64_RelM Elf64_Rela
224#define ELFCLASSM ELFCLASS64
225#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000226#define MATCH_MACHINE(x) (x == EM_PPC)
227#define SHT_RELM SHT_RELA
228#define Elf32_RelM Elf32_Rela
229#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000230#define USE_PLT_ENTRIES
231#define PLT_ENTRY_SIZE 16
232#define USE_PLT_LIST
233#define LIST_ARCHTYPE ElfW(Addr)
234#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000235#define ARCHDATAM "__ftr_fixup"
236#endif
237
Eric Andersen45a05132004-09-02 23:03:25 +0000238/* S390 */
239#if defined(__s390__)
240#define MATCH_MACHINE(x) (x == EM_S390)
241#define SHT_RELM SHT_RELA
242#define Elf32_RelM Elf32_Rela
243#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000244#define USE_PLT_ENTRIES
245#define PLT_ENTRY_SIZE 8
246#define USE_GOT_ENTRIES
247#define GOT_ENTRY_SIZE 8
248#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000249#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000250
Eric Andersen45a05132004-09-02 23:03:25 +0000251/* SuperH */
252#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000253#define MATCH_MACHINE(x) (x == EM_SH)
254#define SHT_RELM SHT_RELA
255#define Elf32_RelM Elf32_Rela
256#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000257#define USE_GOT_ENTRIES
258#define GOT_ENTRY_SIZE 4
259#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000260/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000261/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000262#if defined(__sh__) && BB_BIG_ENDIAN
263# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000264#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000265/* it may or may not work on the SH1/SH2... Error on those also */
266#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000267#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000268#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000269#endif
270
Eric Andersen45a05132004-09-02 23:03:25 +0000271/* Sparc */
272#if defined(__sparc__)
273#define MATCH_MACHINE(x) (x == EM_SPARC)
274#define SHT_RELM SHT_RELA
275#define Elf32_RelM Elf32_Rela
276#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000277#endif
278
Eric Andersen45a05132004-09-02 23:03:25 +0000279/* v850e */
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000280#if defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000281#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
282#define SHT_RELM SHT_RELA
283#define Elf32_RelM Elf32_Rela
284#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000285#define USE_PLT_ENTRIES
286#define PLT_ENTRY_SIZE 8
287#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000288#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000289#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000290#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000291#define SYMBOL_PREFIX "_"
292#endif
293
Eric Andersen45a05132004-09-02 23:03:25 +0000294/* X86_64 */
295#if defined(__x86_64__)
296#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000297#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000298#define USE_GOT_ENTRIES
299#define GOT_ENTRY_SIZE 8
300#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000301#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000302#define ELFCLASSM ELFCLASS64
303#endif
304
Eric Andersencffd5022002-05-24 06:50:15 +0000305#ifndef SHT_RELM
306#error Sorry, but insmod.c does not yet support this architecture...
307#endif
308
309
Eric Andersen9f16d612000-06-12 23:11:16 +0000310//----------------------------------------------------------------------------
311//--------modutils module.h, lines 45-242
312//----------------------------------------------------------------------------
313
314/* Definitions for the Linux module syscall interface.
315 Copyright 1996, 1997 Linux International.
316
317 Contributed by Richard Henderson <rth@tamu.edu>
318
319 This file is part of the Linux modutils.
320
321 This program is free software; you can redistribute it and/or modify it
322 under the terms of the GNU General Public License as published by the
323 Free Software Foundation; either version 2 of the License, or (at your
324 option) any later version.
325
326 This program is distributed in the hope that it will be useful, but
327 WITHOUT ANY WARRANTY; without even the implied warranty of
328 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
329 General Public License for more details.
330
331 You should have received a copy of the GNU General Public License
332 along with this program; if not, write to the Free Software Foundation,
333 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
334
335
336#ifndef MODUTILS_MODULE_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000337
Eric Andersen9f16d612000-06-12 23:11:16 +0000338/*======================================================================*/
339/* For sizeof() which are related to the module platform and not to the
340 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
341
342#define tgt_sizeof_char sizeof(char)
343#define tgt_sizeof_short sizeof(short)
344#define tgt_sizeof_int sizeof(int)
345#define tgt_sizeof_long sizeof(long)
346#define tgt_sizeof_char_p sizeof(char *)
347#define tgt_sizeof_void_p sizeof(void *)
348#define tgt_long long
349
350#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
351#undef tgt_sizeof_long
352#undef tgt_sizeof_char_p
353#undef tgt_sizeof_void_p
354#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000355enum {
356 tgt_sizeof_long = 8,
357 tgt_sizeof_char_p = 8,
358 tgt_sizeof_void_p = 8
359};
Eric Andersen9f16d612000-06-12 23:11:16 +0000360#define tgt_long long long
361#endif
362
363/*======================================================================*/
364/* The structures used in Linux 2.1. */
365
366/* Note: new_module_symbol does not use tgt_long intentionally */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000367struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000368 unsigned long value;
369 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000370};
371
372struct new_module_persist;
373
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000374struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000375 unsigned tgt_long dep; /* kernel addresses */
376 unsigned tgt_long ref;
377 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000378};
379
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000380struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000381 unsigned tgt_long size_of_struct; /* == sizeof(module) */
382 unsigned tgt_long next;
383 unsigned tgt_long name;
384 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000385
Eric Andersen3b1a7442003-12-24 20:30:45 +0000386 tgt_long usecount;
387 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000388
Eric Andersen3b1a7442003-12-24 20:30:45 +0000389 unsigned nsyms;
390 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000391
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned tgt_long syms;
393 unsigned tgt_long deps;
394 unsigned tgt_long refs;
395 unsigned tgt_long init;
396 unsigned tgt_long cleanup;
397 unsigned tgt_long ex_table_start;
398 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000399#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000400 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000401#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000402 /* Everything after here is extension. */
403 unsigned tgt_long persist_start;
404 unsigned tgt_long persist_end;
405 unsigned tgt_long can_unload;
406 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000407 const char *kallsyms_start; /* All symbols for kernel debugging */
408 const char *kallsyms_end;
409 const char *archdata_start; /* arch specific data for module */
410 const char *archdata_end;
411 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000412};
413
Eric Andersencffd5022002-05-24 06:50:15 +0000414#ifdef ARCHDATAM
415#define ARCHDATA_SEC_NAME ARCHDATAM
416#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000417#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000418#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000419#define KALLSYMS_SEC_NAME "__kallsyms"
420
421
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000422struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000423 unsigned long addr;
424 unsigned long size;
425 unsigned long flags;
426 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000427};
428
429/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000430enum {
431 NEW_MOD_RUNNING = 1,
432 NEW_MOD_DELETED = 2,
433 NEW_MOD_AUTOCLEAN = 4,
434 NEW_MOD_VISITED = 8,
435 NEW_MOD_USED_ONCE = 16
436};
Eric Andersen9f16d612000-06-12 23:11:16 +0000437
Eric Andersencb3b9b12004-06-22 11:50:52 +0000438int init_module(const char *name, const struct new_module *);
439int query_module(const char *name, int which, void *buf,
440 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000441
442/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000443enum {
444 QM_MODULES = 1,
445 QM_DEPS = 2,
446 QM_REFS = 3,
447 QM_SYMBOLS = 4,
448 QM_INFO = 5
449};
Eric Andersen9f16d612000-06-12 23:11:16 +0000450
451/*======================================================================*/
452/* The system calls unchanged between 2.0 and 2.1. */
453
454unsigned long create_module(const char *, size_t);
Denis Vlasenkob8e653b2008-06-02 04:51:29 +0000455int delete_module(const char *module, unsigned int flags);
Eric Andersen9f16d612000-06-12 23:11:16 +0000456
457
458#endif /* module.h */
459
460//----------------------------------------------------------------------------
461//--------end of modutils module.h
462//----------------------------------------------------------------------------
463
464
465
466//----------------------------------------------------------------------------
467//--------modutils obj.h, lines 253-462
468//----------------------------------------------------------------------------
469
470/* Elf object file loading and relocation routines.
471 Copyright 1996, 1997 Linux International.
472
473 Contributed by Richard Henderson <rth@tamu.edu>
474
475 This file is part of the Linux modutils.
476
477 This program is free software; you can redistribute it and/or modify it
478 under the terms of the GNU General Public License as published by the
479 Free Software Foundation; either version 2 of the License, or (at your
480 option) any later version.
481
482 This program is distributed in the hope that it will be useful, but
483 WITHOUT ANY WARRANTY; without even the implied warranty of
484 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
485 General Public License for more details.
486
487 You should have received a copy of the GNU General Public License
488 along with this program; if not, write to the Free Software Foundation,
489 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
490
491
492#ifndef MODUTILS_OBJ_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000493
Eric Andersen9f16d612000-06-12 23:11:16 +0000494/* The relocatable object is manipulated using elfin types. */
495
Eric Andersen9f16d612000-06-12 23:11:16 +0000496#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000497#include <endian.h>
498
Eric Andersen9f16d612000-06-12 23:11:16 +0000499#ifndef ElfW
500# if ELFCLASSM == ELFCLASS32
501# define ElfW(x) Elf32_ ## x
502# define ELFW(x) ELF32_ ## x
503# else
504# define ElfW(x) Elf64_ ## x
505# define ELFW(x) ELF64_ ## x
506# endif
507#endif
508
Eric Andersen85e5e722003-07-22 08:56:55 +0000509/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000510#ifndef ELF32_ST_INFO
511# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
512#endif
513
514#ifndef ELF64_ST_INFO
515# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
516#endif
517
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000518#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
519#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
520#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
521#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
522#define ELF_R_SYM(val) ELFW(R_SYM)(val)
523
Eric Andersen9f16d612000-06-12 23:11:16 +0000524struct obj_string_patch;
525struct obj_symbol_patch;
526
527struct obj_section
528{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000529 ElfW(Shdr) header;
530 const char *name;
531 char *contents;
532 struct obj_section *load_next;
533 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000534};
535
536struct obj_symbol
537{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000538 struct obj_symbol *next; /* hash table link */
539 const char *name;
540 unsigned long value;
541 unsigned long size;
542 int secidx; /* the defining section index/module */
543 int info;
544 int ksymidx; /* for export to the kernel symtab */
545 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000546};
547
548/* Hardcode the hash table size. We shouldn't be needing so many
549 symbols that we begin to degrade performance, and we get a big win
550 by giving the compiler a constant divisor. */
551
552#define HASH_BUCKETS 521
553
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000554struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000555 ElfW(Ehdr) header;
556 ElfW(Addr) baseaddr;
557 struct obj_section **sections;
558 struct obj_section *load_order;
559 struct obj_section **load_order_search_start;
560 struct obj_string_patch *string_patches;
561 struct obj_symbol_patch *symbol_patches;
562 int (*symbol_cmp)(const char *, const char *);
563 unsigned long (*symbol_hash)(const char *);
564 unsigned long local_symtab_size;
565 struct obj_symbol **local_symtab;
566 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000567};
568
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000569enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000570 obj_reloc_ok,
571 obj_reloc_overflow,
572 obj_reloc_dangerous,
573 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000574};
575
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000576struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000577 struct obj_string_patch *next;
578 int reloc_secidx;
579 ElfW(Addr) reloc_offset;
580 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000581};
582
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000583struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000584 struct obj_symbol_patch *next;
585 int reloc_secidx;
586 ElfW(Addr) reloc_offset;
587 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000588};
589
590
591/* Generic object manipulation routines. */
592
Eric Andersen044228d2001-07-17 01:12:36 +0000593static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000594
Eric Andersen044228d2001-07-17 01:12:36 +0000595static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000596
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000597static struct obj_symbol *obj_find_symbol(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000598 const char *name);
599
Eric Andersen044228d2001-07-17 01:12:36 +0000600static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000601 struct obj_symbol *sym);
602
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000603#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000604static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000605 int (*cmp)(const char *, const char *),
606 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000607#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000608
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000609static struct obj_section *obj_find_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000610 const char *name);
611
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000612static void obj_insert_section_load_order(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000613 struct obj_section *sec);
614
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000615static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000616 const char *name,
617 unsigned long align,
618 unsigned long size);
619
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000620static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000621 const char *name,
622 unsigned long align,
623 unsigned long size);
624
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000625static void *obj_extend_section(struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000626
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000627static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000628 const char *string);
629
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000630static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000631 struct obj_symbol *sym);
632
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000633static void obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000634
Eric Andersen044228d2001-07-17 01:12:36 +0000635static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000636
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000637static unsigned long obj_load_size(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000638
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000639static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000642
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000643static int obj_create_image(struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
645/* Architecture specific manipulation routines. */
646
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000647static struct obj_file *arch_new_file(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000648
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000649static struct obj_section *arch_new_section(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000651static struct obj_symbol *arch_new_symbol(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000652
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000653static enum obj_reloc arch_apply_relocation(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000654 struct obj_section *targsec,
Denis Vlasenko68404f12008-03-17 09:00:54 +0000655 /*struct obj_section *symsec,*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 struct obj_symbol *sym,
657 ElfW(RelM) *rel, ElfW(Addr) value);
658
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000659static void arch_create_got(struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000660#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000661static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000662#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000663#endif /* obj.h */
664//----------------------------------------------------------------------------
665//--------end of modutils obj.h
666//----------------------------------------------------------------------------
667
668
Miles Baderae28b042002-04-01 09:34:25 +0000669/* SPFX is always a string, so it can be concatenated to string constants. */
670#ifdef SYMBOL_PREFIX
671#define SPFX SYMBOL_PREFIX
672#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000673#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000674#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000675
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000676enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000677
Eric Andersen9f16d612000-06-12 23:11:16 +0000678/*======================================================================*/
679
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000680#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
681enum {
682 OPT_s = 0x1, // -s /* log to syslog */
683 /* Not supported but kernel needs this for request_module(),
684 as this calls: modprobe -k -s -- <module>
685 so silently ignore this flag */
686 OPT_L = 0x2, // -L /* Stub warning */
687 /* Compatibility with modprobe.
688 In theory, this does locking, but we don't do
689 that. So be careful and plan your life around not
690 loading the same module 50 times concurrently. */
691 OPT_o = 0x4, // -o /* name the output module */
692 OPT_f = 0x8, // -f /* force loading */
693 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
694 OPT_v = 0x20, // -v /* verbose output */
695 OPT_q = 0x40, // -q /* silent */
696 OPT_x = 0x80, // -x /* do not export externs */
697 OPT_m = 0x100, // -m /* print module load map */
698};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000699#define flag_force_load (option_mask32 & OPT_f)
700#define flag_autoclean (option_mask32 & OPT_k)
701#define flag_verbose (option_mask32 & OPT_v)
702#define flag_quiet (option_mask32 & OPT_q)
703#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000704#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000705#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000706#else
707#define flag_print_load_map 0
708#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000709
710/*======================================================================*/
711
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000712#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000713
Eric Andersencffd5022002-05-24 06:50:15 +0000714struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000715{
Eric Andersencffd5022002-05-24 06:50:15 +0000716 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000717 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000718 int offset;
719 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000720};
Eric Andersencffd5022002-05-24 06:50:15 +0000721
Eric Andersen21adca72000-12-06 18:18:26 +0000722#endif
723
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000724#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000725
726struct arch_single_entry
727{
Eric Andersen9f16d612000-06-12 23:11:16 +0000728 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000729 int inited : 1;
730 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000731};
Eric Andersencffd5022002-05-24 06:50:15 +0000732
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000733#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000734
Eric Andersen2bf658d2001-02-24 20:01:53 +0000735#if defined(__mips__)
736struct mips_hi16
737{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000738 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000739 ElfW(Addr) *addr;
740 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000741};
742#endif
743
Eric Andersenfe4208f2000-09-24 03:44:29 +0000744struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000745 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000746#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000747 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000748#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000749#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000750 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000751#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000752#if defined(__mips__)
753 struct mips_hi16 *mips_hi16_list;
754#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000755};
756
Eric Andersenfe4208f2000-09-24 03:44:29 +0000757struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000758 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000759#if defined(USE_PLT_ENTRIES)
760#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000761 struct arch_list_entry *pltent;
762#else
763 struct arch_single_entry pltent;
764#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000765#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000766#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000767 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000768#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000769};
770
771
Eric Andersen9f16d612000-06-12 23:11:16 +0000772struct external_module {
773 const char *name;
774 ElfW(Addr) addr;
775 int used;
776 size_t nsyms;
777 struct new_module_symbol *syms;
778};
779
Eric Andersen044228d2001-07-17 01:12:36 +0000780static struct new_module_symbol *ksyms;
781static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000782
Eric Andersen044228d2001-07-17 01:12:36 +0000783static struct external_module *ext_modules;
784static int n_ext_modules;
785static int n_ext_modules_used;
Eric Andersena2a978a2001-04-05 06:08:14 +0000786
Eric Andersen61f83052002-06-22 17:15:42 +0000787static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000788static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000789
Eric Andersenfe4208f2000-09-24 03:44:29 +0000790
Eric Andersen9f16d612000-06-12 23:11:16 +0000791/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000792
Eric Andersen9f16d612000-06-12 23:11:16 +0000793
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +0000794static int FAST_FUNC check_module_name_match(const char *filename,
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000795 struct stat *statbuf UNUSED_PARAM,
796 void *userdata, int depth UNUSED_PARAM)
Eric Andersen9f16d612000-06-12 23:11:16 +0000797{
Eric Andersen14d35432001-05-14 17:07:32 +0000798 char *fullname = (char *) userdata;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000799 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000800
Eric Andersen14d35432001-05-14 17:07:32 +0000801 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000802 return FALSE;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000803
804 tmp = bb_get_last_path_component_nostrip(filename);
805 if (strcmp(tmp, fullname) == 0) {
806 /* Stop searching if we find a match */
807 m_filename = xstrdup(filename);
808 return FALSE;
Erik Andersend387d011999-12-21 02:55:11 +0000809 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000810 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000811}
812
Erik Andersen02104321999-12-17 18:57:34 +0000813
Eric Andersen9f16d612000-06-12 23:11:16 +0000814/*======================================================================*/
815
Eric Andersen044228d2001-07-17 01:12:36 +0000816static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000817{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000818 struct arch_file *f;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000819 f = xzalloc(sizeof(*f));
820 return &f->root; /* it's a first member */
Eric Andersen9f16d612000-06-12 23:11:16 +0000821}
822
Eric Andersen044228d2001-07-17 01:12:36 +0000823static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000824{
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000825 return xzalloc(sizeof(struct obj_section));
Eric Andersen9f16d612000-06-12 23:11:16 +0000826}
827
Eric Andersen044228d2001-07-17 01:12:36 +0000828static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000829{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000830 struct arch_symbol *sym;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000831 sym = xzalloc(sizeof(*sym));
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 return &sym->root;
833}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000834
Eric Andersen044228d2001-07-17 01:12:36 +0000835static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000836arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000837 struct obj_section *targsec,
Denis Vlasenko68404f12008-03-17 09:00:54 +0000838 /*struct obj_section *symsec,*/
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000839 struct obj_symbol *sym,
840 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000841{
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000842#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
Denis Vlasenko09ce45f2008-07-14 21:29:35 +0000843 || defined(__sh__) || defined(__s390__) || defined(__x86_64__) \
Bernhard Reutner-Fischer1a715e42008-07-18 07:42:00 +0000844 || defined(__powerpc__) || defined(__mips__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000845 struct arch_file *ifile = (struct arch_file *) f;
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000846#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000847 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000848 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000849#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \
850 || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \
851 || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \
852 || defined(__s390__) || defined(__sh__) || defined(__x86_64__)
Eric Andersen21adca72000-12-06 18:18:26 +0000853 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000854#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000855#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000856 struct arch_symbol *isym = (struct arch_symbol *) sym;
857#endif
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000858#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
859 || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000860#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000861 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000862#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000863#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000864#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000865 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000866 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000867# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000868 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000869# else
Eric Andersencffd5022002-05-24 06:50:15 +0000870 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000871# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000872#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000873
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000874 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000875
Eric Andersencffd5022002-05-24 06:50:15 +0000876#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 case R_ARM_NONE:
879 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000880
Eric Andersen3b1a7442003-12-24 20:30:45 +0000881 case R_ARM_ABS32:
882 *loc += v;
883 break;
Miles Baderae28b042002-04-01 09:34:25 +0000884
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 case R_ARM_GOT32:
886 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000887
Eric Andersen3b1a7442003-12-24 20:30:45 +0000888 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000889 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
890 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000891 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000892
Eric Andersen3b1a7442003-12-24 20:30:45 +0000893 *loc += got - dot;
894 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000895
Eric Andersen3b1a7442003-12-24 20:30:45 +0000896 case R_ARM_PC24:
897 case R_ARM_PLT32:
898 goto bb_use_plt;
899
900 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000901 *loc += v - got;
902 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000903
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000904#elif defined(__cris__)
905
906 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000907 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000908
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000909 case R_CRIS_32:
910 /* CRIS keeps the relocation value in the r_addend field and
911 * should not use whats in *loc at all
912 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000913 *loc = v;
914 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000915
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000916#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000917
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000918 case R_H8_DIR24R8:
919 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
920 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000921 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000922 case R_H8_DIR24A8:
923 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000924 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000925 case R_H8_DIR32:
926 case R_H8_DIR32A16:
927 *loc += v;
928 break;
929 case R_H8_PCREL16:
930 v -= dot + 2;
931 if ((ElfW(Sword))v > 0x7fff ||
932 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
933 ret = obj_reloc_overflow;
934 else
935 *(unsigned short *)loc = v;
936 break;
937 case R_H8_PCREL8:
938 v -= dot + 1;
939 if ((ElfW(Sword))v > 0x7f ||
940 (ElfW(Sword))v < -(ElfW(Sword))0x80)
941 ret = obj_reloc_overflow;
942 else
943 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000944 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000945
Eric Andersencffd5022002-05-24 06:50:15 +0000946#elif defined(__i386__)
947
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 case R_386_NONE:
949 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000950
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 case R_386_32:
952 *loc += v;
953 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000954
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 case R_386_PLT32:
956 case R_386_PC32:
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +0000957 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000958 *loc += v - dot;
959 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000960
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 case R_386_GLOB_DAT:
962 case R_386_JMP_SLOT:
963 *loc = v;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_RELATIVE:
967 *loc += f->baseaddr;
968 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000969
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000971 *loc += got - dot;
972 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_386_GOT32:
975 goto bb_use_got;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000976 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000977
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000978#elif defined(__microblaze__)
Mike Frysinger280dae72006-06-06 06:30:32 +0000979 case R_MICROBLAZE_NONE:
980 case R_MICROBLAZE_64_NONE:
981 case R_MICROBLAZE_32_SYM_OP_SYM:
982 case R_MICROBLAZE_32_PCREL:
983 break;
984
985 case R_MICROBLAZE_64_PCREL: {
986 /* dot is the address of the current instruction.
987 * v is the target symbol address.
988 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000989 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000990 * of this instruction.
991 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
992 */
993
994 /* Get split offset stored in code */
995 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
996 (loc[1] & 0xFFFF);
997
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000998 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +0000999 * because dot points to the IMM insn, but branch
1000 * is computed relative to the branch instruction itself.
1001 */
1002 temp += v - dot - 4;
1003
1004 /* Store back into code */
1005 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1006 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1007
1008 break;
1009 }
1010
1011 case R_MICROBLAZE_32:
1012 *loc += v;
1013 break;
1014
1015 case R_MICROBLAZE_64: {
1016 /* Get split pointer stored in code */
1017 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1018 (loc[1] & 0xFFFF);
1019
1020 /* Add reloc offset */
1021 temp1+=v;
1022
1023 /* Store back into code */
1024 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1025 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1026
1027 break;
1028 }
1029
1030 case R_MICROBLAZE_32_PCREL_LO:
1031 case R_MICROBLAZE_32_LO:
1032 case R_MICROBLAZE_SRO32:
1033 case R_MICROBLAZE_SRW32:
1034 ret = obj_reloc_unhandled;
1035 break;
1036
Eric Andersencffd5022002-05-24 06:50:15 +00001037#elif defined(__mc68000__)
1038
Eric Andersen3b1a7442003-12-24 20:30:45 +00001039 case R_68K_NONE:
1040 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001041
Eric Andersen3b1a7442003-12-24 20:30:45 +00001042 case R_68K_32:
1043 *loc += v;
1044 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001045
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_8:
1047 if (v > 0xff) {
1048 ret = obj_reloc_overflow;
1049 }
1050 *(char *)loc = v;
1051 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_68K_16:
1054 if (v > 0xffff) {
1055 ret = obj_reloc_overflow;
1056 }
1057 *(short *)loc = v;
1058 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001059
Eric Andersen3b1a7442003-12-24 20:30:45 +00001060 case R_68K_PC8:
1061 v -= dot;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00001062 if ((ElfW(Sword))v > 0x7f
1063 || (ElfW(Sword))v < -(ElfW(Sword))0x80
1064 ) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001065 ret = obj_reloc_overflow;
1066 }
1067 *(char *)loc = v;
1068 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001069
Eric Andersen3b1a7442003-12-24 20:30:45 +00001070 case R_68K_PC16:
1071 v -= dot;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00001072 if ((ElfW(Sword))v > 0x7fff
1073 || (ElfW(Sword))v < -(ElfW(Sword))0x8000
1074 ) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001075 ret = obj_reloc_overflow;
1076 }
1077 *(short *)loc = v;
1078 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001079
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080 case R_68K_PC32:
1081 *(int *)loc = v - dot;
1082 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001083
Eric Andersen3b1a7442003-12-24 20:30:45 +00001084 case R_68K_GLOB_DAT:
1085 case R_68K_JMP_SLOT:
1086 *loc = v;
1087 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001088
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089 case R_68K_RELATIVE:
1090 *(int *)loc += f->baseaddr;
1091 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001092
Eric Andersen3b1a7442003-12-24 20:30:45 +00001093 case R_68K_GOT32:
1094 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001095
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001096# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001097 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001098 *loc += v - got;
1099 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001100# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001101
1102#elif defined(__mips__)
1103
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 case R_MIPS_NONE:
1105 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001106
Eric Andersen3b1a7442003-12-24 20:30:45 +00001107 case R_MIPS_32:
1108 *loc += v;
1109 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001110
Eric Andersen3b1a7442003-12-24 20:30:45 +00001111 case R_MIPS_26:
1112 if (v % 4)
1113 ret = obj_reloc_dangerous;
1114 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1115 ret = obj_reloc_overflow;
1116 *loc =
1117 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1118 0x03ffffff);
1119 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001120
Eric Andersen3b1a7442003-12-24 20:30:45 +00001121 case R_MIPS_HI16:
1122 {
1123 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001124
Eric Andersen3b1a7442003-12-24 20:30:45 +00001125 /* We cannot relocate this one now because we don't know the value
1126 of the carry we need to add. Save the information, and let LO16
1127 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001128 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001129 n->addr = loc;
1130 n->value = v;
1131 n->next = ifile->mips_hi16_list;
1132 ifile->mips_hi16_list = n;
1133 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001134 }
1135
Eric Andersen3b1a7442003-12-24 20:30:45 +00001136 case R_MIPS_LO16:
1137 {
1138 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001139 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001140
1141 /* Sign extend the addend we extract from the lo insn. */
1142 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1143
1144 if (ifile->mips_hi16_list != NULL) {
1145 struct mips_hi16 *l;
1146
1147 l = ifile->mips_hi16_list;
1148 while (l != NULL) {
1149 struct mips_hi16 *next;
1150 unsigned long insn;
1151
Eric Andersen3b1a7442003-12-24 20:30:45 +00001152 /* Do the HI16 relocation. Note that we actually don't
1153 need to know anything about the LO16 itself, except where
1154 to find the low 16 bits of the addend needed by the LO16. */
1155 insn = *l->addr;
1156 val =
1157 ((insn & 0xffff) << 16) +
1158 vallo;
1159 val += v;
1160
1161 /* Account for the sign extension that will happen in the
1162 low bits. */
1163 val =
1164 ((val >> 16) +
1165 ((val & 0x8000) !=
1166 0)) & 0xffff;
1167
1168 insn = (insn & ~0xffff) | val;
1169 *l->addr = insn;
1170
1171 next = l->next;
1172 free(l);
1173 l = next;
1174 }
1175
1176 ifile->mips_hi16_list = NULL;
1177 }
1178
1179 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1180 val = v + vallo;
1181 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1182 *loc = insnlo;
1183 break;
1184 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001185
Mike Frysingerf982d862006-01-04 00:11:26 +00001186#elif defined(__nios2__)
1187
1188 case R_NIOS2_NONE:
1189 break;
1190
1191 case R_NIOS2_BFD_RELOC_32:
1192 *loc += v;
1193 break;
1194
1195 case R_NIOS2_BFD_RELOC_16:
1196 if (v > 0xffff) {
1197 ret = obj_reloc_overflow;
1198 }
1199 *(short *)loc = v;
1200 break;
1201
1202 case R_NIOS2_BFD_RELOC_8:
1203 if (v > 0xff) {
1204 ret = obj_reloc_overflow;
1205 }
1206 *(char *)loc = v;
1207 break;
1208
1209 case R_NIOS2_S16:
1210 {
1211 Elf32_Addr word;
1212
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00001213 if ((Elf32_Sword)v > 0x7fff
1214 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1215 ) {
Mike Frysingerf982d862006-01-04 00:11:26 +00001216 ret = obj_reloc_overflow;
1217 }
1218
1219 word = *loc;
1220 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1221 (word & 0x3f);
1222 }
1223 break;
1224
1225 case R_NIOS2_U16:
1226 {
1227 Elf32_Addr word;
1228
1229 if (v > 0xffff) {
1230 ret = obj_reloc_overflow;
1231 }
1232
1233 word = *loc;
1234 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1235 (word & 0x3f);
1236 }
1237 break;
1238
1239 case R_NIOS2_PCREL16:
1240 {
1241 Elf32_Addr word;
1242
1243 v -= dot + 4;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00001244 if ((Elf32_Sword)v > 0x7fff
1245 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1246 ) {
Mike Frysingerf982d862006-01-04 00:11:26 +00001247 ret = obj_reloc_overflow;
1248 }
1249
1250 word = *loc;
1251 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1252 }
1253 break;
1254
1255 case R_NIOS2_GPREL:
1256 {
1257 Elf32_Addr word, gp;
1258 /* get _gp */
1259 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00001260 v -= gp;
1261 if ((Elf32_Sword)v > 0x7fff
1262 || (Elf32_Sword)v < -(Elf32_Sword)0x8000
1263 ) {
Mike Frysingerf982d862006-01-04 00:11:26 +00001264 ret = obj_reloc_overflow;
1265 }
1266
1267 word = *loc;
1268 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1269 }
1270 break;
1271
1272 case R_NIOS2_CALL26:
1273 if (v & 3)
1274 ret = obj_reloc_dangerous;
1275 if ((v >> 28) != (dot >> 28))
1276 ret = obj_reloc_overflow;
1277 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1278 break;
1279
1280 case R_NIOS2_IMM5:
1281 {
1282 Elf32_Addr word;
1283
1284 if (v > 0x1f) {
1285 ret = obj_reloc_overflow;
1286 }
1287
1288 word = *loc & ~0x7c0;
1289 *loc = word | ((v & 0x1f) << 6);
1290 }
1291 break;
1292
1293 case R_NIOS2_IMM6:
1294 {
1295 Elf32_Addr word;
1296
1297 if (v > 0x3f) {
1298 ret = obj_reloc_overflow;
1299 }
1300
1301 word = *loc & ~0xfc0;
1302 *loc = word | ((v & 0x3f) << 6);
1303 }
1304 break;
1305
1306 case R_NIOS2_IMM8:
1307 {
1308 Elf32_Addr word;
1309
1310 if (v > 0xff) {
1311 ret = obj_reloc_overflow;
1312 }
1313
1314 word = *loc & ~0x3fc0;
1315 *loc = word | ((v & 0xff) << 6);
1316 }
1317 break;
1318
1319 case R_NIOS2_HI16:
1320 {
1321 Elf32_Addr word;
1322
1323 word = *loc;
1324 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1325 (word & 0x3f);
1326 }
1327 break;
1328
1329 case R_NIOS2_LO16:
1330 {
1331 Elf32_Addr word;
1332
1333 word = *loc;
1334 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1335 (word & 0x3f);
1336 }
1337 break;
1338
1339 case R_NIOS2_HIADJ16:
1340 {
1341 Elf32_Addr word1, word2;
1342
1343 word1 = *loc;
1344 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1345 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1346 (word1 & 0x3f);
1347 }
1348 break;
1349
Mike Frysingerebee0e72006-02-18 06:14:31 +00001350#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001351 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001352
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001353#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001354
Eric Andersen3b1a7442003-12-24 20:30:45 +00001355 case R_PPC_ADDR16_HA:
1356 *(unsigned short *)loc = (v + 0x8000) >> 16;
1357 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001358
Eric Andersen3b1a7442003-12-24 20:30:45 +00001359 case R_PPC_ADDR16_HI:
1360 *(unsigned short *)loc = v >> 16;
1361 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001362
Eric Andersen3b1a7442003-12-24 20:30:45 +00001363 case R_PPC_ADDR16_LO:
1364 *(unsigned short *)loc = v;
1365 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001366
Eric Andersen3b1a7442003-12-24 20:30:45 +00001367 case R_PPC_REL24:
1368 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001369
Eric Andersen3b1a7442003-12-24 20:30:45 +00001370 case R_PPC_REL32:
1371 *loc = v - dot;
1372 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001373
Eric Andersen3b1a7442003-12-24 20:30:45 +00001374 case R_PPC_ADDR32:
1375 *loc = v;
1376 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001377
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001378#elif defined(__s390__)
1379
1380 case R_390_32:
1381 *(unsigned int *) loc += v;
1382 break;
1383 case R_390_16:
1384 *(unsigned short *) loc += v;
1385 break;
1386 case R_390_8:
1387 *(unsigned char *) loc += v;
1388 break;
1389
1390 case R_390_PC32:
1391 *(unsigned int *) loc += v - dot;
1392 break;
1393 case R_390_PC16DBL:
1394 *(unsigned short *) loc += (v - dot) >> 1;
1395 break;
1396 case R_390_PC16:
1397 *(unsigned short *) loc += v - dot;
1398 break;
1399
1400 case R_390_PLT32:
1401 case R_390_PLT16DBL:
1402 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001403 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001404 if (pe->inited == 0) {
1405 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1406 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1407 ip[1] = 0x100607f1;
1408 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1409 ip[2] = v - 2;
1410 else
1411 ip[2] = v;
1412 pe->inited = 1;
1413 }
1414
1415 /* Insert relative distance to target. */
1416 v = plt + pe->offset - dot;
1417 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1418 *(unsigned int *) loc = (unsigned int) v;
1419 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1420 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1421 break;
1422
1423 case R_390_GLOB_DAT:
1424 case R_390_JMP_SLOT:
1425 *loc = v;
1426 break;
1427
1428 case R_390_RELATIVE:
1429 *loc += f->baseaddr;
1430 break;
1431
1432 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001433 *(unsigned long *) loc += got - dot;
1434 break;
1435
1436 case R_390_GOT12:
1437 case R_390_GOT16:
1438 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001439 if (!isym->gotent.inited)
1440 {
1441 isym->gotent.inited = 1;
1442 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1443 }
1444 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1445 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1446 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1447 *(unsigned short *) loc += isym->gotent.offset;
1448 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1449 *(unsigned int *) loc += isym->gotent.offset;
1450 break;
1451
1452# ifndef R_390_GOTOFF32
1453# define R_390_GOTOFF32 R_390_GOTOFF
1454# endif
1455 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001456 *loc += v - got;
1457 break;
1458
Eric Andersencffd5022002-05-24 06:50:15 +00001459#elif defined(__sh__)
1460
Eric Andersen3b1a7442003-12-24 20:30:45 +00001461 case R_SH_NONE:
1462 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001463
Eric Andersen3b1a7442003-12-24 20:30:45 +00001464 case R_SH_DIR32:
1465 *loc += v;
1466 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001467
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 case R_SH_REL32:
1469 *loc += v - dot;
1470 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001471
Eric Andersen3b1a7442003-12-24 20:30:45 +00001472 case R_SH_PLT32:
1473 *loc = v - dot;
1474 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 case R_SH_GLOB_DAT:
1477 case R_SH_JMP_SLOT:
1478 *loc = v;
1479 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001480
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 case R_SH_RELATIVE:
1482 *loc = f->baseaddr + rel->r_addend;
1483 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001484
Eric Andersen3b1a7442003-12-24 20:30:45 +00001485 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 *loc = got - dot + rel->r_addend;
1487 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001488
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 case R_SH_GOT32:
1490 goto bb_use_got;
1491
1492 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001493 *loc = v - got;
1494 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001495
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001496# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001497 case R_SH_IMM_MEDLOW16:
1498 case R_SH_IMM_LOW16:
1499 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001500 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001501
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001502 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001503 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001504
Eric Andersen3b1a7442003-12-24 20:30:45 +00001505 /*
1506 * movi and shori have the format:
1507 *
1508 * | op | imm | reg | reserved |
1509 * 31..26 25..10 9.. 4 3 .. 0
1510 *
1511 * so we simply mask and or in imm.
1512 */
1513 word = *loc & ~0x3fffc00;
1514 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001515
Eric Andersen3b1a7442003-12-24 20:30:45 +00001516 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001517
Eric Andersen3b1a7442003-12-24 20:30:45 +00001518 break;
1519 }
Eric Andersenbf833552003-08-13 19:56:33 +00001520
Eric Andersen3b1a7442003-12-24 20:30:45 +00001521 case R_SH_IMM_MEDLOW16_PCREL:
1522 case R_SH_IMM_LOW16_PCREL:
1523 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001524 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001525
Eric Andersen3b1a7442003-12-24 20:30:45 +00001526 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001527
Eric Andersen3b1a7442003-12-24 20:30:45 +00001528 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001529
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001530 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001531 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001532
Eric Andersen3b1a7442003-12-24 20:30:45 +00001533 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001534
Eric Andersen3b1a7442003-12-24 20:30:45 +00001535 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001536
Eric Andersen3b1a7442003-12-24 20:30:45 +00001537 break;
1538 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001539# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001540
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001541#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001542
Eric Andersen3b1a7442003-12-24 20:30:45 +00001543 case R_V850_NONE:
1544 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001545
Eric Andersen3b1a7442003-12-24 20:30:45 +00001546 case R_V850_32:
1547 /* We write two shorts instead of a long because even
1548 32-bit insns only need half-word alignment, but
1549 32-bit data needs to be long-word aligned. */
1550 v += ((unsigned short *)loc)[0];
1551 v += ((unsigned short *)loc)[1] << 16;
1552 ((unsigned short *)loc)[0] = v & 0xffff;
1553 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1554 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001555
Eric Andersen3b1a7442003-12-24 20:30:45 +00001556 case R_V850_22_PCREL:
1557 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001558
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001559#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001560
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001561 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001562 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001563
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001564 case R_X86_64_64:
1565 *loc += v;
1566 break;
1567
1568 case R_X86_64_32:
1569 *(unsigned int *) loc += v;
1570 if (v > 0xffffffff)
1571 {
1572 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1573 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1574 }
1575 break;
1576
1577 case R_X86_64_32S:
1578 *(signed int *) loc += v;
1579 break;
1580
1581 case R_X86_64_16:
1582 *(unsigned short *) loc += v;
1583 break;
1584
1585 case R_X86_64_8:
1586 *(unsigned char *) loc += v;
1587 break;
1588
1589 case R_X86_64_PC32:
1590 *(unsigned int *) loc += v - dot;
1591 break;
1592
1593 case R_X86_64_PC16:
1594 *(unsigned short *) loc += v - dot;
1595 break;
1596
1597 case R_X86_64_PC8:
1598 *(unsigned char *) loc += v - dot;
1599 break;
1600
1601 case R_X86_64_GLOB_DAT:
1602 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001603 *loc = v;
1604 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001605
1606 case R_X86_64_RELATIVE:
1607 *loc += f->baseaddr;
1608 break;
1609
1610 case R_X86_64_GOT32:
1611 case R_X86_64_GOTPCREL:
1612 goto bb_use_got;
1613# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001614 if (!isym->gotent.reloc_done)
1615 {
1616 isym->gotent.reloc_done = 1;
1617 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1618 }
1619 /* XXX are these really correct? */
1620 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1621 *(unsigned int *) loc += v + isym->gotent.offset;
1622 else
1623 *loc += isym->gotent.offset;
1624 break;
1625# endif
1626
Mike Frysingerf982d862006-01-04 00:11:26 +00001627#else
1628# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001629#endif
1630
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001631 default:
1632 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1633 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001634 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001635
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001636#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001637
Eric Andersen3b1a7442003-12-24 20:30:45 +00001638bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001639
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001641
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001642#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1644 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001645#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001647#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001648
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 if (! pe->inited) {
1650 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001651
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001653
1654#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1656 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657#endif
1658#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001660 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 ip[2] = 0x7d6903a6; /* mtctr r11 */
1662 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001663#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001664#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 /* We have to trash a register, so we assume that any control
1666 transfer more than 21-bits away must be a function call
1667 (so we can use a call-clobbered register). */
1668 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1669 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001670#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001671 pe->inited = 1;
1672 }
Eric Andersen21adca72000-12-06 18:18:26 +00001673
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674 /* relative distance to target */
1675 v -= dot;
1676 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001677#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001678 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001679#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001680 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001681#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 /* go via the plt */
1683 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001684
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001685#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001687#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001689#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001691
Eric Andersen3b1a7442003-12-24 20:30:45 +00001692 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001693#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 /* Convert to words. */
1695 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001696
Eric Andersen3b1a7442003-12-24 20:30:45 +00001697 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001698#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001699#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001700 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001701#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001702#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001703 /* We write two shorts instead of a long because even 32-bit insns
1704 only need half-word alignment, but the 32-bit data write needs
1705 to be long-word aligned. */
1706 ((unsigned short *)loc)[0] =
1707 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1708 | ((v >> 16) & 0x3f); /* offs high part */
1709 ((unsigned short *)loc)[1] =
1710 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001711#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001712 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001713#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001714
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001715#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001716bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001717
Eric Andersen3b1a7442003-12-24 20:30:45 +00001718 /* needs an entry in the .got: set it, once */
1719 if (!isym->gotent.inited) {
1720 isym->gotent.inited = 1;
1721 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1722 }
1723 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001724#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001725 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001726#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001727 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001728#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001729 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001730
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001731#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001732 }
1733
1734 return ret;
1735}
1736
Eric Andersencffd5022002-05-24 06:50:15 +00001737
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001738#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001739
1740static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1741 int offset, int size)
1742{
1743 struct arch_list_entry *pe;
1744
1745 for (pe = *list; pe != NULL; pe = pe->next) {
1746 if (pe->addend == rel->r_addend) {
1747 break;
1748 }
1749 }
1750
1751 if (pe == NULL) {
1752 pe = xmalloc(sizeof(struct arch_list_entry));
1753 pe->next = *list;
1754 pe->addend = rel->r_addend;
1755 pe->offset = offset;
1756 pe->inited = 0;
1757 *list = pe;
1758 return size;
1759 }
1760 return 0;
1761}
1762
1763#endif
1764
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001765#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001766
Denis Vlasenko68404f12008-03-17 09:00:54 +00001767static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single,
Eric Andersencffd5022002-05-24 06:50:15 +00001768 int offset, int size)
1769{
1770 if (single->allocated == 0) {
1771 single->allocated = 1;
1772 single->offset = offset;
1773 single->inited = 0;
1774 return size;
1775 }
1776 return 0;
1777}
1778
1779#endif
1780
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001781#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001782
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001783static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001784 int offset, int size)
1785{
1786 struct obj_section *myrelsec = obj_find_section(f, name);
1787
1788 if (offset == 0) {
1789 offset += size;
1790 }
1791
1792 if (myrelsec) {
1793 obj_extend_section(myrelsec, offset);
1794 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001795 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001796 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001797 }
1798
1799 return myrelsec;
1800}
1801
1802#endif
1803
1804static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001805{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001806#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001807 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001808 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001809#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001810 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001811#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001812#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001813 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001814#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001815 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001816 ElfW(RelM) *rel, *relend;
1817 ElfW(Sym) *symtab, *extsym;
1818 const char *strtab, *name;
1819 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001820
Eric Andersen21adca72000-12-06 18:18:26 +00001821 for (i = 0; i < f->header.e_shnum; ++i) {
1822 relsec = f->sections[i];
1823 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001824 continue;
1825
Eric Andersen21adca72000-12-06 18:18:26 +00001826 symsec = f->sections[relsec->header.sh_link];
1827 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001828
Eric Andersen21adca72000-12-06 18:18:26 +00001829 rel = (ElfW(RelM) *) relsec->contents;
1830 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1831 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001832 strtab = (const char *) strsec->contents;
1833
1834 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001835 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001836
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001837#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001838 got_allocate = 0;
1839#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001840#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001841 plt_allocate = 0;
1842#endif
1843
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001844 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001845#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001846 case R_ARM_PC24:
1847 case R_ARM_PLT32:
1848 plt_allocate = 1;
1849 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001850
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001851 case R_ARM_GOTOFF:
1852 case R_ARM_GOTPC:
1853 got_needed = 1;
1854 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001855
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001856 case R_ARM_GOT32:
1857 got_allocate = 1;
1858 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001859
Eric Andersen21adca72000-12-06 18:18:26 +00001860#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001861 case R_386_GOTPC:
1862 case R_386_GOTOFF:
1863 got_needed = 1;
1864 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001865
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001866 case R_386_GOT32:
1867 got_allocate = 1;
1868 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001869
1870#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001871 case R_PPC_REL24:
1872 plt_allocate = 1;
1873 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001874
1875#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001876 case R_68K_GOT32:
1877 got_allocate = 1;
1878 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001879
Eric Andersen16451a02004-03-19 12:16:18 +00001880#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001881 case R_68K_GOTOFF:
1882 got_needed = 1;
1883 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001884#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001885
1886#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001887 case R_SH_GOT32:
1888 got_allocate = 1;
1889 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001890
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001891 case R_SH_GOTPC:
1892 case R_SH_GOTOFF:
1893 got_needed = 1;
1894 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001895
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001896#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001897 case R_V850_22_PCREL:
1898 plt_needed = 1;
1899 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001900
1901#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001902 default:
1903 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001904 }
1905
Eric Andersen21adca72000-12-06 18:18:26 +00001906 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001907 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001908 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001909 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001910 }
1911 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001912#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001913 if (got_allocate) {
1914 got_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001915 /*rel,*/ &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001916 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001917
1918 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001919 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001920#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001921#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001922 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001923#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001924 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001925 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001926 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001927#else
1928 plt_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001929 /*rel,*/ &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001930 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001931#endif
1932 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001933 }
1934#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001935 }
Miles Baderae28b042002-04-01 09:34:25 +00001936 }
Eric Andersen21adca72000-12-06 18:18:26 +00001937
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001938#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001939 if (got_needed) {
1940 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001941 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001942 }
Eric Andersen21adca72000-12-06 18:18:26 +00001943#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001944
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001945#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001946 if (plt_needed) {
1947 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001948 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001949 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001950#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001951
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001952#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001953}
1954
Eric Andersen9f16d612000-06-12 23:11:16 +00001955/*======================================================================*/
1956
1957/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001958static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001959{
1960 unsigned long h = 0;
1961 unsigned long g;
1962 unsigned char ch;
1963
1964 while (n > 0) {
1965 ch = *name++;
1966 h = (h << 4) + ch;
Denis Vlasenko1bec1b92007-11-06 02:23:39 +00001967 g = (h & 0xf0000000);
1968 if (g != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001969 h ^= g >> 24;
1970 h &= ~g;
1971 }
1972 n--;
1973 }
1974 return h;
1975}
1976
Eric Andersen044228d2001-07-17 01:12:36 +00001977static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001978{
1979 return obj_elf_hash_n(name, strlen(name));
1980}
1981
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001982#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001983/* String comparison for non-co-versioned kernel and module. */
1984
1985static int ncv_strcmp(const char *a, const char *b)
1986{
1987 size_t alen = strlen(a), blen = strlen(b);
1988
1989 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1990 return strncmp(a, b, alen);
1991 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1992 return strncmp(a, b, blen);
1993 else
1994 return strcmp(a, b);
1995}
1996
1997/* String hashing for non-co-versioned kernel and module. Here
1998 we are simply forced to drop the crc from the hash. */
1999
2000static unsigned long ncv_symbol_hash(const char *str)
2001{
2002 size_t len = strlen(str);
2003 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2004 len -= 10;
2005 return obj_elf_hash_n(str, len);
2006}
2007
Eric Andersen044228d2001-07-17 01:12:36 +00002008static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002009obj_set_symbol_compare(struct obj_file *f,
2010 int (*cmp) (const char *, const char *),
2011 unsigned long (*hash) (const char *))
2012{
2013 if (cmp)
2014 f->symbol_cmp = cmp;
2015 if (hash) {
2016 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2017 int i;
2018
2019 f->symbol_hash = hash;
2020
2021 memcpy(tmptab, f->symtab, sizeof(tmptab));
2022 memset(f->symtab, 0, sizeof(f->symtab));
2023
2024 for (i = 0; i < HASH_BUCKETS; ++i)
2025 for (sym = tmptab[i]; sym; sym = next) {
2026 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2027 next = sym->next;
2028 sym->next = f->symtab[h];
2029 f->symtab[h] = sym;
2030 }
2031 }
2032}
2033
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002034#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002035
Eric Andersen044228d2001-07-17 01:12:36 +00002036static struct obj_symbol *
2037obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002038 unsigned long symidx, int info,
2039 int secidx, ElfW(Addr) value,
2040 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002041{
2042 struct obj_symbol *sym;
2043 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002044 int n_type = ELF_ST_TYPE(info);
2045 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002046
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002047 for (sym = f->symtab[hash]; sym; sym = sym->next) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002048 if (f->symbol_cmp(sym->name, name) == 0) {
2049 int o_secidx = sym->secidx;
2050 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002051 int o_type = ELF_ST_TYPE(o_info);
2052 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002053
2054 /* A redefinition! Is it legal? */
2055
2056 if (secidx == SHN_UNDEF)
2057 return sym;
2058 else if (o_secidx == SHN_UNDEF)
2059 goto found;
2060 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2061 /* Cope with local and global symbols of the same name
2062 in the same object file, as might have been created
2063 by ld -r. The only reason locals are now seen at this
2064 level at all is so that we can do semi-sensible things
2065 with parameters. */
2066
2067 struct obj_symbol *nsym, **p;
2068
2069 nsym = arch_new_symbol();
2070 nsym->next = sym->next;
2071 nsym->ksymidx = -1;
2072
2073 /* Excise the old (local) symbol from the hash chain. */
2074 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2075 continue;
2076 *p = sym = nsym;
2077 goto found;
2078 } else if (n_binding == STB_LOCAL) {
2079 /* Another symbol of the same name has already been defined.
2080 Just add this to the local table. */
2081 sym = arch_new_symbol();
2082 sym->next = NULL;
2083 sym->ksymidx = -1;
2084 f->local_symtab[symidx] = sym;
2085 goto found;
2086 } else if (n_binding == STB_WEAK)
2087 return sym;
2088 else if (o_binding == STB_WEAK)
2089 goto found;
2090 /* Don't unify COMMON symbols with object types the programmer
2091 doesn't expect. */
2092 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002093 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002094 return sym;
2095 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002096 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002097 goto found;
2098 else {
2099 /* Don't report an error if the symbol is coming from
2100 the kernel or some external module. */
2101 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002102 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002103 return sym;
2104 }
2105 }
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002106 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002107
2108 /* Completely new symbol. */
2109 sym = arch_new_symbol();
2110 sym->next = f->symtab[hash];
2111 f->symtab[hash] = sym;
2112 sym->ksymidx = -1;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002113 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002114 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002115 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002116 name, (long) symidx, (long) f->local_symtab_size);
2117 else
2118 f->local_symtab[symidx] = sym;
2119 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002120
Eric Andersen3b1a7442003-12-24 20:30:45 +00002121found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002122 sym->name = name;
2123 sym->value = value;
2124 sym->size = size;
2125 sym->secidx = secidx;
2126 sym->info = info;
2127
2128 return sym;
2129}
2130
Eric Andersen044228d2001-07-17 01:12:36 +00002131static struct obj_symbol *
2132obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002133{
2134 struct obj_symbol *sym;
2135 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2136
2137 for (sym = f->symtab[hash]; sym; sym = sym->next)
2138 if (f->symbol_cmp(sym->name, name) == 0)
2139 return sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00002140 return NULL;
2141}
2142
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002143static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002144{
2145 if (sym) {
2146 if (sym->secidx >= SHN_LORESERVE)
2147 return sym->value;
Eric Andersen9f16d612000-06-12 23:11:16 +00002148 return sym->value + f->sections[sym->secidx]->header.sh_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002149 }
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002150 /* As a special case, a NULL sym has value zero. */
2151 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002152}
2153
Eric Andersen044228d2001-07-17 01:12:36 +00002154static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002155{
2156 int i, n = f->header.e_shnum;
2157
2158 for (i = 0; i < n; ++i)
2159 if (strcmp(f->sections[i]->name, name) == 0)
2160 return f->sections[i];
Eric Andersen9f16d612000-06-12 23:11:16 +00002161 return NULL;
2162}
2163
2164static int obj_load_order_prio(struct obj_section *a)
2165{
2166 unsigned long af, ac;
2167
2168 af = a->header.sh_flags;
2169
2170 ac = 0;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002171 if (a->name[0] != '.' || strlen(a->name) != 10
2172 || strcmp(a->name + 5, ".init") != 0
2173 ) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002174 ac |= 32;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002175 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002176 if (af & SHF_ALLOC)
2177 ac |= 16;
2178 if (!(af & SHF_WRITE))
2179 ac |= 8;
2180 if (af & SHF_EXECINSTR)
2181 ac |= 4;
2182 if (a->header.sh_type != SHT_NOBITS)
2183 ac |= 2;
2184
2185 return ac;
2186}
2187
Eric Andersen044228d2001-07-17 01:12:36 +00002188static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002189obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2190{
2191 struct obj_section **p;
2192 int prio = obj_load_order_prio(sec);
2193 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2194 if (obj_load_order_prio(*p) < prio)
2195 break;
2196 sec->load_next = *p;
2197 *p = sec;
2198}
2199
Eric Andersen044228d2001-07-17 01:12:36 +00002200static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002201 const char *name,
2202 unsigned long align,
2203 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002204{
2205 int newidx = f->header.e_shnum++;
2206 struct obj_section *sec;
2207
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002208 f->sections = xrealloc_vector(f->sections, 2, newidx);
Eric Andersen9f16d612000-06-12 23:11:16 +00002209 f->sections[newidx] = sec = arch_new_section();
2210
Eric Andersen9f16d612000-06-12 23:11:16 +00002211 sec->header.sh_type = SHT_PROGBITS;
2212 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2213 sec->header.sh_size = size;
2214 sec->header.sh_addralign = align;
2215 sec->name = name;
2216 sec->idx = newidx;
2217 if (size)
Denis Vlasenko18c93022008-08-27 22:29:43 +00002218 sec->contents = xzalloc(size);
Eric Andersen9f16d612000-06-12 23:11:16 +00002219
2220 obj_insert_section_load_order(f, sec);
2221
2222 return sec;
2223}
2224
Eric Andersen044228d2001-07-17 01:12:36 +00002225static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002226 const char *name,
2227 unsigned long align,
2228 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002229{
2230 int newidx = f->header.e_shnum++;
2231 struct obj_section *sec;
2232
Denis Vlasenko18c93022008-08-27 22:29:43 +00002233 f->sections = xrealloc_vector(f->sections, 2, newidx);
Eric Andersen9f16d612000-06-12 23:11:16 +00002234 f->sections[newidx] = sec = arch_new_section();
2235
Eric Andersen9f16d612000-06-12 23:11:16 +00002236 sec->header.sh_type = SHT_PROGBITS;
2237 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2238 sec->header.sh_size = size;
2239 sec->header.sh_addralign = align;
2240 sec->name = name;
2241 sec->idx = newidx;
2242 if (size)
Denis Vlasenko18c93022008-08-27 22:29:43 +00002243 sec->contents = xzalloc(size);
Eric Andersen9f16d612000-06-12 23:11:16 +00002244
2245 sec->load_next = f->load_order;
2246 f->load_order = sec;
2247 if (f->load_order_search_start == &f->load_order)
2248 f->load_order_search_start = &sec->load_next;
2249
2250 return sec;
2251}
2252
Eric Andersen044228d2001-07-17 01:12:36 +00002253static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002254{
2255 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002256 if (more) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002257 sec->header.sh_size += more;
2258 sec->contents = xrealloc(sec->contents, sec->header.sh_size);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002259 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002260 return sec->contents + oldsize;
2261}
2262
2263
Eric Andersen9f16d612000-06-12 23:11:16 +00002264/* Conditionally add the symbols from the given symbol set to the
2265 new module. */
2266
2267static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002268add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002269 int idx, struct new_module_symbol *syms, size_t nsyms)
2270{
2271 struct new_module_symbol *s;
2272 size_t i;
2273 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002274#ifdef SYMBOL_PREFIX
2275 char *name_buf = 0;
2276 size_t name_alloced_size = 0;
2277#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002278#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002279 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002280
Glenn L McGrath759515c2003-08-30 06:00:33 +00002281 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002282#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002283 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002284 /* Only add symbols that are already marked external.
2285 If we override locals we may cause problems for
2286 argument initialization. We will also create a false
2287 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002288 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002289 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002290
Glenn L McGrath759515c2003-08-30 06:00:33 +00002291 /* GPL licensed modules can use symbols exported with
2292 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2293 * exported names. Non-GPL modules never see any GPLONLY_
2294 * symbols so they cannot fudge it by adding the prefix on
2295 * their references.
2296 */
2297 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002298#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002299 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002300 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002301 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002302#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002303 continue;
2304 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002305 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002306
Miles Baderae28b042002-04-01 09:34:25 +00002307#ifdef SYMBOL_PREFIX
2308 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2309 kernel exports `C names', but module object files
2310 reference `linker names'). */
2311 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002312 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002313 if (name_size > name_alloced_size) {
2314 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002315 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002316 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002317 strcpy(name_buf, SYMBOL_PREFIX);
2318 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002319 name = name_buf;
2320#endif /* SYMBOL_PREFIX */
2321
2322 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002323 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002324#ifdef SYMBOL_PREFIX
2325 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002326 name = xmalloc(name_size);
2327 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002328#endif
2329 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002330 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002331 STT_NOTYPE),
2332 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002333 /* Did our symbol just get installed? If so, mark the
2334 module as "used". */
2335 if (sym->secidx == idx)
2336 used = 1;
2337 }
2338 }
2339
2340 return used;
2341}
2342
2343static void add_kernel_symbols(struct obj_file *f)
2344{
2345 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002346 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002347
2348 /* Add module symbols first. */
2349
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002350 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002351 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002352 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2353 ) {
2354 m->used = 1;
2355 ++nused;
2356 }
2357 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002358
2359 n_ext_modules_used = nused;
2360
2361 /* And finally the symbols from the kernel proper. */
2362
2363 if (nksyms)
2364 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2365}
2366
2367static char *get_modinfo_value(struct obj_file *f, const char *key)
2368{
2369 struct obj_section *sec;
2370 char *p, *v, *n, *ep;
2371 size_t klen = strlen(key);
2372
2373 sec = obj_find_section(f, ".modinfo");
2374 if (sec == NULL)
2375 return NULL;
2376 p = sec->contents;
2377 ep = p + sec->header.sh_size;
2378 while (p < ep) {
2379 v = strchr(p, '=');
2380 n = strchr(p, '\0');
2381 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002382 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002383 return v + 1;
2384 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002385 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002386 return n;
2387 }
2388 p = n + 1;
2389 }
2390
2391 return NULL;
2392}
2393
2394
2395/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002396/* Functions relating to module loading after 2.1.18. */
2397
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002398static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002399new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2400{
2401 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002402 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002403 struct obj_symbol *sym;
2404 char *contents, *loc;
2405 int min, max, n;
2406
2407 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002408 q = strchr(p, '=');
2409 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002410 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) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002422 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002423 }
2424
Miles Baderae28b042002-04-01 09:34:25 +00002425#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002426 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2427 strcpy(sym_name, SYMBOL_PREFIX);
2428 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002429#else
2430 sym_name = key;
2431#endif
2432 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002433
2434 /* Also check that the parameter was not resolved from the kernel. */
2435 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002436 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002437 }
2438
2439 if (isdigit(*p)) {
2440 min = strtoul(p, &p, 10);
2441 if (*p == '-')
2442 max = strtoul(p + 1, &p, 10);
2443 else
2444 max = min;
2445 } else
2446 min = max = 1;
2447
2448 contents = f->sections[sym->secidx]->contents;
2449 loc = contents + sym->value;
2450 n = (*++q != '\0');
2451
2452 while (1) {
2453 if ((*p == 's') || (*p == 'c')) {
2454 char *str;
2455
2456 /* Do C quoting if we begin with a ", else slurp the lot. */
2457 if (*q == '"') {
2458 char *r;
2459
2460 str = alloca(strlen(q));
2461 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002462 if (*q == '\0')
2463 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002464 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002465 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002466 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002467 case 'a':
2468 *r = '\a';
2469 break;
2470 case 'b':
2471 *r = '\b';
2472 break;
2473 case 'e':
2474 *r = '\033';
2475 break;
2476 case 'f':
2477 *r = '\f';
2478 break;
2479 case 'n':
2480 *r = '\n';
2481 break;
2482 case 'r':
2483 *r = '\r';
2484 break;
2485 case 't':
2486 *r = '\t';
2487 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002488
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002489 case '0':
2490 case '1':
2491 case '2':
2492 case '3':
2493 case '4':
2494 case '5':
2495 case '6':
2496 case '7':
2497 {
2498 int c = *q - '0';
2499 if (q[1] >= '0' && q[1] <= '7') {
2500 c = (c * 8) + *++q - '0';
2501 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002502 c = (c * 8) + *++q - '0';
2503 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002504 *r = c;
2505 }
2506 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002507
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002508 default:
2509 *r = *q;
2510 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002511 }
2512 else
2513 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002514 }
2515 *r = '\0';
2516 ++q;
2517 } else {
2518 char *r;
2519
2520 /* In this case, the string is not quoted. We will break
2521 it using the coma (like for ints). If the user wants to
2522 include comas in a string, he just has to quote it */
2523
2524 /* Search the next coma */
2525 r = strchr(q, ',');
2526
2527 /* Found ? */
2528 if (r != (char *) NULL) {
2529 /* Recopy the current field */
2530 str = alloca(r - q + 1);
2531 memcpy(str, q, r - q);
2532
Eric Andersenaff114c2004-04-14 17:51:38 +00002533 /* I don't know if it is useful, as the previous case
2534 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002535 str[r - q] = '\0';
2536
2537 /* Keep next fields */
2538 q = r;
2539 } else {
2540 /* last string */
2541 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002542 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002543 }
2544 }
2545
2546 if (*p == 's') {
2547 /* Normal string */
2548 obj_string_patch(f, sym->secidx, loc - contents, str);
2549 loc += tgt_sizeof_char_p;
2550 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002551 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002552 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002553
2554 /* Get the size of each member */
2555 /* Probably we should do that outside the loop ? */
2556 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002557 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002558 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002559 }
2560 charssize = strtoul(p + 1, (char **) NULL, 10);
2561
2562 /* Check length */
2563 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002564 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002565 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002566 }
2567
2568 /* Copy to location */
2569 strcpy((char *) loc, str);
2570 loc += charssize;
2571 }
2572 } else {
2573 long v = strtoul(q, &q, 0);
2574 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002575 case 'b':
2576 *loc++ = v;
2577 break;
2578 case 'h':
2579 *(short *) loc = v;
2580 loc += tgt_sizeof_short;
2581 break;
2582 case 'i':
2583 *(int *) loc = v;
2584 loc += tgt_sizeof_int;
2585 break;
2586 case 'l':
2587 *(long *) loc = v;
2588 loc += tgt_sizeof_long;
2589 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002590
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002591 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002592 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002593 }
2594 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002595 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002596 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002597 case '\0':
2598 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002599
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002600 case ' ':
2601 case '\t':
2602 case '\n':
2603 case '\r':
2604 ++q;
2605 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002606
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002607 case ',':
2608 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002609 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002610 }
2611 ++q;
2612 break;
2613
2614 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002615 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002616 }
2617 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002618 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002619 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002620 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002621 }
2622
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002623 argc--;
2624 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002625 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002626}
2627
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002628#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002629static int new_is_module_checksummed(struct obj_file *f)
2630{
2631 const char *p = get_modinfo_value(f, "using_checksums");
2632 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002633 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002634 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002635}
2636
2637/* Get the module's kernel version in the canonical integer form. */
2638
2639static int
2640new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2641{
2642 char *p, *q;
2643 int a, b, c;
2644
2645 p = get_modinfo_value(f, "kernel_version");
2646 if (p == NULL)
2647 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002648 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002649
2650 a = strtoul(p, &p, 10);
2651 if (*p != '.')
2652 return -1;
2653 b = strtoul(p + 1, &p, 10);
2654 if (*p != '.')
2655 return -1;
2656 c = strtoul(p + 1, &q, 10);
2657 if (p + 1 == q)
2658 return -1;
2659
2660 return a << 16 | b << 8 | c;
2661}
2662
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002663#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002664
2665
Eric Andersen9f16d612000-06-12 23:11:16 +00002666/* Fetch the loaded modules, and all currently exported symbols. */
2667
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002668static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002669{
2670 char *module_names, *mn;
2671 struct external_module *modules, *m;
2672 struct new_module_symbol *syms, *s;
2673 size_t ret, bufsize, nmod, nsyms, i, j;
2674
2675 /* Collect the loaded modules. */
2676
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002677 bufsize = 256;
2678 module_names = xmalloc(bufsize);
2679
2680 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002681 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002682 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002683 bufsize = ret;
2684 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002685 goto retry_modules_load;
2686 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002687 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002688 }
2689
2690 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002691
2692 /* Collect the modules' symbols. */
2693
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002694 if (nmod) {
Denis Vlasenko18c93022008-08-27 22:29:43 +00002695 ext_modules = modules = xzalloc(nmod * sizeof(*modules));
Mark Whitley94fd4802001-03-12 23:08:34 +00002696 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002697 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002698 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002699
Mark Whitley94fd4802001-03-12 23:08:34 +00002700 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2701 if (errno == ENOENT) {
2702 /* The module was removed out from underneath us. */
2703 continue;
2704 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002705 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002706 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002707
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002708 bufsize = 1024;
2709 syms = xmalloc(bufsize);
2710 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002711 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2712 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002713 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002714 bufsize = ret;
2715 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002716 goto retry_mod_sym_load;
2717 case ENOENT:
2718 /* The module was removed out from underneath us. */
2719 continue;
2720 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002721 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002722 }
2723 }
2724 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002725
Mark Whitley94fd4802001-03-12 23:08:34 +00002726 m->name = mn;
2727 m->addr = info.addr;
2728 m->nsyms = nsyms;
2729 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002730
Mark Whitley94fd4802001-03-12 23:08:34 +00002731 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2732 s->name += (unsigned long) syms;
2733 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002734 }
2735 }
2736
2737 /* Collect the kernel's symbols. */
2738
2739 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002740 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002741 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002742 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002743 bufsize = ret;
2744 syms = xrealloc(syms, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002745 goto retry_kern_sym_load;
2746 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002747 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002748 }
2749 nksyms = nsyms = ret;
2750 ksyms = syms;
2751
2752 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2753 s->name += (unsigned long) syms;
2754 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002755}
2756
2757
2758/* Return the kernel symbol checksum version, or zero if not used. */
2759
2760static int new_is_kernel_checksummed(void)
2761{
2762 struct new_module_symbol *s;
2763 size_t i;
2764
2765 /* Using_Versions is not the first symbol, but it should be in there. */
2766
2767 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2768 if (strcmp((char *) s->name, "Using_Versions") == 0)
2769 return s->value;
2770
2771 return 0;
2772}
2773
2774
Denis Vlasenko18c93022008-08-27 22:29:43 +00002775static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002776{
2777 struct obj_section *sec;
2778
2779 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002780 sizeof(struct new_module));
Denis Vlasenko18c93022008-08-27 22:29:43 +00002781 /* done by obj_create_alloced_section_first: */
2782 /*memset(sec->contents, 0, sizeof(struct new_module));*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002783
Miles Baderae28b042002-04-01 09:34:25 +00002784 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002785 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002786 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002787
2788 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002789 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002790}
2791
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002792#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002793/* add an entry to the __ksymtab section, creating it if necessary */
2794static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2795{
2796 struct obj_section *sec;
2797 ElfW(Addr) ofs;
2798
2799 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2800 * If __ksymtab is defined but not marked alloc, x out the first character
2801 * (no obj_delete routine) and create a new __ksymtab with the correct
2802 * characteristics.
2803 */
2804 sec = obj_find_section(f, "__ksymtab");
2805 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2806 *((char *)(sec->name)) = 'x'; /* override const */
2807 sec = NULL;
2808 }
2809 if (!sec)
2810 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002811 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002812 if (!sec)
2813 return;
2814 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002815 /* Empty section might be byte-aligned */
2816 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002817 ofs = sec->header.sh_size;
2818 obj_symbol_patch(f, sec->idx, ofs, sym);
2819 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2820 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2821}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002822#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002823
2824static int new_create_module_ksymtab(struct obj_file *f)
2825{
2826 struct obj_section *sec;
2827 int i;
2828
2829 /* We must always add the module references. */
2830
2831 if (n_ext_modules_used) {
2832 struct new_module_ref *dep;
2833 struct obj_symbol *tm;
2834
2835 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002836 (sizeof(struct new_module_ref)
2837 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002838 if (!sec)
2839 return 0;
2840
Miles Baderae28b042002-04-01 09:34:25 +00002841 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002842 dep = (struct new_module_ref *) sec->contents;
2843 for (i = 0; i < n_ext_modules; ++i)
2844 if (ext_modules[i].used) {
2845 dep->dep = ext_modules[i].addr;
2846 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002847 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002848 dep->next_ref = 0;
2849 ++dep;
2850 }
2851 }
2852
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002853 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002854 size_t nsyms;
2855 int *loaded;
2856
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002857 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002858
2859 /* We don't want to export symbols residing in sections that
2860 aren't loaded. There are a number of these created so that
2861 we make sure certain module options don't appear twice. */
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002862 i = f->header.e_shnum;
2863 loaded = alloca(sizeof(int) * i);
Eric Andersen9f16d612000-06-12 23:11:16 +00002864 while (--i >= 0)
2865 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2866
2867 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2868 struct obj_symbol *sym;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002869 for (sym = f->symtab[i]; sym; sym = sym->next) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002870 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002871 && sym->secidx <= SHN_HIRESERVE
2872 && (sym->secidx >= SHN_LORESERVE
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002873 || loaded[sym->secidx])
2874 ) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002875 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2876
2877 obj_symbol_patch(f, sec->idx, ofs, sym);
2878 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002879 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002880
2881 nsyms++;
2882 }
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002883 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002884 }
2885
2886 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2887 }
2888
2889 return 1;
2890}
2891
2892
2893static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002894new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002895{
2896 struct new_module *module;
2897 struct obj_section *sec;
2898 void *image;
2899 int ret;
2900 tgt_long m_addr;
2901
2902 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002903 if (!sec || !sec->contents) {
Denis Vlasenkof5d8c902008-06-26 14:32:57 +00002904 bb_perror_msg_and_die("corrupt module %s?", m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002905 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002906 module = (struct new_module *) sec->contents;
2907 m_addr = sec->header.sh_addr;
2908
2909 module->size_of_struct = sizeof(*module);
2910 module->size = m_size;
2911 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2912
2913 sec = obj_find_section(f, "__ksymtab");
2914 if (sec && sec->header.sh_size) {
2915 module->syms = sec->header.sh_addr;
2916 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2917 }
2918
2919 if (n_ext_modules_used) {
2920 sec = obj_find_section(f, ".kmodtab");
2921 module->deps = sec->header.sh_addr;
2922 module->ndeps = n_ext_modules_used;
2923 }
2924
2925 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002926 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002927 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002928 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002929
2930 sec = obj_find_section(f, "__ex_table");
2931 if (sec) {
2932 module->ex_table_start = sec->header.sh_addr;
2933 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2934 }
2935
2936 sec = obj_find_section(f, ".text.init");
2937 if (sec) {
2938 module->runsize = sec->header.sh_addr - m_addr;
2939 }
2940 sec = obj_find_section(f, ".data.init");
2941 if (sec) {
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002942 if (!module->runsize
2943 || module->runsize > sec->header.sh_addr - m_addr
2944 ) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002945 module->runsize = sec->header.sh_addr - m_addr;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00002946 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002947 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002948 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2949 if (sec && sec->header.sh_size) {
2950 module->archdata_start = (void*)sec->header.sh_addr;
2951 module->archdata_end = module->archdata_start + sec->header.sh_size;
2952 }
2953 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2954 if (sec && sec->header.sh_size) {
2955 module->kallsyms_start = (void*)sec->header.sh_addr;
2956 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2957 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002958
Eric Andersen9f16d612000-06-12 23:11:16 +00002959 /* Whew! All of the initialization is complete. Collect the final
2960 module image and give it to the kernel. */
2961
2962 image = xmalloc(m_size);
2963 obj_create_image(f, image);
2964
Eric Andersencb3b9b12004-06-22 11:50:52 +00002965 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002966 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002967 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002968
2969 free(image);
2970
2971 return ret == 0;
2972}
2973
Eric Andersen9f16d612000-06-12 23:11:16 +00002974
2975/*======================================================================*/
2976
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002977static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002978obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2979 const char *string)
2980{
2981 struct obj_string_patch *p;
2982 struct obj_section *strsec;
2983 size_t len = strlen(string) + 1;
2984 char *loc;
2985
2986 p = xmalloc(sizeof(*p));
2987 p->next = f->string_patches;
2988 p->reloc_secidx = secidx;
2989 p->reloc_offset = offset;
2990 f->string_patches = p;
2991
2992 strsec = obj_find_section(f, ".kstrtab");
2993 if (strsec == NULL) {
2994 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2995 p->string_offset = 0;
2996 loc = strsec->contents;
2997 } else {
2998 p->string_offset = strsec->header.sh_size;
2999 loc = obj_extend_section(strsec, len);
3000 }
3001 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00003002}
3003
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00003004static void
Eric Andersen9f16d612000-06-12 23:11:16 +00003005obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3006 struct obj_symbol *sym)
3007{
3008 struct obj_symbol_patch *p;
3009
3010 p = xmalloc(sizeof(*p));
3011 p->next = f->symbol_patches;
3012 p->reloc_secidx = secidx;
3013 p->reloc_offset = offset;
3014 p->sym = sym;
3015 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00003016}
3017
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003018static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003019{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003020 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003021
3022 for (i = 0; i < HASH_BUCKETS; ++i) {
3023 struct obj_symbol *sym;
3024 for (sym = f->symtab[i]; sym; sym = sym->next)
3025 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003026 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003027 sym->secidx = SHN_ABS;
3028 sym->value = 0;
3029 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003030 if (!flag_quiet)
3031 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003032 }
3033 }
3034 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003035}
3036
Eric Andersen044228d2001-07-17 01:12:36 +00003037static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003038{
3039 struct common_entry {
3040 struct common_entry *next;
3041 struct obj_symbol *sym;
3042 } *common_head = NULL;
3043
3044 unsigned long i;
3045
3046 for (i = 0; i < HASH_BUCKETS; ++i) {
3047 struct obj_symbol *sym;
3048 for (sym = f->symtab[i]; sym; sym = sym->next)
3049 if (sym->secidx == SHN_COMMON) {
3050 /* Collect all COMMON symbols and sort them by size so as to
3051 minimize space wasted by alignment requirements. */
3052 {
3053 struct common_entry **p, *n;
3054 for (p = &common_head; *p; p = &(*p)->next)
3055 if (sym->size <= (*p)->sym->size)
3056 break;
3057
3058 n = alloca(sizeof(*n));
3059 n->next = *p;
3060 n->sym = sym;
3061 *p = n;
3062 }
3063 }
3064 }
3065
3066 for (i = 1; i < f->local_symtab_size; ++i) {
3067 struct obj_symbol *sym = f->local_symtab[i];
3068 if (sym && sym->secidx == SHN_COMMON) {
3069 struct common_entry **p, *n;
3070 for (p = &common_head; *p; p = &(*p)->next)
3071 if (sym == (*p)->sym)
3072 break;
3073 else if (sym->size < (*p)->sym->size) {
3074 n = alloca(sizeof(*n));
3075 n->next = *p;
3076 n->sym = sym;
3077 *p = n;
3078 break;
3079 }
3080 }
3081 }
3082
3083 if (common_head) {
3084 /* Find the bss section. */
3085 for (i = 0; i < f->header.e_shnum; ++i)
3086 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3087 break;
3088
3089 /* If for some reason there hadn't been one, create one. */
3090 if (i == f->header.e_shnum) {
3091 struct obj_section *sec;
3092
Denis Vlasenko18c93022008-08-27 22:29:43 +00003093 f->header.e_shnum++;
Bernhard Reutner-Fischer5606b1c2008-07-09 17:56:53 +00003094 f->sections = xrealloc_vector(f->sections, 2, i);
Eric Andersen9f16d612000-06-12 23:11:16 +00003095 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003096
Eric Andersen9f16d612000-06-12 23:11:16 +00003097 sec->header.sh_type = SHT_PROGBITS;
3098 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3099 sec->name = ".bss";
3100 sec->idx = i;
3101 }
3102
3103 /* Allocate the COMMONS. */
3104 {
3105 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3106 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3107 struct common_entry *c;
3108
3109 for (c = common_head; c; c = c->next) {
3110 ElfW(Addr) align = c->sym->value;
3111
3112 if (align > max_align)
3113 max_align = align;
3114 if (bss_size & (align - 1))
3115 bss_size = (bss_size | (align - 1)) + 1;
3116
3117 c->sym->secidx = i;
3118 c->sym->value = bss_size;
3119
3120 bss_size += c->sym->size;
3121 }
3122
3123 f->sections[i]->header.sh_size = bss_size;
3124 f->sections[i]->header.sh_addralign = max_align;
3125 }
3126 }
3127
3128 /* For the sake of patch relocation and parameter initialization,
3129 allocate zeroed data for NOBITS sections now. Note that after
3130 this we cannot assume NOBITS are really empty. */
3131 for (i = 0; i < f->header.e_shnum; ++i) {
3132 struct obj_section *s = f->sections[i];
3133 if (s->header.sh_type == SHT_NOBITS) {
Denis Vlasenko18c93022008-08-27 22:29:43 +00003134 s->contents = NULL;
Eric Andersen21adca72000-12-06 18:18:26 +00003135 if (s->header.sh_size != 0)
Denis Vlasenko18c93022008-08-27 22:29:43 +00003136 s->contents = xzalloc(s->header.sh_size),
Eric Andersen9f16d612000-06-12 23:11:16 +00003137 s->header.sh_type = SHT_PROGBITS;
3138 }
3139 }
3140}
3141
Eric Andersen044228d2001-07-17 01:12:36 +00003142static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003143{
3144 unsigned long dot = 0;
3145 struct obj_section *sec;
3146
3147 /* Finalize the positions of the sections relative to one another. */
3148
3149 for (sec = f->load_order; sec; sec = sec->load_next) {
3150 ElfW(Addr) align;
3151
3152 align = sec->header.sh_addralign;
3153 if (align && (dot & (align - 1)))
3154 dot = (dot | (align - 1)) + 1;
3155
3156 sec->header.sh_addr = dot;
3157 dot += sec->header.sh_size;
3158 }
3159
3160 return dot;
3161}
3162
Eric Andersen044228d2001-07-17 01:12:36 +00003163static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003164{
3165 int i, n = f->header.e_shnum;
3166 int ret = 1;
3167
3168 /* Finalize the addresses of the sections. */
3169
3170 f->baseaddr = base;
3171 for (i = 0; i < n; ++i)
3172 f->sections[i]->header.sh_addr += base;
3173
3174 /* And iterate over all of the relocations. */
3175
3176 for (i = 0; i < n; ++i) {
3177 struct obj_section *relsec, *symsec, *targsec, *strsec;
3178 ElfW(RelM) * rel, *relend;
3179 ElfW(Sym) * symtab;
3180 const char *strtab;
3181
3182 relsec = f->sections[i];
3183 if (relsec->header.sh_type != SHT_RELM)
3184 continue;
3185
3186 symsec = f->sections[relsec->header.sh_link];
3187 targsec = f->sections[relsec->header.sh_info];
3188 strsec = f->sections[symsec->header.sh_link];
3189
3190 rel = (ElfW(RelM) *) relsec->contents;
3191 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3192 symtab = (ElfW(Sym) *) symsec->contents;
3193 strtab = (const char *) strsec->contents;
3194
3195 for (; rel < relend; ++rel) {
3196 ElfW(Addr) value = 0;
3197 struct obj_symbol *intsym = NULL;
3198 unsigned long symndx;
3199 ElfW(Sym) * extsym = 0;
3200 const char *errmsg;
3201
3202 /* Attempt to find a value to use for this relocation. */
3203
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003204 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003205 if (symndx) {
3206 /* Note we've already checked for undefined symbols. */
3207
3208 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003209 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003210 /* Local symbols we look up in the local table to be sure
3211 we get the one that is really intended. */
3212 intsym = f->local_symtab[symndx];
3213 } else {
3214 /* Others we look up in the hash table. */
3215 const char *name;
3216 if (extsym->st_name)
3217 name = strtab + extsym->st_name;
3218 else
3219 name = f->sections[extsym->st_shndx]->name;
3220 intsym = obj_find_symbol(f, name);
3221 }
3222
3223 value = obj_symbol_final_value(f, intsym);
3224 intsym->referenced = 1;
3225 }
3226#if SHT_RELM == SHT_RELA
3227#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3228 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003229 if (!extsym || !extsym->st_name
3230 || ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003231#endif
3232 value += rel->r_addend;
3233#endif
3234
3235 /* Do it! */
3236 switch (arch_apply_relocation
Denis Vlasenko68404f12008-03-17 09:00:54 +00003237 (f, targsec, /*symsec,*/ intsym, rel, value)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003238 ) {
3239 case obj_reloc_ok:
3240 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003241
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003242 case obj_reloc_overflow:
3243 errmsg = "Relocation overflow";
3244 goto bad_reloc;
3245 case obj_reloc_dangerous:
3246 errmsg = "Dangerous relocation";
3247 goto bad_reloc;
3248 case obj_reloc_unhandled:
3249 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003250bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003251 if (extsym) {
3252 bb_error_msg("%s of type %ld for %s", errmsg,
3253 (long) ELF_R_TYPE(rel->r_info),
3254 strtab + extsym->st_name);
3255 } else {
3256 bb_error_msg("%s of type %ld", errmsg,
3257 (long) ELF_R_TYPE(rel->r_info));
3258 }
3259 ret = 0;
3260 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003261 }
3262 }
3263 }
3264
3265 /* Finally, take care of the patches. */
3266
3267 if (f->string_patches) {
3268 struct obj_string_patch *p;
3269 struct obj_section *strsec;
3270 ElfW(Addr) strsec_base;
3271 strsec = obj_find_section(f, ".kstrtab");
3272 strsec_base = strsec->header.sh_addr;
3273
3274 for (p = f->string_patches; p; p = p->next) {
3275 struct obj_section *targsec = f->sections[p->reloc_secidx];
3276 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3277 = strsec_base + p->string_offset;
3278 }
3279 }
3280
3281 if (f->symbol_patches) {
3282 struct obj_symbol_patch *p;
3283
3284 for (p = f->symbol_patches; p; p = p->next) {
3285 struct obj_section *targsec = f->sections[p->reloc_secidx];
3286 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3287 = obj_symbol_final_value(f, p->sym);
3288 }
3289 }
3290
3291 return ret;
3292}
3293
Eric Andersen044228d2001-07-17 01:12:36 +00003294static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003295{
3296 struct obj_section *sec;
3297 ElfW(Addr) base = f->baseaddr;
3298
3299 for (sec = f->load_order; sec; sec = sec->load_next) {
3300 char *secimg;
3301
Eric Andersen2bf658d2001-02-24 20:01:53 +00003302 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003303 continue;
3304
3305 secimg = image + (sec->header.sh_addr - base);
3306
3307 /* Note that we allocated data for NOBITS sections earlier. */
3308 memcpy(secimg, sec->contents, sec->header.sh_size);
3309 }
3310
3311 return 1;
3312}
3313
3314/*======================================================================*/
3315
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003316static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM)
Eric Andersen9f16d612000-06-12 23:11:16 +00003317{
3318 struct obj_file *f;
3319 ElfW(Shdr) * section_headers;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003320 size_t shnum, i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003321 char *shstrtab;
3322
3323 /* Read the file header. */
3324
3325 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 f->symbol_cmp = strcmp;
3327 f->symbol_hash = obj_elf_hash;
3328 f->load_order_search_start = &f->load_order;
3329
3330 fseek(fp, 0, SEEK_SET);
3331 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003332 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 }
3334
3335 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003336 || f->header.e_ident[EI_MAG1] != ELFMAG1
3337 || f->header.e_ident[EI_MAG2] != ELFMAG2
3338 || f->header.e_ident[EI_MAG3] != ELFMAG3
3339 ) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003340 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003341 }
3342 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003343 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB)
3344 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3345 || !MATCH_MACHINE(f->header.e_machine)
3346 ) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003347 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003348 }
3349 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003350 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003351 }
3352
3353 /* Read the section headers. */
3354
3355 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003356 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 (unsigned long) f->header.e_shentsize,
3358 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003359 }
3360
3361 shnum = f->header.e_shnum;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003362 /* Growth of ->sections vector will be done by
3363 * xrealloc_vector(..., 2, ...), therefore we must allocate
3364 * at least 2^2 = 4 extra elements here. */
3365 f->sections = xzalloc(sizeof(f->sections[0]) * (shnum + 4));
Eric Andersen9f16d612000-06-12 23:11:16 +00003366
3367 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3368 fseek(fp, f->header.e_shoff, SEEK_SET);
3369 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003370 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003371 }
3372
3373 /* Read the section data. */
3374
3375 for (i = 0; i < shnum; ++i) {
3376 struct obj_section *sec;
3377
3378 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003379
3380 sec->header = section_headers[i];
3381 sec->idx = i;
3382
Denis Vlasenko51742f42007-04-12 00:32:05 +00003383 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003384 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003385 case SHT_NULL:
3386 case SHT_NOTE:
3387 case SHT_NOBITS:
3388 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003389 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003390
3391 case SHT_PROGBITS:
3392#if LOADBITS
3393 if (!loadprogbits) {
3394 sec->contents = NULL;
3395 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003397#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003398 case SHT_SYMTAB:
3399 case SHT_STRTAB:
3400 case SHT_RELM:
Denis Vlasenko18c93022008-08-27 22:29:43 +00003401 sec->contents = NULL;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003402 if (sec->header.sh_size > 0) {
Denis Vlasenko18c93022008-08-27 22:29:43 +00003403 sec->contents = xzalloc(sec->header.sh_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00003404 fseek(fp, sec->header.sh_offset, SEEK_SET);
3405 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003406 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003407 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003408 }
3409 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003410
3411#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003412 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003413 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003414#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003415 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003416 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003417#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003418 default:
3419 if (sec->header.sh_type >= SHT_LOPROC) {
3420 /* Assume processor specific section types are debug
3421 info and can safely be ignored. If this is ever not
3422 the case (Hello MIPS?), don't put ifdefs here but
3423 create an arch_load_proc_section(). */
3424 break;
3425 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003426
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003427 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003428 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003429 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003430 }
3431 }
3432
3433 /* Do what sort of interpretation as needed by each section. */
3434
3435 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3436
3437 for (i = 0; i < shnum; ++i) {
3438 struct obj_section *sec = f->sections[i];
3439 sec->name = shstrtab + sec->header.sh_name;
3440 }
3441
3442 for (i = 0; i < shnum; ++i) {
3443 struct obj_section *sec = f->sections[i];
3444
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003445 /* .modinfo should be contents only but gcc has no attribute for that.
3446 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3447 */
3448 if (strcmp(sec->name, ".modinfo") == 0)
3449 sec->header.sh_flags &= ~SHF_ALLOC;
3450
Eric Andersen9f16d612000-06-12 23:11:16 +00003451 if (sec->header.sh_flags & SHF_ALLOC)
3452 obj_insert_section_load_order(f, sec);
3453
3454 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003455 case SHT_SYMTAB:
3456 {
3457 unsigned long nsym, j;
3458 char *strtab;
3459 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003460
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003461 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003462 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003463 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003464 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003465 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003466
3467 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3468 strtab = f->sections[sec->header.sh_link]->contents;
3469 sym = (ElfW(Sym) *) sec->contents;
3470
3471 /* Allocate space for a table of local symbols. */
3472 j = f->local_symtab_size = sec->header.sh_info;
3473 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3474
3475 /* Insert all symbols into the hash table. */
3476 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3477 ElfW(Addr) val = sym->st_value;
3478 const char *name;
3479 if (sym->st_name)
3480 name = strtab + sym->st_name;
3481 else if (sym->st_shndx < shnum)
3482 name = f->sections[sym->st_shndx]->name;
3483 else
3484 continue;
3485#if defined(__SH5__)
3486 /*
3487 * For sh64 it is possible that the target of a branch
3488 * requires a mode switch (32 to 16 and back again).
3489 *
3490 * This is implied by the lsb being set in the target
3491 * address for SHmedia mode and clear for SHcompact.
3492 */
3493 val |= sym->st_other & 4;
3494#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003495 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3496 val, sym->st_size);
3497 }
3498 }
3499 break;
3500
3501 case SHT_RELM:
3502 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003503 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003504 (unsigned long) sec->header.sh_entsize,
3505 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003506 }
3507 break;
3508 /* XXX Relocation code from modutils-2.3.19 is not here.
3509 * Why? That's about 20 lines of code from obj/obj_load.c,
3510 * which gets done in a second pass through the sections.
3511 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003512 }
3513 }
3514
3515 return f;
3516}
3517
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003518#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003519/*
3520 * load the unloaded sections directly into the memory allocated by
3521 * kernel for the module
3522 */
3523
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +00003524static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003525{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003526 ElfW(Addr) base = f->baseaddr;
3527 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003528
Eric Andersen8ae319a2001-05-21 16:09:18 +00003529 for (sec = f->load_order; sec; sec = sec->load_next) {
3530
3531 /* section already loaded? */
3532 if (sec->contents != NULL)
3533 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003534
Eric Andersen8ae319a2001-05-21 16:09:18 +00003535 if (sec->header.sh_size == 0)
3536 continue;
3537
3538 sec->contents = imagebase + (sec->header.sh_addr - base);
3539 fseek(fp, sec->header.sh_offset, SEEK_SET);
3540 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003541 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003542 return 0;
3543 }
3544
3545 }
3546 return 1;
3547}
3548#endif
3549
Eric Andersen9f16d612000-06-12 23:11:16 +00003550static void hide_special_symbols(struct obj_file *f)
3551{
3552 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003553 SPFX "cleanup_module",
3554 SPFX "init_module",
3555 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003556 NULL
3557 };
3558
3559 struct obj_symbol *sym;
3560 const char *const *p;
3561
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003562 for (p = specials; *p; ++p) {
3563 sym = obj_find_symbol(f, *p);
3564 if (sym != NULL)
3565 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3566 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003567}
3568
Glenn L McGrath759515c2003-08-30 06:00:33 +00003569
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003570#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003571static int obj_gpl_license(struct obj_file *f, const char **license)
3572{
3573 struct obj_section *sec;
3574 /* This list must match *exactly* the list of allowable licenses in
3575 * linux/include/linux/module.h. Checking for leading "GPL" will not
3576 * work, somebody will use "GPL sucks, this is proprietary".
3577 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003578 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003579 "GPL",
3580 "GPL v2",
3581 "GPL and additional rights",
3582 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003583 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003584 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003585
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003586 sec = obj_find_section(f, ".modinfo");
3587 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003588 const char *value, *ptr, *endptr;
3589 ptr = sec->contents;
3590 endptr = ptr + sec->header.sh_size;
3591 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003592 value = strchr(ptr, '=');
3593 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003594 unsigned i;
Eric Andersen166fa462002-09-16 05:30:24 +00003595 if (license)
3596 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003597 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003598 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003599 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003600 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003601 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003602 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003603 ptr = strchr(ptr, '\0');
3604 if (ptr)
3605 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003606 else
3607 ptr = endptr;
3608 }
3609 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003610 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003611}
3612
3613#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003614#define TAINT_PROPRIETORY_MODULE (1 << 0)
3615#define TAINT_FORCED_MODULE (1 << 1)
3616#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003617#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003618
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003619static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003620 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3621{
Denis Vlasenko931de892007-06-21 12:43:45 +00003622 static smallint printed_info;
3623
Eric Andersen166fa462002-09-16 05:30:24 +00003624 char buf[80];
3625 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003626
Eric Andersen166fa462002-09-16 05:30:24 +00003627 if (fd < 0 && !kernel_has_tainted)
3628 return; /* New modutils on old kernel */
3629 printf("Warning: loading %s will taint the kernel: %s%s\n",
3630 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003631 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003632 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003633 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003634 }
3635 if (fd >= 0) {
3636 read(fd, buf, sizeof(buf)-1);
3637 buf[sizeof(buf)-1] = '\0';
3638 oldval = strtoul(buf, NULL, 10);
3639 sprintf(buf, "%d\n", oldval | taint);
3640 write(fd, buf, strlen(buf));
3641 }
3642}
3643
3644/* Check if loading this module will taint the kernel. */
3645static void check_tainted_module(struct obj_file *f, char *m_name)
3646{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003647 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3648
Eric Andersen166fa462002-09-16 05:30:24 +00003649 int fd, kernel_has_tainted;
3650 const char *ptr;
3651
3652 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003653 fd = open(tainted_file, O_RDWR);
3654 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003655 if (errno == ENOENT)
3656 kernel_has_tainted = 0;
3657 else if (errno == EACCES)
3658 kernel_has_tainted = 1;
3659 else {
3660 perror(tainted_file);
3661 kernel_has_tainted = 0;
3662 }
3663 }
3664
3665 switch (obj_gpl_license(f, &ptr)) {
3666 case 0:
3667 break;
3668 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003669 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003670 break;
3671 case 2:
3672 /* The module has a non-GPL license so we pretend that the
3673 * kernel always has a taint flag to get a warning even on
3674 * kernels without the proc flag.
3675 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003676 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003677 break;
3678 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003679 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003680 break;
3681 }
3682
3683 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003684 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003685
3686 if (fd >= 0)
3687 close(fd);
3688}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003689#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003690#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003691#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003692
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003693#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003694/* add module source, timestamp, kernel version and a symbol for the
3695 * start of some sections. this info is used by ksymoops to do better
3696 * debugging.
3697 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00003698#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3699#define get_module_version(f, str) get_module_version(str)
3700#endif
Eric Andersen889dd202003-01-23 04:48:34 +00003701static int
3702get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3703{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003704#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003705 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003706#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003707 strncpy(str, "???", sizeof(str));
3708 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003709#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003710}
3711
3712/* add module source, timestamp, kernel version and a symbol for the
3713 * start of some sections. this info is used by ksymoops to do better
3714 * debugging.
3715 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003716static void
Eric Andersen889dd202003-01-23 04:48:34 +00003717add_ksymoops_symbols(struct obj_file *f, const char *filename,
3718 const char *m_name)
3719{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003720 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003721 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003722 ".text",
3723 ".rodata",
3724 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003725 ".bss",
3726 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003727 };
3728
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003729 struct obj_section *sec;
3730 struct obj_symbol *sym;
3731 char *name, *absolute_filename;
3732 char str[STRVERSIONLEN];
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003733 unsigned i;
3734 int l, lm_name, lfilename, use_ksymtab, version;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003735 struct stat statbuf;
3736
3737 /* WARNING: was using realpath, but replaced by readlink to stop using
3738 * lots of stack. But here it seems to be able to cause problems? */
3739 absolute_filename = xmalloc_readlink(filename);
3740 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003741 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003742
3743 lm_name = strlen(m_name);
3744 lfilename = strlen(absolute_filename);
3745
3746 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3747 * are not to be exported. otherwise leave ksymtab alone for now, the
3748 * "export all symbols" compatibility code will export these symbols later.
3749 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003750 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003751
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003752 sec = obj_find_section(f, ".this");
3753 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003754 /* tag the module header with the object name, last modified
3755 * timestamp and module version. worst case for module version
3756 * is 0xffffff, decimal 16777215. putting all three fields in
3757 * one symbol is less readable but saves kernel space.
3758 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003759 l = sizeof(symprefix) + /* "__insmod_" */
3760 lm_name + /* module name */
3761 2 + /* "_O" */
3762 lfilename + /* object filename */
3763 2 + /* "_M" */
3764 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3765 2 + /* "_V" */
3766 8 + /* version in dec */
3767 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003768 name = xmalloc(l);
3769 if (stat(absolute_filename, &statbuf) != 0)
3770 statbuf.st_mtime = 0;
3771 version = get_module_version(f, str); /* -1 if not found */
3772 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003773 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003774 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003775 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003776 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003777 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003778 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003779 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003780 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003781 }
3782 free(absolute_filename);
3783#ifdef _NOT_SUPPORTED_
3784 /* record where the persistent data is going, same address as previous symbol */
3785
3786 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003787 l = sizeof(symprefix) + /* "__insmod_" */
3788 lm_name + /* module name */
3789 2 + /* "_P" */
3790 strlen(f->persist) + /* data store */
3791 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003792 name = xmalloc(l);
3793 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003794 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003795 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003796 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003797 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003798 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003799 }
3800#endif /* _NOT_SUPPORTED_ */
3801 /* tag the desired sections if size is non-zero */
3802
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003803 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003804 sec = obj_find_section(f, section_names[i]);
3805 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003806 l = sizeof(symprefix) + /* "__insmod_" */
3807 lm_name + /* module name */
3808 2 + /* "_S" */
3809 strlen(sec->name) + /* section name */
3810 2 + /* "_L" */
3811 8 + /* length in dec */
3812 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003813 name = xmalloc(l);
3814 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003815 symprefix, m_name, sec->name,
3816 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003817 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003818 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003819 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003820 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003821 }
3822 }
3823}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003824#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003825
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003826#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003827static void print_load_map(struct obj_file *f)
3828{
Eric Andersenbe65c352003-01-23 04:57:35 +00003829 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003830#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3831 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003832 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003833 struct obj_symbol *sym;
3834#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003835 /* Report on the section layout. */
3836
3837 printf("Sections: Size %-*s Align\n",
3838 (int) (2 * sizeof(void *)), "Address");
3839
3840 for (sec = f->load_order; sec; sec = sec->load_next) {
3841 int a;
3842 unsigned long tmp;
3843
3844 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3845 tmp >>= 1;
3846 if (a == -1)
3847 a = 0;
3848
3849 printf("%-15s %08lx %0*lx 2**%d\n",
3850 sec->name,
3851 (long)sec->header.sh_size,
3852 (int) (2 * sizeof(void *)),
3853 (long)sec->header.sh_addr,
3854 a);
3855 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003856#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Bernhard Reutner-Fischer0328b402008-07-21 11:18:02 +00003857 /* Quick reference which section indices are loaded. */
Eric Andersenbe65c352003-01-23 04:57:35 +00003858
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003859 i = f->header.e_shnum;
3860 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003861 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003862 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003863
3864 /* Collect the symbols we'll be listing. */
3865
3866 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3867 for (sym = f->symtab[i]; sym; sym = sym->next)
3868 if (sym->secidx <= SHN_HIRESERVE
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003869 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
3870 ) {
Eric Andersenbe65c352003-01-23 04:57:35 +00003871 ++nsyms;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003872 }
Eric Andersenbe65c352003-01-23 04:57:35 +00003873
3874 all = alloca(nsyms * sizeof(struct obj_symbol *));
3875
3876 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3877 for (sym = f->symtab[i]; sym; sym = sym->next)
3878 if (sym->secidx <= SHN_HIRESERVE
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003879 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx])
3880 ) {
Eric Andersenbe65c352003-01-23 04:57:35 +00003881 *p++ = sym;
Denis Vlasenko3b80cac2008-08-28 21:38:10 +00003882 }
Eric Andersenbe65c352003-01-23 04:57:35 +00003883
3884 /* And list them. */
3885 printf("\nSymbols:\n");
3886 for (p = all; p < all + nsyms; ++p) {
3887 char type = '?';
3888 unsigned long value;
3889
3890 sym = *p;
3891 if (sym->secidx == SHN_ABS) {
3892 type = 'A';
3893 value = sym->value;
3894 } else if (sym->secidx == SHN_UNDEF) {
3895 type = 'U';
3896 value = 0;
3897 } else {
3898 sec = f->sections[sym->secidx];
3899
3900 if (sec->header.sh_type == SHT_NOBITS)
3901 type = 'B';
3902 else if (sec->header.sh_flags & SHF_ALLOC) {
3903 if (sec->header.sh_flags & SHF_EXECINSTR)
3904 type = 'T';
3905 else if (sec->header.sh_flags & SHF_WRITE)
3906 type = 'D';
3907 else
3908 type = 'R';
3909 }
3910 value = sym->value + sec->header.sh_addr;
3911 }
3912
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003913 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003914 type = tolower(type);
3915
3916 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3917 type, sym->name);
3918 }
3919#endif
3920}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003921#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003922void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003923#endif
3924
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003925int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3926int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003927{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003928 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003929 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003930 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003931 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003932 unsigned long m_size;
3933 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003934 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003935 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003936 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003937 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003938 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003939#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003940 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003941 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003942 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003943#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003944#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003945 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003946#else
3947 FILE *fp;
3948#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003949 int k_version = 0;
3950 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003951
Erik Andersene49d5ec2000-02-08 19:58:47 +00003952 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003953 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003954 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003955 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003956 free(m_name);
3957 m_name = xstrdup(opt_o);
3958 }
Eric Andersen03d80912003-12-19 21:04:19 +00003959
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003960 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003961 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003962 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003963
Erik Andersene49d5ec2000-02-08 19:58:47 +00003964 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003965 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003966 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003967 len = strlen(tmp);
3968
Eric Andersen03d80912003-12-19 21:04:19 +00003969 if (uname(&myuname) == 0) {
3970 if (myuname.release[0] == '2') {
3971 k_version = myuname.release[2] - '0';
3972 }
3973 }
3974
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003975#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003976 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3977 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3978 ) {
3979 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003980 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003981 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003982#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003983 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003984 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003985 tmp[len] = '\0';
3986 }
Eric Andersen2d342152002-06-18 05:16:25 +00003987
Eric Andersen03d80912003-12-19 21:04:19 +00003988
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003989#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003990 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003991 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003992 else
Eric Andersen03d80912003-12-19 21:04:19 +00003993#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003994 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003995
Eric Andersen61f83052002-06-22 17:15:42 +00003996 if (!m_name) {
3997 m_name = tmp;
3998 } else {
3999 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004000 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00004001 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004002
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004003 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004004 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
Denis Vlasenko5415c852008-07-21 23:05:26 +00004005 || (fp = fopen_for_read(arg1)) == NULL
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004006 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00004007 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4008 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004009 if (k_version) { /* uname succeedd */
4010 char *module_dir;
4011 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00004012
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004013 tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004014 /* Jump through hoops in case /lib/modules/`uname -r`
4015 * is a symlink. We do not want recursive_action to
4016 * follow symlinks, but we do want to follow the
4017 * /lib/modules/`uname -r` dir, So resolve it ourselves
4018 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004019 module_dir = xmalloc_readlink(tmdn);
4020 if (!module_dir)
4021 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004022 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004023 check_module_name_match, NULL, m_fullName, 0);
4024 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004025 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004026 }
4027
4028 /* Check if we have found anything yet */
Denis Vlasenko5415c852008-07-21 23:05:26 +00004029 if (!m_filename || ((fp = fopen_for_read(m_filename)) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004030 int r;
4031 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004032
Eric Andersen03d80912003-12-19 21:04:19 +00004033 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004034 m_filename = NULL;
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004035 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004036 if (!module_dir)
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004037 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
Eric Andersen14d35432001-05-14 17:07:32 +00004038 /* No module found under /lib/modules/`uname -r`, this
4039 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004040 r = recursive_action(module_dir, ACTION_RECURSE,
4041 check_module_name_match, NULL, m_fullName, 0);
4042 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004043 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004044 free(module_dir);
4045 if (m_filename == NULL
Denis Vlasenko5415c852008-07-21 23:05:26 +00004046 || ((fp = fopen_for_read(m_filename)) == NULL)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004047 ) {
4048 bb_error_msg_and_die("%s: module not found", m_fullName);
4049 }
Eric Andersen14d35432001-05-14 17:07:32 +00004050 }
Eric Andersen03d80912003-12-19 21:04:19 +00004051 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004052 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004053
Rob Landley999af202005-12-11 20:14:12 +00004054 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004055 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004056
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004057#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004058 if (k_version > 4) {
4059 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004060 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004061 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004062 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004063#endif
4064
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004065 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004066
Eric Andersen9f16d612000-06-12 23:11:16 +00004067 if (get_modinfo_value(f, "kernel_version") == NULL)
4068 m_has_modinfo = 0;
4069 else
4070 m_has_modinfo = 1;
4071
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004072#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004073 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004074 if (!flag_quiet) {
4075 if (uname(&uts_info) < 0)
4076 uts_info.release[0] = '\0';
4077 if (m_has_modinfo) {
4078 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004079 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004080 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004081 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004082 }
4083 }
4084
4085 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004086 bb_error_msg("%skernel-module version mismatch\n"
4087 "\t%s was compiled for kernel version %s\n"
4088 "\twhile this kernel is version %s",
4089 flag_force_load ? "warning: " : "",
4090 m_filename, m_strversion, uts_info.release);
4091 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004092 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004093 }
4094 }
4095 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004096#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004097
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004098 if (query_module(NULL, 0, NULL, 0, NULL))
4099 bb_error_msg_and_die("not configured to support old kernels");
4100 new_get_kernel_symbols();
4101 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004102
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004103#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004104 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004105 if (m_has_modinfo)
4106 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004107
4108 if (m_crcs != k_crcs)
4109 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004110#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004111
Erik Andersene49d5ec2000-02-08 19:58:47 +00004112 /* Let the module know about the kernel symbols. */
4113 add_kernel_symbols(f);
4114
Eric Andersen9f16d612000-06-12 23:11:16 +00004115 /* Allocate common symbols, symbol tables, and string tables. */
4116
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004117 new_create_this_module(f, m_name);
4118 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004119 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004120 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004121
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004122 /* done with the module name, on to the optional var=value arguments */
4123 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004124 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004125 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004126 }
4127
Eric Andersen9f16d612000-06-12 23:11:16 +00004128 arch_create_got(f);
4129 hide_special_symbols(f);
4130
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004131#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004132 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004133#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004134
Eric Andersencb3b9b12004-06-22 11:50:52 +00004135 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004136
Erik Andersene49d5ec2000-02-08 19:58:47 +00004137 /* Find current size of the module */
4138 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004139
Erik Andersene49d5ec2000-02-08 19:58:47 +00004140 m_addr = create_module(m_name, m_size);
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00004141 if (m_addr == (ElfW(Addr))(-1)) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004142 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004143 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004144 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004145 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004146 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004147 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004148 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004149 }
Erik Andersend387d011999-12-21 02:55:11 +00004150
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004151#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004152 /*
4153 * the PROGBITS section was not loaded by the obj_load
4154 * now we can load them directly into the kernel memory
4155 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004156 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004157 delete_module(m_name, 0);
Eric Andersen8ae319a2001-05-21 16:09:18 +00004158 goto out;
4159 }
Eric Andersen03d80912003-12-19 21:04:19 +00004160#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004161
Eric Andersen9f16d612000-06-12 23:11:16 +00004162 if (!obj_relocate(f, m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004163 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004164 goto out;
4165 }
Erik Andersend387d011999-12-21 02:55:11 +00004166
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004167 if (!new_init_module(m_name, f, m_size)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004168 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004169 goto out;
4170 }
4171
Denis Vlasenko51742f42007-04-12 00:32:05 +00004172 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004173 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004174
Matt Kraai3e856ce2000-12-01 02:55:13 +00004175 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004176
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004177 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004178#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004179 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004180 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004181 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004182 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004183 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004184 free(m_filename);
4185#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004186 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004187}
Eric Andersene7047882003-12-11 01:42:13 +00004188
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004189#endif /* ENABLE_FEATURE_2_4_MODULES */
4190/*
4191 * End of big piece of 2.4-specific code
4192 */
Eric Andersene7047882003-12-11 01:42:13 +00004193
4194
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004195#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004196
4197#include <sys/mman.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004198
Bernhard Reutner-Fischer15102162008-05-27 13:27:18 +00004199#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES
4200/* big time suckage. The old prototype above renders our nice fwd-decl wrong */
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004201extern int init_module(void *module, unsigned long len, const char *options);
4202#else
Eric Andersene7047882003-12-11 01:42:13 +00004203#include <asm/unistd.h>
4204#include <sys/syscall.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004205#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
4206#endif
Eric Andersene7047882003-12-11 01:42:13 +00004207
4208/* We use error numbers in a loose translation... */
4209static const char *moderror(int err)
4210{
4211 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004212 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004213 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004214 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004215 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004216 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004217 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004218 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004219 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004220 default:
4221 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004222 }
4223}
4224
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004225#if !ENABLE_FEATURE_2_4_MODULES
4226int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004227int insmod_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004228#else
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004229static int insmod_ng_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004230#endif
Eric Andersene7047882003-12-11 01:42:13 +00004231{
Denis Vlasenko92297942006-11-21 11:58:14 +00004232 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004233 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004234 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004235 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004236
Denis Vlasenko92297942006-11-21 11:58:14 +00004237 filename = *++argv;
4238 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004239 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004240
4241 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004242 options = xzalloc(1);
4243 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004244 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004245 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004246 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004247 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004248 }
4249
Denis Vlasenko92297942006-11-21 11:58:14 +00004250#if 0
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004251 /* Any special reason why mmap? It isn't performance critical. -vda */
4252 /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +00004253 * modules out there that are half a megabyte! mmap()ing is way nicer
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004254 * for small mem boxes, i guess. */
4255 /* But after load, these modules will take up that 0.5mb in kernel
4256 * anyway. Using malloc here causes only a transient spike to 1mb,
4257 * after module is loaded, we go back to normal 0.5mb usage
4258 * (in kernel). Also, mmap isn't magic - when we touch mapped data,
4259 * we use memory. -vda */
Denis Vlasenko92297942006-11-21 11:58:14 +00004260 int fd;
4261 struct stat st;
4262 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004263 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004264 fstat(fd, &st);
4265 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004266 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004267 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004268 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004269 }
4270
Denis Vlasenko92297942006-11-21 11:58:14 +00004271 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4272 if (map == NULL) {
4273 map = xmalloc(len);
4274 xread(fd, map, len);
4275 }
4276#else
4277 len = MAXINT(ssize_t);
4278 map = xmalloc_open_read_close(filename, &len);
4279#endif
4280
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004281 if (init_module(map, len, options) != 0)
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004282 bb_error_msg_and_die("cannot insert '%s': %s",
4283 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004284 return 0;
4285}
4286
4287#endif