blob: 01b619f7e67a7b104480514cc6e1e75a5741864a [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;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001062 if ((ElfW(Sword))v > 0x7f ||
1063 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001064 ret = obj_reloc_overflow;
1065 }
1066 *(char *)loc = v;
1067 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001068
Eric Andersen3b1a7442003-12-24 20:30:45 +00001069 case R_68K_PC16:
1070 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001071 if ((ElfW(Sword))v > 0x7fff ||
1072 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001073 ret = obj_reloc_overflow;
1074 }
1075 *(short *)loc = v;
1076 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001077
Eric Andersen3b1a7442003-12-24 20:30:45 +00001078 case R_68K_PC32:
1079 *(int *)loc = v - dot;
1080 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001081
Eric Andersen3b1a7442003-12-24 20:30:45 +00001082 case R_68K_GLOB_DAT:
1083 case R_68K_JMP_SLOT:
1084 *loc = v;
1085 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001086
Eric Andersen3b1a7442003-12-24 20:30:45 +00001087 case R_68K_RELATIVE:
1088 *(int *)loc += f->baseaddr;
1089 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001090
Eric Andersen3b1a7442003-12-24 20:30:45 +00001091 case R_68K_GOT32:
1092 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001093
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001094# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001096 *loc += v - got;
1097 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001098# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001099
1100#elif defined(__mips__)
1101
Eric Andersen3b1a7442003-12-24 20:30:45 +00001102 case R_MIPS_NONE:
1103 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001104
Eric Andersen3b1a7442003-12-24 20:30:45 +00001105 case R_MIPS_32:
1106 *loc += v;
1107 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001108
Eric Andersen3b1a7442003-12-24 20:30:45 +00001109 case R_MIPS_26:
1110 if (v % 4)
1111 ret = obj_reloc_dangerous;
1112 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1113 ret = obj_reloc_overflow;
1114 *loc =
1115 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1116 0x03ffffff);
1117 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001118
Eric Andersen3b1a7442003-12-24 20:30:45 +00001119 case R_MIPS_HI16:
1120 {
1121 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001122
Eric Andersen3b1a7442003-12-24 20:30:45 +00001123 /* We cannot relocate this one now because we don't know the value
1124 of the carry we need to add. Save the information, and let LO16
1125 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001126 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001127 n->addr = loc;
1128 n->value = v;
1129 n->next = ifile->mips_hi16_list;
1130 ifile->mips_hi16_list = n;
1131 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001132 }
1133
Eric Andersen3b1a7442003-12-24 20:30:45 +00001134 case R_MIPS_LO16:
1135 {
1136 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001137 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001138
1139 /* Sign extend the addend we extract from the lo insn. */
1140 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1141
1142 if (ifile->mips_hi16_list != NULL) {
1143 struct mips_hi16 *l;
1144
1145 l = ifile->mips_hi16_list;
1146 while (l != NULL) {
1147 struct mips_hi16 *next;
1148 unsigned long insn;
1149
Eric Andersen3b1a7442003-12-24 20:30:45 +00001150 /* Do the HI16 relocation. Note that we actually don't
1151 need to know anything about the LO16 itself, except where
1152 to find the low 16 bits of the addend needed by the LO16. */
1153 insn = *l->addr;
1154 val =
1155 ((insn & 0xffff) << 16) +
1156 vallo;
1157 val += v;
1158
1159 /* Account for the sign extension that will happen in the
1160 low bits. */
1161 val =
1162 ((val >> 16) +
1163 ((val & 0x8000) !=
1164 0)) & 0xffff;
1165
1166 insn = (insn & ~0xffff) | val;
1167 *l->addr = insn;
1168
1169 next = l->next;
1170 free(l);
1171 l = next;
1172 }
1173
1174 ifile->mips_hi16_list = NULL;
1175 }
1176
1177 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1178 val = v + vallo;
1179 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1180 *loc = insnlo;
1181 break;
1182 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001183
Mike Frysingerf982d862006-01-04 00:11:26 +00001184#elif defined(__nios2__)
1185
1186 case R_NIOS2_NONE:
1187 break;
1188
1189 case R_NIOS2_BFD_RELOC_32:
1190 *loc += v;
1191 break;
1192
1193 case R_NIOS2_BFD_RELOC_16:
1194 if (v > 0xffff) {
1195 ret = obj_reloc_overflow;
1196 }
1197 *(short *)loc = v;
1198 break;
1199
1200 case R_NIOS2_BFD_RELOC_8:
1201 if (v > 0xff) {
1202 ret = obj_reloc_overflow;
1203 }
1204 *(char *)loc = v;
1205 break;
1206
1207 case R_NIOS2_S16:
1208 {
1209 Elf32_Addr word;
1210
1211 if ((Elf32_Sword)v > 0x7fff ||
1212 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1213 ret = obj_reloc_overflow;
1214 }
1215
1216 word = *loc;
1217 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1218 (word & 0x3f);
1219 }
1220 break;
1221
1222 case R_NIOS2_U16:
1223 {
1224 Elf32_Addr word;
1225
1226 if (v > 0xffff) {
1227 ret = obj_reloc_overflow;
1228 }
1229
1230 word = *loc;
1231 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1232 (word & 0x3f);
1233 }
1234 break;
1235
1236 case R_NIOS2_PCREL16:
1237 {
1238 Elf32_Addr word;
1239
1240 v -= dot + 4;
1241 if ((Elf32_Sword)v > 0x7fff ||
1242 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1243 ret = obj_reloc_overflow;
1244 }
1245
1246 word = *loc;
1247 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1248 }
1249 break;
1250
1251 case R_NIOS2_GPREL:
1252 {
1253 Elf32_Addr word, gp;
1254 /* get _gp */
1255 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1256 v-=gp;
1257 if ((Elf32_Sword)v > 0x7fff ||
1258 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1259 ret = obj_reloc_overflow;
1260 }
1261
1262 word = *loc;
1263 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1264 }
1265 break;
1266
1267 case R_NIOS2_CALL26:
1268 if (v & 3)
1269 ret = obj_reloc_dangerous;
1270 if ((v >> 28) != (dot >> 28))
1271 ret = obj_reloc_overflow;
1272 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1273 break;
1274
1275 case R_NIOS2_IMM5:
1276 {
1277 Elf32_Addr word;
1278
1279 if (v > 0x1f) {
1280 ret = obj_reloc_overflow;
1281 }
1282
1283 word = *loc & ~0x7c0;
1284 *loc = word | ((v & 0x1f) << 6);
1285 }
1286 break;
1287
1288 case R_NIOS2_IMM6:
1289 {
1290 Elf32_Addr word;
1291
1292 if (v > 0x3f) {
1293 ret = obj_reloc_overflow;
1294 }
1295
1296 word = *loc & ~0xfc0;
1297 *loc = word | ((v & 0x3f) << 6);
1298 }
1299 break;
1300
1301 case R_NIOS2_IMM8:
1302 {
1303 Elf32_Addr word;
1304
1305 if (v > 0xff) {
1306 ret = obj_reloc_overflow;
1307 }
1308
1309 word = *loc & ~0x3fc0;
1310 *loc = word | ((v & 0xff) << 6);
1311 }
1312 break;
1313
1314 case R_NIOS2_HI16:
1315 {
1316 Elf32_Addr word;
1317
1318 word = *loc;
1319 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1320 (word & 0x3f);
1321 }
1322 break;
1323
1324 case R_NIOS2_LO16:
1325 {
1326 Elf32_Addr word;
1327
1328 word = *loc;
1329 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1330 (word & 0x3f);
1331 }
1332 break;
1333
1334 case R_NIOS2_HIADJ16:
1335 {
1336 Elf32_Addr word1, word2;
1337
1338 word1 = *loc;
1339 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1340 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1341 (word1 & 0x3f);
1342 }
1343 break;
1344
Mike Frysingerebee0e72006-02-18 06:14:31 +00001345#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001346 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001347
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001348#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001349
Eric Andersen3b1a7442003-12-24 20:30:45 +00001350 case R_PPC_ADDR16_HA:
1351 *(unsigned short *)loc = (v + 0x8000) >> 16;
1352 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001353
Eric Andersen3b1a7442003-12-24 20:30:45 +00001354 case R_PPC_ADDR16_HI:
1355 *(unsigned short *)loc = v >> 16;
1356 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001357
Eric Andersen3b1a7442003-12-24 20:30:45 +00001358 case R_PPC_ADDR16_LO:
1359 *(unsigned short *)loc = v;
1360 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001361
Eric Andersen3b1a7442003-12-24 20:30:45 +00001362 case R_PPC_REL24:
1363 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001364
Eric Andersen3b1a7442003-12-24 20:30:45 +00001365 case R_PPC_REL32:
1366 *loc = v - dot;
1367 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001368
Eric Andersen3b1a7442003-12-24 20:30:45 +00001369 case R_PPC_ADDR32:
1370 *loc = v;
1371 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001372
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001373#elif defined(__s390__)
1374
1375 case R_390_32:
1376 *(unsigned int *) loc += v;
1377 break;
1378 case R_390_16:
1379 *(unsigned short *) loc += v;
1380 break;
1381 case R_390_8:
1382 *(unsigned char *) loc += v;
1383 break;
1384
1385 case R_390_PC32:
1386 *(unsigned int *) loc += v - dot;
1387 break;
1388 case R_390_PC16DBL:
1389 *(unsigned short *) loc += (v - dot) >> 1;
1390 break;
1391 case R_390_PC16:
1392 *(unsigned short *) loc += v - dot;
1393 break;
1394
1395 case R_390_PLT32:
1396 case R_390_PLT16DBL:
1397 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001398 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001399 if (pe->inited == 0) {
1400 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1401 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1402 ip[1] = 0x100607f1;
1403 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1404 ip[2] = v - 2;
1405 else
1406 ip[2] = v;
1407 pe->inited = 1;
1408 }
1409
1410 /* Insert relative distance to target. */
1411 v = plt + pe->offset - dot;
1412 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1413 *(unsigned int *) loc = (unsigned int) v;
1414 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1415 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1416 break;
1417
1418 case R_390_GLOB_DAT:
1419 case R_390_JMP_SLOT:
1420 *loc = v;
1421 break;
1422
1423 case R_390_RELATIVE:
1424 *loc += f->baseaddr;
1425 break;
1426
1427 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001428 *(unsigned long *) loc += got - dot;
1429 break;
1430
1431 case R_390_GOT12:
1432 case R_390_GOT16:
1433 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001434 if (!isym->gotent.inited)
1435 {
1436 isym->gotent.inited = 1;
1437 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1438 }
1439 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1440 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1441 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1442 *(unsigned short *) loc += isym->gotent.offset;
1443 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1444 *(unsigned int *) loc += isym->gotent.offset;
1445 break;
1446
1447# ifndef R_390_GOTOFF32
1448# define R_390_GOTOFF32 R_390_GOTOFF
1449# endif
1450 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001451 *loc += v - got;
1452 break;
1453
Eric Andersencffd5022002-05-24 06:50:15 +00001454#elif defined(__sh__)
1455
Eric Andersen3b1a7442003-12-24 20:30:45 +00001456 case R_SH_NONE:
1457 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001458
Eric Andersen3b1a7442003-12-24 20:30:45 +00001459 case R_SH_DIR32:
1460 *loc += v;
1461 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001462
Eric Andersen3b1a7442003-12-24 20:30:45 +00001463 case R_SH_REL32:
1464 *loc += v - dot;
1465 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001466
Eric Andersen3b1a7442003-12-24 20:30:45 +00001467 case R_SH_PLT32:
1468 *loc = v - dot;
1469 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001470
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 case R_SH_GLOB_DAT:
1472 case R_SH_JMP_SLOT:
1473 *loc = v;
1474 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 case R_SH_RELATIVE:
1477 *loc = f->baseaddr + rel->r_addend;
1478 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001479
Eric Andersen3b1a7442003-12-24 20:30:45 +00001480 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 *loc = got - dot + rel->r_addend;
1482 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001483
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 case R_SH_GOT32:
1485 goto bb_use_got;
1486
1487 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 *loc = v - got;
1489 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001490
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001491# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492 case R_SH_IMM_MEDLOW16:
1493 case R_SH_IMM_LOW16:
1494 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001495 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001496
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001497 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001498 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001499
Eric Andersen3b1a7442003-12-24 20:30:45 +00001500 /*
1501 * movi and shori have the format:
1502 *
1503 * | op | imm | reg | reserved |
1504 * 31..26 25..10 9.. 4 3 .. 0
1505 *
1506 * so we simply mask and or in imm.
1507 */
1508 word = *loc & ~0x3fffc00;
1509 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001510
Eric Andersen3b1a7442003-12-24 20:30:45 +00001511 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001512
Eric Andersen3b1a7442003-12-24 20:30:45 +00001513 break;
1514 }
Eric Andersenbf833552003-08-13 19:56:33 +00001515
Eric Andersen3b1a7442003-12-24 20:30:45 +00001516 case R_SH_IMM_MEDLOW16_PCREL:
1517 case R_SH_IMM_LOW16_PCREL:
1518 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001519 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001520
Eric Andersen3b1a7442003-12-24 20:30:45 +00001521 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001522
Eric Andersen3b1a7442003-12-24 20:30:45 +00001523 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001524
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001525 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001526 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001527
Eric Andersen3b1a7442003-12-24 20:30:45 +00001528 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001529
Eric Andersen3b1a7442003-12-24 20:30:45 +00001530 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001531
Eric Andersen3b1a7442003-12-24 20:30:45 +00001532 break;
1533 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001534# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001535
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001536#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001537
Eric Andersen3b1a7442003-12-24 20:30:45 +00001538 case R_V850_NONE:
1539 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001540
Eric Andersen3b1a7442003-12-24 20:30:45 +00001541 case R_V850_32:
1542 /* We write two shorts instead of a long because even
1543 32-bit insns only need half-word alignment, but
1544 32-bit data needs to be long-word aligned. */
1545 v += ((unsigned short *)loc)[0];
1546 v += ((unsigned short *)loc)[1] << 16;
1547 ((unsigned short *)loc)[0] = v & 0xffff;
1548 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1549 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001550
Eric Andersen3b1a7442003-12-24 20:30:45 +00001551 case R_V850_22_PCREL:
1552 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001553
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001554#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001555
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001556 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001557 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001558
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001559 case R_X86_64_64:
1560 *loc += v;
1561 break;
1562
1563 case R_X86_64_32:
1564 *(unsigned int *) loc += v;
1565 if (v > 0xffffffff)
1566 {
1567 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1568 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1569 }
1570 break;
1571
1572 case R_X86_64_32S:
1573 *(signed int *) loc += v;
1574 break;
1575
1576 case R_X86_64_16:
1577 *(unsigned short *) loc += v;
1578 break;
1579
1580 case R_X86_64_8:
1581 *(unsigned char *) loc += v;
1582 break;
1583
1584 case R_X86_64_PC32:
1585 *(unsigned int *) loc += v - dot;
1586 break;
1587
1588 case R_X86_64_PC16:
1589 *(unsigned short *) loc += v - dot;
1590 break;
1591
1592 case R_X86_64_PC8:
1593 *(unsigned char *) loc += v - dot;
1594 break;
1595
1596 case R_X86_64_GLOB_DAT:
1597 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001598 *loc = v;
1599 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001600
1601 case R_X86_64_RELATIVE:
1602 *loc += f->baseaddr;
1603 break;
1604
1605 case R_X86_64_GOT32:
1606 case R_X86_64_GOTPCREL:
1607 goto bb_use_got;
1608# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001609 if (!isym->gotent.reloc_done)
1610 {
1611 isym->gotent.reloc_done = 1;
1612 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1613 }
1614 /* XXX are these really correct? */
1615 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1616 *(unsigned int *) loc += v + isym->gotent.offset;
1617 else
1618 *loc += isym->gotent.offset;
1619 break;
1620# endif
1621
Mike Frysingerf982d862006-01-04 00:11:26 +00001622#else
1623# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001624#endif
1625
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001626 default:
1627 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1628 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001629 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001630
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001631#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001632
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001634
Eric Andersen3b1a7442003-12-24 20:30:45 +00001635 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001636
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001637#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001638 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1639 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001640#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001641 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001642#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001643
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 if (! pe->inited) {
1645 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001646
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001648
1649#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1651 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001652#endif
1653#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001655 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001656 ip[2] = 0x7d6903a6; /* mtctr r11 */
1657 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001658#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001659#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001660 /* We have to trash a register, so we assume that any control
1661 transfer more than 21-bits away must be a function call
1662 (so we can use a call-clobbered register). */
1663 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1664 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001665#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001666 pe->inited = 1;
1667 }
Eric Andersen21adca72000-12-06 18:18:26 +00001668
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 /* relative distance to target */
1670 v -= dot;
1671 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001672#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001673 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001674#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001675 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001676#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001677 /* go via the plt */
1678 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001679
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001680#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001681 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001682#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001683 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001684#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001685 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001686
Eric Andersen3b1a7442003-12-24 20:30:45 +00001687 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001688#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001689 /* Convert to words. */
1690 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001691
Eric Andersen3b1a7442003-12-24 20:30:45 +00001692 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001693#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001694#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001695 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001696#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001697#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001698 /* We write two shorts instead of a long because even 32-bit insns
1699 only need half-word alignment, but the 32-bit data write needs
1700 to be long-word aligned. */
1701 ((unsigned short *)loc)[0] =
1702 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1703 | ((v >> 16) & 0x3f); /* offs high part */
1704 ((unsigned short *)loc)[1] =
1705 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001706#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001707 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001708#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001709
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001710#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001711bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001712
Eric Andersen3b1a7442003-12-24 20:30:45 +00001713 /* needs an entry in the .got: set it, once */
1714 if (!isym->gotent.inited) {
1715 isym->gotent.inited = 1;
1716 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1717 }
1718 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001719#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001720 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001721#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001722 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001723#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001724 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001725
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001726#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001727 }
1728
1729 return ret;
1730}
1731
Eric Andersencffd5022002-05-24 06:50:15 +00001732
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001733#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001734
1735static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1736 int offset, int size)
1737{
1738 struct arch_list_entry *pe;
1739
1740 for (pe = *list; pe != NULL; pe = pe->next) {
1741 if (pe->addend == rel->r_addend) {
1742 break;
1743 }
1744 }
1745
1746 if (pe == NULL) {
1747 pe = xmalloc(sizeof(struct arch_list_entry));
1748 pe->next = *list;
1749 pe->addend = rel->r_addend;
1750 pe->offset = offset;
1751 pe->inited = 0;
1752 *list = pe;
1753 return size;
1754 }
1755 return 0;
1756}
1757
1758#endif
1759
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001760#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001761
Denis Vlasenko68404f12008-03-17 09:00:54 +00001762static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single,
Eric Andersencffd5022002-05-24 06:50:15 +00001763 int offset, int size)
1764{
1765 if (single->allocated == 0) {
1766 single->allocated = 1;
1767 single->offset = offset;
1768 single->inited = 0;
1769 return size;
1770 }
1771 return 0;
1772}
1773
1774#endif
1775
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001776#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001777
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001778static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001779 int offset, int size)
1780{
1781 struct obj_section *myrelsec = obj_find_section(f, name);
1782
1783 if (offset == 0) {
1784 offset += size;
1785 }
1786
1787 if (myrelsec) {
1788 obj_extend_section(myrelsec, offset);
1789 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001790 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001791 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001792 }
1793
1794 return myrelsec;
1795}
1796
1797#endif
1798
1799static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001800{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001801#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001802 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001803 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001804#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001805 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001806#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001807#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001808 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001809#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001810 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001811 ElfW(RelM) *rel, *relend;
1812 ElfW(Sym) *symtab, *extsym;
1813 const char *strtab, *name;
1814 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001815
Eric Andersen21adca72000-12-06 18:18:26 +00001816 for (i = 0; i < f->header.e_shnum; ++i) {
1817 relsec = f->sections[i];
1818 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001819 continue;
1820
Eric Andersen21adca72000-12-06 18:18:26 +00001821 symsec = f->sections[relsec->header.sh_link];
1822 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001823
Eric Andersen21adca72000-12-06 18:18:26 +00001824 rel = (ElfW(RelM) *) relsec->contents;
1825 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1826 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001827 strtab = (const char *) strsec->contents;
1828
1829 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001830 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001831
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001832#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001833 got_allocate = 0;
1834#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001835#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001836 plt_allocate = 0;
1837#endif
1838
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001839 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001840#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001841 case R_ARM_PC24:
1842 case R_ARM_PLT32:
1843 plt_allocate = 1;
1844 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001845
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001846 case R_ARM_GOTOFF:
1847 case R_ARM_GOTPC:
1848 got_needed = 1;
1849 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001850
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001851 case R_ARM_GOT32:
1852 got_allocate = 1;
1853 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001854
Eric Andersen21adca72000-12-06 18:18:26 +00001855#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001856 case R_386_GOTPC:
1857 case R_386_GOTOFF:
1858 got_needed = 1;
1859 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001860
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001861 case R_386_GOT32:
1862 got_allocate = 1;
1863 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001864
1865#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001866 case R_PPC_REL24:
1867 plt_allocate = 1;
1868 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001869
1870#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001871 case R_68K_GOT32:
1872 got_allocate = 1;
1873 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001874
Eric Andersen16451a02004-03-19 12:16:18 +00001875#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001876 case R_68K_GOTOFF:
1877 got_needed = 1;
1878 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001879#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001880
1881#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001882 case R_SH_GOT32:
1883 got_allocate = 1;
1884 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001885
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001886 case R_SH_GOTPC:
1887 case R_SH_GOTOFF:
1888 got_needed = 1;
1889 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001890
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001891#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001892 case R_V850_22_PCREL:
1893 plt_needed = 1;
1894 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001895
1896#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001897 default:
1898 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001899 }
1900
Eric Andersen21adca72000-12-06 18:18:26 +00001901 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001902 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001903 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001904 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001905 }
1906 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001907#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001908 if (got_allocate) {
1909 got_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001910 /*rel,*/ &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001911 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001912
1913 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001914 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001915#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001916#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001917 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001918#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001919 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001920 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001921 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001922#else
1923 plt_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001924 /*rel,*/ &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001925 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001926#endif
1927 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001928 }
1929#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001930 }
Miles Baderae28b042002-04-01 09:34:25 +00001931 }
Eric Andersen21adca72000-12-06 18:18:26 +00001932
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001933#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001934 if (got_needed) {
1935 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001936 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001937 }
Eric Andersen21adca72000-12-06 18:18:26 +00001938#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001939
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001940#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001941 if (plt_needed) {
1942 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001943 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001944 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001945#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001946
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001947#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001948}
1949
Eric Andersen9f16d612000-06-12 23:11:16 +00001950/*======================================================================*/
1951
1952/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001953static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001954{
1955 unsigned long h = 0;
1956 unsigned long g;
1957 unsigned char ch;
1958
1959 while (n > 0) {
1960 ch = *name++;
1961 h = (h << 4) + ch;
Denis Vlasenko1bec1b92007-11-06 02:23:39 +00001962 g = (h & 0xf0000000);
1963 if (g != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001964 h ^= g >> 24;
1965 h &= ~g;
1966 }
1967 n--;
1968 }
1969 return h;
1970}
1971
Eric Andersen044228d2001-07-17 01:12:36 +00001972static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001973{
1974 return obj_elf_hash_n(name, strlen(name));
1975}
1976
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001977#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001978/* String comparison for non-co-versioned kernel and module. */
1979
1980static int ncv_strcmp(const char *a, const char *b)
1981{
1982 size_t alen = strlen(a), blen = strlen(b);
1983
1984 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1985 return strncmp(a, b, alen);
1986 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1987 return strncmp(a, b, blen);
1988 else
1989 return strcmp(a, b);
1990}
1991
1992/* String hashing for non-co-versioned kernel and module. Here
1993 we are simply forced to drop the crc from the hash. */
1994
1995static unsigned long ncv_symbol_hash(const char *str)
1996{
1997 size_t len = strlen(str);
1998 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1999 len -= 10;
2000 return obj_elf_hash_n(str, len);
2001}
2002
Eric Andersen044228d2001-07-17 01:12:36 +00002003static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002004obj_set_symbol_compare(struct obj_file *f,
2005 int (*cmp) (const char *, const char *),
2006 unsigned long (*hash) (const char *))
2007{
2008 if (cmp)
2009 f->symbol_cmp = cmp;
2010 if (hash) {
2011 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2012 int i;
2013
2014 f->symbol_hash = hash;
2015
2016 memcpy(tmptab, f->symtab, sizeof(tmptab));
2017 memset(f->symtab, 0, sizeof(f->symtab));
2018
2019 for (i = 0; i < HASH_BUCKETS; ++i)
2020 for (sym = tmptab[i]; sym; sym = next) {
2021 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2022 next = sym->next;
2023 sym->next = f->symtab[h];
2024 f->symtab[h] = sym;
2025 }
2026 }
2027}
2028
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002029#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002030
Eric Andersen044228d2001-07-17 01:12:36 +00002031static struct obj_symbol *
2032obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002033 unsigned long symidx, int info,
2034 int secidx, ElfW(Addr) value,
2035 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002036{
2037 struct obj_symbol *sym;
2038 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002039 int n_type = ELF_ST_TYPE(info);
2040 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002041
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002042 for (sym = f->symtab[hash]; sym; sym = sym->next) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002043 if (f->symbol_cmp(sym->name, name) == 0) {
2044 int o_secidx = sym->secidx;
2045 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002046 int o_type = ELF_ST_TYPE(o_info);
2047 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002048
2049 /* A redefinition! Is it legal? */
2050
2051 if (secidx == SHN_UNDEF)
2052 return sym;
2053 else if (o_secidx == SHN_UNDEF)
2054 goto found;
2055 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2056 /* Cope with local and global symbols of the same name
2057 in the same object file, as might have been created
2058 by ld -r. The only reason locals are now seen at this
2059 level at all is so that we can do semi-sensible things
2060 with parameters. */
2061
2062 struct obj_symbol *nsym, **p;
2063
2064 nsym = arch_new_symbol();
2065 nsym->next = sym->next;
2066 nsym->ksymidx = -1;
2067
2068 /* Excise the old (local) symbol from the hash chain. */
2069 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2070 continue;
2071 *p = sym = nsym;
2072 goto found;
2073 } else if (n_binding == STB_LOCAL) {
2074 /* Another symbol of the same name has already been defined.
2075 Just add this to the local table. */
2076 sym = arch_new_symbol();
2077 sym->next = NULL;
2078 sym->ksymidx = -1;
2079 f->local_symtab[symidx] = sym;
2080 goto found;
2081 } else if (n_binding == STB_WEAK)
2082 return sym;
2083 else if (o_binding == STB_WEAK)
2084 goto found;
2085 /* Don't unify COMMON symbols with object types the programmer
2086 doesn't expect. */
2087 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002088 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002089 return sym;
2090 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002091 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002092 goto found;
2093 else {
2094 /* Don't report an error if the symbol is coming from
2095 the kernel or some external module. */
2096 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002097 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002098 return sym;
2099 }
2100 }
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002101 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002102
2103 /* Completely new symbol. */
2104 sym = arch_new_symbol();
2105 sym->next = f->symtab[hash];
2106 f->symtab[hash] = sym;
2107 sym->ksymidx = -1;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002108 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002109 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002110 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002111 name, (long) symidx, (long) f->local_symtab_size);
2112 else
2113 f->local_symtab[symidx] = sym;
2114 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002115
Eric Andersen3b1a7442003-12-24 20:30:45 +00002116found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002117 sym->name = name;
2118 sym->value = value;
2119 sym->size = size;
2120 sym->secidx = secidx;
2121 sym->info = info;
2122
2123 return sym;
2124}
2125
Eric Andersen044228d2001-07-17 01:12:36 +00002126static struct obj_symbol *
2127obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002128{
2129 struct obj_symbol *sym;
2130 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2131
2132 for (sym = f->symtab[hash]; sym; sym = sym->next)
2133 if (f->symbol_cmp(sym->name, name) == 0)
2134 return sym;
2135
2136 return NULL;
2137}
2138
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002139static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002140{
2141 if (sym) {
2142 if (sym->secidx >= SHN_LORESERVE)
2143 return sym->value;
2144
2145 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2146 } else {
2147 /* As a special case, a NULL sym has value zero. */
2148 return 0;
2149 }
2150}
2151
Eric Andersen044228d2001-07-17 01:12:36 +00002152static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002153{
2154 int i, n = f->header.e_shnum;
2155
2156 for (i = 0; i < n; ++i)
2157 if (strcmp(f->sections[i]->name, name) == 0)
2158 return f->sections[i];
2159
2160 return NULL;
2161}
2162
2163static int obj_load_order_prio(struct obj_section *a)
2164{
2165 unsigned long af, ac;
2166
2167 af = a->header.sh_flags;
2168
2169 ac = 0;
2170 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002171 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002172 ac |= 32;
2173 if (af & SHF_ALLOC)
2174 ac |= 16;
2175 if (!(af & SHF_WRITE))
2176 ac |= 8;
2177 if (af & SHF_EXECINSTR)
2178 ac |= 4;
2179 if (a->header.sh_type != SHT_NOBITS)
2180 ac |= 2;
2181
2182 return ac;
2183}
2184
Eric Andersen044228d2001-07-17 01:12:36 +00002185static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002186obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2187{
2188 struct obj_section **p;
2189 int prio = obj_load_order_prio(sec);
2190 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2191 if (obj_load_order_prio(*p) < prio)
2192 break;
2193 sec->load_next = *p;
2194 *p = sec;
2195}
2196
Eric Andersen044228d2001-07-17 01:12:36 +00002197static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002198 const char *name,
2199 unsigned long align,
2200 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002201{
2202 int newidx = f->header.e_shnum++;
2203 struct obj_section *sec;
2204
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002205 f->sections = xrealloc_vector(f->sections, 2, newidx);
Eric Andersen9f16d612000-06-12 23:11:16 +00002206 f->sections[newidx] = sec = arch_new_section();
2207
Eric Andersen9f16d612000-06-12 23:11:16 +00002208 sec->header.sh_type = SHT_PROGBITS;
2209 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2210 sec->header.sh_size = size;
2211 sec->header.sh_addralign = align;
2212 sec->name = name;
2213 sec->idx = newidx;
2214 if (size)
2215 sec->contents = xmalloc(size);
2216
2217 obj_insert_section_load_order(f, sec);
2218
2219 return sec;
2220}
2221
Eric Andersen044228d2001-07-17 01:12:36 +00002222static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002223 const char *name,
2224 unsigned long align,
2225 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002226{
2227 int newidx = f->header.e_shnum++;
2228 struct obj_section *sec;
2229
2230 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2231 f->sections[newidx] = sec = arch_new_section();
2232
Eric Andersen9f16d612000-06-12 23:11:16 +00002233 sec->header.sh_type = SHT_PROGBITS;
2234 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2235 sec->header.sh_size = size;
2236 sec->header.sh_addralign = align;
2237 sec->name = name;
2238 sec->idx = newidx;
2239 if (size)
2240 sec->contents = xmalloc(size);
2241
2242 sec->load_next = f->load_order;
2243 f->load_order = sec;
2244 if (f->load_order_search_start == &f->load_order)
2245 f->load_order_search_start = &sec->load_next;
2246
2247 return sec;
2248}
2249
Eric Andersen044228d2001-07-17 01:12:36 +00002250static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002251{
2252 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002253 if (more) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002254 sec->header.sh_size += more;
2255 sec->contents = xrealloc(sec->contents, sec->header.sh_size);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002256 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002257 return sec->contents + oldsize;
2258}
2259
2260
Eric Andersen9f16d612000-06-12 23:11:16 +00002261/* Conditionally add the symbols from the given symbol set to the
2262 new module. */
2263
2264static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002265add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002266 int idx, struct new_module_symbol *syms, size_t nsyms)
2267{
2268 struct new_module_symbol *s;
2269 size_t i;
2270 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002271#ifdef SYMBOL_PREFIX
2272 char *name_buf = 0;
2273 size_t name_alloced_size = 0;
2274#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002275#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002276 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002277
Glenn L McGrath759515c2003-08-30 06:00:33 +00002278 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002279#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002280 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002281 /* Only add symbols that are already marked external.
2282 If we override locals we may cause problems for
2283 argument initialization. We will also create a false
2284 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002285 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002286 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002287
Glenn L McGrath759515c2003-08-30 06:00:33 +00002288 /* GPL licensed modules can use symbols exported with
2289 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2290 * exported names. Non-GPL modules never see any GPLONLY_
2291 * symbols so they cannot fudge it by adding the prefix on
2292 * their references.
2293 */
2294 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002295#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002296 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002297 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002298 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002299#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002300 continue;
2301 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002302 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002303
Miles Baderae28b042002-04-01 09:34:25 +00002304#ifdef SYMBOL_PREFIX
2305 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2306 kernel exports `C names', but module object files
2307 reference `linker names'). */
2308 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002309 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002310 if (name_size > name_alloced_size) {
2311 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002312 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002313 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002314 strcpy(name_buf, SYMBOL_PREFIX);
2315 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002316 name = name_buf;
2317#endif /* SYMBOL_PREFIX */
2318
2319 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002320 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002321#ifdef SYMBOL_PREFIX
2322 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002323 name = xmalloc(name_size);
2324 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002325#endif
2326 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002327 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002328 STT_NOTYPE),
2329 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002330 /* Did our symbol just get installed? If so, mark the
2331 module as "used". */
2332 if (sym->secidx == idx)
2333 used = 1;
2334 }
2335 }
2336
2337 return used;
2338}
2339
2340static void add_kernel_symbols(struct obj_file *f)
2341{
2342 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002343 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002344
2345 /* Add module symbols first. */
2346
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002347 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002348 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002349 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2350 ) {
2351 m->used = 1;
2352 ++nused;
2353 }
2354 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002355
2356 n_ext_modules_used = nused;
2357
2358 /* And finally the symbols from the kernel proper. */
2359
2360 if (nksyms)
2361 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2362}
2363
2364static char *get_modinfo_value(struct obj_file *f, const char *key)
2365{
2366 struct obj_section *sec;
2367 char *p, *v, *n, *ep;
2368 size_t klen = strlen(key);
2369
2370 sec = obj_find_section(f, ".modinfo");
2371 if (sec == NULL)
2372 return NULL;
2373 p = sec->contents;
2374 ep = p + sec->header.sh_size;
2375 while (p < ep) {
2376 v = strchr(p, '=');
2377 n = strchr(p, '\0');
2378 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002379 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002380 return v + 1;
2381 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002382 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002383 return n;
2384 }
2385 p = n + 1;
2386 }
2387
2388 return NULL;
2389}
2390
2391
2392/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002393/* Functions relating to module loading after 2.1.18. */
2394
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002395static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002396new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2397{
2398 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002399 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002400 struct obj_symbol *sym;
2401 char *contents, *loc;
2402 int min, max, n;
2403
2404 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002405 q = strchr(p, '=');
2406 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002407 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002408 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002409 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002410
2411 key = alloca(q - p + 6);
2412 memcpy(key, "parm_", 5);
2413 memcpy(key + 5, p, q - p);
2414 key[q - p + 5] = 0;
2415
2416 p = get_modinfo_value(f, key);
2417 key += 5;
2418 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002419 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002420 }
2421
Miles Baderae28b042002-04-01 09:34:25 +00002422#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002423 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2424 strcpy(sym_name, SYMBOL_PREFIX);
2425 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002426#else
2427 sym_name = key;
2428#endif
2429 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002430
2431 /* Also check that the parameter was not resolved from the kernel. */
2432 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002433 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002434 }
2435
2436 if (isdigit(*p)) {
2437 min = strtoul(p, &p, 10);
2438 if (*p == '-')
2439 max = strtoul(p + 1, &p, 10);
2440 else
2441 max = min;
2442 } else
2443 min = max = 1;
2444
2445 contents = f->sections[sym->secidx]->contents;
2446 loc = contents + sym->value;
2447 n = (*++q != '\0');
2448
2449 while (1) {
2450 if ((*p == 's') || (*p == 'c')) {
2451 char *str;
2452
2453 /* Do C quoting if we begin with a ", else slurp the lot. */
2454 if (*q == '"') {
2455 char *r;
2456
2457 str = alloca(strlen(q));
2458 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002459 if (*q == '\0')
2460 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002461 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002462 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002463 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002464 case 'a':
2465 *r = '\a';
2466 break;
2467 case 'b':
2468 *r = '\b';
2469 break;
2470 case 'e':
2471 *r = '\033';
2472 break;
2473 case 'f':
2474 *r = '\f';
2475 break;
2476 case 'n':
2477 *r = '\n';
2478 break;
2479 case 'r':
2480 *r = '\r';
2481 break;
2482 case 't':
2483 *r = '\t';
2484 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002485
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002486 case '0':
2487 case '1':
2488 case '2':
2489 case '3':
2490 case '4':
2491 case '5':
2492 case '6':
2493 case '7':
2494 {
2495 int c = *q - '0';
2496 if (q[1] >= '0' && q[1] <= '7') {
2497 c = (c * 8) + *++q - '0';
2498 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002499 c = (c * 8) + *++q - '0';
2500 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002501 *r = c;
2502 }
2503 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002504
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002505 default:
2506 *r = *q;
2507 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002508 }
2509 else
2510 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002511 }
2512 *r = '\0';
2513 ++q;
2514 } else {
2515 char *r;
2516
2517 /* In this case, the string is not quoted. We will break
2518 it using the coma (like for ints). If the user wants to
2519 include comas in a string, he just has to quote it */
2520
2521 /* Search the next coma */
2522 r = strchr(q, ',');
2523
2524 /* Found ? */
2525 if (r != (char *) NULL) {
2526 /* Recopy the current field */
2527 str = alloca(r - q + 1);
2528 memcpy(str, q, r - q);
2529
Eric Andersenaff114c2004-04-14 17:51:38 +00002530 /* I don't know if it is useful, as the previous case
2531 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002532 str[r - q] = '\0';
2533
2534 /* Keep next fields */
2535 q = r;
2536 } else {
2537 /* last string */
2538 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002539 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002540 }
2541 }
2542
2543 if (*p == 's') {
2544 /* Normal string */
2545 obj_string_patch(f, sym->secidx, loc - contents, str);
2546 loc += tgt_sizeof_char_p;
2547 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002548 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002549 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002550
2551 /* Get the size of each member */
2552 /* Probably we should do that outside the loop ? */
2553 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002554 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002555 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002556 }
2557 charssize = strtoul(p + 1, (char **) NULL, 10);
2558
2559 /* Check length */
2560 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002561 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002562 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002563 }
2564
2565 /* Copy to location */
2566 strcpy((char *) loc, str);
2567 loc += charssize;
2568 }
2569 } else {
2570 long v = strtoul(q, &q, 0);
2571 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002572 case 'b':
2573 *loc++ = v;
2574 break;
2575 case 'h':
2576 *(short *) loc = v;
2577 loc += tgt_sizeof_short;
2578 break;
2579 case 'i':
2580 *(int *) loc = v;
2581 loc += tgt_sizeof_int;
2582 break;
2583 case 'l':
2584 *(long *) loc = v;
2585 loc += tgt_sizeof_long;
2586 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002587
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002588 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002589 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002590 }
2591 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002592 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002593 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002594 case '\0':
2595 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002596
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002597 case ' ':
2598 case '\t':
2599 case '\n':
2600 case '\r':
2601 ++q;
2602 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002603
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002604 case ',':
2605 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002606 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002607 }
2608 ++q;
2609 break;
2610
2611 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002612 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002613 }
2614 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002615 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002616 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002617 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002618 }
2619
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002620 argc--;
2621 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002622 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002623}
2624
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002625#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002626static int new_is_module_checksummed(struct obj_file *f)
2627{
2628 const char *p = get_modinfo_value(f, "using_checksums");
2629 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002630 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002631 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002632}
2633
2634/* Get the module's kernel version in the canonical integer form. */
2635
2636static int
2637new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2638{
2639 char *p, *q;
2640 int a, b, c;
2641
2642 p = get_modinfo_value(f, "kernel_version");
2643 if (p == NULL)
2644 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002645 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002646
2647 a = strtoul(p, &p, 10);
2648 if (*p != '.')
2649 return -1;
2650 b = strtoul(p + 1, &p, 10);
2651 if (*p != '.')
2652 return -1;
2653 c = strtoul(p + 1, &q, 10);
2654 if (p + 1 == q)
2655 return -1;
2656
2657 return a << 16 | b << 8 | c;
2658}
2659
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002660#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002661
2662
Eric Andersen9f16d612000-06-12 23:11:16 +00002663/* Fetch the loaded modules, and all currently exported symbols. */
2664
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002665static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002666{
2667 char *module_names, *mn;
2668 struct external_module *modules, *m;
2669 struct new_module_symbol *syms, *s;
2670 size_t ret, bufsize, nmod, nsyms, i, j;
2671
2672 /* Collect the loaded modules. */
2673
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002674 bufsize = 256;
2675 module_names = xmalloc(bufsize);
2676
2677 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002678 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002679 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002680 bufsize = ret;
2681 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002682 goto retry_modules_load;
2683 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002684 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002685 }
2686
2687 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002688
2689 /* Collect the modules' symbols. */
2690
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002691 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002692 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2693 memset(modules, 0, nmod * sizeof(*modules));
2694 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002695 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002696 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002697
Mark Whitley94fd4802001-03-12 23:08:34 +00002698 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2699 if (errno == ENOENT) {
2700 /* The module was removed out from underneath us. */
2701 continue;
2702 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002703 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002704 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002705
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002706 bufsize = 1024;
2707 syms = xmalloc(bufsize);
2708 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002709 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2710 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002711 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002712 bufsize = ret;
2713 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002714 goto retry_mod_sym_load;
2715 case ENOENT:
2716 /* The module was removed out from underneath us. */
2717 continue;
2718 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002719 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002720 }
2721 }
2722 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002723
Mark Whitley94fd4802001-03-12 23:08:34 +00002724 m->name = mn;
2725 m->addr = info.addr;
2726 m->nsyms = nsyms;
2727 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002728
Mark Whitley94fd4802001-03-12 23:08:34 +00002729 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2730 s->name += (unsigned long) syms;
2731 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002732 }
2733 }
2734
2735 /* Collect the kernel's symbols. */
2736
2737 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002738 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002739 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002740 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002741 bufsize = ret;
2742 syms = xrealloc(syms, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002743 goto retry_kern_sym_load;
2744 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002745 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002746 }
2747 nksyms = nsyms = ret;
2748 ksyms = syms;
2749
2750 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2751 s->name += (unsigned long) syms;
2752 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002753}
2754
2755
2756/* Return the kernel symbol checksum version, or zero if not used. */
2757
2758static int new_is_kernel_checksummed(void)
2759{
2760 struct new_module_symbol *s;
2761 size_t i;
2762
2763 /* Using_Versions is not the first symbol, but it should be in there. */
2764
2765 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2766 if (strcmp((char *) s->name, "Using_Versions") == 0)
2767 return s->value;
2768
2769 return 0;
2770}
2771
2772
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002773static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002774{
2775 struct obj_section *sec;
2776
2777 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002778 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002779 memset(sec->contents, 0, sizeof(struct new_module));
2780
Miles Baderae28b042002-04-01 09:34:25 +00002781 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002782 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002783 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002784
2785 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002786 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002787}
2788
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002789#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002790/* add an entry to the __ksymtab section, creating it if necessary */
2791static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2792{
2793 struct obj_section *sec;
2794 ElfW(Addr) ofs;
2795
2796 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2797 * If __ksymtab is defined but not marked alloc, x out the first character
2798 * (no obj_delete routine) and create a new __ksymtab with the correct
2799 * characteristics.
2800 */
2801 sec = obj_find_section(f, "__ksymtab");
2802 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2803 *((char *)(sec->name)) = 'x'; /* override const */
2804 sec = NULL;
2805 }
2806 if (!sec)
2807 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002808 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002809 if (!sec)
2810 return;
2811 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002812 /* Empty section might be byte-aligned */
2813 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002814 ofs = sec->header.sh_size;
2815 obj_symbol_patch(f, sec->idx, ofs, sym);
2816 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2817 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2818}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002819#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002820
2821static int new_create_module_ksymtab(struct obj_file *f)
2822{
2823 struct obj_section *sec;
2824 int i;
2825
2826 /* We must always add the module references. */
2827
2828 if (n_ext_modules_used) {
2829 struct new_module_ref *dep;
2830 struct obj_symbol *tm;
2831
2832 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002833 (sizeof(struct new_module_ref)
2834 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002835 if (!sec)
2836 return 0;
2837
Miles Baderae28b042002-04-01 09:34:25 +00002838 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002839 dep = (struct new_module_ref *) sec->contents;
2840 for (i = 0; i < n_ext_modules; ++i)
2841 if (ext_modules[i].used) {
2842 dep->dep = ext_modules[i].addr;
2843 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002844 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002845 dep->next_ref = 0;
2846 ++dep;
2847 }
2848 }
2849
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002850 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002851 size_t nsyms;
2852 int *loaded;
2853
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002854 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002855
2856 /* We don't want to export symbols residing in sections that
2857 aren't loaded. There are a number of these created so that
2858 we make sure certain module options don't appear twice. */
2859
2860 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2861 while (--i >= 0)
2862 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2863
2864 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2865 struct obj_symbol *sym;
2866 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002867 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002868 && sym->secidx <= SHN_HIRESERVE
2869 && (sym->secidx >= SHN_LORESERVE
2870 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002871 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2872
2873 obj_symbol_patch(f, sec->idx, ofs, sym);
2874 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002875 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002876
2877 nsyms++;
2878 }
2879 }
2880
2881 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2882 }
2883
2884 return 1;
2885}
2886
2887
2888static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002889new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002890{
2891 struct new_module *module;
2892 struct obj_section *sec;
2893 void *image;
2894 int ret;
2895 tgt_long m_addr;
2896
2897 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002898 if (!sec || !sec->contents) {
Denis Vlasenkof5d8c902008-06-26 14:32:57 +00002899 bb_perror_msg_and_die("corrupt module %s?", m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002900 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002901 module = (struct new_module *) sec->contents;
2902 m_addr = sec->header.sh_addr;
2903
2904 module->size_of_struct = sizeof(*module);
2905 module->size = m_size;
2906 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2907
2908 sec = obj_find_section(f, "__ksymtab");
2909 if (sec && sec->header.sh_size) {
2910 module->syms = sec->header.sh_addr;
2911 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2912 }
2913
2914 if (n_ext_modules_used) {
2915 sec = obj_find_section(f, ".kmodtab");
2916 module->deps = sec->header.sh_addr;
2917 module->ndeps = n_ext_modules_used;
2918 }
2919
2920 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002921 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002922 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002923 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002924
2925 sec = obj_find_section(f, "__ex_table");
2926 if (sec) {
2927 module->ex_table_start = sec->header.sh_addr;
2928 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2929 }
2930
2931 sec = obj_find_section(f, ".text.init");
2932 if (sec) {
2933 module->runsize = sec->header.sh_addr - m_addr;
2934 }
2935 sec = obj_find_section(f, ".data.init");
2936 if (sec) {
2937 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002938 module->runsize > sec->header.sh_addr - m_addr)
2939 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002940 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002941 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2942 if (sec && sec->header.sh_size) {
2943 module->archdata_start = (void*)sec->header.sh_addr;
2944 module->archdata_end = module->archdata_start + sec->header.sh_size;
2945 }
2946 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2947 if (sec && sec->header.sh_size) {
2948 module->kallsyms_start = (void*)sec->header.sh_addr;
2949 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2950 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002951
Eric Andersen9f16d612000-06-12 23:11:16 +00002952 /* Whew! All of the initialization is complete. Collect the final
2953 module image and give it to the kernel. */
2954
2955 image = xmalloc(m_size);
2956 obj_create_image(f, image);
2957
Eric Andersencb3b9b12004-06-22 11:50:52 +00002958 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002959 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002960 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002961
2962 free(image);
2963
2964 return ret == 0;
2965}
2966
Eric Andersen9f16d612000-06-12 23:11:16 +00002967
2968/*======================================================================*/
2969
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002970static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002971obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2972 const char *string)
2973{
2974 struct obj_string_patch *p;
2975 struct obj_section *strsec;
2976 size_t len = strlen(string) + 1;
2977 char *loc;
2978
2979 p = xmalloc(sizeof(*p));
2980 p->next = f->string_patches;
2981 p->reloc_secidx = secidx;
2982 p->reloc_offset = offset;
2983 f->string_patches = p;
2984
2985 strsec = obj_find_section(f, ".kstrtab");
2986 if (strsec == NULL) {
2987 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2988 p->string_offset = 0;
2989 loc = strsec->contents;
2990 } else {
2991 p->string_offset = strsec->header.sh_size;
2992 loc = obj_extend_section(strsec, len);
2993 }
2994 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002995}
2996
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00002997static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002998obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2999 struct obj_symbol *sym)
3000{
3001 struct obj_symbol_patch *p;
3002
3003 p = xmalloc(sizeof(*p));
3004 p->next = f->symbol_patches;
3005 p->reloc_secidx = secidx;
3006 p->reloc_offset = offset;
3007 p->sym = sym;
3008 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00003009}
3010
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003011static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003012{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003013 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003014
3015 for (i = 0; i < HASH_BUCKETS; ++i) {
3016 struct obj_symbol *sym;
3017 for (sym = f->symtab[i]; sym; sym = sym->next)
3018 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003019 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003020 sym->secidx = SHN_ABS;
3021 sym->value = 0;
3022 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003023 if (!flag_quiet)
3024 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003025 }
3026 }
3027 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003028}
3029
Eric Andersen044228d2001-07-17 01:12:36 +00003030static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003031{
3032 struct common_entry {
3033 struct common_entry *next;
3034 struct obj_symbol *sym;
3035 } *common_head = NULL;
3036
3037 unsigned long i;
3038
3039 for (i = 0; i < HASH_BUCKETS; ++i) {
3040 struct obj_symbol *sym;
3041 for (sym = f->symtab[i]; sym; sym = sym->next)
3042 if (sym->secidx == SHN_COMMON) {
3043 /* Collect all COMMON symbols and sort them by size so as to
3044 minimize space wasted by alignment requirements. */
3045 {
3046 struct common_entry **p, *n;
3047 for (p = &common_head; *p; p = &(*p)->next)
3048 if (sym->size <= (*p)->sym->size)
3049 break;
3050
3051 n = alloca(sizeof(*n));
3052 n->next = *p;
3053 n->sym = sym;
3054 *p = n;
3055 }
3056 }
3057 }
3058
3059 for (i = 1; i < f->local_symtab_size; ++i) {
3060 struct obj_symbol *sym = f->local_symtab[i];
3061 if (sym && sym->secidx == SHN_COMMON) {
3062 struct common_entry **p, *n;
3063 for (p = &common_head; *p; p = &(*p)->next)
3064 if (sym == (*p)->sym)
3065 break;
3066 else if (sym->size < (*p)->sym->size) {
3067 n = alloca(sizeof(*n));
3068 n->next = *p;
3069 n->sym = sym;
3070 *p = n;
3071 break;
3072 }
3073 }
3074 }
3075
3076 if (common_head) {
3077 /* Find the bss section. */
3078 for (i = 0; i < f->header.e_shnum; ++i)
3079 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3080 break;
3081
3082 /* If for some reason there hadn't been one, create one. */
3083 if (i == f->header.e_shnum) {
3084 struct obj_section *sec;
3085
Bernhard Reutner-Fischer5606b1c2008-07-09 17:56:53 +00003086 f->sections = xrealloc_vector(f->sections, 2, i);
Eric Andersen9f16d612000-06-12 23:11:16 +00003087 f->sections[i] = sec = arch_new_section();
3088 f->header.e_shnum = i + 1;
3089
Eric Andersen9f16d612000-06-12 23:11:16 +00003090 sec->header.sh_type = SHT_PROGBITS;
3091 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3092 sec->name = ".bss";
3093 sec->idx = i;
3094 }
3095
3096 /* Allocate the COMMONS. */
3097 {
3098 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3099 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3100 struct common_entry *c;
3101
3102 for (c = common_head; c; c = c->next) {
3103 ElfW(Addr) align = c->sym->value;
3104
3105 if (align > max_align)
3106 max_align = align;
3107 if (bss_size & (align - 1))
3108 bss_size = (bss_size | (align - 1)) + 1;
3109
3110 c->sym->secidx = i;
3111 c->sym->value = bss_size;
3112
3113 bss_size += c->sym->size;
3114 }
3115
3116 f->sections[i]->header.sh_size = bss_size;
3117 f->sections[i]->header.sh_addralign = max_align;
3118 }
3119 }
3120
3121 /* For the sake of patch relocation and parameter initialization,
3122 allocate zeroed data for NOBITS sections now. Note that after
3123 this we cannot assume NOBITS are really empty. */
3124 for (i = 0; i < f->header.e_shnum; ++i) {
3125 struct obj_section *s = f->sections[i];
3126 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003127 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003128 s->contents = memset(xmalloc(s->header.sh_size),
3129 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003130 else
3131 s->contents = NULL;
3132
Eric Andersen9f16d612000-06-12 23:11:16 +00003133 s->header.sh_type = SHT_PROGBITS;
3134 }
3135 }
3136}
3137
Eric Andersen044228d2001-07-17 01:12:36 +00003138static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003139{
3140 unsigned long dot = 0;
3141 struct obj_section *sec;
3142
3143 /* Finalize the positions of the sections relative to one another. */
3144
3145 for (sec = f->load_order; sec; sec = sec->load_next) {
3146 ElfW(Addr) align;
3147
3148 align = sec->header.sh_addralign;
3149 if (align && (dot & (align - 1)))
3150 dot = (dot | (align - 1)) + 1;
3151
3152 sec->header.sh_addr = dot;
3153 dot += sec->header.sh_size;
3154 }
3155
3156 return dot;
3157}
3158
Eric Andersen044228d2001-07-17 01:12:36 +00003159static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003160{
3161 int i, n = f->header.e_shnum;
3162 int ret = 1;
3163
3164 /* Finalize the addresses of the sections. */
3165
3166 f->baseaddr = base;
3167 for (i = 0; i < n; ++i)
3168 f->sections[i]->header.sh_addr += base;
3169
3170 /* And iterate over all of the relocations. */
3171
3172 for (i = 0; i < n; ++i) {
3173 struct obj_section *relsec, *symsec, *targsec, *strsec;
3174 ElfW(RelM) * rel, *relend;
3175 ElfW(Sym) * symtab;
3176 const char *strtab;
3177
3178 relsec = f->sections[i];
3179 if (relsec->header.sh_type != SHT_RELM)
3180 continue;
3181
3182 symsec = f->sections[relsec->header.sh_link];
3183 targsec = f->sections[relsec->header.sh_info];
3184 strsec = f->sections[symsec->header.sh_link];
3185
3186 rel = (ElfW(RelM) *) relsec->contents;
3187 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3188 symtab = (ElfW(Sym) *) symsec->contents;
3189 strtab = (const char *) strsec->contents;
3190
3191 for (; rel < relend; ++rel) {
3192 ElfW(Addr) value = 0;
3193 struct obj_symbol *intsym = NULL;
3194 unsigned long symndx;
3195 ElfW(Sym) * extsym = 0;
3196 const char *errmsg;
3197
3198 /* Attempt to find a value to use for this relocation. */
3199
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003200 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003201 if (symndx) {
3202 /* Note we've already checked for undefined symbols. */
3203
3204 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003205 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003206 /* Local symbols we look up in the local table to be sure
3207 we get the one that is really intended. */
3208 intsym = f->local_symtab[symndx];
3209 } else {
3210 /* Others we look up in the hash table. */
3211 const char *name;
3212 if (extsym->st_name)
3213 name = strtab + extsym->st_name;
3214 else
3215 name = f->sections[extsym->st_shndx]->name;
3216 intsym = obj_find_symbol(f, name);
3217 }
3218
3219 value = obj_symbol_final_value(f, intsym);
3220 intsym->referenced = 1;
3221 }
3222#if SHT_RELM == SHT_RELA
3223#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3224 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3225 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003226 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003227#endif
3228 value += rel->r_addend;
3229#endif
3230
3231 /* Do it! */
3232 switch (arch_apply_relocation
Denis Vlasenko68404f12008-03-17 09:00:54 +00003233 (f, targsec, /*symsec,*/ intsym, rel, value)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003234 ) {
3235 case obj_reloc_ok:
3236 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003237
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003238 case obj_reloc_overflow:
3239 errmsg = "Relocation overflow";
3240 goto bad_reloc;
3241 case obj_reloc_dangerous:
3242 errmsg = "Dangerous relocation";
3243 goto bad_reloc;
3244 case obj_reloc_unhandled:
3245 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003246bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003247 if (extsym) {
3248 bb_error_msg("%s of type %ld for %s", errmsg,
3249 (long) ELF_R_TYPE(rel->r_info),
3250 strtab + extsym->st_name);
3251 } else {
3252 bb_error_msg("%s of type %ld", errmsg,
3253 (long) ELF_R_TYPE(rel->r_info));
3254 }
3255 ret = 0;
3256 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003257 }
3258 }
3259 }
3260
3261 /* Finally, take care of the patches. */
3262
3263 if (f->string_patches) {
3264 struct obj_string_patch *p;
3265 struct obj_section *strsec;
3266 ElfW(Addr) strsec_base;
3267 strsec = obj_find_section(f, ".kstrtab");
3268 strsec_base = strsec->header.sh_addr;
3269
3270 for (p = f->string_patches; p; p = p->next) {
3271 struct obj_section *targsec = f->sections[p->reloc_secidx];
3272 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3273 = strsec_base + p->string_offset;
3274 }
3275 }
3276
3277 if (f->symbol_patches) {
3278 struct obj_symbol_patch *p;
3279
3280 for (p = f->symbol_patches; p; p = p->next) {
3281 struct obj_section *targsec = f->sections[p->reloc_secidx];
3282 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3283 = obj_symbol_final_value(f, p->sym);
3284 }
3285 }
3286
3287 return ret;
3288}
3289
Eric Andersen044228d2001-07-17 01:12:36 +00003290static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003291{
3292 struct obj_section *sec;
3293 ElfW(Addr) base = f->baseaddr;
3294
3295 for (sec = f->load_order; sec; sec = sec->load_next) {
3296 char *secimg;
3297
Eric Andersen2bf658d2001-02-24 20:01:53 +00003298 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003299 continue;
3300
3301 secimg = image + (sec->header.sh_addr - base);
3302
3303 /* Note that we allocated data for NOBITS sections earlier. */
3304 memcpy(secimg, sec->contents, sec->header.sh_size);
3305 }
3306
3307 return 1;
3308}
3309
3310/*======================================================================*/
3311
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003312static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM)
Eric Andersen9f16d612000-06-12 23:11:16 +00003313{
3314 struct obj_file *f;
3315 ElfW(Shdr) * section_headers;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003316 size_t shnum, i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003317 char *shstrtab;
3318
3319 /* Read the file header. */
3320
3321 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003322 f->symbol_cmp = strcmp;
3323 f->symbol_hash = obj_elf_hash;
3324 f->load_order_search_start = &f->load_order;
3325
3326 fseek(fp, 0, SEEK_SET);
3327 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003328 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003329 }
3330
3331 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003332 || f->header.e_ident[EI_MAG1] != ELFMAG1
3333 || f->header.e_ident[EI_MAG2] != ELFMAG2
3334 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003335 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003336 }
3337 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003338 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003339 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003340 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3341 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003342 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003343 }
3344 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003345 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003346 }
3347
3348 /* Read the section headers. */
3349
3350 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003351 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003352 (unsigned long) f->header.e_shentsize,
3353 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003354 }
3355
3356 shnum = f->header.e_shnum;
3357 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3358 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3359
3360 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3361 fseek(fp, f->header.e_shoff, SEEK_SET);
3362 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003363 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003364 }
3365
3366 /* Read the section data. */
3367
3368 for (i = 0; i < shnum; ++i) {
3369 struct obj_section *sec;
3370
3371 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003372
3373 sec->header = section_headers[i];
3374 sec->idx = i;
3375
Denis Vlasenko51742f42007-04-12 00:32:05 +00003376 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003377 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003378 case SHT_NULL:
3379 case SHT_NOTE:
3380 case SHT_NOBITS:
3381 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003382 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003383
3384 case SHT_PROGBITS:
3385#if LOADBITS
3386 if (!loadprogbits) {
3387 sec->contents = NULL;
3388 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003389 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003390#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003391 case SHT_SYMTAB:
3392 case SHT_STRTAB:
3393 case SHT_RELM:
3394 if (sec->header.sh_size > 0) {
3395 sec->contents = xmalloc(sec->header.sh_size);
3396 fseek(fp, sec->header.sh_offset, SEEK_SET);
3397 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003398 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003399 }
3400 } else {
3401 sec->contents = NULL;
3402 }
3403 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003404
3405#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003406 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003407 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003408#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003409 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003410 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003411#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003412 default:
3413 if (sec->header.sh_type >= SHT_LOPROC) {
3414 /* Assume processor specific section types are debug
3415 info and can safely be ignored. If this is ever not
3416 the case (Hello MIPS?), don't put ifdefs here but
3417 create an arch_load_proc_section(). */
3418 break;
3419 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003420
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003421 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003422 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003423 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003424 }
3425 }
3426
3427 /* Do what sort of interpretation as needed by each section. */
3428
3429 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3430
3431 for (i = 0; i < shnum; ++i) {
3432 struct obj_section *sec = f->sections[i];
3433 sec->name = shstrtab + sec->header.sh_name;
3434 }
3435
3436 for (i = 0; i < shnum; ++i) {
3437 struct obj_section *sec = f->sections[i];
3438
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003439 /* .modinfo should be contents only but gcc has no attribute for that.
3440 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3441 */
3442 if (strcmp(sec->name, ".modinfo") == 0)
3443 sec->header.sh_flags &= ~SHF_ALLOC;
3444
Eric Andersen9f16d612000-06-12 23:11:16 +00003445 if (sec->header.sh_flags & SHF_ALLOC)
3446 obj_insert_section_load_order(f, sec);
3447
3448 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003449 case SHT_SYMTAB:
3450 {
3451 unsigned long nsym, j;
3452 char *strtab;
3453 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003454
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003455 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003456 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003457 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003458 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003459 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003460
3461 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3462 strtab = f->sections[sec->header.sh_link]->contents;
3463 sym = (ElfW(Sym) *) sec->contents;
3464
3465 /* Allocate space for a table of local symbols. */
3466 j = f->local_symtab_size = sec->header.sh_info;
3467 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3468
3469 /* Insert all symbols into the hash table. */
3470 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3471 ElfW(Addr) val = sym->st_value;
3472 const char *name;
3473 if (sym->st_name)
3474 name = strtab + sym->st_name;
3475 else if (sym->st_shndx < shnum)
3476 name = f->sections[sym->st_shndx]->name;
3477 else
3478 continue;
3479#if defined(__SH5__)
3480 /*
3481 * For sh64 it is possible that the target of a branch
3482 * requires a mode switch (32 to 16 and back again).
3483 *
3484 * This is implied by the lsb being set in the target
3485 * address for SHmedia mode and clear for SHcompact.
3486 */
3487 val |= sym->st_other & 4;
3488#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003489 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3490 val, sym->st_size);
3491 }
3492 }
3493 break;
3494
3495 case SHT_RELM:
3496 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003497 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003498 (unsigned long) sec->header.sh_entsize,
3499 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003500 }
3501 break;
3502 /* XXX Relocation code from modutils-2.3.19 is not here.
3503 * Why? That's about 20 lines of code from obj/obj_load.c,
3504 * which gets done in a second pass through the sections.
3505 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003506 }
3507 }
3508
3509 return f;
3510}
3511
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003512#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003513/*
3514 * load the unloaded sections directly into the memory allocated by
3515 * kernel for the module
3516 */
3517
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +00003518static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003519{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003520 ElfW(Addr) base = f->baseaddr;
3521 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003522
Eric Andersen8ae319a2001-05-21 16:09:18 +00003523 for (sec = f->load_order; sec; sec = sec->load_next) {
3524
3525 /* section already loaded? */
3526 if (sec->contents != NULL)
3527 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003528
Eric Andersen8ae319a2001-05-21 16:09:18 +00003529 if (sec->header.sh_size == 0)
3530 continue;
3531
3532 sec->contents = imagebase + (sec->header.sh_addr - base);
3533 fseek(fp, sec->header.sh_offset, SEEK_SET);
3534 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003535 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003536 return 0;
3537 }
3538
3539 }
3540 return 1;
3541}
3542#endif
3543
Eric Andersen9f16d612000-06-12 23:11:16 +00003544static void hide_special_symbols(struct obj_file *f)
3545{
3546 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003547 SPFX "cleanup_module",
3548 SPFX "init_module",
3549 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003550 NULL
3551 };
3552
3553 struct obj_symbol *sym;
3554 const char *const *p;
3555
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003556 for (p = specials; *p; ++p) {
3557 sym = obj_find_symbol(f, *p);
3558 if (sym != NULL)
3559 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3560 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003561}
3562
Glenn L McGrath759515c2003-08-30 06:00:33 +00003563
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003564#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003565static int obj_gpl_license(struct obj_file *f, const char **license)
3566{
3567 struct obj_section *sec;
3568 /* This list must match *exactly* the list of allowable licenses in
3569 * linux/include/linux/module.h. Checking for leading "GPL" will not
3570 * work, somebody will use "GPL sucks, this is proprietary".
3571 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003572 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003573 "GPL",
3574 "GPL v2",
3575 "GPL and additional rights",
3576 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003577 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003578 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003579
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003580 sec = obj_find_section(f, ".modinfo");
3581 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003582 const char *value, *ptr, *endptr;
3583 ptr = sec->contents;
3584 endptr = ptr + sec->header.sh_size;
3585 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003586 value = strchr(ptr, '=');
3587 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003588 unsigned i;
Eric Andersen166fa462002-09-16 05:30:24 +00003589 if (license)
3590 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003591 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003592 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003593 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003594 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003595 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003596 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003597 ptr = strchr(ptr, '\0');
3598 if (ptr)
3599 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003600 else
3601 ptr = endptr;
3602 }
3603 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003604 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003605}
3606
3607#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003608#define TAINT_PROPRIETORY_MODULE (1 << 0)
3609#define TAINT_FORCED_MODULE (1 << 1)
3610#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003611#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003612
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003613static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003614 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3615{
Denis Vlasenko931de892007-06-21 12:43:45 +00003616 static smallint printed_info;
3617
Eric Andersen166fa462002-09-16 05:30:24 +00003618 char buf[80];
3619 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003620
Eric Andersen166fa462002-09-16 05:30:24 +00003621 if (fd < 0 && !kernel_has_tainted)
3622 return; /* New modutils on old kernel */
3623 printf("Warning: loading %s will taint the kernel: %s%s\n",
3624 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003625 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003626 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003627 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003628 }
3629 if (fd >= 0) {
3630 read(fd, buf, sizeof(buf)-1);
3631 buf[sizeof(buf)-1] = '\0';
3632 oldval = strtoul(buf, NULL, 10);
3633 sprintf(buf, "%d\n", oldval | taint);
3634 write(fd, buf, strlen(buf));
3635 }
3636}
3637
3638/* Check if loading this module will taint the kernel. */
3639static void check_tainted_module(struct obj_file *f, char *m_name)
3640{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003641 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3642
Eric Andersen166fa462002-09-16 05:30:24 +00003643 int fd, kernel_has_tainted;
3644 const char *ptr;
3645
3646 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003647 fd = open(tainted_file, O_RDWR);
3648 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003649 if (errno == ENOENT)
3650 kernel_has_tainted = 0;
3651 else if (errno == EACCES)
3652 kernel_has_tainted = 1;
3653 else {
3654 perror(tainted_file);
3655 kernel_has_tainted = 0;
3656 }
3657 }
3658
3659 switch (obj_gpl_license(f, &ptr)) {
3660 case 0:
3661 break;
3662 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003663 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003664 break;
3665 case 2:
3666 /* The module has a non-GPL license so we pretend that the
3667 * kernel always has a taint flag to get a warning even on
3668 * kernels without the proc flag.
3669 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003670 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003671 break;
3672 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003673 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003674 break;
3675 }
3676
3677 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003678 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003679
3680 if (fd >= 0)
3681 close(fd);
3682}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003683#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003684#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003685#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003686
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003687#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003688/* add module source, timestamp, kernel version and a symbol for the
3689 * start of some sections. this info is used by ksymoops to do better
3690 * debugging.
3691 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00003692#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3693#define get_module_version(f, str) get_module_version(str)
3694#endif
Eric Andersen889dd202003-01-23 04:48:34 +00003695static int
3696get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3697{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003698#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003699 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003700#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003701 strncpy(str, "???", sizeof(str));
3702 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003703#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003704}
3705
3706/* add module source, timestamp, kernel version and a symbol for the
3707 * start of some sections. this info is used by ksymoops to do better
3708 * debugging.
3709 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003710static void
Eric Andersen889dd202003-01-23 04:48:34 +00003711add_ksymoops_symbols(struct obj_file *f, const char *filename,
3712 const char *m_name)
3713{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003714 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003715 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003716 ".text",
3717 ".rodata",
3718 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003719 ".bss",
3720 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003721 };
3722
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003723 struct obj_section *sec;
3724 struct obj_symbol *sym;
3725 char *name, *absolute_filename;
3726 char str[STRVERSIONLEN];
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003727 unsigned i;
3728 int l, lm_name, lfilename, use_ksymtab, version;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003729 struct stat statbuf;
3730
3731 /* WARNING: was using realpath, but replaced by readlink to stop using
3732 * lots of stack. But here it seems to be able to cause problems? */
3733 absolute_filename = xmalloc_readlink(filename);
3734 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003735 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003736
3737 lm_name = strlen(m_name);
3738 lfilename = strlen(absolute_filename);
3739
3740 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3741 * are not to be exported. otherwise leave ksymtab alone for now, the
3742 * "export all symbols" compatibility code will export these symbols later.
3743 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003744 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003745
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003746 sec = obj_find_section(f, ".this");
3747 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003748 /* tag the module header with the object name, last modified
3749 * timestamp and module version. worst case for module version
3750 * is 0xffffff, decimal 16777215. putting all three fields in
3751 * one symbol is less readable but saves kernel space.
3752 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003753 l = sizeof(symprefix) + /* "__insmod_" */
3754 lm_name + /* module name */
3755 2 + /* "_O" */
3756 lfilename + /* object filename */
3757 2 + /* "_M" */
3758 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3759 2 + /* "_V" */
3760 8 + /* version in dec */
3761 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003762 name = xmalloc(l);
3763 if (stat(absolute_filename, &statbuf) != 0)
3764 statbuf.st_mtime = 0;
3765 version = get_module_version(f, str); /* -1 if not found */
3766 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003767 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003768 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003769 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003770 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003771 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003772 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003773 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003774 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003775 }
3776 free(absolute_filename);
3777#ifdef _NOT_SUPPORTED_
3778 /* record where the persistent data is going, same address as previous symbol */
3779
3780 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003781 l = sizeof(symprefix) + /* "__insmod_" */
3782 lm_name + /* module name */
3783 2 + /* "_P" */
3784 strlen(f->persist) + /* data store */
3785 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003786 name = xmalloc(l);
3787 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003788 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003789 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003790 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003791 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003792 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003793 }
3794#endif /* _NOT_SUPPORTED_ */
3795 /* tag the desired sections if size is non-zero */
3796
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003797 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003798 sec = obj_find_section(f, section_names[i]);
3799 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003800 l = sizeof(symprefix) + /* "__insmod_" */
3801 lm_name + /* module name */
3802 2 + /* "_S" */
3803 strlen(sec->name) + /* section name */
3804 2 + /* "_L" */
3805 8 + /* length in dec */
3806 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003807 name = xmalloc(l);
3808 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003809 symprefix, m_name, sec->name,
3810 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003811 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003812 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003813 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003814 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003815 }
3816 }
3817}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003818#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003819
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003820#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003821static void print_load_map(struct obj_file *f)
3822{
Eric Andersenbe65c352003-01-23 04:57:35 +00003823 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003824#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3825 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003826 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003827 struct obj_symbol *sym;
3828#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003829 /* Report on the section layout. */
3830
3831 printf("Sections: Size %-*s Align\n",
3832 (int) (2 * sizeof(void *)), "Address");
3833
3834 for (sec = f->load_order; sec; sec = sec->load_next) {
3835 int a;
3836 unsigned long tmp;
3837
3838 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3839 tmp >>= 1;
3840 if (a == -1)
3841 a = 0;
3842
3843 printf("%-15s %08lx %0*lx 2**%d\n",
3844 sec->name,
3845 (long)sec->header.sh_size,
3846 (int) (2 * sizeof(void *)),
3847 (long)sec->header.sh_addr,
3848 a);
3849 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003850#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003851 /* Quick reference which section indicies are loaded. */
3852
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003853 i = f->header.e_shnum;
3854 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003855 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003856 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003857
3858 /* Collect the symbols we'll be listing. */
3859
3860 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3861 for (sym = f->symtab[i]; sym; sym = sym->next)
3862 if (sym->secidx <= SHN_HIRESERVE
3863 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3864 ++nsyms;
3865
3866 all = alloca(nsyms * sizeof(struct obj_symbol *));
3867
3868 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3869 for (sym = f->symtab[i]; sym; sym = sym->next)
3870 if (sym->secidx <= SHN_HIRESERVE
3871 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3872 *p++ = sym;
3873
3874 /* And list them. */
3875 printf("\nSymbols:\n");
3876 for (p = all; p < all + nsyms; ++p) {
3877 char type = '?';
3878 unsigned long value;
3879
3880 sym = *p;
3881 if (sym->secidx == SHN_ABS) {
3882 type = 'A';
3883 value = sym->value;
3884 } else if (sym->secidx == SHN_UNDEF) {
3885 type = 'U';
3886 value = 0;
3887 } else {
3888 sec = f->sections[sym->secidx];
3889
3890 if (sec->header.sh_type == SHT_NOBITS)
3891 type = 'B';
3892 else if (sec->header.sh_flags & SHF_ALLOC) {
3893 if (sec->header.sh_flags & SHF_EXECINSTR)
3894 type = 'T';
3895 else if (sec->header.sh_flags & SHF_WRITE)
3896 type = 'D';
3897 else
3898 type = 'R';
3899 }
3900 value = sym->value + sec->header.sh_addr;
3901 }
3902
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003903 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003904 type = tolower(type);
3905
3906 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3907 type, sym->name);
3908 }
3909#endif
3910}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003911#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003912void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003913#endif
3914
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003915int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3916int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003917{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003918 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003919 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003920 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003921 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003922 unsigned long m_size;
3923 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003924 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003925 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003926 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003927 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003928 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003929#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003930 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003931 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003932 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003933#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003934#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003935 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003936#else
3937 FILE *fp;
3938#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003939 int k_version = 0;
3940 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003941
Erik Andersene49d5ec2000-02-08 19:58:47 +00003942 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003943 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003944 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003945 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003946 free(m_name);
3947 m_name = xstrdup(opt_o);
3948 }
Eric Andersen03d80912003-12-19 21:04:19 +00003949
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003950 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003951 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003952 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003953
Erik Andersene49d5ec2000-02-08 19:58:47 +00003954 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003955 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003956 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003957 len = strlen(tmp);
3958
Eric Andersen03d80912003-12-19 21:04:19 +00003959 if (uname(&myuname) == 0) {
3960 if (myuname.release[0] == '2') {
3961 k_version = myuname.release[2] - '0';
3962 }
3963 }
3964
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003965#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003966 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3967 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3968 ) {
3969 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003970 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003971 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003972#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003973 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003974 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003975 tmp[len] = '\0';
3976 }
Eric Andersen2d342152002-06-18 05:16:25 +00003977
Eric Andersen03d80912003-12-19 21:04:19 +00003978
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003979#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003980 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003981 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003982 else
Eric Andersen03d80912003-12-19 21:04:19 +00003983#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003984 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003985
Eric Andersen61f83052002-06-22 17:15:42 +00003986 if (!m_name) {
3987 m_name = tmp;
3988 } else {
3989 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003990 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003991 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003992
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003993 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003994 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3995 || (fp = fopen(arg1, "r")) == NULL
3996 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003997 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3998 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003999 if (k_version) { /* uname succeedd */
4000 char *module_dir;
4001 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00004002
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004003 tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004004 /* Jump through hoops in case /lib/modules/`uname -r`
4005 * is a symlink. We do not want recursive_action to
4006 * follow symlinks, but we do want to follow the
4007 * /lib/modules/`uname -r` dir, So resolve it ourselves
4008 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004009 module_dir = xmalloc_readlink(tmdn);
4010 if (!module_dir)
4011 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004012 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004013 check_module_name_match, NULL, m_fullName, 0);
4014 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004015 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004016 }
4017
4018 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004019 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004020 int r;
4021 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004022
Eric Andersen03d80912003-12-19 21:04:19 +00004023 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004024 m_filename = NULL;
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004025 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004026 if (!module_dir)
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004027 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
Eric Andersen14d35432001-05-14 17:07:32 +00004028 /* No module found under /lib/modules/`uname -r`, this
4029 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004030 r = recursive_action(module_dir, ACTION_RECURSE,
4031 check_module_name_match, NULL, m_fullName, 0);
4032 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004033 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004034 free(module_dir);
4035 if (m_filename == NULL
4036 || ((fp = fopen(m_filename, "r")) == NULL)
4037 ) {
4038 bb_error_msg_and_die("%s: module not found", m_fullName);
4039 }
Eric Andersen14d35432001-05-14 17:07:32 +00004040 }
Eric Andersen03d80912003-12-19 21:04:19 +00004041 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004042 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004043
Rob Landley999af202005-12-11 20:14:12 +00004044 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004045 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004046
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004047#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004048 if (k_version > 4) {
4049 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004050 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004051 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004052 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004053#endif
4054
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004055 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004056
Eric Andersen9f16d612000-06-12 23:11:16 +00004057 if (get_modinfo_value(f, "kernel_version") == NULL)
4058 m_has_modinfo = 0;
4059 else
4060 m_has_modinfo = 1;
4061
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004062#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004063 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004064 if (!flag_quiet) {
4065 if (uname(&uts_info) < 0)
4066 uts_info.release[0] = '\0';
4067 if (m_has_modinfo) {
4068 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004069 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004070 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004071 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004072 }
4073 }
4074
4075 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004076 bb_error_msg("%skernel-module version mismatch\n"
4077 "\t%s was compiled for kernel version %s\n"
4078 "\twhile this kernel is version %s",
4079 flag_force_load ? "warning: " : "",
4080 m_filename, m_strversion, uts_info.release);
4081 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004082 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004083 }
4084 }
4085 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004086#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004087
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004088 if (query_module(NULL, 0, NULL, 0, NULL))
4089 bb_error_msg_and_die("not configured to support old kernels");
4090 new_get_kernel_symbols();
4091 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004092
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004093#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004094 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004095 if (m_has_modinfo)
4096 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004097
4098 if (m_crcs != k_crcs)
4099 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004100#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004101
Erik Andersene49d5ec2000-02-08 19:58:47 +00004102 /* Let the module know about the kernel symbols. */
4103 add_kernel_symbols(f);
4104
Eric Andersen9f16d612000-06-12 23:11:16 +00004105 /* Allocate common symbols, symbol tables, and string tables. */
4106
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004107 new_create_this_module(f, m_name);
4108 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004109 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004110 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004111
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004112 /* done with the module name, on to the optional var=value arguments */
4113 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004114 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004115 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004116 }
4117
Eric Andersen9f16d612000-06-12 23:11:16 +00004118 arch_create_got(f);
4119 hide_special_symbols(f);
4120
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004121#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004122 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004123#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004124
Eric Andersencb3b9b12004-06-22 11:50:52 +00004125 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004126
Erik Andersene49d5ec2000-02-08 19:58:47 +00004127 /* Find current size of the module */
4128 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004129
Erik Andersene49d5ec2000-02-08 19:58:47 +00004130 m_addr = create_module(m_name, m_size);
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00004131 if (m_addr == (ElfW(Addr))(-1)) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004132 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004133 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004134 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004135 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004136 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004137 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004138 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004139 }
Erik Andersend387d011999-12-21 02:55:11 +00004140
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004141#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004142 /*
4143 * the PROGBITS section was not loaded by the obj_load
4144 * now we can load them directly into the kernel memory
4145 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004146 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004147 delete_module(m_name, 0);
Eric Andersen8ae319a2001-05-21 16:09:18 +00004148 goto out;
4149 }
Eric Andersen03d80912003-12-19 21:04:19 +00004150#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004151
Eric Andersen9f16d612000-06-12 23:11:16 +00004152 if (!obj_relocate(f, m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004153 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004154 goto out;
4155 }
Erik Andersend387d011999-12-21 02:55:11 +00004156
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004157 if (!new_init_module(m_name, f, m_size)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004158 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004159 goto out;
4160 }
4161
Denis Vlasenko51742f42007-04-12 00:32:05 +00004162 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004163 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004164
Matt Kraai3e856ce2000-12-01 02:55:13 +00004165 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004166
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004167 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004168#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004169 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004170 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004171 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004172 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004173 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004174 free(m_filename);
4175#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004176 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004177}
Eric Andersene7047882003-12-11 01:42:13 +00004178
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004179#endif /* ENABLE_FEATURE_2_4_MODULES */
4180/*
4181 * End of big piece of 2.4-specific code
4182 */
Eric Andersene7047882003-12-11 01:42:13 +00004183
4184
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004185#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004186
4187#include <sys/mman.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004188
Bernhard Reutner-Fischer15102162008-05-27 13:27:18 +00004189#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES
4190/* big time suckage. The old prototype above renders our nice fwd-decl wrong */
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004191extern int init_module(void *module, unsigned long len, const char *options);
4192#else
Eric Andersene7047882003-12-11 01:42:13 +00004193#include <asm/unistd.h>
4194#include <sys/syscall.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004195#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
4196#endif
Eric Andersene7047882003-12-11 01:42:13 +00004197
4198/* We use error numbers in a loose translation... */
4199static const char *moderror(int err)
4200{
4201 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004202 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004203 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004204 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004205 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004206 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004207 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004208 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004209 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004210 default:
4211 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004212 }
4213}
4214
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004215#if !ENABLE_FEATURE_2_4_MODULES
4216int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004217int insmod_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004218#else
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004219static int insmod_ng_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004220#endif
Eric Andersene7047882003-12-11 01:42:13 +00004221{
Denis Vlasenko92297942006-11-21 11:58:14 +00004222 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004223 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004224 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004225 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004226
Denis Vlasenko92297942006-11-21 11:58:14 +00004227 filename = *++argv;
4228 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004229 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004230
4231 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004232 options = xzalloc(1);
4233 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004234 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004235 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004236 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004237 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004238 }
4239
Denis Vlasenko92297942006-11-21 11:58:14 +00004240#if 0
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004241 /* Any special reason why mmap? It isn't performance critical. -vda */
4242 /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +00004243 * modules out there that are half a megabyte! mmap()ing is way nicer
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004244 * for small mem boxes, i guess. */
4245 /* But after load, these modules will take up that 0.5mb in kernel
4246 * anyway. Using malloc here causes only a transient spike to 1mb,
4247 * after module is loaded, we go back to normal 0.5mb usage
4248 * (in kernel). Also, mmap isn't magic - when we touch mapped data,
4249 * we use memory. -vda */
Denis Vlasenko92297942006-11-21 11:58:14 +00004250 int fd;
4251 struct stat st;
4252 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004253 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004254 fstat(fd, &st);
4255 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004256 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004257 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004258 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004259 }
4260
Denis Vlasenko92297942006-11-21 11:58:14 +00004261 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4262 if (map == NULL) {
4263 map = xmalloc(len);
4264 xread(fd, map, len);
4265 }
4266#else
4267 len = MAXINT(ssize_t);
4268 map = xmalloc_open_read_close(filename, &len);
4269#endif
4270
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004271 if (init_module(map, len, options) != 0)
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004272 bb_error_msg_and_die("cannot insert '%s': %s",
4273 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004274 return 0;
4275}
4276
4277#endif