blob: 3c8bb41bb75ac8566ee888dd1f5c668b6b2316b2 [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 Vlasenko3aa2d512006-11-21 14:12:53 +000070#if !ENABLE_FEATURE_2_4_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000071#define insmod_ng_main insmod_main
72#endif
73
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000074#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000075extern int insmod_ng_main( int argc, char **argv);
76#endif
77
Eric Andersencb3b9b12004-06-22 11:50:52 +000078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000079#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000080
Eric Andersen64c8b172001-04-05 07:33:10 +000081
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000082#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000083#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000084#else
85#define LOADBITS 1
86#endif
87
Eric Andersen90fe7fe2001-02-20 20:47:08 +000088
Mike Frysinger63654c12004-12-26 09:13:32 +000089/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000090#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000091#define MATCH_MACHINE(x) (x == EM_ALPHA)
92#define SHT_RELM SHT_RELA
93#define Elf64_RelM Elf64_Rela
94#define ELFCLASSM ELFCLASS64
95#endif
96
Eric Andersen45a05132004-09-02 23:03:25 +000097/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000103#define USE_PLT_ENTRIES
104#define PLT_ENTRY_SIZE 8
105#define USE_GOT_ENTRIES
106#define GOT_ENTRY_SIZE 8
107#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000108#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000109
Mike Frysingerb306cb72006-06-06 06:15:52 +0000110/* blackfin */
111#if defined(BFIN)
112#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
113#define SHT_RELM SHT_RELA
114#define Elf32_RelM Elf32_Rela
115#define ELFCLASSM ELFCLASS32
116#endif
117
Eric Andersen45a05132004-09-02 23:03:25 +0000118/* CRIS */
119#if defined(__cris__)
120#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000121#define SHT_RELM SHT_RELA
122#define Elf32_RelM Elf32_Rela
123#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000124#ifndef EM_CRIS
125#define EM_CRIS 76
126#define R_CRIS_NONE 0
127#define R_CRIS_32 3
128#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000129#endif
130
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000131/* H8/300 */
132#if defined(__H8300H__) || defined(__H8300S__)
133#define MATCH_MACHINE(x) (x == EM_H8_300)
134#define SHT_RELM SHT_RELA
135#define Elf32_RelM Elf32_Rela
136#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000137#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000138#define SYMBOL_PREFIX "_"
139#endif
140
Mike Frysinger63654c12004-12-26 09:13:32 +0000141/* PA-RISC / HP-PA */
142#if defined(__hppa__)
143#define MATCH_MACHINE(x) (x == EM_PARISC)
144#define SHT_RELM SHT_RELA
145#if defined(__LP64__)
146#define Elf64_RelM Elf64_Rela
147#define ELFCLASSM ELFCLASS64
148#else
149#define Elf32_RelM Elf32_Rela
150#define ELFCLASSM ELFCLASS32
151#endif
152#endif
153
Eric Andersen45a05132004-09-02 23:03:25 +0000154/* x86 */
155#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000156#ifndef EM_486
157#define MATCH_MACHINE(x) (x == EM_386)
158#else
159#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
160#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000161#define SHT_RELM SHT_REL
162#define Elf32_RelM Elf32_Rel
163#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000164#define USE_GOT_ENTRIES
165#define GOT_ENTRY_SIZE 4
166#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* IA64, aka Itanium */
170#if defined(__ia64__)
171#define MATCH_MACHINE(x) (x == EM_IA_64)
172#define SHT_RELM SHT_RELA
173#define Elf64_RelM Elf64_Rela
174#define ELFCLASSM ELFCLASS64
175#endif
176
177/* m68k */
178#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define MATCH_MACHINE(x) (x == EM_68K)
180#define SHT_RELM SHT_RELA
181#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000182#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000183#define USE_GOT_ENTRIES
184#define GOT_ENTRY_SIZE 4
185#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000186#endif
187
Mike Frysingerb306cb72006-06-06 06:15:52 +0000188/* Microblaze */
189#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000190#define USE_SINGLE
Mike Frysingerb306cb72006-06-06 06:15:52 +0000191#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
192#define SHT_RELM SHT_RELA
193#define Elf32_RelM Elf32_Rela
194#define ELFCLASSM ELFCLASS32
195#endif
196
Eric Andersen45a05132004-09-02 23:03:25 +0000197/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000198#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000199#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
200#define SHT_RELM SHT_REL
201#define Elf32_RelM Elf32_Rel
202#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000203/* Account for ELF spec changes. */
204#ifndef EM_MIPS_RS3_LE
205#ifdef EM_MIPS_RS4_BE
206#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
207#else
208#define EM_MIPS_RS3_LE 10
209#endif
210#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000211#define ARCHDATAM "__dbe_table"
212#endif
213
Mike Frysingerf982d862006-01-04 00:11:26 +0000214/* Nios II */
215#if defined(__nios2__)
216#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
217#define SHT_RELM SHT_RELA
218#define Elf32_RelM Elf32_Rela
219#define ELFCLASSM ELFCLASS32
220#endif
221
Eric Andersen45a05132004-09-02 23:03:25 +0000222/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000223#if defined(__powerpc64__)
224#define MATCH_MACHINE(x) (x == EM_PPC64)
225#define SHT_RELM SHT_RELA
226#define Elf64_RelM Elf64_Rela
227#define ELFCLASSM ELFCLASS64
228#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000229#define MATCH_MACHINE(x) (x == EM_PPC)
230#define SHT_RELM SHT_RELA
231#define Elf32_RelM Elf32_Rela
232#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000233#define USE_PLT_ENTRIES
234#define PLT_ENTRY_SIZE 16
235#define USE_PLT_LIST
236#define LIST_ARCHTYPE ElfW(Addr)
237#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000238#define ARCHDATAM "__ftr_fixup"
239#endif
240
Eric Andersen45a05132004-09-02 23:03:25 +0000241/* S390 */
242#if defined(__s390__)
243#define MATCH_MACHINE(x) (x == EM_S390)
244#define SHT_RELM SHT_RELA
245#define Elf32_RelM Elf32_Rela
246#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000247#define USE_PLT_ENTRIES
248#define PLT_ENTRY_SIZE 8
249#define USE_GOT_ENTRIES
250#define GOT_ENTRY_SIZE 8
251#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000252#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000253
Eric Andersen45a05132004-09-02 23:03:25 +0000254/* SuperH */
255#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000256#define MATCH_MACHINE(x) (x == EM_SH)
257#define SHT_RELM SHT_RELA
258#define Elf32_RelM Elf32_Rela
259#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000260#define USE_GOT_ENTRIES
261#define GOT_ENTRY_SIZE 4
262#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000263/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000264/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000265#if defined(__sh__) && BB_BIG_ENDIAN
266# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000267#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000268/* it may or may not work on the SH1/SH2... Error on those also */
269#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000270#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000271#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000272#endif
273
Eric Andersen45a05132004-09-02 23:03:25 +0000274/* Sparc */
275#if defined(__sparc__)
276#define MATCH_MACHINE(x) (x == EM_SPARC)
277#define SHT_RELM SHT_RELA
278#define Elf32_RelM Elf32_Rela
279#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000280#endif
281
Eric Andersen45a05132004-09-02 23:03:25 +0000282/* v850e */
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000283#if defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000284#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
285#define SHT_RELM SHT_RELA
286#define Elf32_RelM Elf32_Rela
287#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000288#define USE_PLT_ENTRIES
289#define PLT_ENTRY_SIZE 8
290#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000291#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000292#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000293#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000294#define SYMBOL_PREFIX "_"
295#endif
296
Eric Andersen45a05132004-09-02 23:03:25 +0000297/* X86_64 */
298#if defined(__x86_64__)
299#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000300#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000301#define USE_GOT_ENTRIES
302#define GOT_ENTRY_SIZE 8
303#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000304#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000305#define ELFCLASSM ELFCLASS64
306#endif
307
Eric Andersencffd5022002-05-24 06:50:15 +0000308#ifndef SHT_RELM
309#error Sorry, but insmod.c does not yet support this architecture...
310#endif
311
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313//----------------------------------------------------------------------------
314//--------modutils module.h, lines 45-242
315//----------------------------------------------------------------------------
316
317/* Definitions for the Linux module syscall interface.
318 Copyright 1996, 1997 Linux International.
319
320 Contributed by Richard Henderson <rth@tamu.edu>
321
322 This file is part of the Linux modutils.
323
324 This program is free software; you can redistribute it and/or modify it
325 under the terms of the GNU General Public License as published by the
326 Free Software Foundation; either version 2 of the License, or (at your
327 option) any later version.
328
329 This program is distributed in the hope that it will be useful, but
330 WITHOUT ANY WARRANTY; without even the implied warranty of
331 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 General Public License for more details.
333
334 You should have received a copy of the GNU General Public License
335 along with this program; if not, write to the Free Software Foundation,
336 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
337
338
339#ifndef MODUTILS_MODULE_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000340
Eric Andersen9f16d612000-06-12 23:11:16 +0000341/*======================================================================*/
342/* For sizeof() which are related to the module platform and not to the
343 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
344
345#define tgt_sizeof_char sizeof(char)
346#define tgt_sizeof_short sizeof(short)
347#define tgt_sizeof_int sizeof(int)
348#define tgt_sizeof_long sizeof(long)
349#define tgt_sizeof_char_p sizeof(char *)
350#define tgt_sizeof_void_p sizeof(void *)
351#define tgt_long long
352
353#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
354#undef tgt_sizeof_long
355#undef tgt_sizeof_char_p
356#undef tgt_sizeof_void_p
357#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000358enum {
359 tgt_sizeof_long = 8,
360 tgt_sizeof_char_p = 8,
361 tgt_sizeof_void_p = 8
362};
Eric Andersen9f16d612000-06-12 23:11:16 +0000363#define tgt_long long long
364#endif
365
366/*======================================================================*/
367/* The structures used in Linux 2.1. */
368
369/* Note: new_module_symbol does not use tgt_long intentionally */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000370struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000371 unsigned long value;
372 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000373};
374
375struct new_module_persist;
376
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000377struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000378 unsigned tgt_long dep; /* kernel addresses */
379 unsigned tgt_long ref;
380 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000381};
382
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000383struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000384 unsigned tgt_long size_of_struct; /* == sizeof(module) */
385 unsigned tgt_long next;
386 unsigned tgt_long name;
387 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000388
Eric Andersen3b1a7442003-12-24 20:30:45 +0000389 tgt_long usecount;
390 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000391
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned nsyms;
393 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000394
Eric Andersen3b1a7442003-12-24 20:30:45 +0000395 unsigned tgt_long syms;
396 unsigned tgt_long deps;
397 unsigned tgt_long refs;
398 unsigned tgt_long init;
399 unsigned tgt_long cleanup;
400 unsigned tgt_long ex_table_start;
401 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000402#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000403 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 /* Everything after here is extension. */
406 unsigned tgt_long persist_start;
407 unsigned tgt_long persist_end;
408 unsigned tgt_long can_unload;
409 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000410 const char *kallsyms_start; /* All symbols for kernel debugging */
411 const char *kallsyms_end;
412 const char *archdata_start; /* arch specific data for module */
413 const char *archdata_end;
414 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000415};
416
Eric Andersencffd5022002-05-24 06:50:15 +0000417#ifdef ARCHDATAM
418#define ARCHDATA_SEC_NAME ARCHDATAM
419#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000420#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000421#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000422#define KALLSYMS_SEC_NAME "__kallsyms"
423
424
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000425struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000426 unsigned long addr;
427 unsigned long size;
428 unsigned long flags;
429 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000430};
431
432/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000433enum {
434 NEW_MOD_RUNNING = 1,
435 NEW_MOD_DELETED = 2,
436 NEW_MOD_AUTOCLEAN = 4,
437 NEW_MOD_VISITED = 8,
438 NEW_MOD_USED_ONCE = 16
439};
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersencb3b9b12004-06-22 11:50:52 +0000441int init_module(const char *name, const struct new_module *);
442int query_module(const char *name, int which, void *buf,
443 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000444
445/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000446enum {
447 QM_MODULES = 1,
448 QM_DEPS = 2,
449 QM_REFS = 3,
450 QM_SYMBOLS = 4,
451 QM_INFO = 5
452};
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
454/*======================================================================*/
455/* The system calls unchanged between 2.0 and 2.1. */
456
457unsigned long create_module(const char *, size_t);
458int delete_module(const char *);
459
460
461#endif /* module.h */
462
463//----------------------------------------------------------------------------
464//--------end of modutils module.h
465//----------------------------------------------------------------------------
466
467
468
469//----------------------------------------------------------------------------
470//--------modutils obj.h, lines 253-462
471//----------------------------------------------------------------------------
472
473/* Elf object file loading and relocation routines.
474 Copyright 1996, 1997 Linux International.
475
476 Contributed by Richard Henderson <rth@tamu.edu>
477
478 This file is part of the Linux modutils.
479
480 This program is free software; you can redistribute it and/or modify it
481 under the terms of the GNU General Public License as published by the
482 Free Software Foundation; either version 2 of the License, or (at your
483 option) any later version.
484
485 This program is distributed in the hope that it will be useful, but
486 WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 General Public License for more details.
489
490 You should have received a copy of the GNU General Public License
491 along with this program; if not, write to the Free Software Foundation,
492 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
493
494
495#ifndef MODUTILS_OBJ_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000496
Eric Andersen9f16d612000-06-12 23:11:16 +0000497/* The relocatable object is manipulated using elfin types. */
498
Eric Andersen9f16d612000-06-12 23:11:16 +0000499#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000500#include <endian.h>
501
Eric Andersen9f16d612000-06-12 23:11:16 +0000502#ifndef ElfW
503# if ELFCLASSM == ELFCLASS32
504# define ElfW(x) Elf32_ ## x
505# define ELFW(x) ELF32_ ## x
506# else
507# define ElfW(x) Elf64_ ## x
508# define ELFW(x) ELF64_ ## x
509# endif
510#endif
511
Eric Andersen85e5e722003-07-22 08:56:55 +0000512/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000513#ifndef ELF32_ST_INFO
514# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
515#endif
516
517#ifndef ELF64_ST_INFO
518# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
519#endif
520
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000521#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
522#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
523#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
524#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
525#define ELF_R_SYM(val) ELFW(R_SYM)(val)
526
Eric Andersen9f16d612000-06-12 23:11:16 +0000527struct obj_string_patch;
528struct obj_symbol_patch;
529
530struct obj_section
531{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000532 ElfW(Shdr) header;
533 const char *name;
534 char *contents;
535 struct obj_section *load_next;
536 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000537};
538
539struct obj_symbol
540{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000541 struct obj_symbol *next; /* hash table link */
542 const char *name;
543 unsigned long value;
544 unsigned long size;
545 int secidx; /* the defining section index/module */
546 int info;
547 int ksymidx; /* for export to the kernel symtab */
548 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000549};
550
551/* Hardcode the hash table size. We shouldn't be needing so many
552 symbols that we begin to degrade performance, and we get a big win
553 by giving the compiler a constant divisor. */
554
555#define HASH_BUCKETS 521
556
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000557struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000558 ElfW(Ehdr) header;
559 ElfW(Addr) baseaddr;
560 struct obj_section **sections;
561 struct obj_section *load_order;
562 struct obj_section **load_order_search_start;
563 struct obj_string_patch *string_patches;
564 struct obj_symbol_patch *symbol_patches;
565 int (*symbol_cmp)(const char *, const char *);
566 unsigned long (*symbol_hash)(const char *);
567 unsigned long local_symtab_size;
568 struct obj_symbol **local_symtab;
569 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000570};
571
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000572enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000573 obj_reloc_ok,
574 obj_reloc_overflow,
575 obj_reloc_dangerous,
576 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000577};
578
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000579struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000580 struct obj_string_patch *next;
581 int reloc_secidx;
582 ElfW(Addr) reloc_offset;
583 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000584};
585
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000586struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000587 struct obj_symbol_patch *next;
588 int reloc_secidx;
589 ElfW(Addr) reloc_offset;
590 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000591};
592
593
594/* Generic object manipulation routines. */
595
Eric Andersen044228d2001-07-17 01:12:36 +0000596static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000597
Eric Andersen044228d2001-07-17 01:12:36 +0000598static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000599
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000600static struct obj_symbol *obj_find_symbol(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000601 const char *name);
602
Eric Andersen044228d2001-07-17 01:12:36 +0000603static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000604 struct obj_symbol *sym);
605
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000606#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000607static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000608 int (*cmp)(const char *, const char *),
609 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000610#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000611
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000612static struct obj_section *obj_find_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000613 const char *name);
614
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000615static void obj_insert_section_load_order(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000616 struct obj_section *sec);
617
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000618static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000619 const char *name,
620 unsigned long align,
621 unsigned long size);
622
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000623static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000624 const char *name,
625 unsigned long align,
626 unsigned long size);
627
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000628static void *obj_extend_section(struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000629
Eric Andersen044228d2001-07-17 01:12:36 +0000630static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000631 const char *string);
632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000634 struct obj_symbol *sym);
635
Eric Andersen044228d2001-07-17 01:12:36 +0000636static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000637
Eric Andersen044228d2001-07-17 01:12:36 +0000638static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000639
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000640static unsigned long obj_load_size(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000641
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000642static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000645
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000646static int obj_create_image(struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000647
648/* Architecture specific manipulation routines. */
649
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000650static struct obj_file *arch_new_file(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000652static struct obj_section *arch_new_section(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000653
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000654static struct obj_symbol *arch_new_symbol(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000655
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000656static enum obj_reloc arch_apply_relocation(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000657 struct obj_section *targsec,
658 struct obj_section *symsec,
659 struct obj_symbol *sym,
660 ElfW(RelM) *rel, ElfW(Addr) value);
661
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000662static void arch_create_got(struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000663#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000664static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000665#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000666#endif /* obj.h */
667//----------------------------------------------------------------------------
668//--------end of modutils obj.h
669//----------------------------------------------------------------------------
670
671
Miles Baderae28b042002-04-01 09:34:25 +0000672/* SPFX is always a string, so it can be concatenated to string constants. */
673#ifdef SYMBOL_PREFIX
674#define SPFX SYMBOL_PREFIX
675#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000676#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000677#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000678
Erik Andersen02104321999-12-17 18:57:34 +0000679
Erik Andersend387d011999-12-21 02:55:11 +0000680#define _PATH_MODULES "/lib/modules"
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000681enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000682
Eric Andersen9f16d612000-06-12 23:11:16 +0000683/*======================================================================*/
684
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000685#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
686enum {
687 OPT_s = 0x1, // -s /* log to syslog */
688 /* Not supported but kernel needs this for request_module(),
689 as this calls: modprobe -k -s -- <module>
690 so silently ignore this flag */
691 OPT_L = 0x2, // -L /* Stub warning */
692 /* Compatibility with modprobe.
693 In theory, this does locking, but we don't do
694 that. So be careful and plan your life around not
695 loading the same module 50 times concurrently. */
696 OPT_o = 0x4, // -o /* name the output module */
697 OPT_f = 0x8, // -f /* force loading */
698 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
699 OPT_v = 0x20, // -v /* verbose output */
700 OPT_q = 0x40, // -q /* silent */
701 OPT_x = 0x80, // -x /* do not export externs */
702 OPT_m = 0x100, // -m /* print module load map */
703};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000704#define flag_force_load (option_mask32 & OPT_f)
705#define flag_autoclean (option_mask32 & OPT_k)
706#define flag_verbose (option_mask32 & OPT_v)
707#define flag_quiet (option_mask32 & OPT_q)
708#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000709#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000710#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000711#else
712#define flag_print_load_map 0
713#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000714
715/*======================================================================*/
716
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000717#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000718
Eric Andersencffd5022002-05-24 06:50:15 +0000719struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000720{
Eric Andersencffd5022002-05-24 06:50:15 +0000721 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000722 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000723 int offset;
724 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000725};
Eric Andersencffd5022002-05-24 06:50:15 +0000726
Eric Andersen21adca72000-12-06 18:18:26 +0000727#endif
728
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000729#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000730
731struct arch_single_entry
732{
Eric Andersen9f16d612000-06-12 23:11:16 +0000733 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000734 int inited : 1;
735 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000736};
Eric Andersencffd5022002-05-24 06:50:15 +0000737
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000738#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000739
Eric Andersen2bf658d2001-02-24 20:01:53 +0000740#if defined(__mips__)
741struct mips_hi16
742{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000743 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000744 ElfW(Addr) *addr;
745 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000746};
747#endif
748
Eric Andersenfe4208f2000-09-24 03:44:29 +0000749struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000750 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000751#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000752 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000753#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000754#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000755 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000756#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000757#if defined(__mips__)
758 struct mips_hi16 *mips_hi16_list;
759#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000760};
761
Eric Andersenfe4208f2000-09-24 03:44:29 +0000762struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000763 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000764#if defined(USE_PLT_ENTRIES)
765#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000766 struct arch_list_entry *pltent;
767#else
768 struct arch_single_entry pltent;
769#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000770#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000771#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000772 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000773#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000774};
775
776
Eric Andersen9f16d612000-06-12 23:11:16 +0000777struct external_module {
778 const char *name;
779 ElfW(Addr) addr;
780 int used;
781 size_t nsyms;
782 struct new_module_symbol *syms;
783};
784
Eric Andersen044228d2001-07-17 01:12:36 +0000785static struct new_module_symbol *ksyms;
786static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000787
Eric Andersen044228d2001-07-17 01:12:36 +0000788static struct external_module *ext_modules;
789static int n_ext_modules;
790static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000791extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000792
Eric Andersen61f83052002-06-22 17:15:42 +0000793static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000794static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000795
Eric Andersenfe4208f2000-09-24 03:44:29 +0000796
Eric Andersen9f16d612000-06-12 23:11:16 +0000797/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000798
Eric Andersen9f16d612000-06-12 23:11:16 +0000799
Eric Andersen14d35432001-05-14 17:07:32 +0000800static int check_module_name_match(const char *filename, struct stat *statbuf,
Denis Vlasenko8c35d652006-10-27 23:42:25 +0000801 void *userdata, int depth)
Eric Andersen9f16d612000-06-12 23:11:16 +0000802{
Eric Andersen14d35432001-05-14 17:07:32 +0000803 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000804
Eric Andersen14d35432001-05-14 17:07:32 +0000805 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000806 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000807 else {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000808 char *tmp, *tmp1 = xstrdup(filename);
Denis Vlasenko818322b2007-09-24 18:27:04 +0000809 tmp = bb_get_last_path_component_nostrip(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000810 if (strcmp(tmp, fullname) == 0) {
811 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000812 /* Stop searching if we find a match */
Rob Landleyd921b2e2006-08-03 15:41:12 +0000813 m_filename = xstrdup(filename);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000814 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000815 }
Eric Andersen14d35432001-05-14 17:07:32 +0000816 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000817 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000818 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000819}
820
Erik Andersen02104321999-12-17 18:57:34 +0000821
Eric Andersen9f16d612000-06-12 23:11:16 +0000822/*======================================================================*/
823
Eric Andersen044228d2001-07-17 01:12:36 +0000824static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000825{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000826 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000827 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000828
Eric Andersencffd5022002-05-24 06:50:15 +0000829 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000830
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 return &f->root;
832}
833
Eric Andersen044228d2001-07-17 01:12:36 +0000834static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000835{
836 return xmalloc(sizeof(struct obj_section));
837}
838
Eric Andersen044228d2001-07-17 01:12:36 +0000839static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000840{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000841 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000842 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000843
Eric Andersencffd5022002-05-24 06:50:15 +0000844 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000845
Eric Andersen9f16d612000-06-12 23:11:16 +0000846 return &sym->root;
847}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000848
Eric Andersen044228d2001-07-17 01:12:36 +0000849static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000850arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000851 struct obj_section *targsec,
852 struct obj_section *symsec,
853 struct obj_symbol *sym,
854 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000855{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000856 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000857 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000858 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
859 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000860#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000861 struct arch_symbol *isym = (struct arch_symbol *) sym;
862#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000863#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000864#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000865 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000866#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000867#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000868#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000869 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000870 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000871# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000872 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000873# else
Eric Andersencffd5022002-05-24 06:50:15 +0000874 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000875# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000876#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000877
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000878 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000879
Eric Andersencffd5022002-05-24 06:50:15 +0000880#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000881
Eric Andersen3b1a7442003-12-24 20:30:45 +0000882 case R_ARM_NONE:
883 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000884
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 case R_ARM_ABS32:
886 *loc += v;
887 break;
Miles Baderae28b042002-04-01 09:34:25 +0000888
Eric Andersen3b1a7442003-12-24 20:30:45 +0000889 case R_ARM_GOT32:
890 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000891
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000893 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
894 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000896
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 *loc += got - dot;
898 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000899
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 case R_ARM_PC24:
901 case R_ARM_PLT32:
902 goto bb_use_plt;
903
904 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000905 *loc += v - got;
906 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000907
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000908#elif defined(__cris__)
909
910 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000911 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000912
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000913 case R_CRIS_32:
914 /* CRIS keeps the relocation value in the r_addend field and
915 * should not use whats in *loc at all
916 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000917 *loc = v;
918 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000919
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000920#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000921
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000922 case R_H8_DIR24R8:
923 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
924 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000925 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000926 case R_H8_DIR24A8:
927 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000928 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000929 case R_H8_DIR32:
930 case R_H8_DIR32A16:
931 *loc += v;
932 break;
933 case R_H8_PCREL16:
934 v -= dot + 2;
935 if ((ElfW(Sword))v > 0x7fff ||
936 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
937 ret = obj_reloc_overflow;
938 else
939 *(unsigned short *)loc = v;
940 break;
941 case R_H8_PCREL8:
942 v -= dot + 1;
943 if ((ElfW(Sword))v > 0x7f ||
944 (ElfW(Sword))v < -(ElfW(Sword))0x80)
945 ret = obj_reloc_overflow;
946 else
947 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000949
Eric Andersencffd5022002-05-24 06:50:15 +0000950#elif defined(__i386__)
951
Eric Andersen3b1a7442003-12-24 20:30:45 +0000952 case R_386_NONE:
953 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000954
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 case R_386_32:
956 *loc += v;
957 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000958
Eric Andersen3b1a7442003-12-24 20:30:45 +0000959 case R_386_PLT32:
960 case R_386_PC32:
961 *loc += v - dot;
962 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000963
Eric Andersen3b1a7442003-12-24 20:30:45 +0000964 case R_386_GLOB_DAT:
965 case R_386_JMP_SLOT:
966 *loc = v;
967 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_RELATIVE:
970 *loc += f->baseaddr;
971 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000972
Eric Andersen3b1a7442003-12-24 20:30:45 +0000973 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 *loc += got - dot;
975 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000976
Eric Andersen3b1a7442003-12-24 20:30:45 +0000977 case R_386_GOT32:
978 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000979
Eric Andersen3b1a7442003-12-24 20:30:45 +0000980 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000981 *loc += v - got;
982 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000983
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000984#elif defined(__microblaze__)
Mike Frysinger280dae72006-06-06 06:30:32 +0000985 case R_MICROBLAZE_NONE:
986 case R_MICROBLAZE_64_NONE:
987 case R_MICROBLAZE_32_SYM_OP_SYM:
988 case R_MICROBLAZE_32_PCREL:
989 break;
990
991 case R_MICROBLAZE_64_PCREL: {
992 /* dot is the address of the current instruction.
993 * v is the target symbol address.
994 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000995 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000996 * of this instruction.
997 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
998 */
999
1000 /* Get split offset stored in code */
1001 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
1002 (loc[1] & 0xFFFF);
1003
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001004 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +00001005 * because dot points to the IMM insn, but branch
1006 * is computed relative to the branch instruction itself.
1007 */
1008 temp += v - dot - 4;
1009
1010 /* Store back into code */
1011 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1012 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1013
1014 break;
1015 }
1016
1017 case R_MICROBLAZE_32:
1018 *loc += v;
1019 break;
1020
1021 case R_MICROBLAZE_64: {
1022 /* Get split pointer stored in code */
1023 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1024 (loc[1] & 0xFFFF);
1025
1026 /* Add reloc offset */
1027 temp1+=v;
1028
1029 /* Store back into code */
1030 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1031 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1032
1033 break;
1034 }
1035
1036 case R_MICROBLAZE_32_PCREL_LO:
1037 case R_MICROBLAZE_32_LO:
1038 case R_MICROBLAZE_SRO32:
1039 case R_MICROBLAZE_SRW32:
1040 ret = obj_reloc_unhandled;
1041 break;
1042
Eric Andersencffd5022002-05-24 06:50:15 +00001043#elif defined(__mc68000__)
1044
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_68K_NONE:
1046 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001047
Eric Andersen3b1a7442003-12-24 20:30:45 +00001048 case R_68K_32:
1049 *loc += v;
1050 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_68K_8:
1053 if (v > 0xff) {
1054 ret = obj_reloc_overflow;
1055 }
1056 *(char *)loc = v;
1057 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001058
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 case R_68K_16:
1060 if (v > 0xffff) {
1061 ret = obj_reloc_overflow;
1062 }
1063 *(short *)loc = v;
1064 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001065
Eric Andersen3b1a7442003-12-24 20:30:45 +00001066 case R_68K_PC8:
1067 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001068 if ((ElfW(Sword))v > 0x7f ||
1069 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001070 ret = obj_reloc_overflow;
1071 }
1072 *(char *)loc = v;
1073 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001074
Eric Andersen3b1a7442003-12-24 20:30:45 +00001075 case R_68K_PC16:
1076 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001077 if ((ElfW(Sword))v > 0x7fff ||
1078 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001079 ret = obj_reloc_overflow;
1080 }
1081 *(short *)loc = v;
1082 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001083
Eric Andersen3b1a7442003-12-24 20:30:45 +00001084 case R_68K_PC32:
1085 *(int *)loc = v - dot;
1086 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001087
Eric Andersen3b1a7442003-12-24 20:30:45 +00001088 case R_68K_GLOB_DAT:
1089 case R_68K_JMP_SLOT:
1090 *loc = v;
1091 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001092
Eric Andersen3b1a7442003-12-24 20:30:45 +00001093 case R_68K_RELATIVE:
1094 *(int *)loc += f->baseaddr;
1095 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001096
Eric Andersen3b1a7442003-12-24 20:30:45 +00001097 case R_68K_GOT32:
1098 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001099
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001100# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001101 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001102 *loc += v - got;
1103 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001104# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001105
1106#elif defined(__mips__)
1107
Eric Andersen3b1a7442003-12-24 20:30:45 +00001108 case R_MIPS_NONE:
1109 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001110
Eric Andersen3b1a7442003-12-24 20:30:45 +00001111 case R_MIPS_32:
1112 *loc += v;
1113 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001114
Eric Andersen3b1a7442003-12-24 20:30:45 +00001115 case R_MIPS_26:
1116 if (v % 4)
1117 ret = obj_reloc_dangerous;
1118 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1119 ret = obj_reloc_overflow;
1120 *loc =
1121 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1122 0x03ffffff);
1123 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001124
Eric Andersen3b1a7442003-12-24 20:30:45 +00001125 case R_MIPS_HI16:
1126 {
1127 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001128
Eric Andersen3b1a7442003-12-24 20:30:45 +00001129 /* We cannot relocate this one now because we don't know the value
1130 of the carry we need to add. Save the information, and let LO16
1131 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001132 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001133 n->addr = loc;
1134 n->value = v;
1135 n->next = ifile->mips_hi16_list;
1136 ifile->mips_hi16_list = n;
1137 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001138 }
1139
Eric Andersen3b1a7442003-12-24 20:30:45 +00001140 case R_MIPS_LO16:
1141 {
1142 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001143 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001144
1145 /* Sign extend the addend we extract from the lo insn. */
1146 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1147
1148 if (ifile->mips_hi16_list != NULL) {
1149 struct mips_hi16 *l;
1150
1151 l = ifile->mips_hi16_list;
1152 while (l != NULL) {
1153 struct mips_hi16 *next;
1154 unsigned long insn;
1155
Eric Andersen3b1a7442003-12-24 20:30:45 +00001156 /* Do the HI16 relocation. Note that we actually don't
1157 need to know anything about the LO16 itself, except where
1158 to find the low 16 bits of the addend needed by the LO16. */
1159 insn = *l->addr;
1160 val =
1161 ((insn & 0xffff) << 16) +
1162 vallo;
1163 val += v;
1164
1165 /* Account for the sign extension that will happen in the
1166 low bits. */
1167 val =
1168 ((val >> 16) +
1169 ((val & 0x8000) !=
1170 0)) & 0xffff;
1171
1172 insn = (insn & ~0xffff) | val;
1173 *l->addr = insn;
1174
1175 next = l->next;
1176 free(l);
1177 l = next;
1178 }
1179
1180 ifile->mips_hi16_list = NULL;
1181 }
1182
1183 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1184 val = v + vallo;
1185 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1186 *loc = insnlo;
1187 break;
1188 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001189
Mike Frysingerf982d862006-01-04 00:11:26 +00001190#elif defined(__nios2__)
1191
1192 case R_NIOS2_NONE:
1193 break;
1194
1195 case R_NIOS2_BFD_RELOC_32:
1196 *loc += v;
1197 break;
1198
1199 case R_NIOS2_BFD_RELOC_16:
1200 if (v > 0xffff) {
1201 ret = obj_reloc_overflow;
1202 }
1203 *(short *)loc = v;
1204 break;
1205
1206 case R_NIOS2_BFD_RELOC_8:
1207 if (v > 0xff) {
1208 ret = obj_reloc_overflow;
1209 }
1210 *(char *)loc = v;
1211 break;
1212
1213 case R_NIOS2_S16:
1214 {
1215 Elf32_Addr word;
1216
1217 if ((Elf32_Sword)v > 0x7fff ||
1218 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1219 ret = obj_reloc_overflow;
1220 }
1221
1222 word = *loc;
1223 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1224 (word & 0x3f);
1225 }
1226 break;
1227
1228 case R_NIOS2_U16:
1229 {
1230 Elf32_Addr word;
1231
1232 if (v > 0xffff) {
1233 ret = obj_reloc_overflow;
1234 }
1235
1236 word = *loc;
1237 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1238 (word & 0x3f);
1239 }
1240 break;
1241
1242 case R_NIOS2_PCREL16:
1243 {
1244 Elf32_Addr word;
1245
1246 v -= dot + 4;
1247 if ((Elf32_Sword)v > 0x7fff ||
1248 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1249 ret = obj_reloc_overflow;
1250 }
1251
1252 word = *loc;
1253 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1254 }
1255 break;
1256
1257 case R_NIOS2_GPREL:
1258 {
1259 Elf32_Addr word, gp;
1260 /* get _gp */
1261 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1262 v-=gp;
1263 if ((Elf32_Sword)v > 0x7fff ||
1264 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1265 ret = obj_reloc_overflow;
1266 }
1267
1268 word = *loc;
1269 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1270 }
1271 break;
1272
1273 case R_NIOS2_CALL26:
1274 if (v & 3)
1275 ret = obj_reloc_dangerous;
1276 if ((v >> 28) != (dot >> 28))
1277 ret = obj_reloc_overflow;
1278 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1279 break;
1280
1281 case R_NIOS2_IMM5:
1282 {
1283 Elf32_Addr word;
1284
1285 if (v > 0x1f) {
1286 ret = obj_reloc_overflow;
1287 }
1288
1289 word = *loc & ~0x7c0;
1290 *loc = word | ((v & 0x1f) << 6);
1291 }
1292 break;
1293
1294 case R_NIOS2_IMM6:
1295 {
1296 Elf32_Addr word;
1297
1298 if (v > 0x3f) {
1299 ret = obj_reloc_overflow;
1300 }
1301
1302 word = *loc & ~0xfc0;
1303 *loc = word | ((v & 0x3f) << 6);
1304 }
1305 break;
1306
1307 case R_NIOS2_IMM8:
1308 {
1309 Elf32_Addr word;
1310
1311 if (v > 0xff) {
1312 ret = obj_reloc_overflow;
1313 }
1314
1315 word = *loc & ~0x3fc0;
1316 *loc = word | ((v & 0xff) << 6);
1317 }
1318 break;
1319
1320 case R_NIOS2_HI16:
1321 {
1322 Elf32_Addr word;
1323
1324 word = *loc;
1325 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1326 (word & 0x3f);
1327 }
1328 break;
1329
1330 case R_NIOS2_LO16:
1331 {
1332 Elf32_Addr word;
1333
1334 word = *loc;
1335 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1336 (word & 0x3f);
1337 }
1338 break;
1339
1340 case R_NIOS2_HIADJ16:
1341 {
1342 Elf32_Addr word1, word2;
1343
1344 word1 = *loc;
1345 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1346 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1347 (word1 & 0x3f);
1348 }
1349 break;
1350
Mike Frysingerebee0e72006-02-18 06:14:31 +00001351#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001352 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001353
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001354#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001355
Eric Andersen3b1a7442003-12-24 20:30:45 +00001356 case R_PPC_ADDR16_HA:
1357 *(unsigned short *)loc = (v + 0x8000) >> 16;
1358 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001359
Eric Andersen3b1a7442003-12-24 20:30:45 +00001360 case R_PPC_ADDR16_HI:
1361 *(unsigned short *)loc = v >> 16;
1362 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001363
Eric Andersen3b1a7442003-12-24 20:30:45 +00001364 case R_PPC_ADDR16_LO:
1365 *(unsigned short *)loc = v;
1366 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001367
Eric Andersen3b1a7442003-12-24 20:30:45 +00001368 case R_PPC_REL24:
1369 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001370
Eric Andersen3b1a7442003-12-24 20:30:45 +00001371 case R_PPC_REL32:
1372 *loc = v - dot;
1373 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001374
Eric Andersen3b1a7442003-12-24 20:30:45 +00001375 case R_PPC_ADDR32:
1376 *loc = v;
1377 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001378
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001379#elif defined(__s390__)
1380
1381 case R_390_32:
1382 *(unsigned int *) loc += v;
1383 break;
1384 case R_390_16:
1385 *(unsigned short *) loc += v;
1386 break;
1387 case R_390_8:
1388 *(unsigned char *) loc += v;
1389 break;
1390
1391 case R_390_PC32:
1392 *(unsigned int *) loc += v - dot;
1393 break;
1394 case R_390_PC16DBL:
1395 *(unsigned short *) loc += (v - dot) >> 1;
1396 break;
1397 case R_390_PC16:
1398 *(unsigned short *) loc += v - dot;
1399 break;
1400
1401 case R_390_PLT32:
1402 case R_390_PLT16DBL:
1403 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001404 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001405 if (pe->inited == 0) {
1406 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1407 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1408 ip[1] = 0x100607f1;
1409 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1410 ip[2] = v - 2;
1411 else
1412 ip[2] = v;
1413 pe->inited = 1;
1414 }
1415
1416 /* Insert relative distance to target. */
1417 v = plt + pe->offset - dot;
1418 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1419 *(unsigned int *) loc = (unsigned int) v;
1420 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1421 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1422 break;
1423
1424 case R_390_GLOB_DAT:
1425 case R_390_JMP_SLOT:
1426 *loc = v;
1427 break;
1428
1429 case R_390_RELATIVE:
1430 *loc += f->baseaddr;
1431 break;
1432
1433 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001434 *(unsigned long *) loc += got - dot;
1435 break;
1436
1437 case R_390_GOT12:
1438 case R_390_GOT16:
1439 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001440 if (!isym->gotent.inited)
1441 {
1442 isym->gotent.inited = 1;
1443 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1444 }
1445 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1446 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1447 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1448 *(unsigned short *) loc += isym->gotent.offset;
1449 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1450 *(unsigned int *) loc += isym->gotent.offset;
1451 break;
1452
1453# ifndef R_390_GOTOFF32
1454# define R_390_GOTOFF32 R_390_GOTOFF
1455# endif
1456 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001457 *loc += v - got;
1458 break;
1459
Eric Andersencffd5022002-05-24 06:50:15 +00001460#elif defined(__sh__)
1461
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 case R_SH_NONE:
1463 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001464
Eric Andersen3b1a7442003-12-24 20:30:45 +00001465 case R_SH_DIR32:
1466 *loc += v;
1467 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001468
Eric Andersen3b1a7442003-12-24 20:30:45 +00001469 case R_SH_REL32:
1470 *loc += v - dot;
1471 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001472
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 case R_SH_PLT32:
1474 *loc = v - dot;
1475 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001476
Eric Andersen3b1a7442003-12-24 20:30:45 +00001477 case R_SH_GLOB_DAT:
1478 case R_SH_JMP_SLOT:
1479 *loc = v;
1480 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001481
Eric Andersen3b1a7442003-12-24 20:30:45 +00001482 case R_SH_RELATIVE:
1483 *loc = f->baseaddr + rel->r_addend;
1484 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001485
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001487 *loc = got - dot + rel->r_addend;
1488 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 case R_SH_GOT32:
1491 goto bb_use_got;
1492
1493 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001494 *loc = v - got;
1495 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001496
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001497# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001498 case R_SH_IMM_MEDLOW16:
1499 case R_SH_IMM_LOW16:
1500 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001501 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001502
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001503 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001504 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001505
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 /*
1507 * movi and shori have the format:
1508 *
1509 * | op | imm | reg | reserved |
1510 * 31..26 25..10 9.. 4 3 .. 0
1511 *
1512 * so we simply mask and or in imm.
1513 */
1514 word = *loc & ~0x3fffc00;
1515 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001516
Eric Andersen3b1a7442003-12-24 20:30:45 +00001517 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001518
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 break;
1520 }
Eric Andersenbf833552003-08-13 19:56:33 +00001521
Eric Andersen3b1a7442003-12-24 20:30:45 +00001522 case R_SH_IMM_MEDLOW16_PCREL:
1523 case R_SH_IMM_LOW16_PCREL:
1524 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001525 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001526
Eric Andersen3b1a7442003-12-24 20:30:45 +00001527 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001528
Eric Andersen3b1a7442003-12-24 20:30:45 +00001529 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001530
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001531 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001532 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001533
Eric Andersen3b1a7442003-12-24 20:30:45 +00001534 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001535
Eric Andersen3b1a7442003-12-24 20:30:45 +00001536 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001537
Eric Andersen3b1a7442003-12-24 20:30:45 +00001538 break;
1539 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001540# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001541
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001542#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001543
Eric Andersen3b1a7442003-12-24 20:30:45 +00001544 case R_V850_NONE:
1545 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001546
Eric Andersen3b1a7442003-12-24 20:30:45 +00001547 case R_V850_32:
1548 /* We write two shorts instead of a long because even
1549 32-bit insns only need half-word alignment, but
1550 32-bit data needs to be long-word aligned. */
1551 v += ((unsigned short *)loc)[0];
1552 v += ((unsigned short *)loc)[1] << 16;
1553 ((unsigned short *)loc)[0] = v & 0xffff;
1554 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1555 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001556
Eric Andersen3b1a7442003-12-24 20:30:45 +00001557 case R_V850_22_PCREL:
1558 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001559
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001560#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001561
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001562 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001563 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001564
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001565 case R_X86_64_64:
1566 *loc += v;
1567 break;
1568
1569 case R_X86_64_32:
1570 *(unsigned int *) loc += v;
1571 if (v > 0xffffffff)
1572 {
1573 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1574 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1575 }
1576 break;
1577
1578 case R_X86_64_32S:
1579 *(signed int *) loc += v;
1580 break;
1581
1582 case R_X86_64_16:
1583 *(unsigned short *) loc += v;
1584 break;
1585
1586 case R_X86_64_8:
1587 *(unsigned char *) loc += v;
1588 break;
1589
1590 case R_X86_64_PC32:
1591 *(unsigned int *) loc += v - dot;
1592 break;
1593
1594 case R_X86_64_PC16:
1595 *(unsigned short *) loc += v - dot;
1596 break;
1597
1598 case R_X86_64_PC8:
1599 *(unsigned char *) loc += v - dot;
1600 break;
1601
1602 case R_X86_64_GLOB_DAT:
1603 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001604 *loc = v;
1605 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001606
1607 case R_X86_64_RELATIVE:
1608 *loc += f->baseaddr;
1609 break;
1610
1611 case R_X86_64_GOT32:
1612 case R_X86_64_GOTPCREL:
1613 goto bb_use_got;
1614# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001615 if (!isym->gotent.reloc_done)
1616 {
1617 isym->gotent.reloc_done = 1;
1618 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1619 }
1620 /* XXX are these really correct? */
1621 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1622 *(unsigned int *) loc += v + isym->gotent.offset;
1623 else
1624 *loc += isym->gotent.offset;
1625 break;
1626# endif
1627
Mike Frysingerf982d862006-01-04 00:11:26 +00001628#else
1629# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001630#endif
1631
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001632 default:
1633 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1634 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001635 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001636
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001637#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001638
Eric Andersen3b1a7442003-12-24 20:30:45 +00001639bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001640
Eric Andersen3b1a7442003-12-24 20:30:45 +00001641 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001642
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001643#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1645 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001646#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001648#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001649
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 if (! pe->inited) {
1651 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001652
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001654
1655#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001656 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1657 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001658#endif
1659#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001660 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001661 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001662 ip[2] = 0x7d6903a6; /* mtctr r11 */
1663 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001664#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001665#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001666 /* We have to trash a register, so we assume that any control
1667 transfer more than 21-bits away must be a function call
1668 (so we can use a call-clobbered register). */
1669 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1670 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001671#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001672 pe->inited = 1;
1673 }
Eric Andersen21adca72000-12-06 18:18:26 +00001674
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 /* relative distance to target */
1676 v -= dot;
1677 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001678#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001679 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001680#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001681 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001682#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001683 /* go via the plt */
1684 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001685
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001686#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001687 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001688#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001689 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001690#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001691 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001692
Eric Andersen3b1a7442003-12-24 20:30:45 +00001693 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001694#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001695 /* Convert to words. */
1696 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001697
Eric Andersen3b1a7442003-12-24 20:30:45 +00001698 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001699#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001700#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001701 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001702#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001703#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001704 /* We write two shorts instead of a long because even 32-bit insns
1705 only need half-word alignment, but the 32-bit data write needs
1706 to be long-word aligned. */
1707 ((unsigned short *)loc)[0] =
1708 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1709 | ((v >> 16) & 0x3f); /* offs high part */
1710 ((unsigned short *)loc)[1] =
1711 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001712#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001713 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001714#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001715
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001716#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001717bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001718
Eric Andersen3b1a7442003-12-24 20:30:45 +00001719 /* needs an entry in the .got: set it, once */
1720 if (!isym->gotent.inited) {
1721 isym->gotent.inited = 1;
1722 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1723 }
1724 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001725#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001726 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001727#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001728 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001729#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001730 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001731
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001732#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001733 }
1734
1735 return ret;
1736}
1737
Eric Andersencffd5022002-05-24 06:50:15 +00001738
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001739#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001740
1741static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1742 int offset, int size)
1743{
1744 struct arch_list_entry *pe;
1745
1746 for (pe = *list; pe != NULL; pe = pe->next) {
1747 if (pe->addend == rel->r_addend) {
1748 break;
1749 }
1750 }
1751
1752 if (pe == NULL) {
1753 pe = xmalloc(sizeof(struct arch_list_entry));
1754 pe->next = *list;
1755 pe->addend = rel->r_addend;
1756 pe->offset = offset;
1757 pe->inited = 0;
1758 *list = pe;
1759 return size;
1760 }
1761 return 0;
1762}
1763
1764#endif
1765
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001766#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001767
1768static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1769 int offset, int size)
1770{
1771 if (single->allocated == 0) {
1772 single->allocated = 1;
1773 single->offset = offset;
1774 single->inited = 0;
1775 return size;
1776 }
1777 return 0;
1778}
1779
1780#endif
1781
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001782#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001783
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001784static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001785 int offset, int size)
1786{
1787 struct obj_section *myrelsec = obj_find_section(f, name);
1788
1789 if (offset == 0) {
1790 offset += size;
1791 }
1792
1793 if (myrelsec) {
1794 obj_extend_section(myrelsec, offset);
1795 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001796 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001797 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001798 }
1799
1800 return myrelsec;
1801}
1802
1803#endif
1804
1805static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001806{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001807#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001808 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001809 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001810#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001811 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001812#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001813#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001814 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001815#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001816 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001817 ElfW(RelM) *rel, *relend;
1818 ElfW(Sym) *symtab, *extsym;
1819 const char *strtab, *name;
1820 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001821
Eric Andersen21adca72000-12-06 18:18:26 +00001822 for (i = 0; i < f->header.e_shnum; ++i) {
1823 relsec = f->sections[i];
1824 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001825 continue;
1826
Eric Andersen21adca72000-12-06 18:18:26 +00001827 symsec = f->sections[relsec->header.sh_link];
1828 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001829
Eric Andersen21adca72000-12-06 18:18:26 +00001830 rel = (ElfW(RelM) *) relsec->contents;
1831 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1832 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001833 strtab = (const char *) strsec->contents;
1834
1835 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001836 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001837
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001838#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001839 got_allocate = 0;
1840#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001841#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001842 plt_allocate = 0;
1843#endif
1844
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001845 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001846#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001847 case R_ARM_PC24:
1848 case R_ARM_PLT32:
1849 plt_allocate = 1;
1850 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001851
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001852 case R_ARM_GOTOFF:
1853 case R_ARM_GOTPC:
1854 got_needed = 1;
1855 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001856
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001857 case R_ARM_GOT32:
1858 got_allocate = 1;
1859 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001860
Eric Andersen21adca72000-12-06 18:18:26 +00001861#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001862 case R_386_GOTPC:
1863 case R_386_GOTOFF:
1864 got_needed = 1;
1865 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001866
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001867 case R_386_GOT32:
1868 got_allocate = 1;
1869 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001870
1871#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001872 case R_PPC_REL24:
1873 plt_allocate = 1;
1874 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001875
1876#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001877 case R_68K_GOT32:
1878 got_allocate = 1;
1879 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001880
Eric Andersen16451a02004-03-19 12:16:18 +00001881#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001882 case R_68K_GOTOFF:
1883 got_needed = 1;
1884 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001885#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001886
1887#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001888 case R_SH_GOT32:
1889 got_allocate = 1;
1890 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001891
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001892 case R_SH_GOTPC:
1893 case R_SH_GOTOFF:
1894 got_needed = 1;
1895 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001896
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001897#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001898 case R_V850_22_PCREL:
1899 plt_needed = 1;
1900 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001901
1902#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001903 default:
1904 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001905 }
1906
Eric Andersen21adca72000-12-06 18:18:26 +00001907 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001908 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001909 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001910 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001911 }
1912 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001913#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001914 if (got_allocate) {
1915 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001916 rel, &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001917 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001918
1919 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001920 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001921#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001922#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001923 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001924#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001925 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001926 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001927 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001928#else
1929 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001930 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001931 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001932#endif
1933 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001934 }
1935#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001936 }
Miles Baderae28b042002-04-01 09:34:25 +00001937 }
Eric Andersen21adca72000-12-06 18:18:26 +00001938
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001939#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001940 if (got_needed) {
1941 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001942 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001943 }
Eric Andersen21adca72000-12-06 18:18:26 +00001944#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001945
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001946#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001947 if (plt_needed) {
1948 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001949 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001950 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001951#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001952
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001953#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001954}
1955
Eric Andersen9f16d612000-06-12 23:11:16 +00001956/*======================================================================*/
1957
1958/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001959static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001960{
1961 unsigned long h = 0;
1962 unsigned long g;
1963 unsigned char ch;
1964
1965 while (n > 0) {
1966 ch = *name++;
1967 h = (h << 4) + ch;
1968 if ((g = (h & 0xf0000000)) != 0) {
1969 h ^= g >> 24;
1970 h &= ~g;
1971 }
1972 n--;
1973 }
1974 return h;
1975}
1976
Eric Andersen044228d2001-07-17 01:12:36 +00001977static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001978{
1979 return obj_elf_hash_n(name, strlen(name));
1980}
1981
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001982#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001983/* String comparison for non-co-versioned kernel and module. */
1984
1985static int ncv_strcmp(const char *a, const char *b)
1986{
1987 size_t alen = strlen(a), blen = strlen(b);
1988
1989 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1990 return strncmp(a, b, alen);
1991 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1992 return strncmp(a, b, blen);
1993 else
1994 return strcmp(a, b);
1995}
1996
1997/* String hashing for non-co-versioned kernel and module. Here
1998 we are simply forced to drop the crc from the hash. */
1999
2000static unsigned long ncv_symbol_hash(const char *str)
2001{
2002 size_t len = strlen(str);
2003 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2004 len -= 10;
2005 return obj_elf_hash_n(str, len);
2006}
2007
Eric Andersen044228d2001-07-17 01:12:36 +00002008static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002009obj_set_symbol_compare(struct obj_file *f,
2010 int (*cmp) (const char *, const char *),
2011 unsigned long (*hash) (const char *))
2012{
2013 if (cmp)
2014 f->symbol_cmp = cmp;
2015 if (hash) {
2016 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2017 int i;
2018
2019 f->symbol_hash = hash;
2020
2021 memcpy(tmptab, f->symtab, sizeof(tmptab));
2022 memset(f->symtab, 0, sizeof(f->symtab));
2023
2024 for (i = 0; i < HASH_BUCKETS; ++i)
2025 for (sym = tmptab[i]; sym; sym = next) {
2026 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2027 next = sym->next;
2028 sym->next = f->symtab[h];
2029 f->symtab[h] = sym;
2030 }
2031 }
2032}
2033
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002034#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002035
Eric Andersen044228d2001-07-17 01:12:36 +00002036static struct obj_symbol *
2037obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002038 unsigned long symidx, int info,
2039 int secidx, ElfW(Addr) value,
2040 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002041{
2042 struct obj_symbol *sym;
2043 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002044 int n_type = ELF_ST_TYPE(info);
2045 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002046
2047 for (sym = f->symtab[hash]; sym; sym = sym->next)
2048 if (f->symbol_cmp(sym->name, name) == 0) {
2049 int o_secidx = sym->secidx;
2050 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002051 int o_type = ELF_ST_TYPE(o_info);
2052 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002053
2054 /* A redefinition! Is it legal? */
2055
2056 if (secidx == SHN_UNDEF)
2057 return sym;
2058 else if (o_secidx == SHN_UNDEF)
2059 goto found;
2060 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2061 /* Cope with local and global symbols of the same name
2062 in the same object file, as might have been created
2063 by ld -r. The only reason locals are now seen at this
2064 level at all is so that we can do semi-sensible things
2065 with parameters. */
2066
2067 struct obj_symbol *nsym, **p;
2068
2069 nsym = arch_new_symbol();
2070 nsym->next = sym->next;
2071 nsym->ksymidx = -1;
2072
2073 /* Excise the old (local) symbol from the hash chain. */
2074 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2075 continue;
2076 *p = sym = nsym;
2077 goto found;
2078 } else if (n_binding == STB_LOCAL) {
2079 /* Another symbol of the same name has already been defined.
2080 Just add this to the local table. */
2081 sym = arch_new_symbol();
2082 sym->next = NULL;
2083 sym->ksymidx = -1;
2084 f->local_symtab[symidx] = sym;
2085 goto found;
2086 } else if (n_binding == STB_WEAK)
2087 return sym;
2088 else if (o_binding == STB_WEAK)
2089 goto found;
2090 /* Don't unify COMMON symbols with object types the programmer
2091 doesn't expect. */
2092 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002093 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002094 return sym;
2095 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002096 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002097 goto found;
2098 else {
2099 /* Don't report an error if the symbol is coming from
2100 the kernel or some external module. */
2101 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002102 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002103 return sym;
2104 }
2105 }
2106
2107 /* Completely new symbol. */
2108 sym = arch_new_symbol();
2109 sym->next = f->symtab[hash];
2110 f->symtab[hash] = sym;
2111 sym->ksymidx = -1;
2112
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002113 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002114 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002115 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002116 name, (long) symidx, (long) f->local_symtab_size);
2117 else
2118 f->local_symtab[symidx] = sym;
2119 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002120
Eric Andersen3b1a7442003-12-24 20:30:45 +00002121found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002122 sym->name = name;
2123 sym->value = value;
2124 sym->size = size;
2125 sym->secidx = secidx;
2126 sym->info = info;
2127
2128 return sym;
2129}
2130
Eric Andersen044228d2001-07-17 01:12:36 +00002131static struct obj_symbol *
2132obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002133{
2134 struct obj_symbol *sym;
2135 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2136
2137 for (sym = f->symtab[hash]; sym; sym = sym->next)
2138 if (f->symbol_cmp(sym->name, name) == 0)
2139 return sym;
2140
2141 return NULL;
2142}
2143
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002144static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002145{
2146 if (sym) {
2147 if (sym->secidx >= SHN_LORESERVE)
2148 return sym->value;
2149
2150 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2151 } else {
2152 /* As a special case, a NULL sym has value zero. */
2153 return 0;
2154 }
2155}
2156
Eric Andersen044228d2001-07-17 01:12:36 +00002157static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002158{
2159 int i, n = f->header.e_shnum;
2160
2161 for (i = 0; i < n; ++i)
2162 if (strcmp(f->sections[i]->name, name) == 0)
2163 return f->sections[i];
2164
2165 return NULL;
2166}
2167
2168static int obj_load_order_prio(struct obj_section *a)
2169{
2170 unsigned long af, ac;
2171
2172 af = a->header.sh_flags;
2173
2174 ac = 0;
2175 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002176 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002177 ac |= 32;
2178 if (af & SHF_ALLOC)
2179 ac |= 16;
2180 if (!(af & SHF_WRITE))
2181 ac |= 8;
2182 if (af & SHF_EXECINSTR)
2183 ac |= 4;
2184 if (a->header.sh_type != SHT_NOBITS)
2185 ac |= 2;
2186
2187 return ac;
2188}
2189
Eric Andersen044228d2001-07-17 01:12:36 +00002190static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002191obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2192{
2193 struct obj_section **p;
2194 int prio = obj_load_order_prio(sec);
2195 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2196 if (obj_load_order_prio(*p) < prio)
2197 break;
2198 sec->load_next = *p;
2199 *p = sec;
2200}
2201
Eric Andersen044228d2001-07-17 01:12:36 +00002202static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002203 const char *name,
2204 unsigned long align,
2205 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002206{
2207 int newidx = f->header.e_shnum++;
2208 struct obj_section *sec;
2209
2210 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2211 f->sections[newidx] = sec = arch_new_section();
2212
2213 memset(sec, 0, sizeof(*sec));
2214 sec->header.sh_type = SHT_PROGBITS;
2215 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2216 sec->header.sh_size = size;
2217 sec->header.sh_addralign = align;
2218 sec->name = name;
2219 sec->idx = newidx;
2220 if (size)
2221 sec->contents = xmalloc(size);
2222
2223 obj_insert_section_load_order(f, sec);
2224
2225 return sec;
2226}
2227
Eric Andersen044228d2001-07-17 01:12:36 +00002228static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002229 const char *name,
2230 unsigned long align,
2231 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002232{
2233 int newidx = f->header.e_shnum++;
2234 struct obj_section *sec;
2235
2236 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2237 f->sections[newidx] = sec = arch_new_section();
2238
2239 memset(sec, 0, sizeof(*sec));
2240 sec->header.sh_type = SHT_PROGBITS;
2241 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2242 sec->header.sh_size = size;
2243 sec->header.sh_addralign = align;
2244 sec->name = name;
2245 sec->idx = newidx;
2246 if (size)
2247 sec->contents = xmalloc(size);
2248
2249 sec->load_next = f->load_order;
2250 f->load_order = sec;
2251 if (f->load_order_search_start == &f->load_order)
2252 f->load_order_search_start = &sec->load_next;
2253
2254 return sec;
2255}
2256
Eric Andersen044228d2001-07-17 01:12:36 +00002257static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002258{
2259 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002260 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002261 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2262 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002263 return sec->contents + oldsize;
2264}
2265
2266
Eric Andersen9f16d612000-06-12 23:11:16 +00002267/* Conditionally add the symbols from the given symbol set to the
2268 new module. */
2269
2270static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002271add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002272 int idx, struct new_module_symbol *syms, size_t nsyms)
2273{
2274 struct new_module_symbol *s;
2275 size_t i;
2276 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002277#ifdef SYMBOL_PREFIX
2278 char *name_buf = 0;
2279 size_t name_alloced_size = 0;
2280#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002281#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002282 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002283
Glenn L McGrath759515c2003-08-30 06:00:33 +00002284 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002285#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002286 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002287 /* Only add symbols that are already marked external.
2288 If we override locals we may cause problems for
2289 argument initialization. We will also create a false
2290 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002291 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002292 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002293
Glenn L McGrath759515c2003-08-30 06:00:33 +00002294 /* GPL licensed modules can use symbols exported with
2295 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2296 * exported names. Non-GPL modules never see any GPLONLY_
2297 * symbols so they cannot fudge it by adding the prefix on
2298 * their references.
2299 */
2300 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002301#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002302 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002303 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002304 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002305#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002306 continue;
2307 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002308 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002309
Miles Baderae28b042002-04-01 09:34:25 +00002310#ifdef SYMBOL_PREFIX
2311 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2312 kernel exports `C names', but module object files
2313 reference `linker names'). */
2314 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002315 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002316 if (name_size > name_alloced_size) {
2317 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002318 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002319 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002320 strcpy(name_buf, SYMBOL_PREFIX);
2321 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002322 name = name_buf;
2323#endif /* SYMBOL_PREFIX */
2324
2325 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002326 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002327#ifdef SYMBOL_PREFIX
2328 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002329 name = xmalloc(name_size);
2330 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002331#endif
2332 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002333 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002334 STT_NOTYPE),
2335 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002336 /* Did our symbol just get installed? If so, mark the
2337 module as "used". */
2338 if (sym->secidx == idx)
2339 used = 1;
2340 }
2341 }
2342
2343 return used;
2344}
2345
2346static void add_kernel_symbols(struct obj_file *f)
2347{
2348 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002349 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002350
2351 /* Add module symbols first. */
2352
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002353 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002354 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002355 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2356 ) {
2357 m->used = 1;
2358 ++nused;
2359 }
2360 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002361
2362 n_ext_modules_used = nused;
2363
2364 /* And finally the symbols from the kernel proper. */
2365
2366 if (nksyms)
2367 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2368}
2369
2370static char *get_modinfo_value(struct obj_file *f, const char *key)
2371{
2372 struct obj_section *sec;
2373 char *p, *v, *n, *ep;
2374 size_t klen = strlen(key);
2375
2376 sec = obj_find_section(f, ".modinfo");
2377 if (sec == NULL)
2378 return NULL;
2379 p = sec->contents;
2380 ep = p + sec->header.sh_size;
2381 while (p < ep) {
2382 v = strchr(p, '=');
2383 n = strchr(p, '\0');
2384 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002385 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002386 return v + 1;
2387 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002388 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002389 return n;
2390 }
2391 p = n + 1;
2392 }
2393
2394 return NULL;
2395}
2396
2397
2398/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002399/* Functions relating to module loading after 2.1.18. */
2400
2401static int
2402new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2403{
2404 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002405 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002406 struct obj_symbol *sym;
2407 char *contents, *loc;
2408 int min, max, n;
2409
2410 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002411 if ((q = strchr(p, '=')) == NULL) {
2412 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002413 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002414 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002415
2416 key = alloca(q - p + 6);
2417 memcpy(key, "parm_", 5);
2418 memcpy(key + 5, p, q - p);
2419 key[q - p + 5] = 0;
2420
2421 p = get_modinfo_value(f, key);
2422 key += 5;
2423 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002424 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002425 return 0;
2426 }
2427
Miles Baderae28b042002-04-01 09:34:25 +00002428#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002429 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2430 strcpy(sym_name, SYMBOL_PREFIX);
2431 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002432#else
2433 sym_name = key;
2434#endif
2435 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002436
2437 /* Also check that the parameter was not resolved from the kernel. */
2438 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002439 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002440 return 0;
2441 }
2442
2443 if (isdigit(*p)) {
2444 min = strtoul(p, &p, 10);
2445 if (*p == '-')
2446 max = strtoul(p + 1, &p, 10);
2447 else
2448 max = min;
2449 } else
2450 min = max = 1;
2451
2452 contents = f->sections[sym->secidx]->contents;
2453 loc = contents + sym->value;
2454 n = (*++q != '\0');
2455
2456 while (1) {
2457 if ((*p == 's') || (*p == 'c')) {
2458 char *str;
2459
2460 /* Do C quoting if we begin with a ", else slurp the lot. */
2461 if (*q == '"') {
2462 char *r;
2463
2464 str = alloca(strlen(q));
2465 for (r = str, q++; *q != '"'; ++q, ++r) {
2466 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002467 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002468 key);
2469 return 0;
2470 } else if (*q == '\\')
2471 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002472 case 'a':
2473 *r = '\a';
2474 break;
2475 case 'b':
2476 *r = '\b';
2477 break;
2478 case 'e':
2479 *r = '\033';
2480 break;
2481 case 'f':
2482 *r = '\f';
2483 break;
2484 case 'n':
2485 *r = '\n';
2486 break;
2487 case 'r':
2488 *r = '\r';
2489 break;
2490 case 't':
2491 *r = '\t';
2492 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002493
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002494 case '0':
2495 case '1':
2496 case '2':
2497 case '3':
2498 case '4':
2499 case '5':
2500 case '6':
2501 case '7':
2502 {
2503 int c = *q - '0';
2504 if (q[1] >= '0' && q[1] <= '7') {
2505 c = (c * 8) + *++q - '0';
2506 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002507 c = (c * 8) + *++q - '0';
2508 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002509 *r = c;
2510 }
2511 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002512
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002513 default:
2514 *r = *q;
2515 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002516 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002517 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002518 }
2519 *r = '\0';
2520 ++q;
2521 } else {
2522 char *r;
2523
2524 /* In this case, the string is not quoted. We will break
2525 it using the coma (like for ints). If the user wants to
2526 include comas in a string, he just has to quote it */
2527
2528 /* Search the next coma */
2529 r = strchr(q, ',');
2530
2531 /* Found ? */
2532 if (r != (char *) NULL) {
2533 /* Recopy the current field */
2534 str = alloca(r - q + 1);
2535 memcpy(str, q, r - q);
2536
Eric Andersenaff114c2004-04-14 17:51:38 +00002537 /* I don't know if it is useful, as the previous case
2538 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002539 str[r - q] = '\0';
2540
2541 /* Keep next fields */
2542 q = r;
2543 } else {
2544 /* last string */
2545 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002546 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002547 }
2548 }
2549
2550 if (*p == 's') {
2551 /* Normal string */
2552 obj_string_patch(f, sym->secidx, loc - contents, str);
2553 loc += tgt_sizeof_char_p;
2554 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002555 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002556 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002557
2558 /* Get the size of each member */
2559 /* Probably we should do that outside the loop ? */
2560 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002561 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002562 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002563 return 0;
2564 }
2565 charssize = strtoul(p + 1, (char **) NULL, 10);
2566
2567 /* Check length */
2568 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002569 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002570 charssize - 1);
2571 return 0;
2572 }
2573
2574 /* Copy to location */
2575 strcpy((char *) loc, str);
2576 loc += charssize;
2577 }
2578 } else {
2579 long v = strtoul(q, &q, 0);
2580 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002581 case 'b':
2582 *loc++ = v;
2583 break;
2584 case 'h':
2585 *(short *) loc = v;
2586 loc += tgt_sizeof_short;
2587 break;
2588 case 'i':
2589 *(int *) loc = v;
2590 loc += tgt_sizeof_int;
2591 break;
2592 case 'l':
2593 *(long *) loc = v;
2594 loc += tgt_sizeof_long;
2595 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002596
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002597 default:
2598 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2599 return 0;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002600 }
2601 }
2602
2603retry_end_of_value:
2604 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002605 case '\0':
2606 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002607
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002608 case ' ':
2609 case '\t':
2610 case '\n':
2611 case '\r':
2612 ++q;
2613 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002614
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002615 case ',':
2616 if (++n > max) {
2617 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002618 return 0;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002619 }
2620 ++q;
2621 break;
2622
2623 default:
2624 bb_error_msg("invalid argument syntax for %s", key);
2625 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002626 }
2627 }
2628
Eric Andersen3b1a7442003-12-24 20:30:45 +00002629end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002630 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002631 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002632 return 0;
2633 }
2634
2635 argc--, argv++;
2636 }
2637
2638 return 1;
2639}
2640
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002641#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002642static int new_is_module_checksummed(struct obj_file *f)
2643{
2644 const char *p = get_modinfo_value(f, "using_checksums");
2645 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002646 return xatoi(p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002647 else
2648 return 0;
2649}
2650
2651/* Get the module's kernel version in the canonical integer form. */
2652
2653static int
2654new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2655{
2656 char *p, *q;
2657 int a, b, c;
2658
2659 p = get_modinfo_value(f, "kernel_version");
2660 if (p == NULL)
2661 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002662 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002663
2664 a = strtoul(p, &p, 10);
2665 if (*p != '.')
2666 return -1;
2667 b = strtoul(p + 1, &p, 10);
2668 if (*p != '.')
2669 return -1;
2670 c = strtoul(p + 1, &q, 10);
2671 if (p + 1 == q)
2672 return -1;
2673
2674 return a << 16 | b << 8 | c;
2675}
2676
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002677#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002678
2679
Eric Andersen9f16d612000-06-12 23:11:16 +00002680/* Fetch the loaded modules, and all currently exported symbols. */
2681
2682static int new_get_kernel_symbols(void)
2683{
2684 char *module_names, *mn;
2685 struct external_module *modules, *m;
2686 struct new_module_symbol *syms, *s;
2687 size_t ret, bufsize, nmod, nsyms, i, j;
2688
2689 /* Collect the loaded modules. */
2690
2691 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002692retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002693 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002694 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002695 module_names = xrealloc(module_names, bufsize = ret);
2696 goto retry_modules_load;
2697 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002698 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002699 return 0;
2700 }
2701
2702 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002703
2704 /* Collect the modules' symbols. */
2705
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002706 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002707 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2708 memset(modules, 0, nmod * sizeof(*modules));
2709 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002710 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002711 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002712
Mark Whitley94fd4802001-03-12 23:08:34 +00002713 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2714 if (errno == ENOENT) {
2715 /* The module was removed out from underneath us. */
2716 continue;
2717 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002718 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002719 return 0;
2720 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002721
Mark Whitley94fd4802001-03-12 23:08:34 +00002722 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002723retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002724 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2725 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002726 case ENOSPC:
2727 syms = xrealloc(syms, bufsize = ret);
2728 goto retry_mod_sym_load;
2729 case ENOENT:
2730 /* The module was removed out from underneath us. */
2731 continue;
2732 default:
2733 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2734 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002735 }
2736 }
2737 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002738
Mark Whitley94fd4802001-03-12 23:08:34 +00002739 m->name = mn;
2740 m->addr = info.addr;
2741 m->nsyms = nsyms;
2742 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002743
Mark Whitley94fd4802001-03-12 23:08:34 +00002744 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2745 s->name += (unsigned long) syms;
2746 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002747 }
2748 }
2749
2750 /* Collect the kernel's symbols. */
2751
2752 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002753retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002754 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002755 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002756 syms = xrealloc(syms, bufsize = ret);
2757 goto retry_kern_sym_load;
2758 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002759 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002760 return 0;
2761 }
2762 nksyms = nsyms = ret;
2763 ksyms = syms;
2764
2765 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2766 s->name += (unsigned long) syms;
2767 }
2768 return 1;
2769}
2770
2771
2772/* Return the kernel symbol checksum version, or zero if not used. */
2773
2774static int new_is_kernel_checksummed(void)
2775{
2776 struct new_module_symbol *s;
2777 size_t i;
2778
2779 /* Using_Versions is not the first symbol, but it should be in there. */
2780
2781 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2782 if (strcmp((char *) s->name, "Using_Versions") == 0)
2783 return s->value;
2784
2785 return 0;
2786}
2787
2788
2789static int new_create_this_module(struct obj_file *f, const char *m_name)
2790{
2791 struct obj_section *sec;
2792
2793 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002794 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002795 memset(sec->contents, 0, sizeof(struct new_module));
2796
Miles Baderae28b042002-04-01 09:34:25 +00002797 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002798 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002799 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002800
2801 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002802 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002803
2804 return 1;
2805}
2806
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002807#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002808/* add an entry to the __ksymtab section, creating it if necessary */
2809static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2810{
2811 struct obj_section *sec;
2812 ElfW(Addr) ofs;
2813
2814 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2815 * If __ksymtab is defined but not marked alloc, x out the first character
2816 * (no obj_delete routine) and create a new __ksymtab with the correct
2817 * characteristics.
2818 */
2819 sec = obj_find_section(f, "__ksymtab");
2820 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2821 *((char *)(sec->name)) = 'x'; /* override const */
2822 sec = NULL;
2823 }
2824 if (!sec)
2825 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002826 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002827 if (!sec)
2828 return;
2829 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002830 /* Empty section might be byte-aligned */
2831 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002832 ofs = sec->header.sh_size;
2833 obj_symbol_patch(f, sec->idx, ofs, sym);
2834 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2835 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2836}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002837#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002838
2839static int new_create_module_ksymtab(struct obj_file *f)
2840{
2841 struct obj_section *sec;
2842 int i;
2843
2844 /* We must always add the module references. */
2845
2846 if (n_ext_modules_used) {
2847 struct new_module_ref *dep;
2848 struct obj_symbol *tm;
2849
2850 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002851 (sizeof(struct new_module_ref)
2852 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002853 if (!sec)
2854 return 0;
2855
Miles Baderae28b042002-04-01 09:34:25 +00002856 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002857 dep = (struct new_module_ref *) sec->contents;
2858 for (i = 0; i < n_ext_modules; ++i)
2859 if (ext_modules[i].used) {
2860 dep->dep = ext_modules[i].addr;
2861 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002862 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002863 dep->next_ref = 0;
2864 ++dep;
2865 }
2866 }
2867
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002868 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002869 size_t nsyms;
2870 int *loaded;
2871
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002872 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002873
2874 /* We don't want to export symbols residing in sections that
2875 aren't loaded. There are a number of these created so that
2876 we make sure certain module options don't appear twice. */
2877
2878 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2879 while (--i >= 0)
2880 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2881
2882 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2883 struct obj_symbol *sym;
2884 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002885 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002886 && sym->secidx <= SHN_HIRESERVE
2887 && (sym->secidx >= SHN_LORESERVE
2888 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002889 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2890
2891 obj_symbol_patch(f, sec->idx, ofs, sym);
2892 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002893 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002894
2895 nsyms++;
2896 }
2897 }
2898
2899 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2900 }
2901
2902 return 1;
2903}
2904
2905
2906static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002907new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002908{
2909 struct new_module *module;
2910 struct obj_section *sec;
2911 void *image;
2912 int ret;
2913 tgt_long m_addr;
2914
2915 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002916 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002917 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002918 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002919 module = (struct new_module *) sec->contents;
2920 m_addr = sec->header.sh_addr;
2921
2922 module->size_of_struct = sizeof(*module);
2923 module->size = m_size;
2924 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2925
2926 sec = obj_find_section(f, "__ksymtab");
2927 if (sec && sec->header.sh_size) {
2928 module->syms = sec->header.sh_addr;
2929 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2930 }
2931
2932 if (n_ext_modules_used) {
2933 sec = obj_find_section(f, ".kmodtab");
2934 module->deps = sec->header.sh_addr;
2935 module->ndeps = n_ext_modules_used;
2936 }
2937
2938 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002939 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002940 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002941 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002942
2943 sec = obj_find_section(f, "__ex_table");
2944 if (sec) {
2945 module->ex_table_start = sec->header.sh_addr;
2946 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2947 }
2948
2949 sec = obj_find_section(f, ".text.init");
2950 if (sec) {
2951 module->runsize = sec->header.sh_addr - m_addr;
2952 }
2953 sec = obj_find_section(f, ".data.init");
2954 if (sec) {
2955 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002956 module->runsize > sec->header.sh_addr - m_addr)
2957 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002959 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2960 if (sec && sec->header.sh_size) {
2961 module->archdata_start = (void*)sec->header.sh_addr;
2962 module->archdata_end = module->archdata_start + sec->header.sh_size;
2963 }
2964 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2965 if (sec && sec->header.sh_size) {
2966 module->kallsyms_start = (void*)sec->header.sh_addr;
2967 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2968 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002969
Eric Andersen9f16d612000-06-12 23:11:16 +00002970 /* Whew! All of the initialization is complete. Collect the final
2971 module image and give it to the kernel. */
2972
2973 image = xmalloc(m_size);
2974 obj_create_image(f, image);
2975
Eric Andersencb3b9b12004-06-22 11:50:52 +00002976 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002977 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002978 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002979
2980 free(image);
2981
2982 return ret == 0;
2983}
2984
Eric Andersen9f16d612000-06-12 23:11:16 +00002985
2986/*======================================================================*/
2987
Eric Andersen044228d2001-07-17 01:12:36 +00002988static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002989obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2990 const char *string)
2991{
2992 struct obj_string_patch *p;
2993 struct obj_section *strsec;
2994 size_t len = strlen(string) + 1;
2995 char *loc;
2996
2997 p = xmalloc(sizeof(*p));
2998 p->next = f->string_patches;
2999 p->reloc_secidx = secidx;
3000 p->reloc_offset = offset;
3001 f->string_patches = p;
3002
3003 strsec = obj_find_section(f, ".kstrtab");
3004 if (strsec == NULL) {
3005 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3006 p->string_offset = 0;
3007 loc = strsec->contents;
3008 } else {
3009 p->string_offset = strsec->header.sh_size;
3010 loc = obj_extend_section(strsec, len);
3011 }
3012 memcpy(loc, string, len);
3013
3014 return 1;
3015}
3016
Eric Andersen044228d2001-07-17 01:12:36 +00003017static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003018obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3019 struct obj_symbol *sym)
3020{
3021 struct obj_symbol_patch *p;
3022
3023 p = xmalloc(sizeof(*p));
3024 p->next = f->symbol_patches;
3025 p->reloc_secidx = secidx;
3026 p->reloc_offset = offset;
3027 p->sym = sym;
3028 f->symbol_patches = p;
3029
3030 return 1;
3031}
3032
Eric Andersen044228d2001-07-17 01:12:36 +00003033static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003034{
3035 unsigned long i;
3036 int ret = 1;
3037
3038 for (i = 0; i < HASH_BUCKETS; ++i) {
3039 struct obj_symbol *sym;
3040 for (sym = f->symtab[i]; sym; sym = sym->next)
3041 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003042 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003043 sym->secidx = SHN_ABS;
3044 sym->value = 0;
3045 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003046 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003047 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003048 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003049 ret = 0;
3050 }
3051 }
3052 }
3053
3054 return ret;
3055}
3056
Eric Andersen044228d2001-07-17 01:12:36 +00003057static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003058{
3059 struct common_entry {
3060 struct common_entry *next;
3061 struct obj_symbol *sym;
3062 } *common_head = NULL;
3063
3064 unsigned long i;
3065
3066 for (i = 0; i < HASH_BUCKETS; ++i) {
3067 struct obj_symbol *sym;
3068 for (sym = f->symtab[i]; sym; sym = sym->next)
3069 if (sym->secidx == SHN_COMMON) {
3070 /* Collect all COMMON symbols and sort them by size so as to
3071 minimize space wasted by alignment requirements. */
3072 {
3073 struct common_entry **p, *n;
3074 for (p = &common_head; *p; p = &(*p)->next)
3075 if (sym->size <= (*p)->sym->size)
3076 break;
3077
3078 n = alloca(sizeof(*n));
3079 n->next = *p;
3080 n->sym = sym;
3081 *p = n;
3082 }
3083 }
3084 }
3085
3086 for (i = 1; i < f->local_symtab_size; ++i) {
3087 struct obj_symbol *sym = f->local_symtab[i];
3088 if (sym && sym->secidx == SHN_COMMON) {
3089 struct common_entry **p, *n;
3090 for (p = &common_head; *p; p = &(*p)->next)
3091 if (sym == (*p)->sym)
3092 break;
3093 else if (sym->size < (*p)->sym->size) {
3094 n = alloca(sizeof(*n));
3095 n->next = *p;
3096 n->sym = sym;
3097 *p = n;
3098 break;
3099 }
3100 }
3101 }
3102
3103 if (common_head) {
3104 /* Find the bss section. */
3105 for (i = 0; i < f->header.e_shnum; ++i)
3106 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3107 break;
3108
3109 /* If for some reason there hadn't been one, create one. */
3110 if (i == f->header.e_shnum) {
3111 struct obj_section *sec;
3112
3113 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3114 f->sections[i] = sec = arch_new_section();
3115 f->header.e_shnum = i + 1;
3116
3117 memset(sec, 0, sizeof(*sec));
3118 sec->header.sh_type = SHT_PROGBITS;
3119 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3120 sec->name = ".bss";
3121 sec->idx = i;
3122 }
3123
3124 /* Allocate the COMMONS. */
3125 {
3126 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3127 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3128 struct common_entry *c;
3129
3130 for (c = common_head; c; c = c->next) {
3131 ElfW(Addr) align = c->sym->value;
3132
3133 if (align > max_align)
3134 max_align = align;
3135 if (bss_size & (align - 1))
3136 bss_size = (bss_size | (align - 1)) + 1;
3137
3138 c->sym->secidx = i;
3139 c->sym->value = bss_size;
3140
3141 bss_size += c->sym->size;
3142 }
3143
3144 f->sections[i]->header.sh_size = bss_size;
3145 f->sections[i]->header.sh_addralign = max_align;
3146 }
3147 }
3148
3149 /* For the sake of patch relocation and parameter initialization,
3150 allocate zeroed data for NOBITS sections now. Note that after
3151 this we cannot assume NOBITS are really empty. */
3152 for (i = 0; i < f->header.e_shnum; ++i) {
3153 struct obj_section *s = f->sections[i];
3154 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003155 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003156 s->contents = memset(xmalloc(s->header.sh_size),
3157 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003158 else
3159 s->contents = NULL;
3160
Eric Andersen9f16d612000-06-12 23:11:16 +00003161 s->header.sh_type = SHT_PROGBITS;
3162 }
3163 }
3164}
3165
Eric Andersen044228d2001-07-17 01:12:36 +00003166static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003167{
3168 unsigned long dot = 0;
3169 struct obj_section *sec;
3170
3171 /* Finalize the positions of the sections relative to one another. */
3172
3173 for (sec = f->load_order; sec; sec = sec->load_next) {
3174 ElfW(Addr) align;
3175
3176 align = sec->header.sh_addralign;
3177 if (align && (dot & (align - 1)))
3178 dot = (dot | (align - 1)) + 1;
3179
3180 sec->header.sh_addr = dot;
3181 dot += sec->header.sh_size;
3182 }
3183
3184 return dot;
3185}
3186
Eric Andersen044228d2001-07-17 01:12:36 +00003187static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003188{
3189 int i, n = f->header.e_shnum;
3190 int ret = 1;
3191
3192 /* Finalize the addresses of the sections. */
3193
3194 f->baseaddr = base;
3195 for (i = 0; i < n; ++i)
3196 f->sections[i]->header.sh_addr += base;
3197
3198 /* And iterate over all of the relocations. */
3199
3200 for (i = 0; i < n; ++i) {
3201 struct obj_section *relsec, *symsec, *targsec, *strsec;
3202 ElfW(RelM) * rel, *relend;
3203 ElfW(Sym) * symtab;
3204 const char *strtab;
3205
3206 relsec = f->sections[i];
3207 if (relsec->header.sh_type != SHT_RELM)
3208 continue;
3209
3210 symsec = f->sections[relsec->header.sh_link];
3211 targsec = f->sections[relsec->header.sh_info];
3212 strsec = f->sections[symsec->header.sh_link];
3213
3214 rel = (ElfW(RelM) *) relsec->contents;
3215 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3216 symtab = (ElfW(Sym) *) symsec->contents;
3217 strtab = (const char *) strsec->contents;
3218
3219 for (; rel < relend; ++rel) {
3220 ElfW(Addr) value = 0;
3221 struct obj_symbol *intsym = NULL;
3222 unsigned long symndx;
3223 ElfW(Sym) * extsym = 0;
3224 const char *errmsg;
3225
3226 /* Attempt to find a value to use for this relocation. */
3227
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003228 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003229 if (symndx) {
3230 /* Note we've already checked for undefined symbols. */
3231
3232 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003233 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003234 /* Local symbols we look up in the local table to be sure
3235 we get the one that is really intended. */
3236 intsym = f->local_symtab[symndx];
3237 } else {
3238 /* Others we look up in the hash table. */
3239 const char *name;
3240 if (extsym->st_name)
3241 name = strtab + extsym->st_name;
3242 else
3243 name = f->sections[extsym->st_shndx]->name;
3244 intsym = obj_find_symbol(f, name);
3245 }
3246
3247 value = obj_symbol_final_value(f, intsym);
3248 intsym->referenced = 1;
3249 }
3250#if SHT_RELM == SHT_RELA
3251#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3252 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3253 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003254 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003255#endif
3256 value += rel->r_addend;
3257#endif
3258
3259 /* Do it! */
3260 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003261 (f, targsec, symsec, intsym, rel, value)
3262 ) {
3263 case obj_reloc_ok:
3264 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003265
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003266 case obj_reloc_overflow:
3267 errmsg = "Relocation overflow";
3268 goto bad_reloc;
3269 case obj_reloc_dangerous:
3270 errmsg = "Dangerous relocation";
3271 goto bad_reloc;
3272 case obj_reloc_unhandled:
3273 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003274bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003275 if (extsym) {
3276 bb_error_msg("%s of type %ld for %s", errmsg,
3277 (long) ELF_R_TYPE(rel->r_info),
3278 strtab + extsym->st_name);
3279 } else {
3280 bb_error_msg("%s of type %ld", errmsg,
3281 (long) ELF_R_TYPE(rel->r_info));
3282 }
3283 ret = 0;
3284 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003285 }
3286 }
3287 }
3288
3289 /* Finally, take care of the patches. */
3290
3291 if (f->string_patches) {
3292 struct obj_string_patch *p;
3293 struct obj_section *strsec;
3294 ElfW(Addr) strsec_base;
3295 strsec = obj_find_section(f, ".kstrtab");
3296 strsec_base = strsec->header.sh_addr;
3297
3298 for (p = f->string_patches; p; p = p->next) {
3299 struct obj_section *targsec = f->sections[p->reloc_secidx];
3300 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3301 = strsec_base + p->string_offset;
3302 }
3303 }
3304
3305 if (f->symbol_patches) {
3306 struct obj_symbol_patch *p;
3307
3308 for (p = f->symbol_patches; p; p = p->next) {
3309 struct obj_section *targsec = f->sections[p->reloc_secidx];
3310 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3311 = obj_symbol_final_value(f, p->sym);
3312 }
3313 }
3314
3315 return ret;
3316}
3317
Eric Andersen044228d2001-07-17 01:12:36 +00003318static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003319{
3320 struct obj_section *sec;
3321 ElfW(Addr) base = f->baseaddr;
3322
3323 for (sec = f->load_order; sec; sec = sec->load_next) {
3324 char *secimg;
3325
Eric Andersen2bf658d2001-02-24 20:01:53 +00003326 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003327 continue;
3328
3329 secimg = image + (sec->header.sh_addr - base);
3330
3331 /* Note that we allocated data for NOBITS sections earlier. */
3332 memcpy(secimg, sec->contents, sec->header.sh_size);
3333 }
3334
3335 return 1;
3336}
3337
3338/*======================================================================*/
3339
Eric Andersen044228d2001-07-17 01:12:36 +00003340static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003341{
3342 struct obj_file *f;
3343 ElfW(Shdr) * section_headers;
3344 int shnum, i;
3345 char *shstrtab;
3346
3347 /* Read the file header. */
3348
3349 f = arch_new_file();
3350 memset(f, 0, sizeof(*f));
3351 f->symbol_cmp = strcmp;
3352 f->symbol_hash = obj_elf_hash;
3353 f->load_order_search_start = &f->load_order;
3354
3355 fseek(fp, 0, SEEK_SET);
3356 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003357 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003358 return NULL;
3359 }
3360
3361 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003362 || f->header.e_ident[EI_MAG1] != ELFMAG1
3363 || f->header.e_ident[EI_MAG2] != ELFMAG2
3364 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003365 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003366 return NULL;
3367 }
3368 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003369 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003370 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003371 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3372 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003373 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003374 return NULL;
3375 }
3376 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003377 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 return NULL;
3379 }
3380
3381 /* Read the section headers. */
3382
3383 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003384 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003385 (unsigned long) f->header.e_shentsize,
3386 (unsigned long) sizeof(ElfW(Shdr)));
3387 return NULL;
3388 }
3389
3390 shnum = f->header.e_shnum;
3391 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3392 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3393
3394 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3395 fseek(fp, f->header.e_shoff, SEEK_SET);
3396 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003397 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003398 return NULL;
3399 }
3400
3401 /* Read the section data. */
3402
3403 for (i = 0; i < shnum; ++i) {
3404 struct obj_section *sec;
3405
3406 f->sections[i] = sec = arch_new_section();
3407 memset(sec, 0, sizeof(*sec));
3408
3409 sec->header = section_headers[i];
3410 sec->idx = i;
3411
Denis Vlasenko51742f42007-04-12 00:32:05 +00003412 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003413 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003414 case SHT_NULL:
3415 case SHT_NOTE:
3416 case SHT_NOBITS:
3417 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003418 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003419
3420 case SHT_PROGBITS:
3421#if LOADBITS
3422 if (!loadprogbits) {
3423 sec->contents = NULL;
3424 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003425 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003426#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003427 case SHT_SYMTAB:
3428 case SHT_STRTAB:
3429 case SHT_RELM:
3430 if (sec->header.sh_size > 0) {
3431 sec->contents = xmalloc(sec->header.sh_size);
3432 fseek(fp, sec->header.sh_offset, SEEK_SET);
3433 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3434 bb_perror_msg("error reading ELF section data");
3435 return NULL;
3436 }
3437 } else {
3438 sec->contents = NULL;
3439 }
3440 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003441
3442#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003443 case SHT_RELA:
3444 bb_error_msg("RELA relocations not supported on this architecture");
3445 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003446#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 case SHT_REL:
3448 bb_error_msg("REL relocations not supported on this architecture");
3449 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003450#endif
3451
Eric Andersen3b1a7442003-12-24 20:30:45 +00003452 default:
3453 if (sec->header.sh_type >= SHT_LOPROC) {
3454 /* Assume processor specific section types are debug
3455 info and can safely be ignored. If this is ever not
3456 the case (Hello MIPS?), don't put ifdefs here but
3457 create an arch_load_proc_section(). */
3458 break;
3459 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003460
Eric Andersen3b1a7442003-12-24 20:30:45 +00003461 bb_error_msg("can't handle sections of type %ld",
3462 (long) sec->header.sh_type);
3463 return NULL;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003464 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003465 }
3466 }
3467
3468 /* Do what sort of interpretation as needed by each section. */
3469
3470 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3471
3472 for (i = 0; i < shnum; ++i) {
3473 struct obj_section *sec = f->sections[i];
3474 sec->name = shstrtab + sec->header.sh_name;
3475 }
3476
3477 for (i = 0; i < shnum; ++i) {
3478 struct obj_section *sec = f->sections[i];
3479
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003480 /* .modinfo should be contents only but gcc has no attribute for that.
3481 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3482 */
3483 if (strcmp(sec->name, ".modinfo") == 0)
3484 sec->header.sh_flags &= ~SHF_ALLOC;
3485
Eric Andersen9f16d612000-06-12 23:11:16 +00003486 if (sec->header.sh_flags & SHF_ALLOC)
3487 obj_insert_section_load_order(f, sec);
3488
3489 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003490 case SHT_SYMTAB:
3491 {
3492 unsigned long nsym, j;
3493 char *strtab;
3494 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003495
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003496 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3497 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003498 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003499 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003500 return NULL;
3501 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003502
3503 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3504 strtab = f->sections[sec->header.sh_link]->contents;
3505 sym = (ElfW(Sym) *) sec->contents;
3506
3507 /* Allocate space for a table of local symbols. */
3508 j = f->local_symtab_size = sec->header.sh_info;
3509 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3510
3511 /* Insert all symbols into the hash table. */
3512 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3513 ElfW(Addr) val = sym->st_value;
3514 const char *name;
3515 if (sym->st_name)
3516 name = strtab + sym->st_name;
3517 else if (sym->st_shndx < shnum)
3518 name = f->sections[sym->st_shndx]->name;
3519 else
3520 continue;
3521#if defined(__SH5__)
3522 /*
3523 * For sh64 it is possible that the target of a branch
3524 * requires a mode switch (32 to 16 and back again).
3525 *
3526 * This is implied by the lsb being set in the target
3527 * address for SHmedia mode and clear for SHcompact.
3528 */
3529 val |= sym->st_other & 4;
3530#endif
3531
3532 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3533 val, sym->st_size);
3534 }
3535 }
3536 break;
3537
3538 case SHT_RELM:
3539 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3540 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3541 (unsigned long) sec->header.sh_entsize,
3542 (unsigned long) sizeof(ElfW(RelM)));
3543 return NULL;
3544 }
3545 break;
3546 /* XXX Relocation code from modutils-2.3.19 is not here.
3547 * Why? That's about 20 lines of code from obj/obj_load.c,
3548 * which gets done in a second pass through the sections.
3549 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003550 }
3551 }
3552
3553 return f;
3554}
3555
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003556#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003557/*
3558 * load the unloaded sections directly into the memory allocated by
3559 * kernel for the module
3560 */
3561
Eric Andersenac5dbd12001-08-22 05:26:08 +00003562static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003563{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003564 ElfW(Addr) base = f->baseaddr;
3565 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003566
Eric Andersen8ae319a2001-05-21 16:09:18 +00003567 for (sec = f->load_order; sec; sec = sec->load_next) {
3568
3569 /* section already loaded? */
3570 if (sec->contents != NULL)
3571 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003572
Eric Andersen8ae319a2001-05-21 16:09:18 +00003573 if (sec->header.sh_size == 0)
3574 continue;
3575
3576 sec->contents = imagebase + (sec->header.sh_addr - base);
3577 fseek(fp, sec->header.sh_offset, SEEK_SET);
3578 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003579 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003580 return 0;
3581 }
3582
3583 }
3584 return 1;
3585}
3586#endif
3587
Eric Andersen9f16d612000-06-12 23:11:16 +00003588static void hide_special_symbols(struct obj_file *f)
3589{
3590 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003591 SPFX "cleanup_module",
3592 SPFX "init_module",
3593 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003594 NULL
3595 };
3596
3597 struct obj_symbol *sym;
3598 const char *const *p;
3599
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003600 for (p = specials; *p; ++p) {
3601 sym = obj_find_symbol(f, *p);
3602 if (sym != NULL)
3603 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3604 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003605}
3606
Glenn L McGrath759515c2003-08-30 06:00:33 +00003607
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003608#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003609static int obj_gpl_license(struct obj_file *f, const char **license)
3610{
3611 struct obj_section *sec;
3612 /* This list must match *exactly* the list of allowable licenses in
3613 * linux/include/linux/module.h. Checking for leading "GPL" will not
3614 * work, somebody will use "GPL sucks, this is proprietary".
3615 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003616 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003617 "GPL",
3618 "GPL v2",
3619 "GPL and additional rights",
3620 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003621 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003622 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003623
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003624 sec = obj_find_section(f, ".modinfo");
3625 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003626 const char *value, *ptr, *endptr;
3627 ptr = sec->contents;
3628 endptr = ptr + sec->header.sh_size;
3629 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003630 value = strchr(ptr, '=');
3631 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003632 int i;
3633 if (license)
3634 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003635 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003636 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003637 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003638 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003639 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003640 }
3641 if (strchr(ptr, '\0'))
3642 ptr = strchr(ptr, '\0') + 1;
3643 else
3644 ptr = endptr;
3645 }
3646 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003647 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003648}
3649
3650#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3651#define TAINT_PROPRIETORY_MODULE (1<<0)
3652#define TAINT_FORCED_MODULE (1<<1)
3653#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003654#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003655
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003656static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003657 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3658{
Denis Vlasenko931de892007-06-21 12:43:45 +00003659 static smallint printed_info;
3660
Eric Andersen166fa462002-09-16 05:30:24 +00003661 char buf[80];
3662 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003663
Eric Andersen166fa462002-09-16 05:30:24 +00003664 if (fd < 0 && !kernel_has_tainted)
3665 return; /* New modutils on old kernel */
3666 printf("Warning: loading %s will taint the kernel: %s%s\n",
3667 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003668 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003669 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003670 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003671 }
3672 if (fd >= 0) {
3673 read(fd, buf, sizeof(buf)-1);
3674 buf[sizeof(buf)-1] = '\0';
3675 oldval = strtoul(buf, NULL, 10);
3676 sprintf(buf, "%d\n", oldval | taint);
3677 write(fd, buf, strlen(buf));
3678 }
3679}
3680
3681/* Check if loading this module will taint the kernel. */
3682static void check_tainted_module(struct obj_file *f, char *m_name)
3683{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003684 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3685
Eric Andersen166fa462002-09-16 05:30:24 +00003686 int fd, kernel_has_tainted;
3687 const char *ptr;
3688
3689 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003690 fd = open(tainted_file, O_RDWR);
3691 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003692 if (errno == ENOENT)
3693 kernel_has_tainted = 0;
3694 else if (errno == EACCES)
3695 kernel_has_tainted = 1;
3696 else {
3697 perror(tainted_file);
3698 kernel_has_tainted = 0;
3699 }
3700 }
3701
3702 switch (obj_gpl_license(f, &ptr)) {
3703 case 0:
3704 break;
3705 case 1:
3706 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3707 break;
3708 case 2:
3709 /* The module has a non-GPL license so we pretend that the
3710 * kernel always has a taint flag to get a warning even on
3711 * kernels without the proc flag.
3712 */
3713 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3714 break;
3715 default:
3716 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3717 break;
3718 }
3719
3720 if (flag_force_load)
3721 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3722
3723 if (fd >= 0)
3724 close(fd);
3725}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003726#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003727#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003728#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003729
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003730#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003731/* add module source, timestamp, kernel version and a symbol for the
3732 * start of some sections. this info is used by ksymoops to do better
3733 * debugging.
3734 */
3735static int
3736get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3737{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003738#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003739 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003740#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003741 strncpy(str, "???", sizeof(str));
3742 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003743#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003744}
3745
3746/* add module source, timestamp, kernel version and a symbol for the
3747 * start of some sections. this info is used by ksymoops to do better
3748 * debugging.
3749 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003750static void
Eric Andersen889dd202003-01-23 04:48:34 +00003751add_ksymoops_symbols(struct obj_file *f, const char *filename,
3752 const char *m_name)
3753{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003754 static const char symprefix[] ALIGN1 = "__insmod_";
3755
Eric Andersen889dd202003-01-23 04:48:34 +00003756 struct obj_section *sec;
3757 struct obj_symbol *sym;
3758 char *name, *absolute_filename;
3759 char str[STRVERSIONLEN], real[PATH_MAX];
3760 int i, l, lm_name, lfilename, use_ksymtab, version;
3761 struct stat statbuf;
3762
3763 static const char *section_names[] = {
3764 ".text",
3765 ".rodata",
3766 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003767 ".bss",
3768 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003769 };
3770
3771 if (realpath(filename, real)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +00003772 absolute_filename = xstrdup(real);
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003773 } else {
3774 bb_perror_msg("cannot get realpath for %s", filename);
Rob Landleyd921b2e2006-08-03 15:41:12 +00003775 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003776 }
3777
3778 lm_name = strlen(m_name);
3779 lfilename = strlen(absolute_filename);
3780
3781 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3782 * are not to be exported. otherwise leave ksymtab alone for now, the
3783 * "export all symbols" compatibility code will export these symbols later.
3784 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003785 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003786
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003787 sec = obj_find_section(f, ".this");
3788 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003789 /* tag the module header with the object name, last modified
3790 * timestamp and module version. worst case for module version
3791 * is 0xffffff, decimal 16777215. putting all three fields in
3792 * one symbol is less readable but saves kernel space.
3793 */
3794 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003795 lm_name+ /* module name */
3796 2+ /* "_O" */
3797 lfilename+ /* object filename */
3798 2+ /* "_M" */
3799 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3800 2+ /* "_V" */
3801 8+ /* version in dec */
3802 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003803 name = xmalloc(l);
3804 if (stat(absolute_filename, &statbuf) != 0)
3805 statbuf.st_mtime = 0;
3806 version = get_module_version(f, str); /* -1 if not found */
3807 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 symprefix, m_name, absolute_filename,
3809 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3810 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003811 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003812 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003813 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003814 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003815 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003816 }
3817 free(absolute_filename);
3818#ifdef _NOT_SUPPORTED_
3819 /* record where the persistent data is going, same address as previous symbol */
3820
3821 if (f->persist) {
3822 l = sizeof(symprefix)+ /* "__insmod_" */
3823 lm_name+ /* module name */
3824 2+ /* "_P" */
3825 strlen(f->persist)+ /* data store */
3826 1; /* nul */
3827 name = xmalloc(l);
3828 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003829 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003830 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003831 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003832 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003833 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003834 }
3835#endif /* _NOT_SUPPORTED_ */
3836 /* tag the desired sections if size is non-zero */
3837
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003838 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003839 sec = obj_find_section(f, section_names[i]);
3840 if (sec && sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003841 l = sizeof(symprefix)+ /* "__insmod_" */
3842 lm_name+ /* module name */
3843 2+ /* "_S" */
3844 strlen(sec->name)+ /* section name */
3845 2+ /* "_L" */
3846 8+ /* length in dec */
3847 1; /* nul */
3848 name = xmalloc(l);
3849 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003850 symprefix, m_name, sec->name,
3851 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003852 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003853 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003854 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003855 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003856 }
3857 }
3858}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003859#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003860
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003861#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003862static void print_load_map(struct obj_file *f)
3863{
Eric Andersenbe65c352003-01-23 04:57:35 +00003864 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003865#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3866 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003867 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003868 struct obj_symbol *sym;
3869#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003870 /* Report on the section layout. */
3871
3872 printf("Sections: Size %-*s Align\n",
3873 (int) (2 * sizeof(void *)), "Address");
3874
3875 for (sec = f->load_order; sec; sec = sec->load_next) {
3876 int a;
3877 unsigned long tmp;
3878
3879 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3880 tmp >>= 1;
3881 if (a == -1)
3882 a = 0;
3883
3884 printf("%-15s %08lx %0*lx 2**%d\n",
3885 sec->name,
3886 (long)sec->header.sh_size,
3887 (int) (2 * sizeof(void *)),
3888 (long)sec->header.sh_addr,
3889 a);
3890 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003891#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003892 /* Quick reference which section indicies are loaded. */
3893
3894 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3895 while (--i >= 0)
3896 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3897
3898 /* Collect the symbols we'll be listing. */
3899
3900 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3901 for (sym = f->symtab[i]; sym; sym = sym->next)
3902 if (sym->secidx <= SHN_HIRESERVE
3903 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3904 ++nsyms;
3905
3906 all = alloca(nsyms * sizeof(struct obj_symbol *));
3907
3908 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3909 for (sym = f->symtab[i]; sym; sym = sym->next)
3910 if (sym->secidx <= SHN_HIRESERVE
3911 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3912 *p++ = sym;
3913
3914 /* And list them. */
3915 printf("\nSymbols:\n");
3916 for (p = all; p < all + nsyms; ++p) {
3917 char type = '?';
3918 unsigned long value;
3919
3920 sym = *p;
3921 if (sym->secidx == SHN_ABS) {
3922 type = 'A';
3923 value = sym->value;
3924 } else if (sym->secidx == SHN_UNDEF) {
3925 type = 'U';
3926 value = 0;
3927 } else {
3928 sec = f->sections[sym->secidx];
3929
3930 if (sec->header.sh_type == SHT_NOBITS)
3931 type = 'B';
3932 else if (sec->header.sh_flags & SHF_ALLOC) {
3933 if (sec->header.sh_flags & SHF_EXECINSTR)
3934 type = 'T';
3935 else if (sec->header.sh_flags & SHF_WRITE)
3936 type = 'D';
3937 else
3938 type = 'R';
3939 }
3940 value = sym->value + sec->header.sh_addr;
3941 }
3942
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003943 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003944 type = tolower(type);
3945
3946 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3947 type, sym->name);
3948 }
3949#endif
3950}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003951#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003952void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003953#endif
3954
Denis Vlasenko06af2162007-02-03 17:28:39 +00003955int insmod_main( int argc, char **argv);
Rob Landleydfba7412006-03-06 20:47:33 +00003956int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003957{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003958 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003959 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003960 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003961 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003962 unsigned long m_size;
3963 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003964 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003965 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003966 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003967 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003968 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003969#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003970 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003971 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003972 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003973#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003974#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003975 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003976#else
3977 FILE *fp;
3978#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003979 int k_version = 0;
3980 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003981
Erik Andersene49d5ec2000-02-08 19:58:47 +00003982 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003983 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003984 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003985 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003986 free(m_name);
3987 m_name = xstrdup(opt_o);
3988 }
Eric Andersen03d80912003-12-19 21:04:19 +00003989
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003990 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003991 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003992 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003993
Erik Andersene49d5ec2000-02-08 19:58:47 +00003994 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003995 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003996 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003997 len = strlen(tmp);
3998
Eric Andersen03d80912003-12-19 21:04:19 +00003999 if (uname(&myuname) == 0) {
4000 if (myuname.release[0] == '2') {
4001 k_version = myuname.release[2] - '0';
4002 }
4003 }
4004
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004005#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004006 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
4007 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
4008 ) {
4009 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00004010 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004011 } else
Eric Andersen03d80912003-12-19 21:04:19 +00004012#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004013 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004014 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004015 tmp[len] = '\0';
4016 }
Eric Andersen2d342152002-06-18 05:16:25 +00004017
Eric Andersen03d80912003-12-19 21:04:19 +00004018
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004019#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004020 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00004021 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004022 else
Eric Andersen03d80912003-12-19 21:04:19 +00004023#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00004024 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004025
Eric Andersen61f83052002-06-22 17:15:42 +00004026 if (!m_name) {
4027 m_name = tmp;
4028 } else {
4029 free(tmp1);
4030 tmp1 = 0; /* flag for free(m_name) before exit() */
4031 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004032
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004033 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004034 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
4035 || (fp = fopen(arg1, "r")) == NULL
4036 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00004037 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4038 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004039 if (k_version) { /* uname succeedd */
4040 char *module_dir;
4041 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004042 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004043
Eric Andersen03d80912003-12-19 21:04:19 +00004044 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004045 /* Jump through hoops in case /lib/modules/`uname -r`
4046 * is a symlink. We do not want recursive_action to
4047 * follow symlinks, but we do want to follow the
4048 * /lib/modules/`uname -r` dir, So resolve it ourselves
4049 * if it is a link... */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004050 if (realpath(tmdn, real_module_dir) == NULL)
Eric Andersen03d80912003-12-19 21:04:19 +00004051 module_dir = tmdn;
4052 else
4053 module_dir = real_module_dir;
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004054 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004055 check_module_name_match, 0, m_fullName, 0);
Eric Andersen03d80912003-12-19 21:04:19 +00004056 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004057 }
4058
4059 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004060 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004061 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004062
Eric Andersen03d80912003-12-19 21:04:19 +00004063 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004064 m_filename = NULL;
4065 if (realpath(_PATH_MODULES, module_dir) == NULL)
Eric Andersen2416dfc2001-05-14 20:03:04 +00004066 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004067 /* No module found under /lib/modules/`uname -r`, this
4068 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00004069 if (!recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004070 check_module_name_match, 0, m_fullName, 0)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004071 ) {
Eric Andersen61f83052002-06-22 17:15:42 +00004072 if (m_filename == 0
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004073 || ((fp = fopen(m_filename, "r")) == NULL)
4074 ) {
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004075 bb_error_msg("%s: module not found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004076 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004077 }
4078 } else
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004079 bb_error_msg_and_die("%s: module not found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004080 }
Eric Andersen03d80912003-12-19 21:04:19 +00004081 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004082 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004083
Rob Landley999af202005-12-11 20:14:12 +00004084 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004085 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004086
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004087#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004088 if (k_version > 4) {
4089 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004090 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004091 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004092 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004093#endif
4094
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004095 f = obj_load(fp, LOADBITS);
4096 if (f == NULL)
4097 bb_perror_msg_and_die("cannot load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004098
Eric Andersen9f16d612000-06-12 23:11:16 +00004099 if (get_modinfo_value(f, "kernel_version") == NULL)
4100 m_has_modinfo = 0;
4101 else
4102 m_has_modinfo = 1;
4103
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004104#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004105 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004106 if (!flag_quiet) {
4107 if (uname(&uts_info) < 0)
4108 uts_info.release[0] = '\0';
4109 if (m_has_modinfo) {
4110 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004111 if (m_version == -1) {
Denis Vlasenkoa9595882006-09-29 21:30:43 +00004112 bb_error_msg("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004113 "compiled for");
4114 goto out;
4115 }
4116 }
4117
4118 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004119 bb_error_msg("%skernel-module version mismatch\n"
4120 "\t%s was compiled for kernel version %s\n"
4121 "\twhile this kernel is version %s",
4122 flag_force_load ? "warning: " : "",
4123 m_filename, m_strversion, uts_info.release);
4124 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004125 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004126 }
4127 }
4128 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004129#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004130
Eric Andersencb3b9b12004-06-22 11:50:52 +00004131 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004132 if (!new_get_kernel_symbols())
4133 goto out;
4134 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004135 } else {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004136 bb_error_msg("not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 }
4139
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004140#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004141 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004142 if (m_has_modinfo)
4143 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004144
4145 if (m_crcs != k_crcs)
4146 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004147#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004148
Erik Andersene49d5ec2000-02-08 19:58:47 +00004149 /* Let the module know about the kernel symbols. */
4150 add_kernel_symbols(f);
4151
Eric Andersen9f16d612000-06-12 23:11:16 +00004152 /* Allocate common symbols, symbol tables, and string tables. */
4153
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004154 if (!new_create_this_module(f, m_name)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004155 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004156 }
4157
Eric Andersen9f16d612000-06-12 23:11:16 +00004158 if (!obj_check_undefineds(f)) {
4159 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004160 }
4161 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004162 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004163
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004164 /* done with the module name, on to the optional var=value arguments */
4165 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004166 if (optind < argc) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004167 if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004168 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004169 }
4170 }
4171
Eric Andersen9f16d612000-06-12 23:11:16 +00004172 arch_create_got(f);
4173 hide_special_symbols(f);
4174
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004175#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004176 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004177#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004178
Eric Andersencb3b9b12004-06-22 11:50:52 +00004179 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004180
Erik Andersene49d5ec2000-02-08 19:58:47 +00004181 /* Find current size of the module */
4182 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004183
4184
Erik Andersene49d5ec2000-02-08 19:58:47 +00004185 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004186 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004187 case EEXIST:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004188 bb_error_msg("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004189 goto out;
4190 case ENOMEM:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004191 bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004192 m_size);
4193 goto out;
4194 default:
4195 bb_perror_msg("create_module: %s", m_name);
4196 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004197 }
Erik Andersend387d011999-12-21 02:55:11 +00004198
Eric Andersen8ae319a2001-05-21 16:09:18 +00004199#if !LOADBITS
4200 /*
4201 * the PROGBITS section was not loaded by the obj_load
4202 * now we can load them directly into the kernel memory
4203 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004204 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004205 delete_module(m_name);
4206 goto out;
4207 }
Eric Andersen03d80912003-12-19 21:04:19 +00004208#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004209
Eric Andersen9f16d612000-06-12 23:11:16 +00004210 if (!obj_relocate(f, m_addr)) {
4211 delete_module(m_name);
4212 goto out;
4213 }
Erik Andersend387d011999-12-21 02:55:11 +00004214
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004215 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004216 delete_module(m_name);
4217 goto out;
4218 }
4219
Denis Vlasenko51742f42007-04-12 00:32:05 +00004220 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004221 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004222
Matt Kraai3e856ce2000-12-01 02:55:13 +00004223 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004224
4225out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004226#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004227 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004228 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004229 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004230 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004231 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004232 free(m_filename);
4233#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004234 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004235}
Eric Andersene7047882003-12-11 01:42:13 +00004236
4237
4238#endif
4239
4240
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004241#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004242
4243#include <sys/mman.h>
4244#include <asm/unistd.h>
4245#include <sys/syscall.h>
4246
4247/* We use error numbers in a loose translation... */
4248static const char *moderror(int err)
4249{
4250 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004251 case ENOEXEC:
4252 return "Invalid module format";
4253 case ENOENT:
4254 return "Unknown symbol in module";
4255 case ESRCH:
4256 return "Module has wrong symbol version";
4257 case EINVAL:
4258 return "Invalid parameters";
4259 default:
4260 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004261 }
4262}
4263
Denis Vlasenko06af2162007-02-03 17:28:39 +00004264int insmod_ng_main(int argc, char **argv);
Denis Vlasenko92297942006-11-21 11:58:14 +00004265int insmod_ng_main(int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004266{
Denis Vlasenko92297942006-11-21 11:58:14 +00004267 long ret;
4268 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004269 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004270 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004271 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004272
Denis Vlasenko92297942006-11-21 11:58:14 +00004273 filename = *++argv;
4274 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004275 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004276
4277 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004278 options = xzalloc(1);
4279 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004280 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004281 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004282 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004283 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004284 }
4285
Denis Vlasenko92297942006-11-21 11:58:14 +00004286#if 0
4287 /* Any special reason why mmap? It isn't performace critical... */
4288 int fd;
4289 struct stat st;
4290 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004291 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004292 fstat(fd, &st);
4293 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004294 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004295 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004296 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004297 }
4298
Denis Vlasenko92297942006-11-21 11:58:14 +00004299 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4300 if (map == NULL) {
4301 map = xmalloc(len);
4302 xread(fd, map, len);
4303 }
4304#else
4305 len = MAXINT(ssize_t);
4306 map = xmalloc_open_read_close(filename, &len);
4307#endif
4308
Eric Andersene7047882003-12-11 01:42:13 +00004309 ret = syscall(__NR_init_module, map, len, options);
4310 if (ret != 0) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004311 bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004312 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004313 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314
Eric Andersene7047882003-12-11 01:42:13 +00004315 return 0;
4316}
4317
4318#endif