blob: df6bf10a0c36860bf7327631c7cc0b4fe54b68a1 [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__) \
Bernhard Reutner-Fischer825968f2008-05-16 16:00:38 +0000843 || defined(__sh__) || defined(__s390__) || defined(__x86_64__)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000844 struct arch_file *ifile = (struct arch_file *) f;
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000845#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000846 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000847 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000848#if defined(__arm__) || defined(__H8300H__) || defined(__H8300S__) \
849 || defined(__i386__) || defined(__mc68000__) || defined(__microblaze__) \
850 || defined(__mips__) || defined(__nios2__) || defined(__powerpc__) \
851 || defined(__s390__) || defined(__sh__) || defined(__x86_64__)
Eric Andersen21adca72000-12-06 18:18:26 +0000852 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000853#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000854#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000855 struct arch_symbol *isym = (struct arch_symbol *) sym;
856#endif
Denis Vlasenkof3aa4a82008-05-09 11:36:17 +0000857#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) \
858 || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000859#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000860 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000861#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000862#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000863#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000864 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000865 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000866# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000867 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000868# else
Eric Andersencffd5022002-05-24 06:50:15 +0000869 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000870# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000871#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000872
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000873 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000874
Eric Andersencffd5022002-05-24 06:50:15 +0000875#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000876
Eric Andersen3b1a7442003-12-24 20:30:45 +0000877 case R_ARM_NONE:
878 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000879
Eric Andersen3b1a7442003-12-24 20:30:45 +0000880 case R_ARM_ABS32:
881 *loc += v;
882 break;
Miles Baderae28b042002-04-01 09:34:25 +0000883
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 case R_ARM_GOT32:
885 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000888 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
889 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000890 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000891
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 *loc += got - dot;
893 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 case R_ARM_PC24:
896 case R_ARM_PLT32:
897 goto bb_use_plt;
898
899 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 *loc += v - got;
901 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000902
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000903#elif defined(__cris__)
904
905 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000906 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000907
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000908 case R_CRIS_32:
909 /* CRIS keeps the relocation value in the r_addend field and
910 * should not use whats in *loc at all
911 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 *loc = v;
913 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000914
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000916
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000917 case R_H8_DIR24R8:
918 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
919 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000920 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000921 case R_H8_DIR24A8:
922 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000923 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000924 case R_H8_DIR32:
925 case R_H8_DIR32A16:
926 *loc += v;
927 break;
928 case R_H8_PCREL16:
929 v -= dot + 2;
930 if ((ElfW(Sword))v > 0x7fff ||
931 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
932 ret = obj_reloc_overflow;
933 else
934 *(unsigned short *)loc = v;
935 break;
936 case R_H8_PCREL8:
937 v -= dot + 1;
938 if ((ElfW(Sword))v > 0x7f ||
939 (ElfW(Sword))v < -(ElfW(Sword))0x80)
940 ret = obj_reloc_overflow;
941 else
942 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000943 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000944
Eric Andersencffd5022002-05-24 06:50:15 +0000945#elif defined(__i386__)
946
Eric Andersen3b1a7442003-12-24 20:30:45 +0000947 case R_386_NONE:
948 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000949
Eric Andersen3b1a7442003-12-24 20:30:45 +0000950 case R_386_32:
951 *loc += v;
952 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000953
Eric Andersen3b1a7442003-12-24 20:30:45 +0000954 case R_386_PLT32:
955 case R_386_PC32:
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +0000956 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 *loc += v - dot;
958 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 case R_386_GLOB_DAT:
961 case R_386_JMP_SLOT:
962 *loc = v;
963 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000964
Eric Andersen3b1a7442003-12-24 20:30:45 +0000965 case R_386_RELATIVE:
966 *loc += f->baseaddr;
967 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 *loc += got - dot;
971 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000972
Eric Andersen3b1a7442003-12-24 20:30:45 +0000973 case R_386_GOT32:
974 goto bb_use_got;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000975 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000976
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000977#elif defined(__microblaze__)
Mike Frysinger280dae72006-06-06 06:30:32 +0000978 case R_MICROBLAZE_NONE:
979 case R_MICROBLAZE_64_NONE:
980 case R_MICROBLAZE_32_SYM_OP_SYM:
981 case R_MICROBLAZE_32_PCREL:
982 break;
983
984 case R_MICROBLAZE_64_PCREL: {
985 /* dot is the address of the current instruction.
986 * v is the target symbol address.
987 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000988 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000989 * of this instruction.
990 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
991 */
992
993 /* Get split offset stored in code */
994 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
995 (loc[1] & 0xFFFF);
996
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000997 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +0000998 * because dot points to the IMM insn, but branch
999 * is computed relative to the branch instruction itself.
1000 */
1001 temp += v - dot - 4;
1002
1003 /* Store back into code */
1004 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1005 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1006
1007 break;
1008 }
1009
1010 case R_MICROBLAZE_32:
1011 *loc += v;
1012 break;
1013
1014 case R_MICROBLAZE_64: {
1015 /* Get split pointer stored in code */
1016 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1017 (loc[1] & 0xFFFF);
1018
1019 /* Add reloc offset */
1020 temp1+=v;
1021
1022 /* Store back into code */
1023 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1024 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1025
1026 break;
1027 }
1028
1029 case R_MICROBLAZE_32_PCREL_LO:
1030 case R_MICROBLAZE_32_LO:
1031 case R_MICROBLAZE_SRO32:
1032 case R_MICROBLAZE_SRW32:
1033 ret = obj_reloc_unhandled;
1034 break;
1035
Eric Andersencffd5022002-05-24 06:50:15 +00001036#elif defined(__mc68000__)
1037
Eric Andersen3b1a7442003-12-24 20:30:45 +00001038 case R_68K_NONE:
1039 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001040
Eric Andersen3b1a7442003-12-24 20:30:45 +00001041 case R_68K_32:
1042 *loc += v;
1043 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001044
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_68K_8:
1046 if (v > 0xff) {
1047 ret = obj_reloc_overflow;
1048 }
1049 *(char *)loc = v;
1050 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_68K_16:
1053 if (v > 0xffff) {
1054 ret = obj_reloc_overflow;
1055 }
1056 *(short *)loc = v;
1057 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001058
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 case R_68K_PC8:
1060 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001061 if ((ElfW(Sword))v > 0x7f ||
1062 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001063 ret = obj_reloc_overflow;
1064 }
1065 *(char *)loc = v;
1066 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001067
Eric Andersen3b1a7442003-12-24 20:30:45 +00001068 case R_68K_PC16:
1069 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001070 if ((ElfW(Sword))v > 0x7fff ||
1071 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001072 ret = obj_reloc_overflow;
1073 }
1074 *(short *)loc = v;
1075 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001076
Eric Andersen3b1a7442003-12-24 20:30:45 +00001077 case R_68K_PC32:
1078 *(int *)loc = v - dot;
1079 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001080
Eric Andersen3b1a7442003-12-24 20:30:45 +00001081 case R_68K_GLOB_DAT:
1082 case R_68K_JMP_SLOT:
1083 *loc = v;
1084 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_68K_RELATIVE:
1087 *(int *)loc += f->baseaddr;
1088 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001089
Eric Andersen3b1a7442003-12-24 20:30:45 +00001090 case R_68K_GOT32:
1091 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001092
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001093# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001094 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095 *loc += v - got;
1096 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001097# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001098
1099#elif defined(__mips__)
1100
Eric Andersen3b1a7442003-12-24 20:30:45 +00001101 case R_MIPS_NONE:
1102 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001103
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 case R_MIPS_32:
1105 *loc += v;
1106 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001107
Eric Andersen3b1a7442003-12-24 20:30:45 +00001108 case R_MIPS_26:
1109 if (v % 4)
1110 ret = obj_reloc_dangerous;
1111 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1112 ret = obj_reloc_overflow;
1113 *loc =
1114 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1115 0x03ffffff);
1116 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001117
Eric Andersen3b1a7442003-12-24 20:30:45 +00001118 case R_MIPS_HI16:
1119 {
1120 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001121
Eric Andersen3b1a7442003-12-24 20:30:45 +00001122 /* We cannot relocate this one now because we don't know the value
1123 of the carry we need to add. Save the information, and let LO16
1124 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001125 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001126 n->addr = loc;
1127 n->value = v;
1128 n->next = ifile->mips_hi16_list;
1129 ifile->mips_hi16_list = n;
1130 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001131 }
1132
Eric Andersen3b1a7442003-12-24 20:30:45 +00001133 case R_MIPS_LO16:
1134 {
1135 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001136 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001137
1138 /* Sign extend the addend we extract from the lo insn. */
1139 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1140
1141 if (ifile->mips_hi16_list != NULL) {
1142 struct mips_hi16 *l;
1143
1144 l = ifile->mips_hi16_list;
1145 while (l != NULL) {
1146 struct mips_hi16 *next;
1147 unsigned long insn;
1148
Eric Andersen3b1a7442003-12-24 20:30:45 +00001149 /* Do the HI16 relocation. Note that we actually don't
1150 need to know anything about the LO16 itself, except where
1151 to find the low 16 bits of the addend needed by the LO16. */
1152 insn = *l->addr;
1153 val =
1154 ((insn & 0xffff) << 16) +
1155 vallo;
1156 val += v;
1157
1158 /* Account for the sign extension that will happen in the
1159 low bits. */
1160 val =
1161 ((val >> 16) +
1162 ((val & 0x8000) !=
1163 0)) & 0xffff;
1164
1165 insn = (insn & ~0xffff) | val;
1166 *l->addr = insn;
1167
1168 next = l->next;
1169 free(l);
1170 l = next;
1171 }
1172
1173 ifile->mips_hi16_list = NULL;
1174 }
1175
1176 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1177 val = v + vallo;
1178 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1179 *loc = insnlo;
1180 break;
1181 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001182
Mike Frysingerf982d862006-01-04 00:11:26 +00001183#elif defined(__nios2__)
1184
1185 case R_NIOS2_NONE:
1186 break;
1187
1188 case R_NIOS2_BFD_RELOC_32:
1189 *loc += v;
1190 break;
1191
1192 case R_NIOS2_BFD_RELOC_16:
1193 if (v > 0xffff) {
1194 ret = obj_reloc_overflow;
1195 }
1196 *(short *)loc = v;
1197 break;
1198
1199 case R_NIOS2_BFD_RELOC_8:
1200 if (v > 0xff) {
1201 ret = obj_reloc_overflow;
1202 }
1203 *(char *)loc = v;
1204 break;
1205
1206 case R_NIOS2_S16:
1207 {
1208 Elf32_Addr word;
1209
1210 if ((Elf32_Sword)v > 0x7fff ||
1211 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1212 ret = obj_reloc_overflow;
1213 }
1214
1215 word = *loc;
1216 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1217 (word & 0x3f);
1218 }
1219 break;
1220
1221 case R_NIOS2_U16:
1222 {
1223 Elf32_Addr word;
1224
1225 if (v > 0xffff) {
1226 ret = obj_reloc_overflow;
1227 }
1228
1229 word = *loc;
1230 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1231 (word & 0x3f);
1232 }
1233 break;
1234
1235 case R_NIOS2_PCREL16:
1236 {
1237 Elf32_Addr word;
1238
1239 v -= dot + 4;
1240 if ((Elf32_Sword)v > 0x7fff ||
1241 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1242 ret = obj_reloc_overflow;
1243 }
1244
1245 word = *loc;
1246 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1247 }
1248 break;
1249
1250 case R_NIOS2_GPREL:
1251 {
1252 Elf32_Addr word, gp;
1253 /* get _gp */
1254 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1255 v-=gp;
1256 if ((Elf32_Sword)v > 0x7fff ||
1257 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1258 ret = obj_reloc_overflow;
1259 }
1260
1261 word = *loc;
1262 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1263 }
1264 break;
1265
1266 case R_NIOS2_CALL26:
1267 if (v & 3)
1268 ret = obj_reloc_dangerous;
1269 if ((v >> 28) != (dot >> 28))
1270 ret = obj_reloc_overflow;
1271 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1272 break;
1273
1274 case R_NIOS2_IMM5:
1275 {
1276 Elf32_Addr word;
1277
1278 if (v > 0x1f) {
1279 ret = obj_reloc_overflow;
1280 }
1281
1282 word = *loc & ~0x7c0;
1283 *loc = word | ((v & 0x1f) << 6);
1284 }
1285 break;
1286
1287 case R_NIOS2_IMM6:
1288 {
1289 Elf32_Addr word;
1290
1291 if (v > 0x3f) {
1292 ret = obj_reloc_overflow;
1293 }
1294
1295 word = *loc & ~0xfc0;
1296 *loc = word | ((v & 0x3f) << 6);
1297 }
1298 break;
1299
1300 case R_NIOS2_IMM8:
1301 {
1302 Elf32_Addr word;
1303
1304 if (v > 0xff) {
1305 ret = obj_reloc_overflow;
1306 }
1307
1308 word = *loc & ~0x3fc0;
1309 *loc = word | ((v & 0xff) << 6);
1310 }
1311 break;
1312
1313 case R_NIOS2_HI16:
1314 {
1315 Elf32_Addr word;
1316
1317 word = *loc;
1318 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1319 (word & 0x3f);
1320 }
1321 break;
1322
1323 case R_NIOS2_LO16:
1324 {
1325 Elf32_Addr word;
1326
1327 word = *loc;
1328 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1329 (word & 0x3f);
1330 }
1331 break;
1332
1333 case R_NIOS2_HIADJ16:
1334 {
1335 Elf32_Addr word1, word2;
1336
1337 word1 = *loc;
1338 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1339 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1340 (word1 & 0x3f);
1341 }
1342 break;
1343
Mike Frysingerebee0e72006-02-18 06:14:31 +00001344#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001345 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001346
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001347#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001348
Eric Andersen3b1a7442003-12-24 20:30:45 +00001349 case R_PPC_ADDR16_HA:
1350 *(unsigned short *)loc = (v + 0x8000) >> 16;
1351 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001352
Eric Andersen3b1a7442003-12-24 20:30:45 +00001353 case R_PPC_ADDR16_HI:
1354 *(unsigned short *)loc = v >> 16;
1355 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001356
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 case R_PPC_ADDR16_LO:
1358 *(unsigned short *)loc = v;
1359 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001360
Eric Andersen3b1a7442003-12-24 20:30:45 +00001361 case R_PPC_REL24:
1362 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001363
Eric Andersen3b1a7442003-12-24 20:30:45 +00001364 case R_PPC_REL32:
1365 *loc = v - dot;
1366 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001367
Eric Andersen3b1a7442003-12-24 20:30:45 +00001368 case R_PPC_ADDR32:
1369 *loc = v;
1370 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001371
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001372#elif defined(__s390__)
1373
1374 case R_390_32:
1375 *(unsigned int *) loc += v;
1376 break;
1377 case R_390_16:
1378 *(unsigned short *) loc += v;
1379 break;
1380 case R_390_8:
1381 *(unsigned char *) loc += v;
1382 break;
1383
1384 case R_390_PC32:
1385 *(unsigned int *) loc += v - dot;
1386 break;
1387 case R_390_PC16DBL:
1388 *(unsigned short *) loc += (v - dot) >> 1;
1389 break;
1390 case R_390_PC16:
1391 *(unsigned short *) loc += v - dot;
1392 break;
1393
1394 case R_390_PLT32:
1395 case R_390_PLT16DBL:
1396 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001397 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001398 if (pe->inited == 0) {
1399 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1400 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1401 ip[1] = 0x100607f1;
1402 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1403 ip[2] = v - 2;
1404 else
1405 ip[2] = v;
1406 pe->inited = 1;
1407 }
1408
1409 /* Insert relative distance to target. */
1410 v = plt + pe->offset - dot;
1411 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1412 *(unsigned int *) loc = (unsigned int) v;
1413 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1414 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1415 break;
1416
1417 case R_390_GLOB_DAT:
1418 case R_390_JMP_SLOT:
1419 *loc = v;
1420 break;
1421
1422 case R_390_RELATIVE:
1423 *loc += f->baseaddr;
1424 break;
1425
1426 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001427 *(unsigned long *) loc += got - dot;
1428 break;
1429
1430 case R_390_GOT12:
1431 case R_390_GOT16:
1432 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001433 if (!isym->gotent.inited)
1434 {
1435 isym->gotent.inited = 1;
1436 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1437 }
1438 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1439 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1440 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1441 *(unsigned short *) loc += isym->gotent.offset;
1442 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1443 *(unsigned int *) loc += isym->gotent.offset;
1444 break;
1445
1446# ifndef R_390_GOTOFF32
1447# define R_390_GOTOFF32 R_390_GOTOFF
1448# endif
1449 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001450 *loc += v - got;
1451 break;
1452
Eric Andersencffd5022002-05-24 06:50:15 +00001453#elif defined(__sh__)
1454
Eric Andersen3b1a7442003-12-24 20:30:45 +00001455 case R_SH_NONE:
1456 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001457
Eric Andersen3b1a7442003-12-24 20:30:45 +00001458 case R_SH_DIR32:
1459 *loc += v;
1460 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001461
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 case R_SH_REL32:
1463 *loc += v - dot;
1464 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001465
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 case R_SH_PLT32:
1467 *loc = v - dot;
1468 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001469
Eric Andersen3b1a7442003-12-24 20:30:45 +00001470 case R_SH_GLOB_DAT:
1471 case R_SH_JMP_SLOT:
1472 *loc = v;
1473 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001474
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 case R_SH_RELATIVE:
1476 *loc = f->baseaddr + rel->r_addend;
1477 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001480 *loc = got - dot + rel->r_addend;
1481 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001482
Eric Andersen3b1a7442003-12-24 20:30:45 +00001483 case R_SH_GOT32:
1484 goto bb_use_got;
1485
1486 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001487 *loc = v - got;
1488 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001489
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001490# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001491 case R_SH_IMM_MEDLOW16:
1492 case R_SH_IMM_LOW16:
1493 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001494 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001495
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001496 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001497 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001498
Eric Andersen3b1a7442003-12-24 20:30:45 +00001499 /*
1500 * movi and shori have the format:
1501 *
1502 * | op | imm | reg | reserved |
1503 * 31..26 25..10 9.. 4 3 .. 0
1504 *
1505 * so we simply mask and or in imm.
1506 */
1507 word = *loc & ~0x3fffc00;
1508 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001509
Eric Andersen3b1a7442003-12-24 20:30:45 +00001510 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001511
Eric Andersen3b1a7442003-12-24 20:30:45 +00001512 break;
1513 }
Eric Andersenbf833552003-08-13 19:56:33 +00001514
Eric Andersen3b1a7442003-12-24 20:30:45 +00001515 case R_SH_IMM_MEDLOW16_PCREL:
1516 case R_SH_IMM_LOW16_PCREL:
1517 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001518 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001519
Eric Andersen3b1a7442003-12-24 20:30:45 +00001520 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001521
Eric Andersen3b1a7442003-12-24 20:30:45 +00001522 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001523
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001524 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001526
Eric Andersen3b1a7442003-12-24 20:30:45 +00001527 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001528
Eric Andersen3b1a7442003-12-24 20:30:45 +00001529 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001530
Eric Andersen3b1a7442003-12-24 20:30:45 +00001531 break;
1532 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001533# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001534
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001535#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001536
Eric Andersen3b1a7442003-12-24 20:30:45 +00001537 case R_V850_NONE:
1538 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001539
Eric Andersen3b1a7442003-12-24 20:30:45 +00001540 case R_V850_32:
1541 /* We write two shorts instead of a long because even
1542 32-bit insns only need half-word alignment, but
1543 32-bit data needs to be long-word aligned. */
1544 v += ((unsigned short *)loc)[0];
1545 v += ((unsigned short *)loc)[1] << 16;
1546 ((unsigned short *)loc)[0] = v & 0xffff;
1547 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1548 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001549
Eric Andersen3b1a7442003-12-24 20:30:45 +00001550 case R_V850_22_PCREL:
1551 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001552
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001553#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001554
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001555 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001556 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001557
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001558 case R_X86_64_64:
1559 *loc += v;
1560 break;
1561
1562 case R_X86_64_32:
1563 *(unsigned int *) loc += v;
1564 if (v > 0xffffffff)
1565 {
1566 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1567 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1568 }
1569 break;
1570
1571 case R_X86_64_32S:
1572 *(signed int *) loc += v;
1573 break;
1574
1575 case R_X86_64_16:
1576 *(unsigned short *) loc += v;
1577 break;
1578
1579 case R_X86_64_8:
1580 *(unsigned char *) loc += v;
1581 break;
1582
1583 case R_X86_64_PC32:
1584 *(unsigned int *) loc += v - dot;
1585 break;
1586
1587 case R_X86_64_PC16:
1588 *(unsigned short *) loc += v - dot;
1589 break;
1590
1591 case R_X86_64_PC8:
1592 *(unsigned char *) loc += v - dot;
1593 break;
1594
1595 case R_X86_64_GLOB_DAT:
1596 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001597 *loc = v;
1598 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001599
1600 case R_X86_64_RELATIVE:
1601 *loc += f->baseaddr;
1602 break;
1603
1604 case R_X86_64_GOT32:
1605 case R_X86_64_GOTPCREL:
1606 goto bb_use_got;
1607# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001608 if (!isym->gotent.reloc_done)
1609 {
1610 isym->gotent.reloc_done = 1;
1611 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1612 }
1613 /* XXX are these really correct? */
1614 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1615 *(unsigned int *) loc += v + isym->gotent.offset;
1616 else
1617 *loc += isym->gotent.offset;
1618 break;
1619# endif
1620
Mike Frysingerf982d862006-01-04 00:11:26 +00001621#else
1622# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001623#endif
1624
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001625 default:
1626 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1627 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001628 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001629
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001630#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001631
Eric Andersen3b1a7442003-12-24 20:30:45 +00001632bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001633
Eric Andersen3b1a7442003-12-24 20:30:45 +00001634 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001635
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001636#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001637 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1638 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001639#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001641#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001642
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 if (! pe->inited) {
1644 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001645
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001647
1648#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1650 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001651#endif
1652#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001654 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 ip[2] = 0x7d6903a6; /* mtctr r11 */
1656 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001658#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 /* We have to trash a register, so we assume that any control
1660 transfer more than 21-bits away must be a function call
1661 (so we can use a call-clobbered register). */
1662 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1663 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001664#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 pe->inited = 1;
1666 }
Eric Andersen21adca72000-12-06 18:18:26 +00001667
Eric Andersen3b1a7442003-12-24 20:30:45 +00001668 /* relative distance to target */
1669 v -= dot;
1670 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001671#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001672 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001673#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001674 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001675#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 /* go via the plt */
1677 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001678
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001679#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001680 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001681#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001683#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001685
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001687#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 /* Convert to words. */
1689 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001690
Eric Andersen3b1a7442003-12-24 20:30:45 +00001691 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001692#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001693#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001695#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001696#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001697 /* We write two shorts instead of a long because even 32-bit insns
1698 only need half-word alignment, but the 32-bit data write needs
1699 to be long-word aligned. */
1700 ((unsigned short *)loc)[0] =
1701 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1702 | ((v >> 16) & 0x3f); /* offs high part */
1703 ((unsigned short *)loc)[1] =
1704 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001705#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001706 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001707#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001708
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001709#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001710bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001711
Eric Andersen3b1a7442003-12-24 20:30:45 +00001712 /* needs an entry in the .got: set it, once */
1713 if (!isym->gotent.inited) {
1714 isym->gotent.inited = 1;
1715 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1716 }
1717 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001718#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001719 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001720#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001721 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001722#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001723 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001724
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001725#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001726 }
1727
1728 return ret;
1729}
1730
Eric Andersencffd5022002-05-24 06:50:15 +00001731
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001732#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001733
1734static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1735 int offset, int size)
1736{
1737 struct arch_list_entry *pe;
1738
1739 for (pe = *list; pe != NULL; pe = pe->next) {
1740 if (pe->addend == rel->r_addend) {
1741 break;
1742 }
1743 }
1744
1745 if (pe == NULL) {
1746 pe = xmalloc(sizeof(struct arch_list_entry));
1747 pe->next = *list;
1748 pe->addend = rel->r_addend;
1749 pe->offset = offset;
1750 pe->inited = 0;
1751 *list = pe;
1752 return size;
1753 }
1754 return 0;
1755}
1756
1757#endif
1758
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001759#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001760
Denis Vlasenko68404f12008-03-17 09:00:54 +00001761static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single,
Eric Andersencffd5022002-05-24 06:50:15 +00001762 int offset, int size)
1763{
1764 if (single->allocated == 0) {
1765 single->allocated = 1;
1766 single->offset = offset;
1767 single->inited = 0;
1768 return size;
1769 }
1770 return 0;
1771}
1772
1773#endif
1774
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001775#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001776
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001777static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001778 int offset, int size)
1779{
1780 struct obj_section *myrelsec = obj_find_section(f, name);
1781
1782 if (offset == 0) {
1783 offset += size;
1784 }
1785
1786 if (myrelsec) {
1787 obj_extend_section(myrelsec, offset);
1788 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001789 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001790 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001791 }
1792
1793 return myrelsec;
1794}
1795
1796#endif
1797
1798static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001799{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001800#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001801 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001802 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001803#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001804 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001805#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001806#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001807 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001808#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001809 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001810 ElfW(RelM) *rel, *relend;
1811 ElfW(Sym) *symtab, *extsym;
1812 const char *strtab, *name;
1813 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001814
Eric Andersen21adca72000-12-06 18:18:26 +00001815 for (i = 0; i < f->header.e_shnum; ++i) {
1816 relsec = f->sections[i];
1817 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001818 continue;
1819
Eric Andersen21adca72000-12-06 18:18:26 +00001820 symsec = f->sections[relsec->header.sh_link];
1821 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001822
Eric Andersen21adca72000-12-06 18:18:26 +00001823 rel = (ElfW(RelM) *) relsec->contents;
1824 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1825 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001826 strtab = (const char *) strsec->contents;
1827
1828 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001829 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001830
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001831#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001832 got_allocate = 0;
1833#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001834#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001835 plt_allocate = 0;
1836#endif
1837
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001838 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001839#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001840 case R_ARM_PC24:
1841 case R_ARM_PLT32:
1842 plt_allocate = 1;
1843 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001844
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001845 case R_ARM_GOTOFF:
1846 case R_ARM_GOTPC:
1847 got_needed = 1;
1848 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001849
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001850 case R_ARM_GOT32:
1851 got_allocate = 1;
1852 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001853
Eric Andersen21adca72000-12-06 18:18:26 +00001854#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001855 case R_386_GOTPC:
1856 case R_386_GOTOFF:
1857 got_needed = 1;
1858 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001859
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001860 case R_386_GOT32:
1861 got_allocate = 1;
1862 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001863
1864#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001865 case R_PPC_REL24:
1866 plt_allocate = 1;
1867 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001868
1869#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001870 case R_68K_GOT32:
1871 got_allocate = 1;
1872 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001873
Eric Andersen16451a02004-03-19 12:16:18 +00001874#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001875 case R_68K_GOTOFF:
1876 got_needed = 1;
1877 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001878#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001879
1880#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001881 case R_SH_GOT32:
1882 got_allocate = 1;
1883 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001884
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001885 case R_SH_GOTPC:
1886 case R_SH_GOTOFF:
1887 got_needed = 1;
1888 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001889
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001890#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001891 case R_V850_22_PCREL:
1892 plt_needed = 1;
1893 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001894
1895#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001896 default:
1897 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001898 }
1899
Eric Andersen21adca72000-12-06 18:18:26 +00001900 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001901 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001902 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001903 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001904 }
1905 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001906#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001907 if (got_allocate) {
1908 got_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001909 /*rel,*/ &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001910 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001911
1912 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001913 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001914#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001915#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001916 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001917#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001918 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001919 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001920 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001921#else
1922 plt_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001923 /*rel,*/ &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001924 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001925#endif
1926 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001927 }
1928#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001929 }
Miles Baderae28b042002-04-01 09:34:25 +00001930 }
Eric Andersen21adca72000-12-06 18:18:26 +00001931
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001932#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001933 if (got_needed) {
1934 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001935 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001936 }
Eric Andersen21adca72000-12-06 18:18:26 +00001937#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001938
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001939#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001940 if (plt_needed) {
1941 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001942 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001943 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001944#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001945
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001946#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001947}
1948
Eric Andersen9f16d612000-06-12 23:11:16 +00001949/*======================================================================*/
1950
1951/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001952static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001953{
1954 unsigned long h = 0;
1955 unsigned long g;
1956 unsigned char ch;
1957
1958 while (n > 0) {
1959 ch = *name++;
1960 h = (h << 4) + ch;
Denis Vlasenko1bec1b92007-11-06 02:23:39 +00001961 g = (h & 0xf0000000);
1962 if (g != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001963 h ^= g >> 24;
1964 h &= ~g;
1965 }
1966 n--;
1967 }
1968 return h;
1969}
1970
Eric Andersen044228d2001-07-17 01:12:36 +00001971static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001972{
1973 return obj_elf_hash_n(name, strlen(name));
1974}
1975
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001976#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001977/* String comparison for non-co-versioned kernel and module. */
1978
1979static int ncv_strcmp(const char *a, const char *b)
1980{
1981 size_t alen = strlen(a), blen = strlen(b);
1982
1983 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1984 return strncmp(a, b, alen);
1985 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1986 return strncmp(a, b, blen);
1987 else
1988 return strcmp(a, b);
1989}
1990
1991/* String hashing for non-co-versioned kernel and module. Here
1992 we are simply forced to drop the crc from the hash. */
1993
1994static unsigned long ncv_symbol_hash(const char *str)
1995{
1996 size_t len = strlen(str);
1997 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1998 len -= 10;
1999 return obj_elf_hash_n(str, len);
2000}
2001
Eric Andersen044228d2001-07-17 01:12:36 +00002002static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002003obj_set_symbol_compare(struct obj_file *f,
2004 int (*cmp) (const char *, const char *),
2005 unsigned long (*hash) (const char *))
2006{
2007 if (cmp)
2008 f->symbol_cmp = cmp;
2009 if (hash) {
2010 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2011 int i;
2012
2013 f->symbol_hash = hash;
2014
2015 memcpy(tmptab, f->symtab, sizeof(tmptab));
2016 memset(f->symtab, 0, sizeof(f->symtab));
2017
2018 for (i = 0; i < HASH_BUCKETS; ++i)
2019 for (sym = tmptab[i]; sym; sym = next) {
2020 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2021 next = sym->next;
2022 sym->next = f->symtab[h];
2023 f->symtab[h] = sym;
2024 }
2025 }
2026}
2027
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002028#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002029
Eric Andersen044228d2001-07-17 01:12:36 +00002030static struct obj_symbol *
2031obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002032 unsigned long symidx, int info,
2033 int secidx, ElfW(Addr) value,
2034 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002035{
2036 struct obj_symbol *sym;
2037 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002038 int n_type = ELF_ST_TYPE(info);
2039 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002040
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002041 for (sym = f->symtab[hash]; sym; sym = sym->next) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002042 if (f->symbol_cmp(sym->name, name) == 0) {
2043 int o_secidx = sym->secidx;
2044 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002045 int o_type = ELF_ST_TYPE(o_info);
2046 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002047
2048 /* A redefinition! Is it legal? */
2049
2050 if (secidx == SHN_UNDEF)
2051 return sym;
2052 else if (o_secidx == SHN_UNDEF)
2053 goto found;
2054 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2055 /* Cope with local and global symbols of the same name
2056 in the same object file, as might have been created
2057 by ld -r. The only reason locals are now seen at this
2058 level at all is so that we can do semi-sensible things
2059 with parameters. */
2060
2061 struct obj_symbol *nsym, **p;
2062
2063 nsym = arch_new_symbol();
2064 nsym->next = sym->next;
2065 nsym->ksymidx = -1;
2066
2067 /* Excise the old (local) symbol from the hash chain. */
2068 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2069 continue;
2070 *p = sym = nsym;
2071 goto found;
2072 } else if (n_binding == STB_LOCAL) {
2073 /* Another symbol of the same name has already been defined.
2074 Just add this to the local table. */
2075 sym = arch_new_symbol();
2076 sym->next = NULL;
2077 sym->ksymidx = -1;
2078 f->local_symtab[symidx] = sym;
2079 goto found;
2080 } else if (n_binding == STB_WEAK)
2081 return sym;
2082 else if (o_binding == STB_WEAK)
2083 goto found;
2084 /* Don't unify COMMON symbols with object types the programmer
2085 doesn't expect. */
2086 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002087 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002088 return sym;
2089 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002090 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002091 goto found;
2092 else {
2093 /* Don't report an error if the symbol is coming from
2094 the kernel or some external module. */
2095 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002096 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002097 return sym;
2098 }
2099 }
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002100 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002101
2102 /* Completely new symbol. */
2103 sym = arch_new_symbol();
2104 sym->next = f->symtab[hash];
2105 f->symtab[hash] = sym;
2106 sym->ksymidx = -1;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00002107 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != (unsigned long)(-1)) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002108 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002109 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002110 name, (long) symidx, (long) f->local_symtab_size);
2111 else
2112 f->local_symtab[symidx] = sym;
2113 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002114
Eric Andersen3b1a7442003-12-24 20:30:45 +00002115found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002116 sym->name = name;
2117 sym->value = value;
2118 sym->size = size;
2119 sym->secidx = secidx;
2120 sym->info = info;
2121
2122 return sym;
2123}
2124
Eric Andersen044228d2001-07-17 01:12:36 +00002125static struct obj_symbol *
2126obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002127{
2128 struct obj_symbol *sym;
2129 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2130
2131 for (sym = f->symtab[hash]; sym; sym = sym->next)
2132 if (f->symbol_cmp(sym->name, name) == 0)
2133 return sym;
2134
2135 return NULL;
2136}
2137
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002138static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002139{
2140 if (sym) {
2141 if (sym->secidx >= SHN_LORESERVE)
2142 return sym->value;
2143
2144 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2145 } else {
2146 /* As a special case, a NULL sym has value zero. */
2147 return 0;
2148 }
2149}
2150
Eric Andersen044228d2001-07-17 01:12:36 +00002151static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002152{
2153 int i, n = f->header.e_shnum;
2154
2155 for (i = 0; i < n; ++i)
2156 if (strcmp(f->sections[i]->name, name) == 0)
2157 return f->sections[i];
2158
2159 return NULL;
2160}
2161
2162static int obj_load_order_prio(struct obj_section *a)
2163{
2164 unsigned long af, ac;
2165
2166 af = a->header.sh_flags;
2167
2168 ac = 0;
2169 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002170 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002171 ac |= 32;
2172 if (af & SHF_ALLOC)
2173 ac |= 16;
2174 if (!(af & SHF_WRITE))
2175 ac |= 8;
2176 if (af & SHF_EXECINSTR)
2177 ac |= 4;
2178 if (a->header.sh_type != SHT_NOBITS)
2179 ac |= 2;
2180
2181 return ac;
2182}
2183
Eric Andersen044228d2001-07-17 01:12:36 +00002184static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002185obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2186{
2187 struct obj_section **p;
2188 int prio = obj_load_order_prio(sec);
2189 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2190 if (obj_load_order_prio(*p) < prio)
2191 break;
2192 sec->load_next = *p;
2193 *p = sec;
2194}
2195
Eric Andersen044228d2001-07-17 01:12:36 +00002196static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002197 const char *name,
2198 unsigned long align,
2199 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002200{
2201 int newidx = f->header.e_shnum++;
2202 struct obj_section *sec;
2203
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002204 f->sections = xrealloc_vector(f->sections, 2, newidx);
Eric Andersen9f16d612000-06-12 23:11:16 +00002205 f->sections[newidx] = sec = arch_new_section();
2206
Eric Andersen9f16d612000-06-12 23:11:16 +00002207 sec->header.sh_type = SHT_PROGBITS;
2208 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2209 sec->header.sh_size = size;
2210 sec->header.sh_addralign = align;
2211 sec->name = name;
2212 sec->idx = newidx;
2213 if (size)
2214 sec->contents = xmalloc(size);
2215
2216 obj_insert_section_load_order(f, sec);
2217
2218 return sec;
2219}
2220
Eric Andersen044228d2001-07-17 01:12:36 +00002221static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002222 const char *name,
2223 unsigned long align,
2224 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002225{
2226 int newidx = f->header.e_shnum++;
2227 struct obj_section *sec;
2228
2229 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2230 f->sections[newidx] = sec = arch_new_section();
2231
Eric Andersen9f16d612000-06-12 23:11:16 +00002232 sec->header.sh_type = SHT_PROGBITS;
2233 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2234 sec->header.sh_size = size;
2235 sec->header.sh_addralign = align;
2236 sec->name = name;
2237 sec->idx = newidx;
2238 if (size)
2239 sec->contents = xmalloc(size);
2240
2241 sec->load_next = f->load_order;
2242 f->load_order = sec;
2243 if (f->load_order_search_start == &f->load_order)
2244 f->load_order_search_start = &sec->load_next;
2245
2246 return sec;
2247}
2248
Eric Andersen044228d2001-07-17 01:12:36 +00002249static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002250{
2251 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002252 if (more) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002253 sec->header.sh_size += more;
2254 sec->contents = xrealloc(sec->contents, sec->header.sh_size);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002255 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002256 return sec->contents + oldsize;
2257}
2258
2259
Eric Andersen9f16d612000-06-12 23:11:16 +00002260/* Conditionally add the symbols from the given symbol set to the
2261 new module. */
2262
2263static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002264add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002265 int idx, struct new_module_symbol *syms, size_t nsyms)
2266{
2267 struct new_module_symbol *s;
2268 size_t i;
2269 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002270#ifdef SYMBOL_PREFIX
2271 char *name_buf = 0;
2272 size_t name_alloced_size = 0;
2273#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002274#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002275 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002276
Glenn L McGrath759515c2003-08-30 06:00:33 +00002277 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002278#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002279 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002280 /* Only add symbols that are already marked external.
2281 If we override locals we may cause problems for
2282 argument initialization. We will also create a false
2283 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002284 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002285 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002286
Glenn L McGrath759515c2003-08-30 06:00:33 +00002287 /* GPL licensed modules can use symbols exported with
2288 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2289 * exported names. Non-GPL modules never see any GPLONLY_
2290 * symbols so they cannot fudge it by adding the prefix on
2291 * their references.
2292 */
2293 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002294#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002295 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002296 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002297 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002298#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002299 continue;
2300 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002301 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002302
Miles Baderae28b042002-04-01 09:34:25 +00002303#ifdef SYMBOL_PREFIX
2304 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2305 kernel exports `C names', but module object files
2306 reference `linker names'). */
2307 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002308 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002309 if (name_size > name_alloced_size) {
2310 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002311 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002312 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002313 strcpy(name_buf, SYMBOL_PREFIX);
2314 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002315 name = name_buf;
2316#endif /* SYMBOL_PREFIX */
2317
2318 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002319 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002320#ifdef SYMBOL_PREFIX
2321 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002322 name = xmalloc(name_size);
2323 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002324#endif
2325 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002326 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002327 STT_NOTYPE),
2328 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002329 /* Did our symbol just get installed? If so, mark the
2330 module as "used". */
2331 if (sym->secidx == idx)
2332 used = 1;
2333 }
2334 }
2335
2336 return used;
2337}
2338
2339static void add_kernel_symbols(struct obj_file *f)
2340{
2341 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002342 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002343
2344 /* Add module symbols first. */
2345
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002346 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002347 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002348 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2349 ) {
2350 m->used = 1;
2351 ++nused;
2352 }
2353 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002354
2355 n_ext_modules_used = nused;
2356
2357 /* And finally the symbols from the kernel proper. */
2358
2359 if (nksyms)
2360 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2361}
2362
2363static char *get_modinfo_value(struct obj_file *f, const char *key)
2364{
2365 struct obj_section *sec;
2366 char *p, *v, *n, *ep;
2367 size_t klen = strlen(key);
2368
2369 sec = obj_find_section(f, ".modinfo");
2370 if (sec == NULL)
2371 return NULL;
2372 p = sec->contents;
2373 ep = p + sec->header.sh_size;
2374 while (p < ep) {
2375 v = strchr(p, '=');
2376 n = strchr(p, '\0');
2377 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002378 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002379 return v + 1;
2380 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002381 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002382 return n;
2383 }
2384 p = n + 1;
2385 }
2386
2387 return NULL;
2388}
2389
2390
2391/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002392/* Functions relating to module loading after 2.1.18. */
2393
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002394static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002395new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2396{
2397 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002398 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 struct obj_symbol *sym;
2400 char *contents, *loc;
2401 int min, max, n;
2402
2403 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002404 q = strchr(p, '=');
2405 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002406 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002407 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002408 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002409
2410 key = alloca(q - p + 6);
2411 memcpy(key, "parm_", 5);
2412 memcpy(key + 5, p, q - p);
2413 key[q - p + 5] = 0;
2414
2415 p = get_modinfo_value(f, key);
2416 key += 5;
2417 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002418 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002419 }
2420
Miles Baderae28b042002-04-01 09:34:25 +00002421#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002422 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2423 strcpy(sym_name, SYMBOL_PREFIX);
2424 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002425#else
2426 sym_name = key;
2427#endif
2428 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002429
2430 /* Also check that the parameter was not resolved from the kernel. */
2431 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002432 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002433 }
2434
2435 if (isdigit(*p)) {
2436 min = strtoul(p, &p, 10);
2437 if (*p == '-')
2438 max = strtoul(p + 1, &p, 10);
2439 else
2440 max = min;
2441 } else
2442 min = max = 1;
2443
2444 contents = f->sections[sym->secidx]->contents;
2445 loc = contents + sym->value;
2446 n = (*++q != '\0');
2447
2448 while (1) {
2449 if ((*p == 's') || (*p == 'c')) {
2450 char *str;
2451
2452 /* Do C quoting if we begin with a ", else slurp the lot. */
2453 if (*q == '"') {
2454 char *r;
2455
2456 str = alloca(strlen(q));
2457 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002458 if (*q == '\0')
2459 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002460 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002461 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002462 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002463 case 'a':
2464 *r = '\a';
2465 break;
2466 case 'b':
2467 *r = '\b';
2468 break;
2469 case 'e':
2470 *r = '\033';
2471 break;
2472 case 'f':
2473 *r = '\f';
2474 break;
2475 case 'n':
2476 *r = '\n';
2477 break;
2478 case 'r':
2479 *r = '\r';
2480 break;
2481 case 't':
2482 *r = '\t';
2483 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002484
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002485 case '0':
2486 case '1':
2487 case '2':
2488 case '3':
2489 case '4':
2490 case '5':
2491 case '6':
2492 case '7':
2493 {
2494 int c = *q - '0';
2495 if (q[1] >= '0' && q[1] <= '7') {
2496 c = (c * 8) + *++q - '0';
2497 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002498 c = (c * 8) + *++q - '0';
2499 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002500 *r = c;
2501 }
2502 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002503
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002504 default:
2505 *r = *q;
2506 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002507 }
2508 else
2509 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002510 }
2511 *r = '\0';
2512 ++q;
2513 } else {
2514 char *r;
2515
2516 /* In this case, the string is not quoted. We will break
2517 it using the coma (like for ints). If the user wants to
2518 include comas in a string, he just has to quote it */
2519
2520 /* Search the next coma */
2521 r = strchr(q, ',');
2522
2523 /* Found ? */
2524 if (r != (char *) NULL) {
2525 /* Recopy the current field */
2526 str = alloca(r - q + 1);
2527 memcpy(str, q, r - q);
2528
Eric Andersenaff114c2004-04-14 17:51:38 +00002529 /* I don't know if it is useful, as the previous case
2530 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002531 str[r - q] = '\0';
2532
2533 /* Keep next fields */
2534 q = r;
2535 } else {
2536 /* last string */
2537 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002538 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002539 }
2540 }
2541
2542 if (*p == 's') {
2543 /* Normal string */
2544 obj_string_patch(f, sym->secidx, loc - contents, str);
2545 loc += tgt_sizeof_char_p;
2546 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002547 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002548 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002549
2550 /* Get the size of each member */
2551 /* Probably we should do that outside the loop ? */
2552 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002553 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002554 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002555 }
2556 charssize = strtoul(p + 1, (char **) NULL, 10);
2557
2558 /* Check length */
2559 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002560 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002561 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002562 }
2563
2564 /* Copy to location */
2565 strcpy((char *) loc, str);
2566 loc += charssize;
2567 }
2568 } else {
2569 long v = strtoul(q, &q, 0);
2570 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002571 case 'b':
2572 *loc++ = v;
2573 break;
2574 case 'h':
2575 *(short *) loc = v;
2576 loc += tgt_sizeof_short;
2577 break;
2578 case 'i':
2579 *(int *) loc = v;
2580 loc += tgt_sizeof_int;
2581 break;
2582 case 'l':
2583 *(long *) loc = v;
2584 loc += tgt_sizeof_long;
2585 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002586
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002587 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002588 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002589 }
2590 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002591 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002592 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002593 case '\0':
2594 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002595
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002596 case ' ':
2597 case '\t':
2598 case '\n':
2599 case '\r':
2600 ++q;
2601 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002602
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002603 case ',':
2604 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002605 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002606 }
2607 ++q;
2608 break;
2609
2610 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002611 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002612 }
2613 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002614 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002615 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002616 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002617 }
2618
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002619 argc--;
2620 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002621 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002622}
2623
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002624#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002625static int new_is_module_checksummed(struct obj_file *f)
2626{
2627 const char *p = get_modinfo_value(f, "using_checksums");
2628 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002629 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002630 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002631}
2632
2633/* Get the module's kernel version in the canonical integer form. */
2634
2635static int
2636new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2637{
2638 char *p, *q;
2639 int a, b, c;
2640
2641 p = get_modinfo_value(f, "kernel_version");
2642 if (p == NULL)
2643 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002644 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002645
2646 a = strtoul(p, &p, 10);
2647 if (*p != '.')
2648 return -1;
2649 b = strtoul(p + 1, &p, 10);
2650 if (*p != '.')
2651 return -1;
2652 c = strtoul(p + 1, &q, 10);
2653 if (p + 1 == q)
2654 return -1;
2655
2656 return a << 16 | b << 8 | c;
2657}
2658
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002659#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002660
2661
Eric Andersen9f16d612000-06-12 23:11:16 +00002662/* Fetch the loaded modules, and all currently exported symbols. */
2663
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002664static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002665{
2666 char *module_names, *mn;
2667 struct external_module *modules, *m;
2668 struct new_module_symbol *syms, *s;
2669 size_t ret, bufsize, nmod, nsyms, i, j;
2670
2671 /* Collect the loaded modules. */
2672
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002673 bufsize = 256;
2674 module_names = xmalloc(bufsize);
2675
2676 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002677 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002678 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002679 bufsize = ret;
2680 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002681 goto retry_modules_load;
2682 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002683 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002684 }
2685
2686 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002687
2688 /* Collect the modules' symbols. */
2689
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002690 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002691 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2692 memset(modules, 0, nmod * sizeof(*modules));
2693 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002694 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002695 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002696
Mark Whitley94fd4802001-03-12 23:08:34 +00002697 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2698 if (errno == ENOENT) {
2699 /* The module was removed out from underneath us. */
2700 continue;
2701 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002702 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002703 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002704
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002705 bufsize = 1024;
2706 syms = xmalloc(bufsize);
2707 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002708 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2709 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002710 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002711 bufsize = ret;
2712 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002713 goto retry_mod_sym_load;
2714 case ENOENT:
2715 /* The module was removed out from underneath us. */
2716 continue;
2717 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002718 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002719 }
2720 }
2721 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002722
Mark Whitley94fd4802001-03-12 23:08:34 +00002723 m->name = mn;
2724 m->addr = info.addr;
2725 m->nsyms = nsyms;
2726 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002727
Mark Whitley94fd4802001-03-12 23:08:34 +00002728 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2729 s->name += (unsigned long) syms;
2730 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002731 }
2732 }
2733
2734 /* Collect the kernel's symbols. */
2735
2736 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002737 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002738 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002739 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkodeeed592008-07-08 05:14:36 +00002740 bufsize = ret;
2741 syms = xrealloc(syms, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002742 goto retry_kern_sym_load;
2743 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002744 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002745 }
2746 nksyms = nsyms = ret;
2747 ksyms = syms;
2748
2749 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2750 s->name += (unsigned long) syms;
2751 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002752}
2753
2754
2755/* Return the kernel symbol checksum version, or zero if not used. */
2756
2757static int new_is_kernel_checksummed(void)
2758{
2759 struct new_module_symbol *s;
2760 size_t i;
2761
2762 /* Using_Versions is not the first symbol, but it should be in there. */
2763
2764 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2765 if (strcmp((char *) s->name, "Using_Versions") == 0)
2766 return s->value;
2767
2768 return 0;
2769}
2770
2771
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002772static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002773{
2774 struct obj_section *sec;
2775
2776 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002777 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002778 memset(sec->contents, 0, sizeof(struct new_module));
2779
Miles Baderae28b042002-04-01 09:34:25 +00002780 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002781 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002782 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002783
2784 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002785 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002786}
2787
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002788#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002789/* add an entry to the __ksymtab section, creating it if necessary */
2790static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2791{
2792 struct obj_section *sec;
2793 ElfW(Addr) ofs;
2794
2795 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2796 * If __ksymtab is defined but not marked alloc, x out the first character
2797 * (no obj_delete routine) and create a new __ksymtab with the correct
2798 * characteristics.
2799 */
2800 sec = obj_find_section(f, "__ksymtab");
2801 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2802 *((char *)(sec->name)) = 'x'; /* override const */
2803 sec = NULL;
2804 }
2805 if (!sec)
2806 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002807 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002808 if (!sec)
2809 return;
2810 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002811 /* Empty section might be byte-aligned */
2812 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002813 ofs = sec->header.sh_size;
2814 obj_symbol_patch(f, sec->idx, ofs, sym);
2815 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2816 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2817}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002818#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002819
2820static int new_create_module_ksymtab(struct obj_file *f)
2821{
2822 struct obj_section *sec;
2823 int i;
2824
2825 /* We must always add the module references. */
2826
2827 if (n_ext_modules_used) {
2828 struct new_module_ref *dep;
2829 struct obj_symbol *tm;
2830
2831 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002832 (sizeof(struct new_module_ref)
2833 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002834 if (!sec)
2835 return 0;
2836
Miles Baderae28b042002-04-01 09:34:25 +00002837 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002838 dep = (struct new_module_ref *) sec->contents;
2839 for (i = 0; i < n_ext_modules; ++i)
2840 if (ext_modules[i].used) {
2841 dep->dep = ext_modules[i].addr;
2842 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002843 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002844 dep->next_ref = 0;
2845 ++dep;
2846 }
2847 }
2848
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002849 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002850 size_t nsyms;
2851 int *loaded;
2852
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002853 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002854
2855 /* We don't want to export symbols residing in sections that
2856 aren't loaded. There are a number of these created so that
2857 we make sure certain module options don't appear twice. */
2858
2859 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2860 while (--i >= 0)
2861 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2862
2863 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2864 struct obj_symbol *sym;
2865 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002866 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002867 && sym->secidx <= SHN_HIRESERVE
2868 && (sym->secidx >= SHN_LORESERVE
2869 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002870 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2871
2872 obj_symbol_patch(f, sec->idx, ofs, sym);
2873 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002874 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002875
2876 nsyms++;
2877 }
2878 }
2879
2880 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2881 }
2882
2883 return 1;
2884}
2885
2886
2887static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002888new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002889{
2890 struct new_module *module;
2891 struct obj_section *sec;
2892 void *image;
2893 int ret;
2894 tgt_long m_addr;
2895
2896 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002897 if (!sec || !sec->contents) {
Denis Vlasenkof5d8c902008-06-26 14:32:57 +00002898 bb_perror_msg_and_die("corrupt module %s?", m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002899 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002900 module = (struct new_module *) sec->contents;
2901 m_addr = sec->header.sh_addr;
2902
2903 module->size_of_struct = sizeof(*module);
2904 module->size = m_size;
2905 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2906
2907 sec = obj_find_section(f, "__ksymtab");
2908 if (sec && sec->header.sh_size) {
2909 module->syms = sec->header.sh_addr;
2910 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2911 }
2912
2913 if (n_ext_modules_used) {
2914 sec = obj_find_section(f, ".kmodtab");
2915 module->deps = sec->header.sh_addr;
2916 module->ndeps = n_ext_modules_used;
2917 }
2918
2919 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002920 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002921 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002922 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002923
2924 sec = obj_find_section(f, "__ex_table");
2925 if (sec) {
2926 module->ex_table_start = sec->header.sh_addr;
2927 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2928 }
2929
2930 sec = obj_find_section(f, ".text.init");
2931 if (sec) {
2932 module->runsize = sec->header.sh_addr - m_addr;
2933 }
2934 sec = obj_find_section(f, ".data.init");
2935 if (sec) {
2936 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002937 module->runsize > sec->header.sh_addr - m_addr)
2938 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002939 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002940 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2941 if (sec && sec->header.sh_size) {
2942 module->archdata_start = (void*)sec->header.sh_addr;
2943 module->archdata_end = module->archdata_start + sec->header.sh_size;
2944 }
2945 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2946 if (sec && sec->header.sh_size) {
2947 module->kallsyms_start = (void*)sec->header.sh_addr;
2948 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2949 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002950
Eric Andersen9f16d612000-06-12 23:11:16 +00002951 /* Whew! All of the initialization is complete. Collect the final
2952 module image and give it to the kernel. */
2953
2954 image = xmalloc(m_size);
2955 obj_create_image(f, image);
2956
Eric Andersencb3b9b12004-06-22 11:50:52 +00002957 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002959 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002960
2961 free(image);
2962
2963 return ret == 0;
2964}
2965
Eric Andersen9f16d612000-06-12 23:11:16 +00002966
2967/*======================================================================*/
2968
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002969static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002970obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2971 const char *string)
2972{
2973 struct obj_string_patch *p;
2974 struct obj_section *strsec;
2975 size_t len = strlen(string) + 1;
2976 char *loc;
2977
2978 p = xmalloc(sizeof(*p));
2979 p->next = f->string_patches;
2980 p->reloc_secidx = secidx;
2981 p->reloc_offset = offset;
2982 f->string_patches = p;
2983
2984 strsec = obj_find_section(f, ".kstrtab");
2985 if (strsec == NULL) {
2986 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2987 p->string_offset = 0;
2988 loc = strsec->contents;
2989 } else {
2990 p->string_offset = strsec->header.sh_size;
2991 loc = obj_extend_section(strsec, len);
2992 }
2993 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002994}
2995
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00002996static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002997obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2998 struct obj_symbol *sym)
2999{
3000 struct obj_symbol_patch *p;
3001
3002 p = xmalloc(sizeof(*p));
3003 p->next = f->symbol_patches;
3004 p->reloc_secidx = secidx;
3005 p->reloc_offset = offset;
3006 p->sym = sym;
3007 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00003008}
3009
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003010static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003011{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003012 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003013
3014 for (i = 0; i < HASH_BUCKETS; ++i) {
3015 struct obj_symbol *sym;
3016 for (sym = f->symtab[i]; sym; sym = sym->next)
3017 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003018 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003019 sym->secidx = SHN_ABS;
3020 sym->value = 0;
3021 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003022 if (!flag_quiet)
3023 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003024 }
3025 }
3026 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003027}
3028
Eric Andersen044228d2001-07-17 01:12:36 +00003029static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003030{
3031 struct common_entry {
3032 struct common_entry *next;
3033 struct obj_symbol *sym;
3034 } *common_head = NULL;
3035
3036 unsigned long i;
3037
3038 for (i = 0; i < HASH_BUCKETS; ++i) {
3039 struct obj_symbol *sym;
3040 for (sym = f->symtab[i]; sym; sym = sym->next)
3041 if (sym->secidx == SHN_COMMON) {
3042 /* Collect all COMMON symbols and sort them by size so as to
3043 minimize space wasted by alignment requirements. */
3044 {
3045 struct common_entry **p, *n;
3046 for (p = &common_head; *p; p = &(*p)->next)
3047 if (sym->size <= (*p)->sym->size)
3048 break;
3049
3050 n = alloca(sizeof(*n));
3051 n->next = *p;
3052 n->sym = sym;
3053 *p = n;
3054 }
3055 }
3056 }
3057
3058 for (i = 1; i < f->local_symtab_size; ++i) {
3059 struct obj_symbol *sym = f->local_symtab[i];
3060 if (sym && sym->secidx == SHN_COMMON) {
3061 struct common_entry **p, *n;
3062 for (p = &common_head; *p; p = &(*p)->next)
3063 if (sym == (*p)->sym)
3064 break;
3065 else if (sym->size < (*p)->sym->size) {
3066 n = alloca(sizeof(*n));
3067 n->next = *p;
3068 n->sym = sym;
3069 *p = n;
3070 break;
3071 }
3072 }
3073 }
3074
3075 if (common_head) {
3076 /* Find the bss section. */
3077 for (i = 0; i < f->header.e_shnum; ++i)
3078 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3079 break;
3080
3081 /* If for some reason there hadn't been one, create one. */
3082 if (i == f->header.e_shnum) {
3083 struct obj_section *sec;
3084
Denis Vlasenkodeeed592008-07-08 05:14:36 +00003085 f->sections = xrealloc(f->sections, 2, i);
Eric Andersen9f16d612000-06-12 23:11:16 +00003086 f->sections[i] = sec = arch_new_section();
3087 f->header.e_shnum = i + 1;
3088
Eric Andersen9f16d612000-06-12 23:11:16 +00003089 sec->header.sh_type = SHT_PROGBITS;
3090 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3091 sec->name = ".bss";
3092 sec->idx = i;
3093 }
3094
3095 /* Allocate the COMMONS. */
3096 {
3097 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3098 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3099 struct common_entry *c;
3100
3101 for (c = common_head; c; c = c->next) {
3102 ElfW(Addr) align = c->sym->value;
3103
3104 if (align > max_align)
3105 max_align = align;
3106 if (bss_size & (align - 1))
3107 bss_size = (bss_size | (align - 1)) + 1;
3108
3109 c->sym->secidx = i;
3110 c->sym->value = bss_size;
3111
3112 bss_size += c->sym->size;
3113 }
3114
3115 f->sections[i]->header.sh_size = bss_size;
3116 f->sections[i]->header.sh_addralign = max_align;
3117 }
3118 }
3119
3120 /* For the sake of patch relocation and parameter initialization,
3121 allocate zeroed data for NOBITS sections now. Note that after
3122 this we cannot assume NOBITS are really empty. */
3123 for (i = 0; i < f->header.e_shnum; ++i) {
3124 struct obj_section *s = f->sections[i];
3125 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003126 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003127 s->contents = memset(xmalloc(s->header.sh_size),
3128 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003129 else
3130 s->contents = NULL;
3131
Eric Andersen9f16d612000-06-12 23:11:16 +00003132 s->header.sh_type = SHT_PROGBITS;
3133 }
3134 }
3135}
3136
Eric Andersen044228d2001-07-17 01:12:36 +00003137static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003138{
3139 unsigned long dot = 0;
3140 struct obj_section *sec;
3141
3142 /* Finalize the positions of the sections relative to one another. */
3143
3144 for (sec = f->load_order; sec; sec = sec->load_next) {
3145 ElfW(Addr) align;
3146
3147 align = sec->header.sh_addralign;
3148 if (align && (dot & (align - 1)))
3149 dot = (dot | (align - 1)) + 1;
3150
3151 sec->header.sh_addr = dot;
3152 dot += sec->header.sh_size;
3153 }
3154
3155 return dot;
3156}
3157
Eric Andersen044228d2001-07-17 01:12:36 +00003158static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003159{
3160 int i, n = f->header.e_shnum;
3161 int ret = 1;
3162
3163 /* Finalize the addresses of the sections. */
3164
3165 f->baseaddr = base;
3166 for (i = 0; i < n; ++i)
3167 f->sections[i]->header.sh_addr += base;
3168
3169 /* And iterate over all of the relocations. */
3170
3171 for (i = 0; i < n; ++i) {
3172 struct obj_section *relsec, *symsec, *targsec, *strsec;
3173 ElfW(RelM) * rel, *relend;
3174 ElfW(Sym) * symtab;
3175 const char *strtab;
3176
3177 relsec = f->sections[i];
3178 if (relsec->header.sh_type != SHT_RELM)
3179 continue;
3180
3181 symsec = f->sections[relsec->header.sh_link];
3182 targsec = f->sections[relsec->header.sh_info];
3183 strsec = f->sections[symsec->header.sh_link];
3184
3185 rel = (ElfW(RelM) *) relsec->contents;
3186 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3187 symtab = (ElfW(Sym) *) symsec->contents;
3188 strtab = (const char *) strsec->contents;
3189
3190 for (; rel < relend; ++rel) {
3191 ElfW(Addr) value = 0;
3192 struct obj_symbol *intsym = NULL;
3193 unsigned long symndx;
3194 ElfW(Sym) * extsym = 0;
3195 const char *errmsg;
3196
3197 /* Attempt to find a value to use for this relocation. */
3198
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003199 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003200 if (symndx) {
3201 /* Note we've already checked for undefined symbols. */
3202
3203 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003204 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003205 /* Local symbols we look up in the local table to be sure
3206 we get the one that is really intended. */
3207 intsym = f->local_symtab[symndx];
3208 } else {
3209 /* Others we look up in the hash table. */
3210 const char *name;
3211 if (extsym->st_name)
3212 name = strtab + extsym->st_name;
3213 else
3214 name = f->sections[extsym->st_shndx]->name;
3215 intsym = obj_find_symbol(f, name);
3216 }
3217
3218 value = obj_symbol_final_value(f, intsym);
3219 intsym->referenced = 1;
3220 }
3221#if SHT_RELM == SHT_RELA
3222#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3223 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3224 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003225 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003226#endif
3227 value += rel->r_addend;
3228#endif
3229
3230 /* Do it! */
3231 switch (arch_apply_relocation
Denis Vlasenko68404f12008-03-17 09:00:54 +00003232 (f, targsec, /*symsec,*/ intsym, rel, value)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003233 ) {
3234 case obj_reloc_ok:
3235 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003236
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003237 case obj_reloc_overflow:
3238 errmsg = "Relocation overflow";
3239 goto bad_reloc;
3240 case obj_reloc_dangerous:
3241 errmsg = "Dangerous relocation";
3242 goto bad_reloc;
3243 case obj_reloc_unhandled:
3244 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003245bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003246 if (extsym) {
3247 bb_error_msg("%s of type %ld for %s", errmsg,
3248 (long) ELF_R_TYPE(rel->r_info),
3249 strtab + extsym->st_name);
3250 } else {
3251 bb_error_msg("%s of type %ld", errmsg,
3252 (long) ELF_R_TYPE(rel->r_info));
3253 }
3254 ret = 0;
3255 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003256 }
3257 }
3258 }
3259
3260 /* Finally, take care of the patches. */
3261
3262 if (f->string_patches) {
3263 struct obj_string_patch *p;
3264 struct obj_section *strsec;
3265 ElfW(Addr) strsec_base;
3266 strsec = obj_find_section(f, ".kstrtab");
3267 strsec_base = strsec->header.sh_addr;
3268
3269 for (p = f->string_patches; p; p = p->next) {
3270 struct obj_section *targsec = f->sections[p->reloc_secidx];
3271 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3272 = strsec_base + p->string_offset;
3273 }
3274 }
3275
3276 if (f->symbol_patches) {
3277 struct obj_symbol_patch *p;
3278
3279 for (p = f->symbol_patches; p; p = p->next) {
3280 struct obj_section *targsec = f->sections[p->reloc_secidx];
3281 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3282 = obj_symbol_final_value(f, p->sym);
3283 }
3284 }
3285
3286 return ret;
3287}
3288
Eric Andersen044228d2001-07-17 01:12:36 +00003289static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003290{
3291 struct obj_section *sec;
3292 ElfW(Addr) base = f->baseaddr;
3293
3294 for (sec = f->load_order; sec; sec = sec->load_next) {
3295 char *secimg;
3296
Eric Andersen2bf658d2001-02-24 20:01:53 +00003297 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003298 continue;
3299
3300 secimg = image + (sec->header.sh_addr - base);
3301
3302 /* Note that we allocated data for NOBITS sections earlier. */
3303 memcpy(secimg, sec->contents, sec->header.sh_size);
3304 }
3305
3306 return 1;
3307}
3308
3309/*======================================================================*/
3310
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003311static struct obj_file *obj_load(FILE *fp, int loadprogbits UNUSED_PARAM)
Eric Andersen9f16d612000-06-12 23:11:16 +00003312{
3313 struct obj_file *f;
3314 ElfW(Shdr) * section_headers;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003315 size_t shnum, i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003316 char *shstrtab;
3317
3318 /* Read the file header. */
3319
3320 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003321 f->symbol_cmp = strcmp;
3322 f->symbol_hash = obj_elf_hash;
3323 f->load_order_search_start = &f->load_order;
3324
3325 fseek(fp, 0, SEEK_SET);
3326 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003327 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003328 }
3329
3330 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003331 || f->header.e_ident[EI_MAG1] != ELFMAG1
3332 || f->header.e_ident[EI_MAG2] != ELFMAG2
3333 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003334 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003335 }
3336 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003337 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003338 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003339 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3340 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003341 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003342 }
3343 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003344 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003345 }
3346
3347 /* Read the section headers. */
3348
3349 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003350 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003351 (unsigned long) f->header.e_shentsize,
3352 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003353 }
3354
3355 shnum = f->header.e_shnum;
3356 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3357 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3358
3359 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3360 fseek(fp, f->header.e_shoff, SEEK_SET);
3361 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003362 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003363 }
3364
3365 /* Read the section data. */
3366
3367 for (i = 0; i < shnum; ++i) {
3368 struct obj_section *sec;
3369
3370 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003371
3372 sec->header = section_headers[i];
3373 sec->idx = i;
3374
Denis Vlasenko51742f42007-04-12 00:32:05 +00003375 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003376 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003377 case SHT_NULL:
3378 case SHT_NOTE:
3379 case SHT_NOBITS:
3380 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003381 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003382
3383 case SHT_PROGBITS:
3384#if LOADBITS
3385 if (!loadprogbits) {
3386 sec->contents = NULL;
3387 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003389#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003390 case SHT_SYMTAB:
3391 case SHT_STRTAB:
3392 case SHT_RELM:
3393 if (sec->header.sh_size > 0) {
3394 sec->contents = xmalloc(sec->header.sh_size);
3395 fseek(fp, sec->header.sh_offset, SEEK_SET);
3396 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003397 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003398 }
3399 } else {
3400 sec->contents = NULL;
3401 }
3402 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003403
3404#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003405 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003406 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003407#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003408 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003409 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003410#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003411 default:
3412 if (sec->header.sh_type >= SHT_LOPROC) {
3413 /* Assume processor specific section types are debug
3414 info and can safely be ignored. If this is ever not
3415 the case (Hello MIPS?), don't put ifdefs here but
3416 create an arch_load_proc_section(). */
3417 break;
3418 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003419
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003420 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003421 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003422 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003423 }
3424 }
3425
3426 /* Do what sort of interpretation as needed by each section. */
3427
3428 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3429
3430 for (i = 0; i < shnum; ++i) {
3431 struct obj_section *sec = f->sections[i];
3432 sec->name = shstrtab + sec->header.sh_name;
3433 }
3434
3435 for (i = 0; i < shnum; ++i) {
3436 struct obj_section *sec = f->sections[i];
3437
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003438 /* .modinfo should be contents only but gcc has no attribute for that.
3439 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3440 */
3441 if (strcmp(sec->name, ".modinfo") == 0)
3442 sec->header.sh_flags &= ~SHF_ALLOC;
3443
Eric Andersen9f16d612000-06-12 23:11:16 +00003444 if (sec->header.sh_flags & SHF_ALLOC)
3445 obj_insert_section_load_order(f, sec);
3446
3447 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003448 case SHT_SYMTAB:
3449 {
3450 unsigned long nsym, j;
3451 char *strtab;
3452 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003453
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003454 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003455 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003456 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003457 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003458 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003459
3460 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3461 strtab = f->sections[sec->header.sh_link]->contents;
3462 sym = (ElfW(Sym) *) sec->contents;
3463
3464 /* Allocate space for a table of local symbols. */
3465 j = f->local_symtab_size = sec->header.sh_info;
3466 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3467
3468 /* Insert all symbols into the hash table. */
3469 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3470 ElfW(Addr) val = sym->st_value;
3471 const char *name;
3472 if (sym->st_name)
3473 name = strtab + sym->st_name;
3474 else if (sym->st_shndx < shnum)
3475 name = f->sections[sym->st_shndx]->name;
3476 else
3477 continue;
3478#if defined(__SH5__)
3479 /*
3480 * For sh64 it is possible that the target of a branch
3481 * requires a mode switch (32 to 16 and back again).
3482 *
3483 * This is implied by the lsb being set in the target
3484 * address for SHmedia mode and clear for SHcompact.
3485 */
3486 val |= sym->st_other & 4;
3487#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003488 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3489 val, sym->st_size);
3490 }
3491 }
3492 break;
3493
3494 case SHT_RELM:
3495 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003496 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003497 (unsigned long) sec->header.sh_entsize,
3498 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003499 }
3500 break;
3501 /* XXX Relocation code from modutils-2.3.19 is not here.
3502 * Why? That's about 20 lines of code from obj/obj_load.c,
3503 * which gets done in a second pass through the sections.
3504 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003505 }
3506 }
3507
3508 return f;
3509}
3510
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003511#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003512/*
3513 * load the unloaded sections directly into the memory allocated by
3514 * kernel for the module
3515 */
3516
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +00003517static int obj_load_progbits(FILE *fp, struct obj_file *f, char *imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003518{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003519 ElfW(Addr) base = f->baseaddr;
3520 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003521
Eric Andersen8ae319a2001-05-21 16:09:18 +00003522 for (sec = f->load_order; sec; sec = sec->load_next) {
3523
3524 /* section already loaded? */
3525 if (sec->contents != NULL)
3526 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003527
Eric Andersen8ae319a2001-05-21 16:09:18 +00003528 if (sec->header.sh_size == 0)
3529 continue;
3530
3531 sec->contents = imagebase + (sec->header.sh_addr - base);
3532 fseek(fp, sec->header.sh_offset, SEEK_SET);
3533 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003534 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003535 return 0;
3536 }
3537
3538 }
3539 return 1;
3540}
3541#endif
3542
Eric Andersen9f16d612000-06-12 23:11:16 +00003543static void hide_special_symbols(struct obj_file *f)
3544{
3545 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003546 SPFX "cleanup_module",
3547 SPFX "init_module",
3548 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003549 NULL
3550 };
3551
3552 struct obj_symbol *sym;
3553 const char *const *p;
3554
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003555 for (p = specials; *p; ++p) {
3556 sym = obj_find_symbol(f, *p);
3557 if (sym != NULL)
3558 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3559 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003560}
3561
Glenn L McGrath759515c2003-08-30 06:00:33 +00003562
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003563#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003564static int obj_gpl_license(struct obj_file *f, const char **license)
3565{
3566 struct obj_section *sec;
3567 /* This list must match *exactly* the list of allowable licenses in
3568 * linux/include/linux/module.h. Checking for leading "GPL" will not
3569 * work, somebody will use "GPL sucks, this is proprietary".
3570 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003571 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003572 "GPL",
3573 "GPL v2",
3574 "GPL and additional rights",
3575 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003576 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003577 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003578
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003579 sec = obj_find_section(f, ".modinfo");
3580 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003581 const char *value, *ptr, *endptr;
3582 ptr = sec->contents;
3583 endptr = ptr + sec->header.sh_size;
3584 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003585 value = strchr(ptr, '=');
3586 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003587 unsigned i;
Eric Andersen166fa462002-09-16 05:30:24 +00003588 if (license)
3589 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003590 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003591 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003592 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003593 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003594 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003595 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003596 ptr = strchr(ptr, '\0');
3597 if (ptr)
3598 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003599 else
3600 ptr = endptr;
3601 }
3602 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003603 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003604}
3605
3606#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003607#define TAINT_PROPRIETORY_MODULE (1 << 0)
3608#define TAINT_FORCED_MODULE (1 << 1)
3609#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003610#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003611
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003612static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003613 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3614{
Denis Vlasenko931de892007-06-21 12:43:45 +00003615 static smallint printed_info;
3616
Eric Andersen166fa462002-09-16 05:30:24 +00003617 char buf[80];
3618 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003619
Eric Andersen166fa462002-09-16 05:30:24 +00003620 if (fd < 0 && !kernel_has_tainted)
3621 return; /* New modutils on old kernel */
3622 printf("Warning: loading %s will taint the kernel: %s%s\n",
3623 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003624 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003625 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003626 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003627 }
3628 if (fd >= 0) {
3629 read(fd, buf, sizeof(buf)-1);
3630 buf[sizeof(buf)-1] = '\0';
3631 oldval = strtoul(buf, NULL, 10);
3632 sprintf(buf, "%d\n", oldval | taint);
3633 write(fd, buf, strlen(buf));
3634 }
3635}
3636
3637/* Check if loading this module will taint the kernel. */
3638static void check_tainted_module(struct obj_file *f, char *m_name)
3639{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003640 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3641
Eric Andersen166fa462002-09-16 05:30:24 +00003642 int fd, kernel_has_tainted;
3643 const char *ptr;
3644
3645 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003646 fd = open(tainted_file, O_RDWR);
3647 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003648 if (errno == ENOENT)
3649 kernel_has_tainted = 0;
3650 else if (errno == EACCES)
3651 kernel_has_tainted = 1;
3652 else {
3653 perror(tainted_file);
3654 kernel_has_tainted = 0;
3655 }
3656 }
3657
3658 switch (obj_gpl_license(f, &ptr)) {
3659 case 0:
3660 break;
3661 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003662 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003663 break;
3664 case 2:
3665 /* The module has a non-GPL license so we pretend that the
3666 * kernel always has a taint flag to get a warning even on
3667 * kernels without the proc flag.
3668 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003669 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003670 break;
3671 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003672 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003673 break;
3674 }
3675
3676 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003677 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003678
3679 if (fd >= 0)
3680 close(fd);
3681}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003682#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003683#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003684#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003685
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003686#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003687/* add module source, timestamp, kernel version and a symbol for the
3688 * start of some sections. this info is used by ksymoops to do better
3689 * debugging.
3690 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00003691#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3692#define get_module_version(f, str) get_module_version(str)
3693#endif
Eric Andersen889dd202003-01-23 04:48:34 +00003694static int
3695get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3696{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003697#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003698 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003699#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003700 strncpy(str, "???", sizeof(str));
3701 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003702#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003703}
3704
3705/* add module source, timestamp, kernel version and a symbol for the
3706 * start of some sections. this info is used by ksymoops to do better
3707 * debugging.
3708 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003709static void
Eric Andersen889dd202003-01-23 04:48:34 +00003710add_ksymoops_symbols(struct obj_file *f, const char *filename,
3711 const char *m_name)
3712{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003713 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003714 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003715 ".text",
3716 ".rodata",
3717 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003718 ".bss",
3719 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003720 };
3721
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003722 struct obj_section *sec;
3723 struct obj_symbol *sym;
3724 char *name, *absolute_filename;
3725 char str[STRVERSIONLEN];
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003726 unsigned i;
3727 int l, lm_name, lfilename, use_ksymtab, version;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003728 struct stat statbuf;
3729
3730 /* WARNING: was using realpath, but replaced by readlink to stop using
3731 * lots of stack. But here it seems to be able to cause problems? */
3732 absolute_filename = xmalloc_readlink(filename);
3733 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003734 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003735
3736 lm_name = strlen(m_name);
3737 lfilename = strlen(absolute_filename);
3738
3739 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3740 * are not to be exported. otherwise leave ksymtab alone for now, the
3741 * "export all symbols" compatibility code will export these symbols later.
3742 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003743 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003744
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003745 sec = obj_find_section(f, ".this");
3746 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003747 /* tag the module header with the object name, last modified
3748 * timestamp and module version. worst case for module version
3749 * is 0xffffff, decimal 16777215. putting all three fields in
3750 * one symbol is less readable but saves kernel space.
3751 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003752 l = sizeof(symprefix) + /* "__insmod_" */
3753 lm_name + /* module name */
3754 2 + /* "_O" */
3755 lfilename + /* object filename */
3756 2 + /* "_M" */
3757 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3758 2 + /* "_V" */
3759 8 + /* version in dec */
3760 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003761 name = xmalloc(l);
3762 if (stat(absolute_filename, &statbuf) != 0)
3763 statbuf.st_mtime = 0;
3764 version = get_module_version(f, str); /* -1 if not found */
3765 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003766 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003767 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003768 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003769 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003770 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003771 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003772 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003773 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003774 }
3775 free(absolute_filename);
3776#ifdef _NOT_SUPPORTED_
3777 /* record where the persistent data is going, same address as previous symbol */
3778
3779 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003780 l = sizeof(symprefix) + /* "__insmod_" */
3781 lm_name + /* module name */
3782 2 + /* "_P" */
3783 strlen(f->persist) + /* data store */
3784 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003785 name = xmalloc(l);
3786 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003787 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003788 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003789 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003790 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003791 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003792 }
3793#endif /* _NOT_SUPPORTED_ */
3794 /* tag the desired sections if size is non-zero */
3795
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003796 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003797 sec = obj_find_section(f, section_names[i]);
3798 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003799 l = sizeof(symprefix) + /* "__insmod_" */
3800 lm_name + /* module name */
3801 2 + /* "_S" */
3802 strlen(sec->name) + /* section name */
3803 2 + /* "_L" */
3804 8 + /* length in dec */
3805 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003806 name = xmalloc(l);
3807 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 symprefix, m_name, sec->name,
3809 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003810 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003811 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003812 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003813 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003814 }
3815 }
3816}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003817#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003818
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003819#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003820static void print_load_map(struct obj_file *f)
3821{
Eric Andersenbe65c352003-01-23 04:57:35 +00003822 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003823#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3824 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003825 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003826 struct obj_symbol *sym;
3827#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003828 /* Report on the section layout. */
3829
3830 printf("Sections: Size %-*s Align\n",
3831 (int) (2 * sizeof(void *)), "Address");
3832
3833 for (sec = f->load_order; sec; sec = sec->load_next) {
3834 int a;
3835 unsigned long tmp;
3836
3837 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3838 tmp >>= 1;
3839 if (a == -1)
3840 a = 0;
3841
3842 printf("%-15s %08lx %0*lx 2**%d\n",
3843 sec->name,
3844 (long)sec->header.sh_size,
3845 (int) (2 * sizeof(void *)),
3846 (long)sec->header.sh_addr,
3847 a);
3848 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003849#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003850 /* Quick reference which section indicies are loaded. */
3851
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003852 i = f->header.e_shnum;
3853 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003854 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003855 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003856
3857 /* Collect the symbols we'll be listing. */
3858
3859 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3860 for (sym = f->symtab[i]; sym; sym = sym->next)
3861 if (sym->secidx <= SHN_HIRESERVE
3862 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3863 ++nsyms;
3864
3865 all = alloca(nsyms * sizeof(struct obj_symbol *));
3866
3867 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3868 for (sym = f->symtab[i]; sym; sym = sym->next)
3869 if (sym->secidx <= SHN_HIRESERVE
3870 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3871 *p++ = sym;
3872
3873 /* And list them. */
3874 printf("\nSymbols:\n");
3875 for (p = all; p < all + nsyms; ++p) {
3876 char type = '?';
3877 unsigned long value;
3878
3879 sym = *p;
3880 if (sym->secidx == SHN_ABS) {
3881 type = 'A';
3882 value = sym->value;
3883 } else if (sym->secidx == SHN_UNDEF) {
3884 type = 'U';
3885 value = 0;
3886 } else {
3887 sec = f->sections[sym->secidx];
3888
3889 if (sec->header.sh_type == SHT_NOBITS)
3890 type = 'B';
3891 else if (sec->header.sh_flags & SHF_ALLOC) {
3892 if (sec->header.sh_flags & SHF_EXECINSTR)
3893 type = 'T';
3894 else if (sec->header.sh_flags & SHF_WRITE)
3895 type = 'D';
3896 else
3897 type = 'R';
3898 }
3899 value = sym->value + sec->header.sh_addr;
3900 }
3901
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003902 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003903 type = tolower(type);
3904
3905 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3906 type, sym->name);
3907 }
3908#endif
3909}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003910#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003911void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003912#endif
3913
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003914int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3915int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003916{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003917 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003918 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003919 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003920 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003921 unsigned long m_size;
3922 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003923 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003924 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003925 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003926 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003927 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003928#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003929 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003930 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003931 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003932#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003933#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003934 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003935#else
3936 FILE *fp;
3937#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003938 int k_version = 0;
3939 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003940
Erik Andersene49d5ec2000-02-08 19:58:47 +00003941 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003942 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003943 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003944 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003945 free(m_name);
3946 m_name = xstrdup(opt_o);
3947 }
Eric Andersen03d80912003-12-19 21:04:19 +00003948
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003949 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003950 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003951 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003952
Erik Andersene49d5ec2000-02-08 19:58:47 +00003953 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003954 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003955 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003956 len = strlen(tmp);
3957
Eric Andersen03d80912003-12-19 21:04:19 +00003958 if (uname(&myuname) == 0) {
3959 if (myuname.release[0] == '2') {
3960 k_version = myuname.release[2] - '0';
3961 }
3962 }
3963
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003964#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003965 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3966 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3967 ) {
3968 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003969 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003970 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003971#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003972 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003973 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003974 tmp[len] = '\0';
3975 }
Eric Andersen2d342152002-06-18 05:16:25 +00003976
Eric Andersen03d80912003-12-19 21:04:19 +00003977
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003978#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003979 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003980 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003981 else
Eric Andersen03d80912003-12-19 21:04:19 +00003982#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003983 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003984
Eric Andersen61f83052002-06-22 17:15:42 +00003985 if (!m_name) {
3986 m_name = tmp;
3987 } else {
3988 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003989 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003990 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003991
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003992 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003993 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3994 || (fp = fopen(arg1, "r")) == NULL
3995 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003996 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3997 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003998 if (k_version) { /* uname succeedd */
3999 char *module_dir;
4000 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00004001
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004002 tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004003 /* Jump through hoops in case /lib/modules/`uname -r`
4004 * is a symlink. We do not want recursive_action to
4005 * follow symlinks, but we do want to follow the
4006 * /lib/modules/`uname -r` dir, So resolve it ourselves
4007 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004008 module_dir = xmalloc_readlink(tmdn);
4009 if (!module_dir)
4010 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004011 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004012 check_module_name_match, NULL, m_fullName, 0);
4013 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004014 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004015 }
4016
4017 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004018 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004019 int r;
4020 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004021
Eric Andersen03d80912003-12-19 21:04:19 +00004022 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004023 m_filename = NULL;
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004024 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004025 if (!module_dir)
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004026 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
Eric Andersen14d35432001-05-14 17:07:32 +00004027 /* No module found under /lib/modules/`uname -r`, this
4028 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004029 r = recursive_action(module_dir, ACTION_RECURSE,
4030 check_module_name_match, NULL, m_fullName, 0);
4031 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004032 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004033 free(module_dir);
4034 if (m_filename == NULL
4035 || ((fp = fopen(m_filename, "r")) == NULL)
4036 ) {
4037 bb_error_msg_and_die("%s: module not found", m_fullName);
4038 }
Eric Andersen14d35432001-05-14 17:07:32 +00004039 }
Eric Andersen03d80912003-12-19 21:04:19 +00004040 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004041 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004042
Rob Landley999af202005-12-11 20:14:12 +00004043 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004044 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004045
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004046#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004047 if (k_version > 4) {
4048 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004049 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004050 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004051 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004052#endif
4053
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004054 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004055
Eric Andersen9f16d612000-06-12 23:11:16 +00004056 if (get_modinfo_value(f, "kernel_version") == NULL)
4057 m_has_modinfo = 0;
4058 else
4059 m_has_modinfo = 1;
4060
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004061#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004062 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004063 if (!flag_quiet) {
4064 if (uname(&uts_info) < 0)
4065 uts_info.release[0] = '\0';
4066 if (m_has_modinfo) {
4067 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004068 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004069 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004070 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004071 }
4072 }
4073
4074 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004075 bb_error_msg("%skernel-module version mismatch\n"
4076 "\t%s was compiled for kernel version %s\n"
4077 "\twhile this kernel is version %s",
4078 flag_force_load ? "warning: " : "",
4079 m_filename, m_strversion, uts_info.release);
4080 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004081 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004082 }
4083 }
4084 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004085#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004086
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004087 if (query_module(NULL, 0, NULL, 0, NULL))
4088 bb_error_msg_and_die("not configured to support old kernels");
4089 new_get_kernel_symbols();
4090 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004091
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004092#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004093 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004094 if (m_has_modinfo)
4095 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004096
4097 if (m_crcs != k_crcs)
4098 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004099#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004100
Erik Andersene49d5ec2000-02-08 19:58:47 +00004101 /* Let the module know about the kernel symbols. */
4102 add_kernel_symbols(f);
4103
Eric Andersen9f16d612000-06-12 23:11:16 +00004104 /* Allocate common symbols, symbol tables, and string tables. */
4105
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004106 new_create_this_module(f, m_name);
4107 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004108 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004109 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004110
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004111 /* done with the module name, on to the optional var=value arguments */
4112 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004113 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004114 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004115 }
4116
Eric Andersen9f16d612000-06-12 23:11:16 +00004117 arch_create_got(f);
4118 hide_special_symbols(f);
4119
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004120#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004121 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004122#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004123
Eric Andersencb3b9b12004-06-22 11:50:52 +00004124 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004125
Erik Andersene49d5ec2000-02-08 19:58:47 +00004126 /* Find current size of the module */
4127 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004128
Erik Andersene49d5ec2000-02-08 19:58:47 +00004129 m_addr = create_module(m_name, m_size);
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00004130 if (m_addr == (ElfW(Addr))(-1)) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004131 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004132 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004133 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004134 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004135 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004136 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004137 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004138 }
Erik Andersend387d011999-12-21 02:55:11 +00004139
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004140#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004141 /*
4142 * the PROGBITS section was not loaded by the obj_load
4143 * now we can load them directly into the kernel memory
4144 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004145 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004146 delete_module(m_name, 0);
Eric Andersen8ae319a2001-05-21 16:09:18 +00004147 goto out;
4148 }
Eric Andersen03d80912003-12-19 21:04:19 +00004149#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004150
Eric Andersen9f16d612000-06-12 23:11:16 +00004151 if (!obj_relocate(f, m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004152 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004153 goto out;
4154 }
Erik Andersend387d011999-12-21 02:55:11 +00004155
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004156 if (!new_init_module(m_name, f, m_size)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004157 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004158 goto out;
4159 }
4160
Denis Vlasenko51742f42007-04-12 00:32:05 +00004161 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004162 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004163
Matt Kraai3e856ce2000-12-01 02:55:13 +00004164 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004165
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004166 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004167#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004168 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004169 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004170 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004171 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004172 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004173 free(m_filename);
4174#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004175 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004176}
Eric Andersene7047882003-12-11 01:42:13 +00004177
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004178#endif /* ENABLE_FEATURE_2_4_MODULES */
4179/*
4180 * End of big piece of 2.4-specific code
4181 */
Eric Andersene7047882003-12-11 01:42:13 +00004182
4183
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004184#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004185
4186#include <sys/mman.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004187
Bernhard Reutner-Fischer15102162008-05-27 13:27:18 +00004188#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES
4189/* big time suckage. The old prototype above renders our nice fwd-decl wrong */
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004190extern int init_module(void *module, unsigned long len, const char *options);
4191#else
Eric Andersene7047882003-12-11 01:42:13 +00004192#include <asm/unistd.h>
4193#include <sys/syscall.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004194#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
4195#endif
Eric Andersene7047882003-12-11 01:42:13 +00004196
4197/* We use error numbers in a loose translation... */
4198static const char *moderror(int err)
4199{
4200 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004201 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004202 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004203 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004204 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004205 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004206 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004207 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004208 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004209 default:
4210 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004211 }
4212}
4213
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004214#if !ENABLE_FEATURE_2_4_MODULES
4215int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004216int insmod_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004217#else
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00004218static int insmod_ng_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004219#endif
Eric Andersene7047882003-12-11 01:42:13 +00004220{
Denis Vlasenko92297942006-11-21 11:58:14 +00004221 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004222 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004223 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004224 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004225
Denis Vlasenko92297942006-11-21 11:58:14 +00004226 filename = *++argv;
4227 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004228 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004229
4230 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004231 options = xzalloc(1);
4232 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004233 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004234 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004235 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004236 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004237 }
4238
Denis Vlasenko92297942006-11-21 11:58:14 +00004239#if 0
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004240 /* Any special reason why mmap? It isn't performance critical. -vda */
4241 /* Yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +00004242 * modules out there that are half a megabyte! mmap()ing is way nicer
Denis Vlasenkofe733a92008-06-24 16:08:22 +00004243 * for small mem boxes, i guess. */
4244 /* But after load, these modules will take up that 0.5mb in kernel
4245 * anyway. Using malloc here causes only a transient spike to 1mb,
4246 * after module is loaded, we go back to normal 0.5mb usage
4247 * (in kernel). Also, mmap isn't magic - when we touch mapped data,
4248 * we use memory. -vda */
Denis Vlasenko92297942006-11-21 11:58:14 +00004249 int fd;
4250 struct stat st;
4251 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004252 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004253 fstat(fd, &st);
4254 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004255 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004256 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004257 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004258 }
4259
Denis Vlasenko92297942006-11-21 11:58:14 +00004260 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4261 if (map == NULL) {
4262 map = xmalloc(len);
4263 xread(fd, map, len);
4264 }
4265#else
4266 len = MAXINT(ssize_t);
4267 map = xmalloc_open_read_close(filename, &len);
4268#endif
4269
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004270 if (init_module(map, len, options) != 0)
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004271 bb_error_msg_and_die("cannot insert '%s': %s",
4272 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004273 return 0;
4274}
4275
4276#endif