blob: f45a5946554ffada43a256bd6db83a68975a60b8 [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 Vlasenko68404f12008-03-17 09:00:54 +0000794static int check_module_name_match(const char *filename,
795 struct stat *statbuf ATTRIBUTE_UNUSED,
796 void *userdata, int depth ATTRIBUTE_UNUSED)
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
2204 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2205 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) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002253 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2254 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002255 return sec->contents + oldsize;
2256}
2257
2258
Eric Andersen9f16d612000-06-12 23:11:16 +00002259/* Conditionally add the symbols from the given symbol set to the
2260 new module. */
2261
2262static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002263add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002264 int idx, struct new_module_symbol *syms, size_t nsyms)
2265{
2266 struct new_module_symbol *s;
2267 size_t i;
2268 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002269#ifdef SYMBOL_PREFIX
2270 char *name_buf = 0;
2271 size_t name_alloced_size = 0;
2272#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002273#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002274 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002275
Glenn L McGrath759515c2003-08-30 06:00:33 +00002276 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002277#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002278 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002279 /* Only add symbols that are already marked external.
2280 If we override locals we may cause problems for
2281 argument initialization. We will also create a false
2282 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002283 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002284 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002285
Glenn L McGrath759515c2003-08-30 06:00:33 +00002286 /* GPL licensed modules can use symbols exported with
2287 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2288 * exported names. Non-GPL modules never see any GPLONLY_
2289 * symbols so they cannot fudge it by adding the prefix on
2290 * their references.
2291 */
2292 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002293#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002294 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002295 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002296 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002297#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002298 continue;
2299 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002300 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002301
Miles Baderae28b042002-04-01 09:34:25 +00002302#ifdef SYMBOL_PREFIX
2303 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2304 kernel exports `C names', but module object files
2305 reference `linker names'). */
2306 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002307 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002308 if (name_size > name_alloced_size) {
2309 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002310 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002311 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002312 strcpy(name_buf, SYMBOL_PREFIX);
2313 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002314 name = name_buf;
2315#endif /* SYMBOL_PREFIX */
2316
2317 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002318 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002319#ifdef SYMBOL_PREFIX
2320 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002321 name = xmalloc(name_size);
2322 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002323#endif
2324 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002325 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002326 STT_NOTYPE),
2327 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002328 /* Did our symbol just get installed? If so, mark the
2329 module as "used". */
2330 if (sym->secidx == idx)
2331 used = 1;
2332 }
2333 }
2334
2335 return used;
2336}
2337
2338static void add_kernel_symbols(struct obj_file *f)
2339{
2340 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002341 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002342
2343 /* Add module symbols first. */
2344
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002345 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002346 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002347 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2348 ) {
2349 m->used = 1;
2350 ++nused;
2351 }
2352 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002353
2354 n_ext_modules_used = nused;
2355
2356 /* And finally the symbols from the kernel proper. */
2357
2358 if (nksyms)
2359 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2360}
2361
2362static char *get_modinfo_value(struct obj_file *f, const char *key)
2363{
2364 struct obj_section *sec;
2365 char *p, *v, *n, *ep;
2366 size_t klen = strlen(key);
2367
2368 sec = obj_find_section(f, ".modinfo");
2369 if (sec == NULL)
2370 return NULL;
2371 p = sec->contents;
2372 ep = p + sec->header.sh_size;
2373 while (p < ep) {
2374 v = strchr(p, '=');
2375 n = strchr(p, '\0');
2376 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002377 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002378 return v + 1;
2379 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002380 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002381 return n;
2382 }
2383 p = n + 1;
2384 }
2385
2386 return NULL;
2387}
2388
2389
2390/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002391/* Functions relating to module loading after 2.1.18. */
2392
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002393static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002394new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2395{
2396 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002397 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002398 struct obj_symbol *sym;
2399 char *contents, *loc;
2400 int min, max, n;
2401
2402 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002403 q = strchr(p, '=');
2404 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002405 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002407 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002408
2409 key = alloca(q - p + 6);
2410 memcpy(key, "parm_", 5);
2411 memcpy(key + 5, p, q - p);
2412 key[q - p + 5] = 0;
2413
2414 p = get_modinfo_value(f, key);
2415 key += 5;
2416 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002417 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002418 }
2419
Miles Baderae28b042002-04-01 09:34:25 +00002420#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002421 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2422 strcpy(sym_name, SYMBOL_PREFIX);
2423 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002424#else
2425 sym_name = key;
2426#endif
2427 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002428
2429 /* Also check that the parameter was not resolved from the kernel. */
2430 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002431 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002432 }
2433
2434 if (isdigit(*p)) {
2435 min = strtoul(p, &p, 10);
2436 if (*p == '-')
2437 max = strtoul(p + 1, &p, 10);
2438 else
2439 max = min;
2440 } else
2441 min = max = 1;
2442
2443 contents = f->sections[sym->secidx]->contents;
2444 loc = contents + sym->value;
2445 n = (*++q != '\0');
2446
2447 while (1) {
2448 if ((*p == 's') || (*p == 'c')) {
2449 char *str;
2450
2451 /* Do C quoting if we begin with a ", else slurp the lot. */
2452 if (*q == '"') {
2453 char *r;
2454
2455 str = alloca(strlen(q));
2456 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002457 if (*q == '\0')
2458 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002459 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002460 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002461 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002462 case 'a':
2463 *r = '\a';
2464 break;
2465 case 'b':
2466 *r = '\b';
2467 break;
2468 case 'e':
2469 *r = '\033';
2470 break;
2471 case 'f':
2472 *r = '\f';
2473 break;
2474 case 'n':
2475 *r = '\n';
2476 break;
2477 case 'r':
2478 *r = '\r';
2479 break;
2480 case 't':
2481 *r = '\t';
2482 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002483
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002484 case '0':
2485 case '1':
2486 case '2':
2487 case '3':
2488 case '4':
2489 case '5':
2490 case '6':
2491 case '7':
2492 {
2493 int c = *q - '0';
2494 if (q[1] >= '0' && q[1] <= '7') {
2495 c = (c * 8) + *++q - '0';
2496 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002497 c = (c * 8) + *++q - '0';
2498 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002499 *r = c;
2500 }
2501 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002502
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002503 default:
2504 *r = *q;
2505 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002506 }
2507 else
2508 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002509 }
2510 *r = '\0';
2511 ++q;
2512 } else {
2513 char *r;
2514
2515 /* In this case, the string is not quoted. We will break
2516 it using the coma (like for ints). If the user wants to
2517 include comas in a string, he just has to quote it */
2518
2519 /* Search the next coma */
2520 r = strchr(q, ',');
2521
2522 /* Found ? */
2523 if (r != (char *) NULL) {
2524 /* Recopy the current field */
2525 str = alloca(r - q + 1);
2526 memcpy(str, q, r - q);
2527
Eric Andersenaff114c2004-04-14 17:51:38 +00002528 /* I don't know if it is useful, as the previous case
2529 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002530 str[r - q] = '\0';
2531
2532 /* Keep next fields */
2533 q = r;
2534 } else {
2535 /* last string */
2536 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002537 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002538 }
2539 }
2540
2541 if (*p == 's') {
2542 /* Normal string */
2543 obj_string_patch(f, sym->secidx, loc - contents, str);
2544 loc += tgt_sizeof_char_p;
2545 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002546 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002547 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002548
2549 /* Get the size of each member */
2550 /* Probably we should do that outside the loop ? */
2551 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002552 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002553 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002554 }
2555 charssize = strtoul(p + 1, (char **) NULL, 10);
2556
2557 /* Check length */
2558 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002559 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002561 }
2562
2563 /* Copy to location */
2564 strcpy((char *) loc, str);
2565 loc += charssize;
2566 }
2567 } else {
2568 long v = strtoul(q, &q, 0);
2569 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002570 case 'b':
2571 *loc++ = v;
2572 break;
2573 case 'h':
2574 *(short *) loc = v;
2575 loc += tgt_sizeof_short;
2576 break;
2577 case 'i':
2578 *(int *) loc = v;
2579 loc += tgt_sizeof_int;
2580 break;
2581 case 'l':
2582 *(long *) loc = v;
2583 loc += tgt_sizeof_long;
2584 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002585
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002586 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002587 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002588 }
2589 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002590 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002591 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002592 case '\0':
2593 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002594
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002595 case ' ':
2596 case '\t':
2597 case '\n':
2598 case '\r':
2599 ++q;
2600 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002601
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002602 case ',':
2603 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002604 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002605 }
2606 ++q;
2607 break;
2608
2609 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002610 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002611 }
2612 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002613 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002614 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002615 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002616 }
2617
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002618 argc--;
2619 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002620 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002621}
2622
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002623#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002624static int new_is_module_checksummed(struct obj_file *f)
2625{
2626 const char *p = get_modinfo_value(f, "using_checksums");
2627 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002628 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002629 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002630}
2631
2632/* Get the module's kernel version in the canonical integer form. */
2633
2634static int
2635new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2636{
2637 char *p, *q;
2638 int a, b, c;
2639
2640 p = get_modinfo_value(f, "kernel_version");
2641 if (p == NULL)
2642 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002643 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002644
2645 a = strtoul(p, &p, 10);
2646 if (*p != '.')
2647 return -1;
2648 b = strtoul(p + 1, &p, 10);
2649 if (*p != '.')
2650 return -1;
2651 c = strtoul(p + 1, &q, 10);
2652 if (p + 1 == q)
2653 return -1;
2654
2655 return a << 16 | b << 8 | c;
2656}
2657
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002658#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002659
2660
Eric Andersen9f16d612000-06-12 23:11:16 +00002661/* Fetch the loaded modules, and all currently exported symbols. */
2662
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002663static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002664{
2665 char *module_names, *mn;
2666 struct external_module *modules, *m;
2667 struct new_module_symbol *syms, *s;
2668 size_t ret, bufsize, nmod, nsyms, i, j;
2669
2670 /* Collect the loaded modules. */
2671
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002672 bufsize = 256;
2673 module_names = xmalloc(bufsize);
2674
2675 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002676 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002677 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002678 bufsize = ret;
2679 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002680 goto retry_modules_load;
2681 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002682 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002683 }
2684
2685 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002686
2687 /* Collect the modules' symbols. */
2688
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002689 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002690 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2691 memset(modules, 0, nmod * sizeof(*modules));
2692 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002693 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002694 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002695
Mark Whitley94fd4802001-03-12 23:08:34 +00002696 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2697 if (errno == ENOENT) {
2698 /* The module was removed out from underneath us. */
2699 continue;
2700 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002701 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002702 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002703
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002704 bufsize = 1024;
2705 syms = xmalloc(bufsize);
2706 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002707 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2708 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002709 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002710 bufsize = ret;
2711 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002712 goto retry_mod_sym_load;
2713 case ENOENT:
2714 /* The module was removed out from underneath us. */
2715 continue;
2716 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002717 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002718 }
2719 }
2720 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002721
Mark Whitley94fd4802001-03-12 23:08:34 +00002722 m->name = mn;
2723 m->addr = info.addr;
2724 m->nsyms = nsyms;
2725 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002726
Mark Whitley94fd4802001-03-12 23:08:34 +00002727 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2728 s->name += (unsigned long) syms;
2729 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002730 }
2731 }
2732
2733 /* Collect the kernel's symbols. */
2734
2735 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002736 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002737 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002738 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002739 syms = xrealloc(syms, bufsize = ret);
2740 goto retry_kern_sym_load;
2741 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002742 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002743 }
2744 nksyms = nsyms = ret;
2745 ksyms = syms;
2746
2747 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2748 s->name += (unsigned long) syms;
2749 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002750}
2751
2752
2753/* Return the kernel symbol checksum version, or zero if not used. */
2754
2755static int new_is_kernel_checksummed(void)
2756{
2757 struct new_module_symbol *s;
2758 size_t i;
2759
2760 /* Using_Versions is not the first symbol, but it should be in there. */
2761
2762 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2763 if (strcmp((char *) s->name, "Using_Versions") == 0)
2764 return s->value;
2765
2766 return 0;
2767}
2768
2769
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002770static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002771{
2772 struct obj_section *sec;
2773
2774 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002775 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002776 memset(sec->contents, 0, sizeof(struct new_module));
2777
Miles Baderae28b042002-04-01 09:34:25 +00002778 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002779 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002780 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002781
2782 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002783 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002784}
2785
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002786#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002787/* add an entry to the __ksymtab section, creating it if necessary */
2788static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2789{
2790 struct obj_section *sec;
2791 ElfW(Addr) ofs;
2792
2793 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2794 * If __ksymtab is defined but not marked alloc, x out the first character
2795 * (no obj_delete routine) and create a new __ksymtab with the correct
2796 * characteristics.
2797 */
2798 sec = obj_find_section(f, "__ksymtab");
2799 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2800 *((char *)(sec->name)) = 'x'; /* override const */
2801 sec = NULL;
2802 }
2803 if (!sec)
2804 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002805 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002806 if (!sec)
2807 return;
2808 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002809 /* Empty section might be byte-aligned */
2810 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002811 ofs = sec->header.sh_size;
2812 obj_symbol_patch(f, sec->idx, ofs, sym);
2813 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2814 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2815}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002816#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002817
2818static int new_create_module_ksymtab(struct obj_file *f)
2819{
2820 struct obj_section *sec;
2821 int i;
2822
2823 /* We must always add the module references. */
2824
2825 if (n_ext_modules_used) {
2826 struct new_module_ref *dep;
2827 struct obj_symbol *tm;
2828
2829 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002830 (sizeof(struct new_module_ref)
2831 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002832 if (!sec)
2833 return 0;
2834
Miles Baderae28b042002-04-01 09:34:25 +00002835 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002836 dep = (struct new_module_ref *) sec->contents;
2837 for (i = 0; i < n_ext_modules; ++i)
2838 if (ext_modules[i].used) {
2839 dep->dep = ext_modules[i].addr;
2840 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002841 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002842 dep->next_ref = 0;
2843 ++dep;
2844 }
2845 }
2846
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002847 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002848 size_t nsyms;
2849 int *loaded;
2850
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002851 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002852
2853 /* We don't want to export symbols residing in sections that
2854 aren't loaded. There are a number of these created so that
2855 we make sure certain module options don't appear twice. */
2856
2857 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2858 while (--i >= 0)
2859 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2860
2861 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2862 struct obj_symbol *sym;
2863 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002864 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002865 && sym->secidx <= SHN_HIRESERVE
2866 && (sym->secidx >= SHN_LORESERVE
2867 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002868 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2869
2870 obj_symbol_patch(f, sec->idx, ofs, sym);
2871 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002872 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002873
2874 nsyms++;
2875 }
2876 }
2877
2878 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2879 }
2880
2881 return 1;
2882}
2883
2884
2885static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002886new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002887{
2888 struct new_module *module;
2889 struct obj_section *sec;
2890 void *image;
2891 int ret;
2892 tgt_long m_addr;
2893
2894 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002895 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002896 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002897 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002898 module = (struct new_module *) sec->contents;
2899 m_addr = sec->header.sh_addr;
2900
2901 module->size_of_struct = sizeof(*module);
2902 module->size = m_size;
2903 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2904
2905 sec = obj_find_section(f, "__ksymtab");
2906 if (sec && sec->header.sh_size) {
2907 module->syms = sec->header.sh_addr;
2908 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2909 }
2910
2911 if (n_ext_modules_used) {
2912 sec = obj_find_section(f, ".kmodtab");
2913 module->deps = sec->header.sh_addr;
2914 module->ndeps = n_ext_modules_used;
2915 }
2916
2917 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002918 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002919 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002920 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002921
2922 sec = obj_find_section(f, "__ex_table");
2923 if (sec) {
2924 module->ex_table_start = sec->header.sh_addr;
2925 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2926 }
2927
2928 sec = obj_find_section(f, ".text.init");
2929 if (sec) {
2930 module->runsize = sec->header.sh_addr - m_addr;
2931 }
2932 sec = obj_find_section(f, ".data.init");
2933 if (sec) {
2934 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002935 module->runsize > sec->header.sh_addr - m_addr)
2936 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002937 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002938 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2939 if (sec && sec->header.sh_size) {
2940 module->archdata_start = (void*)sec->header.sh_addr;
2941 module->archdata_end = module->archdata_start + sec->header.sh_size;
2942 }
2943 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2944 if (sec && sec->header.sh_size) {
2945 module->kallsyms_start = (void*)sec->header.sh_addr;
2946 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2947 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002948
Eric Andersen9f16d612000-06-12 23:11:16 +00002949 /* Whew! All of the initialization is complete. Collect the final
2950 module image and give it to the kernel. */
2951
2952 image = xmalloc(m_size);
2953 obj_create_image(f, image);
2954
Eric Andersencb3b9b12004-06-22 11:50:52 +00002955 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002956 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002957 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002958
2959 free(image);
2960
2961 return ret == 0;
2962}
2963
Eric Andersen9f16d612000-06-12 23:11:16 +00002964
2965/*======================================================================*/
2966
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002967static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002968obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2969 const char *string)
2970{
2971 struct obj_string_patch *p;
2972 struct obj_section *strsec;
2973 size_t len = strlen(string) + 1;
2974 char *loc;
2975
2976 p = xmalloc(sizeof(*p));
2977 p->next = f->string_patches;
2978 p->reloc_secidx = secidx;
2979 p->reloc_offset = offset;
2980 f->string_patches = p;
2981
2982 strsec = obj_find_section(f, ".kstrtab");
2983 if (strsec == NULL) {
2984 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2985 p->string_offset = 0;
2986 loc = strsec->contents;
2987 } else {
2988 p->string_offset = strsec->header.sh_size;
2989 loc = obj_extend_section(strsec, len);
2990 }
2991 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002992}
2993
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00002994static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002995obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2996 struct obj_symbol *sym)
2997{
2998 struct obj_symbol_patch *p;
2999
3000 p = xmalloc(sizeof(*p));
3001 p->next = f->symbol_patches;
3002 p->reloc_secidx = secidx;
3003 p->reloc_offset = offset;
3004 p->sym = sym;
3005 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00003006}
3007
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003008static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003009{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003010 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003011
3012 for (i = 0; i < HASH_BUCKETS; ++i) {
3013 struct obj_symbol *sym;
3014 for (sym = f->symtab[i]; sym; sym = sym->next)
3015 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003016 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003017 sym->secidx = SHN_ABS;
3018 sym->value = 0;
3019 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003020 if (!flag_quiet)
3021 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003022 }
3023 }
3024 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003025}
3026
Eric Andersen044228d2001-07-17 01:12:36 +00003027static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003028{
3029 struct common_entry {
3030 struct common_entry *next;
3031 struct obj_symbol *sym;
3032 } *common_head = NULL;
3033
3034 unsigned long i;
3035
3036 for (i = 0; i < HASH_BUCKETS; ++i) {
3037 struct obj_symbol *sym;
3038 for (sym = f->symtab[i]; sym; sym = sym->next)
3039 if (sym->secidx == SHN_COMMON) {
3040 /* Collect all COMMON symbols and sort them by size so as to
3041 minimize space wasted by alignment requirements. */
3042 {
3043 struct common_entry **p, *n;
3044 for (p = &common_head; *p; p = &(*p)->next)
3045 if (sym->size <= (*p)->sym->size)
3046 break;
3047
3048 n = alloca(sizeof(*n));
3049 n->next = *p;
3050 n->sym = sym;
3051 *p = n;
3052 }
3053 }
3054 }
3055
3056 for (i = 1; i < f->local_symtab_size; ++i) {
3057 struct obj_symbol *sym = f->local_symtab[i];
3058 if (sym && sym->secidx == SHN_COMMON) {
3059 struct common_entry **p, *n;
3060 for (p = &common_head; *p; p = &(*p)->next)
3061 if (sym == (*p)->sym)
3062 break;
3063 else if (sym->size < (*p)->sym->size) {
3064 n = alloca(sizeof(*n));
3065 n->next = *p;
3066 n->sym = sym;
3067 *p = n;
3068 break;
3069 }
3070 }
3071 }
3072
3073 if (common_head) {
3074 /* Find the bss section. */
3075 for (i = 0; i < f->header.e_shnum; ++i)
3076 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3077 break;
3078
3079 /* If for some reason there hadn't been one, create one. */
3080 if (i == f->header.e_shnum) {
3081 struct obj_section *sec;
3082
3083 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3084 f->sections[i] = sec = arch_new_section();
3085 f->header.e_shnum = i + 1;
3086
Eric Andersen9f16d612000-06-12 23:11:16 +00003087 sec->header.sh_type = SHT_PROGBITS;
3088 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3089 sec->name = ".bss";
3090 sec->idx = i;
3091 }
3092
3093 /* Allocate the COMMONS. */
3094 {
3095 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3096 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3097 struct common_entry *c;
3098
3099 for (c = common_head; c; c = c->next) {
3100 ElfW(Addr) align = c->sym->value;
3101
3102 if (align > max_align)
3103 max_align = align;
3104 if (bss_size & (align - 1))
3105 bss_size = (bss_size | (align - 1)) + 1;
3106
3107 c->sym->secidx = i;
3108 c->sym->value = bss_size;
3109
3110 bss_size += c->sym->size;
3111 }
3112
3113 f->sections[i]->header.sh_size = bss_size;
3114 f->sections[i]->header.sh_addralign = max_align;
3115 }
3116 }
3117
3118 /* For the sake of patch relocation and parameter initialization,
3119 allocate zeroed data for NOBITS sections now. Note that after
3120 this we cannot assume NOBITS are really empty. */
3121 for (i = 0; i < f->header.e_shnum; ++i) {
3122 struct obj_section *s = f->sections[i];
3123 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003124 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003125 s->contents = memset(xmalloc(s->header.sh_size),
3126 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003127 else
3128 s->contents = NULL;
3129
Eric Andersen9f16d612000-06-12 23:11:16 +00003130 s->header.sh_type = SHT_PROGBITS;
3131 }
3132 }
3133}
3134
Eric Andersen044228d2001-07-17 01:12:36 +00003135static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003136{
3137 unsigned long dot = 0;
3138 struct obj_section *sec;
3139
3140 /* Finalize the positions of the sections relative to one another. */
3141
3142 for (sec = f->load_order; sec; sec = sec->load_next) {
3143 ElfW(Addr) align;
3144
3145 align = sec->header.sh_addralign;
3146 if (align && (dot & (align - 1)))
3147 dot = (dot | (align - 1)) + 1;
3148
3149 sec->header.sh_addr = dot;
3150 dot += sec->header.sh_size;
3151 }
3152
3153 return dot;
3154}
3155
Eric Andersen044228d2001-07-17 01:12:36 +00003156static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003157{
3158 int i, n = f->header.e_shnum;
3159 int ret = 1;
3160
3161 /* Finalize the addresses of the sections. */
3162
3163 f->baseaddr = base;
3164 for (i = 0; i < n; ++i)
3165 f->sections[i]->header.sh_addr += base;
3166
3167 /* And iterate over all of the relocations. */
3168
3169 for (i = 0; i < n; ++i) {
3170 struct obj_section *relsec, *symsec, *targsec, *strsec;
3171 ElfW(RelM) * rel, *relend;
3172 ElfW(Sym) * symtab;
3173 const char *strtab;
3174
3175 relsec = f->sections[i];
3176 if (relsec->header.sh_type != SHT_RELM)
3177 continue;
3178
3179 symsec = f->sections[relsec->header.sh_link];
3180 targsec = f->sections[relsec->header.sh_info];
3181 strsec = f->sections[symsec->header.sh_link];
3182
3183 rel = (ElfW(RelM) *) relsec->contents;
3184 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3185 symtab = (ElfW(Sym) *) symsec->contents;
3186 strtab = (const char *) strsec->contents;
3187
3188 for (; rel < relend; ++rel) {
3189 ElfW(Addr) value = 0;
3190 struct obj_symbol *intsym = NULL;
3191 unsigned long symndx;
3192 ElfW(Sym) * extsym = 0;
3193 const char *errmsg;
3194
3195 /* Attempt to find a value to use for this relocation. */
3196
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003197 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003198 if (symndx) {
3199 /* Note we've already checked for undefined symbols. */
3200
3201 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003202 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003203 /* Local symbols we look up in the local table to be sure
3204 we get the one that is really intended. */
3205 intsym = f->local_symtab[symndx];
3206 } else {
3207 /* Others we look up in the hash table. */
3208 const char *name;
3209 if (extsym->st_name)
3210 name = strtab + extsym->st_name;
3211 else
3212 name = f->sections[extsym->st_shndx]->name;
3213 intsym = obj_find_symbol(f, name);
3214 }
3215
3216 value = obj_symbol_final_value(f, intsym);
3217 intsym->referenced = 1;
3218 }
3219#if SHT_RELM == SHT_RELA
3220#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3221 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3222 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003223 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003224#endif
3225 value += rel->r_addend;
3226#endif
3227
3228 /* Do it! */
3229 switch (arch_apply_relocation
Denis Vlasenko68404f12008-03-17 09:00:54 +00003230 (f, targsec, /*symsec,*/ intsym, rel, value)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003231 ) {
3232 case obj_reloc_ok:
3233 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003234
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003235 case obj_reloc_overflow:
3236 errmsg = "Relocation overflow";
3237 goto bad_reloc;
3238 case obj_reloc_dangerous:
3239 errmsg = "Dangerous relocation";
3240 goto bad_reloc;
3241 case obj_reloc_unhandled:
3242 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003243bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003244 if (extsym) {
3245 bb_error_msg("%s of type %ld for %s", errmsg,
3246 (long) ELF_R_TYPE(rel->r_info),
3247 strtab + extsym->st_name);
3248 } else {
3249 bb_error_msg("%s of type %ld", errmsg,
3250 (long) ELF_R_TYPE(rel->r_info));
3251 }
3252 ret = 0;
3253 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003254 }
3255 }
3256 }
3257
3258 /* Finally, take care of the patches. */
3259
3260 if (f->string_patches) {
3261 struct obj_string_patch *p;
3262 struct obj_section *strsec;
3263 ElfW(Addr) strsec_base;
3264 strsec = obj_find_section(f, ".kstrtab");
3265 strsec_base = strsec->header.sh_addr;
3266
3267 for (p = f->string_patches; p; p = p->next) {
3268 struct obj_section *targsec = f->sections[p->reloc_secidx];
3269 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3270 = strsec_base + p->string_offset;
3271 }
3272 }
3273
3274 if (f->symbol_patches) {
3275 struct obj_symbol_patch *p;
3276
3277 for (p = f->symbol_patches; p; p = p->next) {
3278 struct obj_section *targsec = f->sections[p->reloc_secidx];
3279 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3280 = obj_symbol_final_value(f, p->sym);
3281 }
3282 }
3283
3284 return ret;
3285}
3286
Eric Andersen044228d2001-07-17 01:12:36 +00003287static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003288{
3289 struct obj_section *sec;
3290 ElfW(Addr) base = f->baseaddr;
3291
3292 for (sec = f->load_order; sec; sec = sec->load_next) {
3293 char *secimg;
3294
Eric Andersen2bf658d2001-02-24 20:01:53 +00003295 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003296 continue;
3297
3298 secimg = image + (sec->header.sh_addr - base);
3299
3300 /* Note that we allocated data for NOBITS sections earlier. */
3301 memcpy(secimg, sec->contents, sec->header.sh_size);
3302 }
3303
3304 return 1;
3305}
3306
3307/*======================================================================*/
3308
Denis Vlasenko68404f12008-03-17 09:00:54 +00003309static struct obj_file *obj_load(FILE * fp, int loadprogbits ATTRIBUTE_UNUSED)
Eric Andersen9f16d612000-06-12 23:11:16 +00003310{
3311 struct obj_file *f;
3312 ElfW(Shdr) * section_headers;
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003313 size_t shnum, i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003314 char *shstrtab;
3315
3316 /* Read the file header. */
3317
3318 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003319 f->symbol_cmp = strcmp;
3320 f->symbol_hash = obj_elf_hash;
3321 f->load_order_search_start = &f->load_order;
3322
3323 fseek(fp, 0, SEEK_SET);
3324 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003325 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 }
3327
3328 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003329 || f->header.e_ident[EI_MAG1] != ELFMAG1
3330 || f->header.e_ident[EI_MAG2] != ELFMAG2
3331 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003332 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 }
3334 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003335 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003336 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003337 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3338 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003339 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003340 }
3341 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003342 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003343 }
3344
3345 /* Read the section headers. */
3346
3347 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003348 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003349 (unsigned long) f->header.e_shentsize,
3350 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003351 }
3352
3353 shnum = f->header.e_shnum;
3354 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3355 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3356
3357 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3358 fseek(fp, f->header.e_shoff, SEEK_SET);
3359 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003360 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003361 }
3362
3363 /* Read the section data. */
3364
3365 for (i = 0; i < shnum; ++i) {
3366 struct obj_section *sec;
3367
3368 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003369
3370 sec->header = section_headers[i];
3371 sec->idx = i;
3372
Denis Vlasenko51742f42007-04-12 00:32:05 +00003373 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003374 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003375 case SHT_NULL:
3376 case SHT_NOTE:
3377 case SHT_NOBITS:
3378 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003379 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003380
3381 case SHT_PROGBITS:
3382#if LOADBITS
3383 if (!loadprogbits) {
3384 sec->contents = NULL;
3385 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003386 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003387#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003388 case SHT_SYMTAB:
3389 case SHT_STRTAB:
3390 case SHT_RELM:
3391 if (sec->header.sh_size > 0) {
3392 sec->contents = xmalloc(sec->header.sh_size);
3393 fseek(fp, sec->header.sh_offset, SEEK_SET);
3394 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003395 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003396 }
3397 } else {
3398 sec->contents = NULL;
3399 }
3400 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003401
3402#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003403 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003404 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003405#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003406 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003407 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003408#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003409 default:
3410 if (sec->header.sh_type >= SHT_LOPROC) {
3411 /* Assume processor specific section types are debug
3412 info and can safely be ignored. If this is ever not
3413 the case (Hello MIPS?), don't put ifdefs here but
3414 create an arch_load_proc_section(). */
3415 break;
3416 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003417
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003418 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003419 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003420 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003421 }
3422 }
3423
3424 /* Do what sort of interpretation as needed by each section. */
3425
3426 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3427
3428 for (i = 0; i < shnum; ++i) {
3429 struct obj_section *sec = f->sections[i];
3430 sec->name = shstrtab + sec->header.sh_name;
3431 }
3432
3433 for (i = 0; i < shnum; ++i) {
3434 struct obj_section *sec = f->sections[i];
3435
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003436 /* .modinfo should be contents only but gcc has no attribute for that.
3437 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3438 */
3439 if (strcmp(sec->name, ".modinfo") == 0)
3440 sec->header.sh_flags &= ~SHF_ALLOC;
3441
Eric Andersen9f16d612000-06-12 23:11:16 +00003442 if (sec->header.sh_flags & SHF_ALLOC)
3443 obj_insert_section_load_order(f, sec);
3444
3445 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003446 case SHT_SYMTAB:
3447 {
3448 unsigned long nsym, j;
3449 char *strtab;
3450 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003451
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003452 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003453 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003454 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003455 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003456 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003457
3458 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3459 strtab = f->sections[sec->header.sh_link]->contents;
3460 sym = (ElfW(Sym) *) sec->contents;
3461
3462 /* Allocate space for a table of local symbols. */
3463 j = f->local_symtab_size = sec->header.sh_info;
3464 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3465
3466 /* Insert all symbols into the hash table. */
3467 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3468 ElfW(Addr) val = sym->st_value;
3469 const char *name;
3470 if (sym->st_name)
3471 name = strtab + sym->st_name;
3472 else if (sym->st_shndx < shnum)
3473 name = f->sections[sym->st_shndx]->name;
3474 else
3475 continue;
3476#if defined(__SH5__)
3477 /*
3478 * For sh64 it is possible that the target of a branch
3479 * requires a mode switch (32 to 16 and back again).
3480 *
3481 * This is implied by the lsb being set in the target
3482 * address for SHmedia mode and clear for SHcompact.
3483 */
3484 val |= sym->st_other & 4;
3485#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003486 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3487 val, sym->st_size);
3488 }
3489 }
3490 break;
3491
3492 case SHT_RELM:
3493 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003494 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003495 (unsigned long) sec->header.sh_entsize,
3496 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003497 }
3498 break;
3499 /* XXX Relocation code from modutils-2.3.19 is not here.
3500 * Why? That's about 20 lines of code from obj/obj_load.c,
3501 * which gets done in a second pass through the sections.
3502 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003503 }
3504 }
3505
3506 return f;
3507}
3508
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003509#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003510/*
3511 * load the unloaded sections directly into the memory allocated by
3512 * kernel for the module
3513 */
3514
Eric Andersenac5dbd12001-08-22 05:26:08 +00003515static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003516{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003517 ElfW(Addr) base = f->baseaddr;
3518 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003519
Eric Andersen8ae319a2001-05-21 16:09:18 +00003520 for (sec = f->load_order; sec; sec = sec->load_next) {
3521
3522 /* section already loaded? */
3523 if (sec->contents != NULL)
3524 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003525
Eric Andersen8ae319a2001-05-21 16:09:18 +00003526 if (sec->header.sh_size == 0)
3527 continue;
3528
3529 sec->contents = imagebase + (sec->header.sh_addr - base);
3530 fseek(fp, sec->header.sh_offset, SEEK_SET);
3531 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003532 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003533 return 0;
3534 }
3535
3536 }
3537 return 1;
3538}
3539#endif
3540
Eric Andersen9f16d612000-06-12 23:11:16 +00003541static void hide_special_symbols(struct obj_file *f)
3542{
3543 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003544 SPFX "cleanup_module",
3545 SPFX "init_module",
3546 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003547 NULL
3548 };
3549
3550 struct obj_symbol *sym;
3551 const char *const *p;
3552
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003553 for (p = specials; *p; ++p) {
3554 sym = obj_find_symbol(f, *p);
3555 if (sym != NULL)
3556 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3557 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003558}
3559
Glenn L McGrath759515c2003-08-30 06:00:33 +00003560
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003561#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003562static int obj_gpl_license(struct obj_file *f, const char **license)
3563{
3564 struct obj_section *sec;
3565 /* This list must match *exactly* the list of allowable licenses in
3566 * linux/include/linux/module.h. Checking for leading "GPL" will not
3567 * work, somebody will use "GPL sucks, this is proprietary".
3568 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003569 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003570 "GPL",
3571 "GPL v2",
3572 "GPL and additional rights",
3573 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003574 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003575 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003576
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003577 sec = obj_find_section(f, ".modinfo");
3578 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003579 const char *value, *ptr, *endptr;
3580 ptr = sec->contents;
3581 endptr = ptr + sec->header.sh_size;
3582 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003583 value = strchr(ptr, '=');
3584 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003585 unsigned i;
Eric Andersen166fa462002-09-16 05:30:24 +00003586 if (license)
3587 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003588 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003589 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003590 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003591 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003592 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003593 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003594 ptr = strchr(ptr, '\0');
3595 if (ptr)
3596 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003597 else
3598 ptr = endptr;
3599 }
3600 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003601 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003602}
3603
3604#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003605#define TAINT_PROPRIETORY_MODULE (1 << 0)
3606#define TAINT_FORCED_MODULE (1 << 1)
3607#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003608#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003609
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003610static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003611 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3612{
Denis Vlasenko931de892007-06-21 12:43:45 +00003613 static smallint printed_info;
3614
Eric Andersen166fa462002-09-16 05:30:24 +00003615 char buf[80];
3616 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003617
Eric Andersen166fa462002-09-16 05:30:24 +00003618 if (fd < 0 && !kernel_has_tainted)
3619 return; /* New modutils on old kernel */
3620 printf("Warning: loading %s will taint the kernel: %s%s\n",
3621 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003622 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003623 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003624 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003625 }
3626 if (fd >= 0) {
3627 read(fd, buf, sizeof(buf)-1);
3628 buf[sizeof(buf)-1] = '\0';
3629 oldval = strtoul(buf, NULL, 10);
3630 sprintf(buf, "%d\n", oldval | taint);
3631 write(fd, buf, strlen(buf));
3632 }
3633}
3634
3635/* Check if loading this module will taint the kernel. */
3636static void check_tainted_module(struct obj_file *f, char *m_name)
3637{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003638 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3639
Eric Andersen166fa462002-09-16 05:30:24 +00003640 int fd, kernel_has_tainted;
3641 const char *ptr;
3642
3643 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003644 fd = open(tainted_file, O_RDWR);
3645 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003646 if (errno == ENOENT)
3647 kernel_has_tainted = 0;
3648 else if (errno == EACCES)
3649 kernel_has_tainted = 1;
3650 else {
3651 perror(tainted_file);
3652 kernel_has_tainted = 0;
3653 }
3654 }
3655
3656 switch (obj_gpl_license(f, &ptr)) {
3657 case 0:
3658 break;
3659 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003660 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003661 break;
3662 case 2:
3663 /* The module has a non-GPL license so we pretend that the
3664 * kernel always has a taint flag to get a warning even on
3665 * kernels without the proc flag.
3666 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003667 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003668 break;
3669 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003670 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003671 break;
3672 }
3673
3674 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003675 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003676
3677 if (fd >= 0)
3678 close(fd);
3679}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003680#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003681#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003682#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003683
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003684#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003685/* add module source, timestamp, kernel version and a symbol for the
3686 * start of some sections. this info is used by ksymoops to do better
3687 * debugging.
3688 */
Denis Vlasenko85c24712008-03-17 09:04:04 +00003689#if !ENABLE_FEATURE_INSMOD_VERSION_CHECKING
3690#define get_module_version(f, str) get_module_version(str)
3691#endif
Eric Andersen889dd202003-01-23 04:48:34 +00003692static int
3693get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3694{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003695#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003696 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003697#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003698 strncpy(str, "???", sizeof(str));
3699 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003700#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003701}
3702
3703/* add module source, timestamp, kernel version and a symbol for the
3704 * start of some sections. this info is used by ksymoops to do better
3705 * debugging.
3706 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003707static void
Eric Andersen889dd202003-01-23 04:48:34 +00003708add_ksymoops_symbols(struct obj_file *f, const char *filename,
3709 const char *m_name)
3710{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003711 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003712 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003713 ".text",
3714 ".rodata",
3715 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003716 ".bss",
3717 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003718 };
3719
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003720 struct obj_section *sec;
3721 struct obj_symbol *sym;
3722 char *name, *absolute_filename;
3723 char str[STRVERSIONLEN];
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00003724 unsigned i;
3725 int l, lm_name, lfilename, use_ksymtab, version;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003726 struct stat statbuf;
3727
3728 /* WARNING: was using realpath, but replaced by readlink to stop using
3729 * lots of stack. But here it seems to be able to cause problems? */
3730 absolute_filename = xmalloc_readlink(filename);
3731 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003732 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003733
3734 lm_name = strlen(m_name);
3735 lfilename = strlen(absolute_filename);
3736
3737 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3738 * are not to be exported. otherwise leave ksymtab alone for now, the
3739 * "export all symbols" compatibility code will export these symbols later.
3740 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003741 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003742
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003743 sec = obj_find_section(f, ".this");
3744 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003745 /* tag the module header with the object name, last modified
3746 * timestamp and module version. worst case for module version
3747 * is 0xffffff, decimal 16777215. putting all three fields in
3748 * one symbol is less readable but saves kernel space.
3749 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003750 l = sizeof(symprefix) + /* "__insmod_" */
3751 lm_name + /* module name */
3752 2 + /* "_O" */
3753 lfilename + /* object filename */
3754 2 + /* "_M" */
3755 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3756 2 + /* "_V" */
3757 8 + /* version in dec */
3758 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003759 name = xmalloc(l);
3760 if (stat(absolute_filename, &statbuf) != 0)
3761 statbuf.st_mtime = 0;
3762 version = get_module_version(f, str); /* -1 if not found */
3763 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003764 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003765 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003766 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003767 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003768 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003769 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003770 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003771 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003772 }
3773 free(absolute_filename);
3774#ifdef _NOT_SUPPORTED_
3775 /* record where the persistent data is going, same address as previous symbol */
3776
3777 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003778 l = sizeof(symprefix) + /* "__insmod_" */
3779 lm_name + /* module name */
3780 2 + /* "_P" */
3781 strlen(f->persist) + /* data store */
3782 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003783 name = xmalloc(l);
3784 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003785 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003786 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003787 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003788 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003789 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003790 }
3791#endif /* _NOT_SUPPORTED_ */
3792 /* tag the desired sections if size is non-zero */
3793
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003794 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003795 sec = obj_find_section(f, section_names[i]);
3796 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003797 l = sizeof(symprefix) + /* "__insmod_" */
3798 lm_name + /* module name */
3799 2 + /* "_S" */
3800 strlen(sec->name) + /* section name */
3801 2 + /* "_L" */
3802 8 + /* length in dec */
3803 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003804 name = xmalloc(l);
3805 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003806 symprefix, m_name, sec->name,
3807 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003808 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003809 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003810 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003811 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003812 }
3813 }
3814}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003815#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003816
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003817#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003818static void print_load_map(struct obj_file *f)
3819{
Eric Andersenbe65c352003-01-23 04:57:35 +00003820 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003821#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3822 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003823 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003824 struct obj_symbol *sym;
3825#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003826 /* Report on the section layout. */
3827
3828 printf("Sections: Size %-*s Align\n",
3829 (int) (2 * sizeof(void *)), "Address");
3830
3831 for (sec = f->load_order; sec; sec = sec->load_next) {
3832 int a;
3833 unsigned long tmp;
3834
3835 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3836 tmp >>= 1;
3837 if (a == -1)
3838 a = 0;
3839
3840 printf("%-15s %08lx %0*lx 2**%d\n",
3841 sec->name,
3842 (long)sec->header.sh_size,
3843 (int) (2 * sizeof(void *)),
3844 (long)sec->header.sh_addr,
3845 a);
3846 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003847#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003848 /* Quick reference which section indicies are loaded. */
3849
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003850 i = f->header.e_shnum;
3851 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003852 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003853 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003854
3855 /* Collect the symbols we'll be listing. */
3856
3857 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3858 for (sym = f->symtab[i]; sym; sym = sym->next)
3859 if (sym->secidx <= SHN_HIRESERVE
3860 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3861 ++nsyms;
3862
3863 all = alloca(nsyms * sizeof(struct obj_symbol *));
3864
3865 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3866 for (sym = f->symtab[i]; sym; sym = sym->next)
3867 if (sym->secidx <= SHN_HIRESERVE
3868 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3869 *p++ = sym;
3870
3871 /* And list them. */
3872 printf("\nSymbols:\n");
3873 for (p = all; p < all + nsyms; ++p) {
3874 char type = '?';
3875 unsigned long value;
3876
3877 sym = *p;
3878 if (sym->secidx == SHN_ABS) {
3879 type = 'A';
3880 value = sym->value;
3881 } else if (sym->secidx == SHN_UNDEF) {
3882 type = 'U';
3883 value = 0;
3884 } else {
3885 sec = f->sections[sym->secidx];
3886
3887 if (sec->header.sh_type == SHT_NOBITS)
3888 type = 'B';
3889 else if (sec->header.sh_flags & SHF_ALLOC) {
3890 if (sec->header.sh_flags & SHF_EXECINSTR)
3891 type = 'T';
3892 else if (sec->header.sh_flags & SHF_WRITE)
3893 type = 'D';
3894 else
3895 type = 'R';
3896 }
3897 value = sym->value + sec->header.sh_addr;
3898 }
3899
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003900 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003901 type = tolower(type);
3902
3903 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3904 type, sym->name);
3905 }
3906#endif
3907}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003908#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003909void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003910#endif
3911
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003912int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3913int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003914{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003915 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003916 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003917 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003918 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003919 unsigned long m_size;
3920 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003921 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003922 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003923 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003924 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003925 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003926#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003927 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003928 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003929 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003930#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003931#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003932 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003933#else
3934 FILE *fp;
3935#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003936 int k_version = 0;
3937 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003938
Erik Andersene49d5ec2000-02-08 19:58:47 +00003939 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003940 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003941 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003942 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003943 free(m_name);
3944 m_name = xstrdup(opt_o);
3945 }
Eric Andersen03d80912003-12-19 21:04:19 +00003946
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003947 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003948 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003949 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003950
Erik Andersene49d5ec2000-02-08 19:58:47 +00003951 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003952 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003953 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003954 len = strlen(tmp);
3955
Eric Andersen03d80912003-12-19 21:04:19 +00003956 if (uname(&myuname) == 0) {
3957 if (myuname.release[0] == '2') {
3958 k_version = myuname.release[2] - '0';
3959 }
3960 }
3961
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003962#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003963 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3964 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3965 ) {
3966 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003967 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003968 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003969#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003970 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003971 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003972 tmp[len] = '\0';
3973 }
Eric Andersen2d342152002-06-18 05:16:25 +00003974
Eric Andersen03d80912003-12-19 21:04:19 +00003975
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003976#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003977 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003978 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003979 else
Eric Andersen03d80912003-12-19 21:04:19 +00003980#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003981 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003982
Eric Andersen61f83052002-06-22 17:15:42 +00003983 if (!m_name) {
3984 m_name = tmp;
3985 } else {
3986 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003987 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003988 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003989
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003990 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003991 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3992 || (fp = fopen(arg1, "r")) == NULL
3993 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003994 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3995 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003996 if (k_version) { /* uname succeedd */
3997 char *module_dir;
3998 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00003999
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004000 tmdn = concat_path_file(CONFIG_DEFAULT_MODULES_DIR, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004001 /* Jump through hoops in case /lib/modules/`uname -r`
4002 * is a symlink. We do not want recursive_action to
4003 * follow symlinks, but we do want to follow the
4004 * /lib/modules/`uname -r` dir, So resolve it ourselves
4005 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004006 module_dir = xmalloc_readlink(tmdn);
4007 if (!module_dir)
4008 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004009 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004010 check_module_name_match, NULL, m_fullName, 0);
4011 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004012 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004013 }
4014
4015 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004016 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004017 int r;
4018 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004019
Eric Andersen03d80912003-12-19 21:04:19 +00004020 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004021 m_filename = NULL;
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004022 module_dir = xmalloc_readlink(CONFIG_DEFAULT_MODULES_DIR);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004023 if (!module_dir)
Bernhard Reutner-Fischerb85fb692008-05-27 10:55:34 +00004024 module_dir = xstrdup(CONFIG_DEFAULT_MODULES_DIR);
Eric Andersen14d35432001-05-14 17:07:32 +00004025 /* No module found under /lib/modules/`uname -r`, this
4026 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004027 r = recursive_action(module_dir, ACTION_RECURSE,
4028 check_module_name_match, NULL, m_fullName, 0);
4029 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004030 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004031 free(module_dir);
4032 if (m_filename == NULL
4033 || ((fp = fopen(m_filename, "r")) == NULL)
4034 ) {
4035 bb_error_msg_and_die("%s: module not found", m_fullName);
4036 }
Eric Andersen14d35432001-05-14 17:07:32 +00004037 }
Eric Andersen03d80912003-12-19 21:04:19 +00004038 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004039 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004040
Rob Landley999af202005-12-11 20:14:12 +00004041 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004042 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004043
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004044#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004045 if (k_version > 4) {
4046 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004047 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004048 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004049 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004050#endif
4051
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004052 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004053
Eric Andersen9f16d612000-06-12 23:11:16 +00004054 if (get_modinfo_value(f, "kernel_version") == NULL)
4055 m_has_modinfo = 0;
4056 else
4057 m_has_modinfo = 1;
4058
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004059#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004060 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004061 if (!flag_quiet) {
4062 if (uname(&uts_info) < 0)
4063 uts_info.release[0] = '\0';
4064 if (m_has_modinfo) {
4065 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004066 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004067 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004068 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004069 }
4070 }
4071
4072 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004073 bb_error_msg("%skernel-module version mismatch\n"
4074 "\t%s was compiled for kernel version %s\n"
4075 "\twhile this kernel is version %s",
4076 flag_force_load ? "warning: " : "",
4077 m_filename, m_strversion, uts_info.release);
4078 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004079 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004080 }
4081 }
4082 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004083#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004084
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004085 if (query_module(NULL, 0, NULL, 0, NULL))
4086 bb_error_msg_and_die("not configured to support old kernels");
4087 new_get_kernel_symbols();
4088 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004089
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004090#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004091 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004092 if (m_has_modinfo)
4093 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004094
4095 if (m_crcs != k_crcs)
4096 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004097#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004098
Erik Andersene49d5ec2000-02-08 19:58:47 +00004099 /* Let the module know about the kernel symbols. */
4100 add_kernel_symbols(f);
4101
Eric Andersen9f16d612000-06-12 23:11:16 +00004102 /* Allocate common symbols, symbol tables, and string tables. */
4103
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004104 new_create_this_module(f, m_name);
4105 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004106 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004107 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004108
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004109 /* done with the module name, on to the optional var=value arguments */
4110 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004111 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004112 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004113 }
4114
Eric Andersen9f16d612000-06-12 23:11:16 +00004115 arch_create_got(f);
4116 hide_special_symbols(f);
4117
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004118#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004119 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004120#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004121
Eric Andersencb3b9b12004-06-22 11:50:52 +00004122 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004123
Erik Andersene49d5ec2000-02-08 19:58:47 +00004124 /* Find current size of the module */
4125 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004126
Erik Andersene49d5ec2000-02-08 19:58:47 +00004127 m_addr = create_module(m_name, m_size);
Denis Vlasenko6b06cb82008-05-15 21:30:45 +00004128 if (m_addr == (ElfW(Addr))(-1)) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004129 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004130 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004131 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004132 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004133 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004134 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004135 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004136 }
Erik Andersend387d011999-12-21 02:55:11 +00004137
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004138#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004139 /*
4140 * the PROGBITS section was not loaded by the obj_load
4141 * now we can load them directly into the kernel memory
4142 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004143 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004144 delete_module(m_name, 0);
Eric Andersen8ae319a2001-05-21 16:09:18 +00004145 goto out;
4146 }
Eric Andersen03d80912003-12-19 21:04:19 +00004147#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004148
Eric Andersen9f16d612000-06-12 23:11:16 +00004149 if (!obj_relocate(f, m_addr)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004150 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004151 goto out;
4152 }
Erik Andersend387d011999-12-21 02:55:11 +00004153
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004154 if (!new_init_module(m_name, f, m_size)) {
Denis Vlasenkob8e653b2008-06-02 04:51:29 +00004155 delete_module(m_name, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 goto out;
4157 }
4158
Denis Vlasenko51742f42007-04-12 00:32:05 +00004159 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004160 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004161
Matt Kraai3e856ce2000-12-01 02:55:13 +00004162 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004163
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004164 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004165#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004166 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004167 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004168 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004169 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004170 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004171 free(m_filename);
4172#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004173 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004174}
Eric Andersene7047882003-12-11 01:42:13 +00004175
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004176#endif /* ENABLE_FEATURE_2_4_MODULES */
4177/*
4178 * End of big piece of 2.4-specific code
4179 */
Eric Andersene7047882003-12-11 01:42:13 +00004180
4181
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004182#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004183
4184#include <sys/mman.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004185
Bernhard Reutner-Fischer15102162008-05-27 13:27:18 +00004186#if defined __UCLIBC__ && !ENABLE_FEATURE_2_4_MODULES
4187/* big time suckage. The old prototype above renders our nice fwd-decl wrong */
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004188extern int init_module(void *module, unsigned long len, const char *options);
4189#else
Eric Andersene7047882003-12-11 01:42:13 +00004190#include <asm/unistd.h>
4191#include <sys/syscall.h>
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004192#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
4193#endif
Eric Andersene7047882003-12-11 01:42:13 +00004194
4195/* We use error numbers in a loose translation... */
4196static const char *moderror(int err)
4197{
4198 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004199 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004200 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004201 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004202 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004203 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004204 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004205 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004206 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004207 default:
4208 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004209 }
4210}
4211
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004212#if !ENABLE_FEATURE_2_4_MODULES
4213int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko68404f12008-03-17 09:00:54 +00004214int insmod_main(int argc ATTRIBUTE_UNUSED, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004215#else
Denis Vlasenko68404f12008-03-17 09:00:54 +00004216static int insmod_ng_main(int argc ATTRIBUTE_UNUSED, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004217#endif
Eric Andersene7047882003-12-11 01:42:13 +00004218{
Denis Vlasenko92297942006-11-21 11:58:14 +00004219 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004220 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004221 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004222 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004223
Denis Vlasenko92297942006-11-21 11:58:14 +00004224 filename = *++argv;
4225 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004226 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004227
4228 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004229 options = xzalloc(1);
4230 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004231 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004232 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004233 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004234 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004235 }
4236
Denis Vlasenko92297942006-11-21 11:58:14 +00004237#if 0
4238 /* Any special reason why mmap? It isn't performace critical... */
Bernhard Reutner-Fischer9cf0f622008-05-27 09:06:05 +00004239
4240 /* yes, xmalloc'ing can use *alot* of RAM. Don't forget that there are
4241 * modules out there that are half a megabyte! mmap()ing is way nicer
4242 * for small mem boxes, i guess.
4243 */
Denis Vlasenko92297942006-11-21 11:58:14 +00004244 int fd;
4245 struct stat st;
4246 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004247 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004248 fstat(fd, &st);
4249 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004250 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004251 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004252 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004253 }
4254
Denis Vlasenko92297942006-11-21 11:58:14 +00004255 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4256 if (map == NULL) {
4257 map = xmalloc(len);
4258 xread(fd, map, len);
4259 }
4260#else
4261 len = MAXINT(ssize_t);
4262 map = xmalloc_open_read_close(filename, &len);
4263#endif
4264
Bernhard Reutner-Fischer4fec3462008-05-27 10:13:54 +00004265 if (init_module(map, len, options) != 0)
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004266 bb_error_msg_and_die("cannot insert '%s': %s",
4267 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004268 return 0;
4269}
4270
4271#endif