blob: 079de69402af3178c1dc9914b8a0567b6a96ca50 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
Eric Andersen2835efe2001-07-25 16:58:58 +00004 *
Eric Andersen45a05132004-09-02 23:03:25 +00005 * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
6 * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00008 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +00009 * and Ron Alder <alder@lineo.com>
10 *
Eric Andersena4d27d22004-08-19 19:17:30 +000011 * Rodney Radford <rradford@mindspring.com> 17-Aug-2004.
12 * Added x86_64 support.
13 *
Miles Bader75ce8d72002-04-01 14:25:51 +000014 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000015 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000017 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
18 *
19 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
20 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
21 * very minor changes required to also work with StrongArm and presumably
22 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000023 *
Eric Andersenee70fa52004-05-26 11:38:46 +000024 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
25 * added Renesas H8/300 support.
26 *
Eric Andersenbf833552003-08-13 19:56:33 +000027 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
28 * Integrated support for sh64 (SH-5), from preliminary modutils
29 * patches from Benedict Gaster <benedict.gaster@superh.com>.
30 * Currently limited to support for 32bit ABI.
31 *
Eric Andersencffd5022002-05-24 06:50:15 +000032 * Magnus Damm <damm@opensource.se> 22-May-2002.
33 * The plt and got code are now using the same structs.
34 * Added generic linked list code to fully support PowerPC.
35 * Replaced the mess in arch_apply_relocation() with architecture blocks.
36 * The arch_create_got() function got cleaned up with architecture blocks.
37 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
38 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000040 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
42 * I've only tested the code on mpc8xx platforms in big-endian mode.
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000043 * Did some cleanup and added USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000044 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000045 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
46 * based on modutils-2.4.2
47 * MIPS specific support for Elf loading and relocation.
48 * Copyright 1996, 1997 Linux International.
49 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
50 *
Eric Andersen9f16d612000-06-12 23:11:16 +000051 * Based almost entirely on the Linux modutils-2.3.11 implementation.
52 * Copyright 1996, 1997 Linux International.
53 * New implementation contributed by Richard Henderson <rth@tamu.edu>
54 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
55 * Restructured (and partly rewritten) by:
56 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000057 *
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +000058 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Erik Andersen02104321999-12-17 18:57:34 +000059 */
60
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000061#include "libbb.h"
Rob Landley519d7df2006-08-09 20:56:23 +000062#include <libgen.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000065#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko3bba5452006-12-30 17:57:03 +000066#undef ENABLE_FEATURE_2_4_MODULES
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000067#define ENABLE_FEATURE_2_4_MODULES 1
Eric Andersene7047882003-12-11 01:42:13 +000068#endif
69
Denis Vlasenkob68979a2007-11-02 23:31:10 +000070/*
71 * Big piece of 2.4-specific code
72 */
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000073#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000074
Denis Vlasenkob68979a2007-11-02 23:31:10 +000075#if ENABLE_FEATURE_2_6_MODULES
76static int insmod_ng_main(int argc, char **argv);
77#endif
Eric Andersen64c8b172001-04-05 07:33:10 +000078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000079#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000080#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000081#else
82#define LOADBITS 1
83#endif
84
Mike Frysinger63654c12004-12-26 09:13:32 +000085/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000086#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000087#define MATCH_MACHINE(x) (x == EM_ALPHA)
88#define SHT_RELM SHT_RELA
89#define Elf64_RelM Elf64_Rela
90#define ELFCLASSM ELFCLASS64
91#endif
92
Eric Andersen45a05132004-09-02 23:03:25 +000093/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000094#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000095#define MATCH_MACHINE(x) (x == EM_ARM)
96#define SHT_RELM SHT_REL
97#define Elf32_RelM Elf32_Rel
98#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000099#define USE_PLT_ENTRIES
100#define PLT_ENTRY_SIZE 8
101#define USE_GOT_ENTRIES
102#define GOT_ENTRY_SIZE 8
103#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000104#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000105
Mike Frysingerb306cb72006-06-06 06:15:52 +0000106/* blackfin */
107#if defined(BFIN)
108#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
109#define SHT_RELM SHT_RELA
110#define Elf32_RelM Elf32_Rela
111#define ELFCLASSM ELFCLASS32
112#endif
113
Eric Andersen45a05132004-09-02 23:03:25 +0000114/* CRIS */
115#if defined(__cris__)
116#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000117#define SHT_RELM SHT_RELA
118#define Elf32_RelM Elf32_Rela
119#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000120#ifndef EM_CRIS
121#define EM_CRIS 76
122#define R_CRIS_NONE 0
123#define R_CRIS_32 3
124#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000125#endif
126
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000127/* H8/300 */
128#if defined(__H8300H__) || defined(__H8300S__)
129#define MATCH_MACHINE(x) (x == EM_H8_300)
130#define SHT_RELM SHT_RELA
131#define Elf32_RelM Elf32_Rela
132#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000133#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000134#define SYMBOL_PREFIX "_"
135#endif
136
Mike Frysinger63654c12004-12-26 09:13:32 +0000137/* PA-RISC / HP-PA */
138#if defined(__hppa__)
139#define MATCH_MACHINE(x) (x == EM_PARISC)
140#define SHT_RELM SHT_RELA
141#if defined(__LP64__)
142#define Elf64_RelM Elf64_Rela
143#define ELFCLASSM ELFCLASS64
144#else
145#define Elf32_RelM Elf32_Rela
146#define ELFCLASSM ELFCLASS32
147#endif
148#endif
149
Eric Andersen45a05132004-09-02 23:03:25 +0000150/* x86 */
151#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000152#ifndef EM_486
153#define MATCH_MACHINE(x) (x == EM_386)
154#else
155#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
156#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000157#define SHT_RELM SHT_REL
158#define Elf32_RelM Elf32_Rel
159#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000160#define USE_GOT_ENTRIES
161#define GOT_ENTRY_SIZE 4
162#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000163#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000164
Eric Andersen45a05132004-09-02 23:03:25 +0000165/* IA64, aka Itanium */
166#if defined(__ia64__)
167#define MATCH_MACHINE(x) (x == EM_IA_64)
168#define SHT_RELM SHT_RELA
169#define Elf64_RelM Elf64_Rela
170#define ELFCLASSM ELFCLASS64
171#endif
172
173/* m68k */
174#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000175#define MATCH_MACHINE(x) (x == EM_68K)
176#define SHT_RELM SHT_RELA
177#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000178#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000179#define USE_GOT_ENTRIES
180#define GOT_ENTRY_SIZE 4
181#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000182#endif
183
Mike Frysingerb306cb72006-06-06 06:15:52 +0000184/* Microblaze */
185#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000186#define USE_SINGLE
Mike Frysingerb306cb72006-06-06 06:15:52 +0000187#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
188#define SHT_RELM SHT_RELA
189#define Elf32_RelM Elf32_Rela
190#define ELFCLASSM ELFCLASS32
191#endif
192
Eric Andersen45a05132004-09-02 23:03:25 +0000193/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000194#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000195#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
196#define SHT_RELM SHT_REL
197#define Elf32_RelM Elf32_Rel
198#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000199/* Account for ELF spec changes. */
200#ifndef EM_MIPS_RS3_LE
201#ifdef EM_MIPS_RS4_BE
202#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
203#else
204#define EM_MIPS_RS3_LE 10
205#endif
206#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000207#define ARCHDATAM "__dbe_table"
208#endif
209
Mike Frysingerf982d862006-01-04 00:11:26 +0000210/* Nios II */
211#if defined(__nios2__)
212#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
213#define SHT_RELM SHT_RELA
214#define Elf32_RelM Elf32_Rela
215#define ELFCLASSM ELFCLASS32
216#endif
217
Eric Andersen45a05132004-09-02 23:03:25 +0000218/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000219#if defined(__powerpc64__)
220#define MATCH_MACHINE(x) (x == EM_PPC64)
221#define SHT_RELM SHT_RELA
222#define Elf64_RelM Elf64_Rela
223#define ELFCLASSM ELFCLASS64
224#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000225#define MATCH_MACHINE(x) (x == EM_PPC)
226#define SHT_RELM SHT_RELA
227#define Elf32_RelM Elf32_Rela
228#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000229#define USE_PLT_ENTRIES
230#define PLT_ENTRY_SIZE 16
231#define USE_PLT_LIST
232#define LIST_ARCHTYPE ElfW(Addr)
233#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000234#define ARCHDATAM "__ftr_fixup"
235#endif
236
Eric Andersen45a05132004-09-02 23:03:25 +0000237/* S390 */
238#if defined(__s390__)
239#define MATCH_MACHINE(x) (x == EM_S390)
240#define SHT_RELM SHT_RELA
241#define Elf32_RelM Elf32_Rela
242#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000243#define USE_PLT_ENTRIES
244#define PLT_ENTRY_SIZE 8
245#define USE_GOT_ENTRIES
246#define GOT_ENTRY_SIZE 8
247#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000248#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000249
Eric Andersen45a05132004-09-02 23:03:25 +0000250/* SuperH */
251#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000252#define MATCH_MACHINE(x) (x == EM_SH)
253#define SHT_RELM SHT_RELA
254#define Elf32_RelM Elf32_Rela
255#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000256#define USE_GOT_ENTRIES
257#define GOT_ENTRY_SIZE 4
258#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000259/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000260/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000261#if defined(__sh__) && BB_BIG_ENDIAN
262# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000263#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000264/* it may or may not work on the SH1/SH2... Error on those also */
265#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000266#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000267#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000268#endif
269
Eric Andersen45a05132004-09-02 23:03:25 +0000270/* Sparc */
271#if defined(__sparc__)
272#define MATCH_MACHINE(x) (x == EM_SPARC)
273#define SHT_RELM SHT_RELA
274#define Elf32_RelM Elf32_Rela
275#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000276#endif
277
Eric Andersen45a05132004-09-02 23:03:25 +0000278/* v850e */
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000279#if defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000280#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
281#define SHT_RELM SHT_RELA
282#define Elf32_RelM Elf32_Rela
283#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000284#define USE_PLT_ENTRIES
285#define PLT_ENTRY_SIZE 8
286#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000287#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000288#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000289#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000290#define SYMBOL_PREFIX "_"
291#endif
292
Eric Andersen45a05132004-09-02 23:03:25 +0000293/* X86_64 */
294#if defined(__x86_64__)
295#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000296#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000297#define USE_GOT_ENTRIES
298#define GOT_ENTRY_SIZE 8
299#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000300#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000301#define ELFCLASSM ELFCLASS64
302#endif
303
Eric Andersencffd5022002-05-24 06:50:15 +0000304#ifndef SHT_RELM
305#error Sorry, but insmod.c does not yet support this architecture...
306#endif
307
308
Eric Andersen9f16d612000-06-12 23:11:16 +0000309//----------------------------------------------------------------------------
310//--------modutils module.h, lines 45-242
311//----------------------------------------------------------------------------
312
313/* Definitions for the Linux module syscall interface.
314 Copyright 1996, 1997 Linux International.
315
316 Contributed by Richard Henderson <rth@tamu.edu>
317
318 This file is part of the Linux modutils.
319
320 This program is free software; you can redistribute it and/or modify it
321 under the terms of the GNU General Public License as published by the
322 Free Software Foundation; either version 2 of the License, or (at your
323 option) any later version.
324
325 This program is distributed in the hope that it will be useful, but
326 WITHOUT ANY WARRANTY; without even the implied warranty of
327 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
328 General Public License for more details.
329
330 You should have received a copy of the GNU General Public License
331 along with this program; if not, write to the Free Software Foundation,
332 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
333
334
335#ifndef MODUTILS_MODULE_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000336
Eric Andersen9f16d612000-06-12 23:11:16 +0000337/*======================================================================*/
338/* For sizeof() which are related to the module platform and not to the
339 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
340
341#define tgt_sizeof_char sizeof(char)
342#define tgt_sizeof_short sizeof(short)
343#define tgt_sizeof_int sizeof(int)
344#define tgt_sizeof_long sizeof(long)
345#define tgt_sizeof_char_p sizeof(char *)
346#define tgt_sizeof_void_p sizeof(void *)
347#define tgt_long long
348
349#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
350#undef tgt_sizeof_long
351#undef tgt_sizeof_char_p
352#undef tgt_sizeof_void_p
353#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000354enum {
355 tgt_sizeof_long = 8,
356 tgt_sizeof_char_p = 8,
357 tgt_sizeof_void_p = 8
358};
Eric Andersen9f16d612000-06-12 23:11:16 +0000359#define tgt_long long long
360#endif
361
362/*======================================================================*/
363/* The structures used in Linux 2.1. */
364
365/* Note: new_module_symbol does not use tgt_long intentionally */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000366struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000367 unsigned long value;
368 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000369};
370
371struct new_module_persist;
372
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000373struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000374 unsigned tgt_long dep; /* kernel addresses */
375 unsigned tgt_long ref;
376 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000377};
378
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000379struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000380 unsigned tgt_long size_of_struct; /* == sizeof(module) */
381 unsigned tgt_long next;
382 unsigned tgt_long name;
383 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000384
Eric Andersen3b1a7442003-12-24 20:30:45 +0000385 tgt_long usecount;
386 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000387
Eric Andersen3b1a7442003-12-24 20:30:45 +0000388 unsigned nsyms;
389 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000390
Eric Andersen3b1a7442003-12-24 20:30:45 +0000391 unsigned tgt_long syms;
392 unsigned tgt_long deps;
393 unsigned tgt_long refs;
394 unsigned tgt_long init;
395 unsigned tgt_long cleanup;
396 unsigned tgt_long ex_table_start;
397 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000398#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000399 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000400#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000401 /* Everything after here is extension. */
402 unsigned tgt_long persist_start;
403 unsigned tgt_long persist_end;
404 unsigned tgt_long can_unload;
405 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000406 const char *kallsyms_start; /* All symbols for kernel debugging */
407 const char *kallsyms_end;
408 const char *archdata_start; /* arch specific data for module */
409 const char *archdata_end;
410 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000411};
412
Eric Andersencffd5022002-05-24 06:50:15 +0000413#ifdef ARCHDATAM
414#define ARCHDATA_SEC_NAME ARCHDATAM
415#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000416#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000417#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000418#define KALLSYMS_SEC_NAME "__kallsyms"
419
420
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000421struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000422 unsigned long addr;
423 unsigned long size;
424 unsigned long flags;
425 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000426};
427
428/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000429enum {
430 NEW_MOD_RUNNING = 1,
431 NEW_MOD_DELETED = 2,
432 NEW_MOD_AUTOCLEAN = 4,
433 NEW_MOD_VISITED = 8,
434 NEW_MOD_USED_ONCE = 16
435};
Eric Andersen9f16d612000-06-12 23:11:16 +0000436
Eric Andersencb3b9b12004-06-22 11:50:52 +0000437int init_module(const char *name, const struct new_module *);
438int query_module(const char *name, int which, void *buf,
439 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
441/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000442enum {
443 QM_MODULES = 1,
444 QM_DEPS = 2,
445 QM_REFS = 3,
446 QM_SYMBOLS = 4,
447 QM_INFO = 5
448};
Eric Andersen9f16d612000-06-12 23:11:16 +0000449
450/*======================================================================*/
451/* The system calls unchanged between 2.0 and 2.1. */
452
453unsigned long create_module(const char *, size_t);
454int delete_module(const char *);
455
456
457#endif /* module.h */
458
459//----------------------------------------------------------------------------
460//--------end of modutils module.h
461//----------------------------------------------------------------------------
462
463
464
465//----------------------------------------------------------------------------
466//--------modutils obj.h, lines 253-462
467//----------------------------------------------------------------------------
468
469/* Elf object file loading and relocation routines.
470 Copyright 1996, 1997 Linux International.
471
472 Contributed by Richard Henderson <rth@tamu.edu>
473
474 This file is part of the Linux modutils.
475
476 This program is free software; you can redistribute it and/or modify it
477 under the terms of the GNU General Public License as published by the
478 Free Software Foundation; either version 2 of the License, or (at your
479 option) any later version.
480
481 This program is distributed in the hope that it will be useful, but
482 WITHOUT ANY WARRANTY; without even the implied warranty of
483 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484 General Public License for more details.
485
486 You should have received a copy of the GNU General Public License
487 along with this program; if not, write to the Free Software Foundation,
488 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
489
490
491#ifndef MODUTILS_OBJ_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000492
Eric Andersen9f16d612000-06-12 23:11:16 +0000493/* The relocatable object is manipulated using elfin types. */
494
Eric Andersen9f16d612000-06-12 23:11:16 +0000495#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000496#include <endian.h>
497
Eric Andersen9f16d612000-06-12 23:11:16 +0000498#ifndef ElfW
499# if ELFCLASSM == ELFCLASS32
500# define ElfW(x) Elf32_ ## x
501# define ELFW(x) ELF32_ ## x
502# else
503# define ElfW(x) Elf64_ ## x
504# define ELFW(x) ELF64_ ## x
505# endif
506#endif
507
Eric Andersen85e5e722003-07-22 08:56:55 +0000508/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000509#ifndef ELF32_ST_INFO
510# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
511#endif
512
513#ifndef ELF64_ST_INFO
514# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
515#endif
516
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000517#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
518#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
519#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
520#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
521#define ELF_R_SYM(val) ELFW(R_SYM)(val)
522
Eric Andersen9f16d612000-06-12 23:11:16 +0000523struct obj_string_patch;
524struct obj_symbol_patch;
525
526struct obj_section
527{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000528 ElfW(Shdr) header;
529 const char *name;
530 char *contents;
531 struct obj_section *load_next;
532 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000533};
534
535struct obj_symbol
536{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000537 struct obj_symbol *next; /* hash table link */
538 const char *name;
539 unsigned long value;
540 unsigned long size;
541 int secidx; /* the defining section index/module */
542 int info;
543 int ksymidx; /* for export to the kernel symtab */
544 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000545};
546
547/* Hardcode the hash table size. We shouldn't be needing so many
548 symbols that we begin to degrade performance, and we get a big win
549 by giving the compiler a constant divisor. */
550
551#define HASH_BUCKETS 521
552
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000553struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000554 ElfW(Ehdr) header;
555 ElfW(Addr) baseaddr;
556 struct obj_section **sections;
557 struct obj_section *load_order;
558 struct obj_section **load_order_search_start;
559 struct obj_string_patch *string_patches;
560 struct obj_symbol_patch *symbol_patches;
561 int (*symbol_cmp)(const char *, const char *);
562 unsigned long (*symbol_hash)(const char *);
563 unsigned long local_symtab_size;
564 struct obj_symbol **local_symtab;
565 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000566};
567
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000568enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000569 obj_reloc_ok,
570 obj_reloc_overflow,
571 obj_reloc_dangerous,
572 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000573};
574
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000575struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000576 struct obj_string_patch *next;
577 int reloc_secidx;
578 ElfW(Addr) reloc_offset;
579 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000580};
581
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000582struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000583 struct obj_symbol_patch *next;
584 int reloc_secidx;
585 ElfW(Addr) reloc_offset;
586 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000587};
588
589
590/* Generic object manipulation routines. */
591
Eric Andersen044228d2001-07-17 01:12:36 +0000592static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000593
Eric Andersen044228d2001-07-17 01:12:36 +0000594static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000595
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000596static struct obj_symbol *obj_find_symbol(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000597 const char *name);
598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000600 struct obj_symbol *sym);
601
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000602#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000603static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000604 int (*cmp)(const char *, const char *),
605 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000606#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000607
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000608static struct obj_section *obj_find_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000609 const char *name);
610
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000611static void obj_insert_section_load_order(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000612 struct obj_section *sec);
613
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000614static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000615 const char *name,
616 unsigned long align,
617 unsigned long size);
618
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000619static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000620 const char *name,
621 unsigned long align,
622 unsigned long size);
623
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000624static void *obj_extend_section(struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000625
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000626static void obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 const char *string);
628
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000629static void obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000630 struct obj_symbol *sym);
631
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000632static void obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000633
Eric Andersen044228d2001-07-17 01:12:36 +0000634static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000635
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000636static unsigned long obj_load_size(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000637
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000638static int obj_relocate(struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000639
Eric Andersen044228d2001-07-17 01:12:36 +0000640static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000641
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000642static int obj_create_image(struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000643
644/* Architecture specific manipulation routines. */
645
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000646static struct obj_file *arch_new_file(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000647
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000648static struct obj_section *arch_new_section(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000649
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000650static struct obj_symbol *arch_new_symbol(void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000651
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000652static enum obj_reloc arch_apply_relocation(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000653 struct obj_section *targsec,
Denis Vlasenko68404f12008-03-17 09:00:54 +0000654 /*struct obj_section *symsec,*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000655 struct obj_symbol *sym,
656 ElfW(RelM) *rel, ElfW(Addr) value);
657
Denis Vlasenko6398cf42007-04-11 17:04:29 +0000658static void arch_create_got(struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000659#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000660static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000661#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000662#endif /* obj.h */
663//----------------------------------------------------------------------------
664//--------end of modutils obj.h
665//----------------------------------------------------------------------------
666
667
Miles Baderae28b042002-04-01 09:34:25 +0000668/* SPFX is always a string, so it can be concatenated to string constants. */
669#ifdef SYMBOL_PREFIX
670#define SPFX SYMBOL_PREFIX
671#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000672#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000673#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000674
Erik Andersen02104321999-12-17 18:57:34 +0000675
Erik Andersend387d011999-12-21 02:55:11 +0000676#define _PATH_MODULES "/lib/modules"
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000677enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000678
Eric Andersen9f16d612000-06-12 23:11:16 +0000679/*======================================================================*/
680
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000681#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
682enum {
683 OPT_s = 0x1, // -s /* log to syslog */
684 /* Not supported but kernel needs this for request_module(),
685 as this calls: modprobe -k -s -- <module>
686 so silently ignore this flag */
687 OPT_L = 0x2, // -L /* Stub warning */
688 /* Compatibility with modprobe.
689 In theory, this does locking, but we don't do
690 that. So be careful and plan your life around not
691 loading the same module 50 times concurrently. */
692 OPT_o = 0x4, // -o /* name the output module */
693 OPT_f = 0x8, // -f /* force loading */
694 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
695 OPT_v = 0x20, // -v /* verbose output */
696 OPT_q = 0x40, // -q /* silent */
697 OPT_x = 0x80, // -x /* do not export externs */
698 OPT_m = 0x100, // -m /* print module load map */
699};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000700#define flag_force_load (option_mask32 & OPT_f)
701#define flag_autoclean (option_mask32 & OPT_k)
702#define flag_verbose (option_mask32 & OPT_v)
703#define flag_quiet (option_mask32 & OPT_q)
704#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000705#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000706#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000707#else
708#define flag_print_load_map 0
709#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000710
711/*======================================================================*/
712
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000713#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000714
Eric Andersencffd5022002-05-24 06:50:15 +0000715struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000716{
Eric Andersencffd5022002-05-24 06:50:15 +0000717 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000718 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000719 int offset;
720 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000721};
Eric Andersencffd5022002-05-24 06:50:15 +0000722
Eric Andersen21adca72000-12-06 18:18:26 +0000723#endif
724
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000725#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000726
727struct arch_single_entry
728{
Eric Andersen9f16d612000-06-12 23:11:16 +0000729 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000730 int inited : 1;
731 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000732};
Eric Andersencffd5022002-05-24 06:50:15 +0000733
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000734#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000735
Eric Andersen2bf658d2001-02-24 20:01:53 +0000736#if defined(__mips__)
737struct mips_hi16
738{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000739 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000740 ElfW(Addr) *addr;
741 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000742};
743#endif
744
Eric Andersenfe4208f2000-09-24 03:44:29 +0000745struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000746 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000747#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000748 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000749#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000750#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000751 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000752#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000753#if defined(__mips__)
754 struct mips_hi16 *mips_hi16_list;
755#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000756};
757
Eric Andersenfe4208f2000-09-24 03:44:29 +0000758struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000759 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000760#if defined(USE_PLT_ENTRIES)
761#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000762 struct arch_list_entry *pltent;
763#else
764 struct arch_single_entry pltent;
765#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000766#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000767#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000768 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000769#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000770};
771
772
Eric Andersen9f16d612000-06-12 23:11:16 +0000773struct external_module {
774 const char *name;
775 ElfW(Addr) addr;
776 int used;
777 size_t nsyms;
778 struct new_module_symbol *syms;
779};
780
Eric Andersen044228d2001-07-17 01:12:36 +0000781static struct new_module_symbol *ksyms;
782static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000783
Eric Andersen044228d2001-07-17 01:12:36 +0000784static struct external_module *ext_modules;
785static int n_ext_modules;
786static int n_ext_modules_used;
Eric Andersena2a978a2001-04-05 06:08:14 +0000787
Eric Andersen61f83052002-06-22 17:15:42 +0000788static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000789static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000790
Eric Andersenfe4208f2000-09-24 03:44:29 +0000791
Eric Andersen9f16d612000-06-12 23:11:16 +0000792/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000793
Eric Andersen9f16d612000-06-12 23:11:16 +0000794
Denis Vlasenko68404f12008-03-17 09:00:54 +0000795static int check_module_name_match(const char *filename,
796 struct stat *statbuf ATTRIBUTE_UNUSED,
797 void *userdata, int depth ATTRIBUTE_UNUSED)
Eric Andersen9f16d612000-06-12 23:11:16 +0000798{
Eric Andersen14d35432001-05-14 17:07:32 +0000799 char *fullname = (char *) userdata;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000800 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000801
Eric Andersen14d35432001-05-14 17:07:32 +0000802 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000803 return FALSE;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000804
805 tmp = bb_get_last_path_component_nostrip(filename);
806 if (strcmp(tmp, fullname) == 0) {
807 /* Stop searching if we find a match */
808 m_filename = xstrdup(filename);
809 return FALSE;
Erik Andersend387d011999-12-21 02:55:11 +0000810 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000811 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000812}
813
Erik Andersen02104321999-12-17 18:57:34 +0000814
Eric Andersen9f16d612000-06-12 23:11:16 +0000815/*======================================================================*/
816
Eric Andersen044228d2001-07-17 01:12:36 +0000817static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000818{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000819 struct arch_file *f;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000820 f = xzalloc(sizeof(*f));
821 return &f->root; /* it's a first member */
Eric Andersen9f16d612000-06-12 23:11:16 +0000822}
823
Eric Andersen044228d2001-07-17 01:12:36 +0000824static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000825{
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000826 return xzalloc(sizeof(struct obj_section));
Eric Andersen9f16d612000-06-12 23:11:16 +0000827}
828
Eric Andersen044228d2001-07-17 01:12:36 +0000829static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000830{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000831 struct arch_symbol *sym;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000832 sym = xzalloc(sizeof(*sym));
Eric Andersen9f16d612000-06-12 23:11:16 +0000833 return &sym->root;
834}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000835
Eric Andersen044228d2001-07-17 01:12:36 +0000836static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000837arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000838 struct obj_section *targsec,
Denis Vlasenko68404f12008-03-17 09:00:54 +0000839 /*struct obj_section *symsec,*/
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000840 struct obj_symbol *sym,
841 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000842{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000843 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000844 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000845 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
846 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000847#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000848 struct arch_symbol *isym = (struct arch_symbol *) sym;
849#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000850#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000851#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000852 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000853#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000854#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000855#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000856 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000857 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000858# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000859 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000860# else
Eric Andersencffd5022002-05-24 06:50:15 +0000861 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000862# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000863#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000864
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000865 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000866
Eric Andersencffd5022002-05-24 06:50:15 +0000867#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000868
Eric Andersen3b1a7442003-12-24 20:30:45 +0000869 case R_ARM_NONE:
870 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000871
Eric Andersen3b1a7442003-12-24 20:30:45 +0000872 case R_ARM_ABS32:
873 *loc += v;
874 break;
Miles Baderae28b042002-04-01 09:34:25 +0000875
Eric Andersen3b1a7442003-12-24 20:30:45 +0000876 case R_ARM_GOT32:
877 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000878
Eric Andersen3b1a7442003-12-24 20:30:45 +0000879 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000880 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
881 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000882 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000883
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 *loc += got - dot;
885 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000886
Eric Andersen3b1a7442003-12-24 20:30:45 +0000887 case R_ARM_PC24:
888 case R_ARM_PLT32:
889 goto bb_use_plt;
890
891 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 *loc += v - got;
893 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000895#elif defined(__cris__)
896
897 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000898 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000899
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000900 case R_CRIS_32:
901 /* CRIS keeps the relocation value in the r_addend field and
902 * should not use whats in *loc at all
903 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000904 *loc = v;
905 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000906
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000907#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000908
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000909 case R_H8_DIR24R8:
910 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
911 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000913 case R_H8_DIR24A8:
914 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000915 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000916 case R_H8_DIR32:
917 case R_H8_DIR32A16:
918 *loc += v;
919 break;
920 case R_H8_PCREL16:
921 v -= dot + 2;
922 if ((ElfW(Sword))v > 0x7fff ||
923 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
924 ret = obj_reloc_overflow;
925 else
926 *(unsigned short *)loc = v;
927 break;
928 case R_H8_PCREL8:
929 v -= dot + 1;
930 if ((ElfW(Sword))v > 0x7f ||
931 (ElfW(Sword))v < -(ElfW(Sword))0x80)
932 ret = obj_reloc_overflow;
933 else
934 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000935 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000936
Eric Andersencffd5022002-05-24 06:50:15 +0000937#elif defined(__i386__)
938
Eric Andersen3b1a7442003-12-24 20:30:45 +0000939 case R_386_NONE:
940 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000941
Eric Andersen3b1a7442003-12-24 20:30:45 +0000942 case R_386_32:
943 *loc += v;
944 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000945
Eric Andersen3b1a7442003-12-24 20:30:45 +0000946 case R_386_PLT32:
947 case R_386_PC32:
948 *loc += v - dot;
949 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000950
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 case R_386_GLOB_DAT:
952 case R_386_JMP_SLOT:
953 *loc = v;
954 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000955
Eric Andersen3b1a7442003-12-24 20:30:45 +0000956 case R_386_RELATIVE:
957 *loc += f->baseaddr;
958 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000961 *loc += got - dot;
962 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000963
Eric Andersen3b1a7442003-12-24 20:30:45 +0000964 case R_386_GOT32:
965 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000966
Eric Andersen3b1a7442003-12-24 20:30:45 +0000967 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000968 *loc += v - got;
969 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000970
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000971#elif defined(__microblaze__)
Mike Frysinger280dae72006-06-06 06:30:32 +0000972 case R_MICROBLAZE_NONE:
973 case R_MICROBLAZE_64_NONE:
974 case R_MICROBLAZE_32_SYM_OP_SYM:
975 case R_MICROBLAZE_32_PCREL:
976 break;
977
978 case R_MICROBLAZE_64_PCREL: {
979 /* dot is the address of the current instruction.
980 * v is the target symbol address.
981 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000982 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000983 * of this instruction.
984 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
985 */
986
987 /* Get split offset stored in code */
988 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
989 (loc[1] & 0xFFFF);
990
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000991 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +0000992 * because dot points to the IMM insn, but branch
993 * is computed relative to the branch instruction itself.
994 */
995 temp += v - dot - 4;
996
997 /* Store back into code */
998 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
999 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1000
1001 break;
1002 }
1003
1004 case R_MICROBLAZE_32:
1005 *loc += v;
1006 break;
1007
1008 case R_MICROBLAZE_64: {
1009 /* Get split pointer stored in code */
1010 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1011 (loc[1] & 0xFFFF);
1012
1013 /* Add reloc offset */
1014 temp1+=v;
1015
1016 /* Store back into code */
1017 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1018 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1019
1020 break;
1021 }
1022
1023 case R_MICROBLAZE_32_PCREL_LO:
1024 case R_MICROBLAZE_32_LO:
1025 case R_MICROBLAZE_SRO32:
1026 case R_MICROBLAZE_SRW32:
1027 ret = obj_reloc_unhandled;
1028 break;
1029
Eric Andersencffd5022002-05-24 06:50:15 +00001030#elif defined(__mc68000__)
1031
Eric Andersen3b1a7442003-12-24 20:30:45 +00001032 case R_68K_NONE:
1033 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001034
Eric Andersen3b1a7442003-12-24 20:30:45 +00001035 case R_68K_32:
1036 *loc += v;
1037 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001038
Eric Andersen3b1a7442003-12-24 20:30:45 +00001039 case R_68K_8:
1040 if (v > 0xff) {
1041 ret = obj_reloc_overflow;
1042 }
1043 *(char *)loc = v;
1044 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001045
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_16:
1047 if (v > 0xffff) {
1048 ret = obj_reloc_overflow;
1049 }
1050 *(short *)loc = v;
1051 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_68K_PC8:
1054 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001055 if ((ElfW(Sword))v > 0x7f ||
1056 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001057 ret = obj_reloc_overflow;
1058 }
1059 *(char *)loc = v;
1060 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001061
Eric Andersen3b1a7442003-12-24 20:30:45 +00001062 case R_68K_PC16:
1063 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001064 if ((ElfW(Sword))v > 0x7fff ||
1065 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001066 ret = obj_reloc_overflow;
1067 }
1068 *(short *)loc = v;
1069 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001070
Eric Andersen3b1a7442003-12-24 20:30:45 +00001071 case R_68K_PC32:
1072 *(int *)loc = v - dot;
1073 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001074
Eric Andersen3b1a7442003-12-24 20:30:45 +00001075 case R_68K_GLOB_DAT:
1076 case R_68K_JMP_SLOT:
1077 *loc = v;
1078 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001079
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080 case R_68K_RELATIVE:
1081 *(int *)loc += f->baseaddr;
1082 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001083
Eric Andersen3b1a7442003-12-24 20:30:45 +00001084 case R_68K_GOT32:
1085 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001086
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001087# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001088 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089 *loc += v - got;
1090 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001091# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001092
1093#elif defined(__mips__)
1094
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095 case R_MIPS_NONE:
1096 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001097
Eric Andersen3b1a7442003-12-24 20:30:45 +00001098 case R_MIPS_32:
1099 *loc += v;
1100 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001101
Eric Andersen3b1a7442003-12-24 20:30:45 +00001102 case R_MIPS_26:
1103 if (v % 4)
1104 ret = obj_reloc_dangerous;
1105 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1106 ret = obj_reloc_overflow;
1107 *loc =
1108 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1109 0x03ffffff);
1110 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001111
Eric Andersen3b1a7442003-12-24 20:30:45 +00001112 case R_MIPS_HI16:
1113 {
1114 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001115
Eric Andersen3b1a7442003-12-24 20:30:45 +00001116 /* We cannot relocate this one now because we don't know the value
1117 of the carry we need to add. Save the information, and let LO16
1118 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001119 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001120 n->addr = loc;
1121 n->value = v;
1122 n->next = ifile->mips_hi16_list;
1123 ifile->mips_hi16_list = n;
1124 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001125 }
1126
Eric Andersen3b1a7442003-12-24 20:30:45 +00001127 case R_MIPS_LO16:
1128 {
1129 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001130 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001131
1132 /* Sign extend the addend we extract from the lo insn. */
1133 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1134
1135 if (ifile->mips_hi16_list != NULL) {
1136 struct mips_hi16 *l;
1137
1138 l = ifile->mips_hi16_list;
1139 while (l != NULL) {
1140 struct mips_hi16 *next;
1141 unsigned long insn;
1142
Eric Andersen3b1a7442003-12-24 20:30:45 +00001143 /* Do the HI16 relocation. Note that we actually don't
1144 need to know anything about the LO16 itself, except where
1145 to find the low 16 bits of the addend needed by the LO16. */
1146 insn = *l->addr;
1147 val =
1148 ((insn & 0xffff) << 16) +
1149 vallo;
1150 val += v;
1151
1152 /* Account for the sign extension that will happen in the
1153 low bits. */
1154 val =
1155 ((val >> 16) +
1156 ((val & 0x8000) !=
1157 0)) & 0xffff;
1158
1159 insn = (insn & ~0xffff) | val;
1160 *l->addr = insn;
1161
1162 next = l->next;
1163 free(l);
1164 l = next;
1165 }
1166
1167 ifile->mips_hi16_list = NULL;
1168 }
1169
1170 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1171 val = v + vallo;
1172 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1173 *loc = insnlo;
1174 break;
1175 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001176
Mike Frysingerf982d862006-01-04 00:11:26 +00001177#elif defined(__nios2__)
1178
1179 case R_NIOS2_NONE:
1180 break;
1181
1182 case R_NIOS2_BFD_RELOC_32:
1183 *loc += v;
1184 break;
1185
1186 case R_NIOS2_BFD_RELOC_16:
1187 if (v > 0xffff) {
1188 ret = obj_reloc_overflow;
1189 }
1190 *(short *)loc = v;
1191 break;
1192
1193 case R_NIOS2_BFD_RELOC_8:
1194 if (v > 0xff) {
1195 ret = obj_reloc_overflow;
1196 }
1197 *(char *)loc = v;
1198 break;
1199
1200 case R_NIOS2_S16:
1201 {
1202 Elf32_Addr word;
1203
1204 if ((Elf32_Sword)v > 0x7fff ||
1205 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1206 ret = obj_reloc_overflow;
1207 }
1208
1209 word = *loc;
1210 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1211 (word & 0x3f);
1212 }
1213 break;
1214
1215 case R_NIOS2_U16:
1216 {
1217 Elf32_Addr word;
1218
1219 if (v > 0xffff) {
1220 ret = obj_reloc_overflow;
1221 }
1222
1223 word = *loc;
1224 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1225 (word & 0x3f);
1226 }
1227 break;
1228
1229 case R_NIOS2_PCREL16:
1230 {
1231 Elf32_Addr word;
1232
1233 v -= dot + 4;
1234 if ((Elf32_Sword)v > 0x7fff ||
1235 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1236 ret = obj_reloc_overflow;
1237 }
1238
1239 word = *loc;
1240 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1241 }
1242 break;
1243
1244 case R_NIOS2_GPREL:
1245 {
1246 Elf32_Addr word, gp;
1247 /* get _gp */
1248 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1249 v-=gp;
1250 if ((Elf32_Sword)v > 0x7fff ||
1251 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1252 ret = obj_reloc_overflow;
1253 }
1254
1255 word = *loc;
1256 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1257 }
1258 break;
1259
1260 case R_NIOS2_CALL26:
1261 if (v & 3)
1262 ret = obj_reloc_dangerous;
1263 if ((v >> 28) != (dot >> 28))
1264 ret = obj_reloc_overflow;
1265 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1266 break;
1267
1268 case R_NIOS2_IMM5:
1269 {
1270 Elf32_Addr word;
1271
1272 if (v > 0x1f) {
1273 ret = obj_reloc_overflow;
1274 }
1275
1276 word = *loc & ~0x7c0;
1277 *loc = word | ((v & 0x1f) << 6);
1278 }
1279 break;
1280
1281 case R_NIOS2_IMM6:
1282 {
1283 Elf32_Addr word;
1284
1285 if (v > 0x3f) {
1286 ret = obj_reloc_overflow;
1287 }
1288
1289 word = *loc & ~0xfc0;
1290 *loc = word | ((v & 0x3f) << 6);
1291 }
1292 break;
1293
1294 case R_NIOS2_IMM8:
1295 {
1296 Elf32_Addr word;
1297
1298 if (v > 0xff) {
1299 ret = obj_reloc_overflow;
1300 }
1301
1302 word = *loc & ~0x3fc0;
1303 *loc = word | ((v & 0xff) << 6);
1304 }
1305 break;
1306
1307 case R_NIOS2_HI16:
1308 {
1309 Elf32_Addr word;
1310
1311 word = *loc;
1312 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1313 (word & 0x3f);
1314 }
1315 break;
1316
1317 case R_NIOS2_LO16:
1318 {
1319 Elf32_Addr word;
1320
1321 word = *loc;
1322 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1323 (word & 0x3f);
1324 }
1325 break;
1326
1327 case R_NIOS2_HIADJ16:
1328 {
1329 Elf32_Addr word1, word2;
1330
1331 word1 = *loc;
1332 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1333 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1334 (word1 & 0x3f);
1335 }
1336 break;
1337
Mike Frysingerebee0e72006-02-18 06:14:31 +00001338#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001339 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001340
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001341#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001342
Eric Andersen3b1a7442003-12-24 20:30:45 +00001343 case R_PPC_ADDR16_HA:
1344 *(unsigned short *)loc = (v + 0x8000) >> 16;
1345 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001346
Eric Andersen3b1a7442003-12-24 20:30:45 +00001347 case R_PPC_ADDR16_HI:
1348 *(unsigned short *)loc = v >> 16;
1349 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001350
Eric Andersen3b1a7442003-12-24 20:30:45 +00001351 case R_PPC_ADDR16_LO:
1352 *(unsigned short *)loc = v;
1353 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001354
Eric Andersen3b1a7442003-12-24 20:30:45 +00001355 case R_PPC_REL24:
1356 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001357
Eric Andersen3b1a7442003-12-24 20:30:45 +00001358 case R_PPC_REL32:
1359 *loc = v - dot;
1360 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001361
Eric Andersen3b1a7442003-12-24 20:30:45 +00001362 case R_PPC_ADDR32:
1363 *loc = v;
1364 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001365
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001366#elif defined(__s390__)
1367
1368 case R_390_32:
1369 *(unsigned int *) loc += v;
1370 break;
1371 case R_390_16:
1372 *(unsigned short *) loc += v;
1373 break;
1374 case R_390_8:
1375 *(unsigned char *) loc += v;
1376 break;
1377
1378 case R_390_PC32:
1379 *(unsigned int *) loc += v - dot;
1380 break;
1381 case R_390_PC16DBL:
1382 *(unsigned short *) loc += (v - dot) >> 1;
1383 break;
1384 case R_390_PC16:
1385 *(unsigned short *) loc += v - dot;
1386 break;
1387
1388 case R_390_PLT32:
1389 case R_390_PLT16DBL:
1390 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001391 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001392 if (pe->inited == 0) {
1393 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1394 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1395 ip[1] = 0x100607f1;
1396 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1397 ip[2] = v - 2;
1398 else
1399 ip[2] = v;
1400 pe->inited = 1;
1401 }
1402
1403 /* Insert relative distance to target. */
1404 v = plt + pe->offset - dot;
1405 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1406 *(unsigned int *) loc = (unsigned int) v;
1407 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1408 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1409 break;
1410
1411 case R_390_GLOB_DAT:
1412 case R_390_JMP_SLOT:
1413 *loc = v;
1414 break;
1415
1416 case R_390_RELATIVE:
1417 *loc += f->baseaddr;
1418 break;
1419
1420 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001421 *(unsigned long *) loc += got - dot;
1422 break;
1423
1424 case R_390_GOT12:
1425 case R_390_GOT16:
1426 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001427 if (!isym->gotent.inited)
1428 {
1429 isym->gotent.inited = 1;
1430 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1431 }
1432 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1433 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1434 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1435 *(unsigned short *) loc += isym->gotent.offset;
1436 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1437 *(unsigned int *) loc += isym->gotent.offset;
1438 break;
1439
1440# ifndef R_390_GOTOFF32
1441# define R_390_GOTOFF32 R_390_GOTOFF
1442# endif
1443 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001444 *loc += v - got;
1445 break;
1446
Eric Andersencffd5022002-05-24 06:50:15 +00001447#elif defined(__sh__)
1448
Eric Andersen3b1a7442003-12-24 20:30:45 +00001449 case R_SH_NONE:
1450 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001451
Eric Andersen3b1a7442003-12-24 20:30:45 +00001452 case R_SH_DIR32:
1453 *loc += v;
1454 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001455
Eric Andersen3b1a7442003-12-24 20:30:45 +00001456 case R_SH_REL32:
1457 *loc += v - dot;
1458 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001459
Eric Andersen3b1a7442003-12-24 20:30:45 +00001460 case R_SH_PLT32:
1461 *loc = v - dot;
1462 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001463
Eric Andersen3b1a7442003-12-24 20:30:45 +00001464 case R_SH_GLOB_DAT:
1465 case R_SH_JMP_SLOT:
1466 *loc = v;
1467 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001468
Eric Andersen3b1a7442003-12-24 20:30:45 +00001469 case R_SH_RELATIVE:
1470 *loc = f->baseaddr + rel->r_addend;
1471 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001472
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001474 *loc = got - dot + rel->r_addend;
1475 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001476
Eric Andersen3b1a7442003-12-24 20:30:45 +00001477 case R_SH_GOT32:
1478 goto bb_use_got;
1479
1480 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001481 *loc = v - got;
1482 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001483
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001484# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001485 case R_SH_IMM_MEDLOW16:
1486 case R_SH_IMM_LOW16:
1487 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001488 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001489
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001490 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001491 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001492
Eric Andersen3b1a7442003-12-24 20:30:45 +00001493 /*
1494 * movi and shori have the format:
1495 *
1496 * | op | imm | reg | reserved |
1497 * 31..26 25..10 9.. 4 3 .. 0
1498 *
1499 * so we simply mask and or in imm.
1500 */
1501 word = *loc & ~0x3fffc00;
1502 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001503
Eric Andersen3b1a7442003-12-24 20:30:45 +00001504 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001505
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 break;
1507 }
Eric Andersenbf833552003-08-13 19:56:33 +00001508
Eric Andersen3b1a7442003-12-24 20:30:45 +00001509 case R_SH_IMM_MEDLOW16_PCREL:
1510 case R_SH_IMM_LOW16_PCREL:
1511 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001512 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001513
Eric Andersen3b1a7442003-12-24 20:30:45 +00001514 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001515
Eric Andersen3b1a7442003-12-24 20:30:45 +00001516 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001517
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001518 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001520
Eric Andersen3b1a7442003-12-24 20:30:45 +00001521 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001522
Eric Andersen3b1a7442003-12-24 20:30:45 +00001523 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001524
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 break;
1526 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001527# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001528
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001529#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001530
Eric Andersen3b1a7442003-12-24 20:30:45 +00001531 case R_V850_NONE:
1532 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001533
Eric Andersen3b1a7442003-12-24 20:30:45 +00001534 case R_V850_32:
1535 /* We write two shorts instead of a long because even
1536 32-bit insns only need half-word alignment, but
1537 32-bit data needs to be long-word aligned. */
1538 v += ((unsigned short *)loc)[0];
1539 v += ((unsigned short *)loc)[1] << 16;
1540 ((unsigned short *)loc)[0] = v & 0xffff;
1541 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1542 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001543
Eric Andersen3b1a7442003-12-24 20:30:45 +00001544 case R_V850_22_PCREL:
1545 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001546
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001547#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001548
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001549 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001550 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001551
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001552 case R_X86_64_64:
1553 *loc += v;
1554 break;
1555
1556 case R_X86_64_32:
1557 *(unsigned int *) loc += v;
1558 if (v > 0xffffffff)
1559 {
1560 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1561 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1562 }
1563 break;
1564
1565 case R_X86_64_32S:
1566 *(signed int *) loc += v;
1567 break;
1568
1569 case R_X86_64_16:
1570 *(unsigned short *) loc += v;
1571 break;
1572
1573 case R_X86_64_8:
1574 *(unsigned char *) loc += v;
1575 break;
1576
1577 case R_X86_64_PC32:
1578 *(unsigned int *) loc += v - dot;
1579 break;
1580
1581 case R_X86_64_PC16:
1582 *(unsigned short *) loc += v - dot;
1583 break;
1584
1585 case R_X86_64_PC8:
1586 *(unsigned char *) loc += v - dot;
1587 break;
1588
1589 case R_X86_64_GLOB_DAT:
1590 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001591 *loc = v;
1592 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001593
1594 case R_X86_64_RELATIVE:
1595 *loc += f->baseaddr;
1596 break;
1597
1598 case R_X86_64_GOT32:
1599 case R_X86_64_GOTPCREL:
1600 goto bb_use_got;
1601# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001602 if (!isym->gotent.reloc_done)
1603 {
1604 isym->gotent.reloc_done = 1;
1605 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1606 }
1607 /* XXX are these really correct? */
1608 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1609 *(unsigned int *) loc += v + isym->gotent.offset;
1610 else
1611 *loc += isym->gotent.offset;
1612 break;
1613# endif
1614
Mike Frysingerf982d862006-01-04 00:11:26 +00001615#else
1616# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001617#endif
1618
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001619 default:
1620 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1621 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001622 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001623
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001624#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001625
Eric Andersen3b1a7442003-12-24 20:30:45 +00001626bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001627
Eric Andersen3b1a7442003-12-24 20:30:45 +00001628 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001629
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001630#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001631 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1632 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001633#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001634 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001635#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001636
Eric Andersen3b1a7442003-12-24 20:30:45 +00001637 if (! pe->inited) {
1638 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001639
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001641
1642#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001643 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1644 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001645#endif
1646#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001648 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 ip[2] = 0x7d6903a6; /* mtctr r11 */
1650 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001651#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001652#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 /* We have to trash a register, so we assume that any control
1654 transfer more than 21-bits away must be a function call
1655 (so we can use a call-clobbered register). */
1656 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1657 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001658#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 pe->inited = 1;
1660 }
Eric Andersen21adca72000-12-06 18:18:26 +00001661
Eric Andersen3b1a7442003-12-24 20:30:45 +00001662 /* relative distance to target */
1663 v -= dot;
1664 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001665#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001666 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001667#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001668 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001669#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001670 /* go via the plt */
1671 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001672
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001673#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001674 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001675#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001677#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001679
Eric Andersen3b1a7442003-12-24 20:30:45 +00001680 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001681#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 /* Convert to words. */
1683 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001684
Eric Andersen3b1a7442003-12-24 20:30:45 +00001685 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001686#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001687#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001689#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001690#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001691 /* We write two shorts instead of a long because even 32-bit insns
1692 only need half-word alignment, but the 32-bit data write needs
1693 to be long-word aligned. */
1694 ((unsigned short *)loc)[0] =
1695 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1696 | ((v >> 16) & 0x3f); /* offs high part */
1697 ((unsigned short *)loc)[1] =
1698 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001699#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001700 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001701#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001702
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001703#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001704bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001705
Eric Andersen3b1a7442003-12-24 20:30:45 +00001706 /* needs an entry in the .got: set it, once */
1707 if (!isym->gotent.inited) {
1708 isym->gotent.inited = 1;
1709 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1710 }
1711 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001712#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001713 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001714#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001715 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001716#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001717 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001718
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001719#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001720 }
1721
1722 return ret;
1723}
1724
Eric Andersencffd5022002-05-24 06:50:15 +00001725
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001726#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001727
1728static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1729 int offset, int size)
1730{
1731 struct arch_list_entry *pe;
1732
1733 for (pe = *list; pe != NULL; pe = pe->next) {
1734 if (pe->addend == rel->r_addend) {
1735 break;
1736 }
1737 }
1738
1739 if (pe == NULL) {
1740 pe = xmalloc(sizeof(struct arch_list_entry));
1741 pe->next = *list;
1742 pe->addend = rel->r_addend;
1743 pe->offset = offset;
1744 pe->inited = 0;
1745 *list = pe;
1746 return size;
1747 }
1748 return 0;
1749}
1750
1751#endif
1752
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001753#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001754
Denis Vlasenko68404f12008-03-17 09:00:54 +00001755static int arch_single_init(/*ElfW(RelM) *rel,*/ struct arch_single_entry *single,
Eric Andersencffd5022002-05-24 06:50:15 +00001756 int offset, int size)
1757{
1758 if (single->allocated == 0) {
1759 single->allocated = 1;
1760 single->offset = offset;
1761 single->inited = 0;
1762 return size;
1763 }
1764 return 0;
1765}
1766
1767#endif
1768
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001769#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001770
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001771static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001772 int offset, int size)
1773{
1774 struct obj_section *myrelsec = obj_find_section(f, name);
1775
1776 if (offset == 0) {
1777 offset += size;
1778 }
1779
1780 if (myrelsec) {
1781 obj_extend_section(myrelsec, offset);
1782 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001783 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001784 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001785 }
1786
1787 return myrelsec;
1788}
1789
1790#endif
1791
1792static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001793{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001794#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001795 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001796 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001797#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001798 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001799#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001800#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001801 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001802#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001803 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001804 ElfW(RelM) *rel, *relend;
1805 ElfW(Sym) *symtab, *extsym;
1806 const char *strtab, *name;
1807 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001808
Eric Andersen21adca72000-12-06 18:18:26 +00001809 for (i = 0; i < f->header.e_shnum; ++i) {
1810 relsec = f->sections[i];
1811 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001812 continue;
1813
Eric Andersen21adca72000-12-06 18:18:26 +00001814 symsec = f->sections[relsec->header.sh_link];
1815 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001816
Eric Andersen21adca72000-12-06 18:18:26 +00001817 rel = (ElfW(RelM) *) relsec->contents;
1818 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1819 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001820 strtab = (const char *) strsec->contents;
1821
1822 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001823 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001824
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001825#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001826 got_allocate = 0;
1827#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001828#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001829 plt_allocate = 0;
1830#endif
1831
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001832 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001833#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001834 case R_ARM_PC24:
1835 case R_ARM_PLT32:
1836 plt_allocate = 1;
1837 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001838
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001839 case R_ARM_GOTOFF:
1840 case R_ARM_GOTPC:
1841 got_needed = 1;
1842 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001843
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001844 case R_ARM_GOT32:
1845 got_allocate = 1;
1846 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001847
Eric Andersen21adca72000-12-06 18:18:26 +00001848#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001849 case R_386_GOTPC:
1850 case R_386_GOTOFF:
1851 got_needed = 1;
1852 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001853
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001854 case R_386_GOT32:
1855 got_allocate = 1;
1856 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001857
1858#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001859 case R_PPC_REL24:
1860 plt_allocate = 1;
1861 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001862
1863#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001864 case R_68K_GOT32:
1865 got_allocate = 1;
1866 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001867
Eric Andersen16451a02004-03-19 12:16:18 +00001868#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001869 case R_68K_GOTOFF:
1870 got_needed = 1;
1871 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001872#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001873
1874#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001875 case R_SH_GOT32:
1876 got_allocate = 1;
1877 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001878
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001879 case R_SH_GOTPC:
1880 case R_SH_GOTOFF:
1881 got_needed = 1;
1882 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001883
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001884#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001885 case R_V850_22_PCREL:
1886 plt_needed = 1;
1887 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001888
1889#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001890 default:
1891 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001892 }
1893
Eric Andersen21adca72000-12-06 18:18:26 +00001894 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001895 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001896 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001897 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001898 }
1899 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001900#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001901 if (got_allocate) {
1902 got_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001903 /*rel,*/ &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001904 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001905
1906 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001907 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001908#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001909#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001910 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001911#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001912 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001913 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001914 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001915#else
1916 plt_offset += arch_single_init(
Denis Vlasenko68404f12008-03-17 09:00:54 +00001917 /*rel,*/ &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001918 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001919#endif
1920 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001921 }
1922#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001923 }
Miles Baderae28b042002-04-01 09:34:25 +00001924 }
Eric Andersen21adca72000-12-06 18:18:26 +00001925
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001926#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001927 if (got_needed) {
1928 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001929 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001930 }
Eric Andersen21adca72000-12-06 18:18:26 +00001931#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001932
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001933#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001934 if (plt_needed) {
1935 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001936 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001937 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001938#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001939
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001940#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001941}
1942
Eric Andersen9f16d612000-06-12 23:11:16 +00001943/*======================================================================*/
1944
1945/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001946static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001947{
1948 unsigned long h = 0;
1949 unsigned long g;
1950 unsigned char ch;
1951
1952 while (n > 0) {
1953 ch = *name++;
1954 h = (h << 4) + ch;
Denis Vlasenko1bec1b92007-11-06 02:23:39 +00001955 g = (h & 0xf0000000);
1956 if (g != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001957 h ^= g >> 24;
1958 h &= ~g;
1959 }
1960 n--;
1961 }
1962 return h;
1963}
1964
Eric Andersen044228d2001-07-17 01:12:36 +00001965static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001966{
1967 return obj_elf_hash_n(name, strlen(name));
1968}
1969
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001970#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001971/* String comparison for non-co-versioned kernel and module. */
1972
1973static int ncv_strcmp(const char *a, const char *b)
1974{
1975 size_t alen = strlen(a), blen = strlen(b);
1976
1977 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1978 return strncmp(a, b, alen);
1979 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1980 return strncmp(a, b, blen);
1981 else
1982 return strcmp(a, b);
1983}
1984
1985/* String hashing for non-co-versioned kernel and module. Here
1986 we are simply forced to drop the crc from the hash. */
1987
1988static unsigned long ncv_symbol_hash(const char *str)
1989{
1990 size_t len = strlen(str);
1991 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1992 len -= 10;
1993 return obj_elf_hash_n(str, len);
1994}
1995
Eric Andersen044228d2001-07-17 01:12:36 +00001996static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001997obj_set_symbol_compare(struct obj_file *f,
1998 int (*cmp) (const char *, const char *),
1999 unsigned long (*hash) (const char *))
2000{
2001 if (cmp)
2002 f->symbol_cmp = cmp;
2003 if (hash) {
2004 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2005 int i;
2006
2007 f->symbol_hash = hash;
2008
2009 memcpy(tmptab, f->symtab, sizeof(tmptab));
2010 memset(f->symtab, 0, sizeof(f->symtab));
2011
2012 for (i = 0; i < HASH_BUCKETS; ++i)
2013 for (sym = tmptab[i]; sym; sym = next) {
2014 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2015 next = sym->next;
2016 sym->next = f->symtab[h];
2017 f->symtab[h] = sym;
2018 }
2019 }
2020}
2021
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002022#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002023
Eric Andersen044228d2001-07-17 01:12:36 +00002024static struct obj_symbol *
2025obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002026 unsigned long symidx, int info,
2027 int secidx, ElfW(Addr) value,
2028 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002029{
2030 struct obj_symbol *sym;
2031 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002032 int n_type = ELF_ST_TYPE(info);
2033 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002034
2035 for (sym = f->symtab[hash]; sym; sym = sym->next)
2036 if (f->symbol_cmp(sym->name, name) == 0) {
2037 int o_secidx = sym->secidx;
2038 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002039 int o_type = ELF_ST_TYPE(o_info);
2040 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002041
2042 /* A redefinition! Is it legal? */
2043
2044 if (secidx == SHN_UNDEF)
2045 return sym;
2046 else if (o_secidx == SHN_UNDEF)
2047 goto found;
2048 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2049 /* Cope with local and global symbols of the same name
2050 in the same object file, as might have been created
2051 by ld -r. The only reason locals are now seen at this
2052 level at all is so that we can do semi-sensible things
2053 with parameters. */
2054
2055 struct obj_symbol *nsym, **p;
2056
2057 nsym = arch_new_symbol();
2058 nsym->next = sym->next;
2059 nsym->ksymidx = -1;
2060
2061 /* Excise the old (local) symbol from the hash chain. */
2062 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2063 continue;
2064 *p = sym = nsym;
2065 goto found;
2066 } else if (n_binding == STB_LOCAL) {
2067 /* Another symbol of the same name has already been defined.
2068 Just add this to the local table. */
2069 sym = arch_new_symbol();
2070 sym->next = NULL;
2071 sym->ksymidx = -1;
2072 f->local_symtab[symidx] = sym;
2073 goto found;
2074 } else if (n_binding == STB_WEAK)
2075 return sym;
2076 else if (o_binding == STB_WEAK)
2077 goto found;
2078 /* Don't unify COMMON symbols with object types the programmer
2079 doesn't expect. */
2080 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002081 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002082 return sym;
2083 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002084 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002085 goto found;
2086 else {
2087 /* Don't report an error if the symbol is coming from
2088 the kernel or some external module. */
2089 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002090 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002091 return sym;
2092 }
2093 }
2094
2095 /* Completely new symbol. */
2096 sym = arch_new_symbol();
2097 sym->next = f->symtab[hash];
2098 f->symtab[hash] = sym;
2099 sym->ksymidx = -1;
2100
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002101 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002102 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002103 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002104 name, (long) symidx, (long) f->local_symtab_size);
2105 else
2106 f->local_symtab[symidx] = sym;
2107 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002108
Eric Andersen3b1a7442003-12-24 20:30:45 +00002109found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002110 sym->name = name;
2111 sym->value = value;
2112 sym->size = size;
2113 sym->secidx = secidx;
2114 sym->info = info;
2115
2116 return sym;
2117}
2118
Eric Andersen044228d2001-07-17 01:12:36 +00002119static struct obj_symbol *
2120obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002121{
2122 struct obj_symbol *sym;
2123 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2124
2125 for (sym = f->symtab[hash]; sym; sym = sym->next)
2126 if (f->symbol_cmp(sym->name, name) == 0)
2127 return sym;
2128
2129 return NULL;
2130}
2131
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002132static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002133{
2134 if (sym) {
2135 if (sym->secidx >= SHN_LORESERVE)
2136 return sym->value;
2137
2138 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2139 } else {
2140 /* As a special case, a NULL sym has value zero. */
2141 return 0;
2142 }
2143}
2144
Eric Andersen044228d2001-07-17 01:12:36 +00002145static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002146{
2147 int i, n = f->header.e_shnum;
2148
2149 for (i = 0; i < n; ++i)
2150 if (strcmp(f->sections[i]->name, name) == 0)
2151 return f->sections[i];
2152
2153 return NULL;
2154}
2155
2156static int obj_load_order_prio(struct obj_section *a)
2157{
2158 unsigned long af, ac;
2159
2160 af = a->header.sh_flags;
2161
2162 ac = 0;
2163 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002164 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002165 ac |= 32;
2166 if (af & SHF_ALLOC)
2167 ac |= 16;
2168 if (!(af & SHF_WRITE))
2169 ac |= 8;
2170 if (af & SHF_EXECINSTR)
2171 ac |= 4;
2172 if (a->header.sh_type != SHT_NOBITS)
2173 ac |= 2;
2174
2175 return ac;
2176}
2177
Eric Andersen044228d2001-07-17 01:12:36 +00002178static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002179obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2180{
2181 struct obj_section **p;
2182 int prio = obj_load_order_prio(sec);
2183 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2184 if (obj_load_order_prio(*p) < prio)
2185 break;
2186 sec->load_next = *p;
2187 *p = sec;
2188}
2189
Eric Andersen044228d2001-07-17 01:12:36 +00002190static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002191 const char *name,
2192 unsigned long align,
2193 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002194{
2195 int newidx = f->header.e_shnum++;
2196 struct obj_section *sec;
2197
2198 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2199 f->sections[newidx] = sec = arch_new_section();
2200
Eric Andersen9f16d612000-06-12 23:11:16 +00002201 sec->header.sh_type = SHT_PROGBITS;
2202 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2203 sec->header.sh_size = size;
2204 sec->header.sh_addralign = align;
2205 sec->name = name;
2206 sec->idx = newidx;
2207 if (size)
2208 sec->contents = xmalloc(size);
2209
2210 obj_insert_section_load_order(f, sec);
2211
2212 return sec;
2213}
2214
Eric Andersen044228d2001-07-17 01:12:36 +00002215static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002216 const char *name,
2217 unsigned long align,
2218 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002219{
2220 int newidx = f->header.e_shnum++;
2221 struct obj_section *sec;
2222
2223 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2224 f->sections[newidx] = sec = arch_new_section();
2225
Eric Andersen9f16d612000-06-12 23:11:16 +00002226 sec->header.sh_type = SHT_PROGBITS;
2227 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2228 sec->header.sh_size = size;
2229 sec->header.sh_addralign = align;
2230 sec->name = name;
2231 sec->idx = newidx;
2232 if (size)
2233 sec->contents = xmalloc(size);
2234
2235 sec->load_next = f->load_order;
2236 f->load_order = sec;
2237 if (f->load_order_search_start == &f->load_order)
2238 f->load_order_search_start = &sec->load_next;
2239
2240 return sec;
2241}
2242
Eric Andersen044228d2001-07-17 01:12:36 +00002243static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002244{
2245 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002246 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002247 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2248 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002249 return sec->contents + oldsize;
2250}
2251
2252
Eric Andersen9f16d612000-06-12 23:11:16 +00002253/* Conditionally add the symbols from the given symbol set to the
2254 new module. */
2255
2256static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002257add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002258 int idx, struct new_module_symbol *syms, size_t nsyms)
2259{
2260 struct new_module_symbol *s;
2261 size_t i;
2262 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002263#ifdef SYMBOL_PREFIX
2264 char *name_buf = 0;
2265 size_t name_alloced_size = 0;
2266#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002267#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002268 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002269
Glenn L McGrath759515c2003-08-30 06:00:33 +00002270 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002271#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002272 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002273 /* Only add symbols that are already marked external.
2274 If we override locals we may cause problems for
2275 argument initialization. We will also create a false
2276 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002277 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002278 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002279
Glenn L McGrath759515c2003-08-30 06:00:33 +00002280 /* GPL licensed modules can use symbols exported with
2281 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2282 * exported names. Non-GPL modules never see any GPLONLY_
2283 * symbols so they cannot fudge it by adding the prefix on
2284 * their references.
2285 */
2286 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002287#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002288 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002289 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002290 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002291#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002292 continue;
2293 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002294 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002295
Miles Baderae28b042002-04-01 09:34:25 +00002296#ifdef SYMBOL_PREFIX
2297 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2298 kernel exports `C names', but module object files
2299 reference `linker names'). */
2300 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002301 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002302 if (name_size > name_alloced_size) {
2303 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002304 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002305 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002306 strcpy(name_buf, SYMBOL_PREFIX);
2307 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002308 name = name_buf;
2309#endif /* SYMBOL_PREFIX */
2310
2311 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002312 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002313#ifdef SYMBOL_PREFIX
2314 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002315 name = xmalloc(name_size);
2316 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002317#endif
2318 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002319 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002320 STT_NOTYPE),
2321 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002322 /* Did our symbol just get installed? If so, mark the
2323 module as "used". */
2324 if (sym->secidx == idx)
2325 used = 1;
2326 }
2327 }
2328
2329 return used;
2330}
2331
2332static void add_kernel_symbols(struct obj_file *f)
2333{
2334 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002335 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002336
2337 /* Add module symbols first. */
2338
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002339 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002340 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002341 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2342 ) {
2343 m->used = 1;
2344 ++nused;
2345 }
2346 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002347
2348 n_ext_modules_used = nused;
2349
2350 /* And finally the symbols from the kernel proper. */
2351
2352 if (nksyms)
2353 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2354}
2355
2356static char *get_modinfo_value(struct obj_file *f, const char *key)
2357{
2358 struct obj_section *sec;
2359 char *p, *v, *n, *ep;
2360 size_t klen = strlen(key);
2361
2362 sec = obj_find_section(f, ".modinfo");
2363 if (sec == NULL)
2364 return NULL;
2365 p = sec->contents;
2366 ep = p + sec->header.sh_size;
2367 while (p < ep) {
2368 v = strchr(p, '=');
2369 n = strchr(p, '\0');
2370 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002371 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002372 return v + 1;
2373 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002374 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002375 return n;
2376 }
2377 p = n + 1;
2378 }
2379
2380 return NULL;
2381}
2382
2383
2384/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002385/* Functions relating to module loading after 2.1.18. */
2386
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002387static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002388new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2389{
2390 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002391 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002392 struct obj_symbol *sym;
2393 char *contents, *loc;
2394 int min, max, n;
2395
2396 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002397 q = strchr(p, '=');
2398 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002399 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002400 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002401 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002402
2403 key = alloca(q - p + 6);
2404 memcpy(key, "parm_", 5);
2405 memcpy(key + 5, p, q - p);
2406 key[q - p + 5] = 0;
2407
2408 p = get_modinfo_value(f, key);
2409 key += 5;
2410 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002411 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002412 }
2413
Miles Baderae28b042002-04-01 09:34:25 +00002414#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002415 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2416 strcpy(sym_name, SYMBOL_PREFIX);
2417 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002418#else
2419 sym_name = key;
2420#endif
2421 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002422
2423 /* Also check that the parameter was not resolved from the kernel. */
2424 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002425 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002426 }
2427
2428 if (isdigit(*p)) {
2429 min = strtoul(p, &p, 10);
2430 if (*p == '-')
2431 max = strtoul(p + 1, &p, 10);
2432 else
2433 max = min;
2434 } else
2435 min = max = 1;
2436
2437 contents = f->sections[sym->secidx]->contents;
2438 loc = contents + sym->value;
2439 n = (*++q != '\0');
2440
2441 while (1) {
2442 if ((*p == 's') || (*p == 'c')) {
2443 char *str;
2444
2445 /* Do C quoting if we begin with a ", else slurp the lot. */
2446 if (*q == '"') {
2447 char *r;
2448
2449 str = alloca(strlen(q));
2450 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002451 if (*q == '\0')
2452 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002453 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002454 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002455 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002456 case 'a':
2457 *r = '\a';
2458 break;
2459 case 'b':
2460 *r = '\b';
2461 break;
2462 case 'e':
2463 *r = '\033';
2464 break;
2465 case 'f':
2466 *r = '\f';
2467 break;
2468 case 'n':
2469 *r = '\n';
2470 break;
2471 case 'r':
2472 *r = '\r';
2473 break;
2474 case 't':
2475 *r = '\t';
2476 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002477
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002478 case '0':
2479 case '1':
2480 case '2':
2481 case '3':
2482 case '4':
2483 case '5':
2484 case '6':
2485 case '7':
2486 {
2487 int c = *q - '0';
2488 if (q[1] >= '0' && q[1] <= '7') {
2489 c = (c * 8) + *++q - '0';
2490 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002491 c = (c * 8) + *++q - '0';
2492 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002493 *r = c;
2494 }
2495 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002496
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002497 default:
2498 *r = *q;
2499 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002500 }
2501 else
2502 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002503 }
2504 *r = '\0';
2505 ++q;
2506 } else {
2507 char *r;
2508
2509 /* In this case, the string is not quoted. We will break
2510 it using the coma (like for ints). If the user wants to
2511 include comas in a string, he just has to quote it */
2512
2513 /* Search the next coma */
2514 r = strchr(q, ',');
2515
2516 /* Found ? */
2517 if (r != (char *) NULL) {
2518 /* Recopy the current field */
2519 str = alloca(r - q + 1);
2520 memcpy(str, q, r - q);
2521
Eric Andersenaff114c2004-04-14 17:51:38 +00002522 /* I don't know if it is useful, as the previous case
2523 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002524 str[r - q] = '\0';
2525
2526 /* Keep next fields */
2527 q = r;
2528 } else {
2529 /* last string */
2530 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002531 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002532 }
2533 }
2534
2535 if (*p == 's') {
2536 /* Normal string */
2537 obj_string_patch(f, sym->secidx, loc - contents, str);
2538 loc += tgt_sizeof_char_p;
2539 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002540 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002541 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002542
2543 /* Get the size of each member */
2544 /* Probably we should do that outside the loop ? */
2545 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002546 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002547 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002548 }
2549 charssize = strtoul(p + 1, (char **) NULL, 10);
2550
2551 /* Check length */
2552 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002553 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002554 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002555 }
2556
2557 /* Copy to location */
2558 strcpy((char *) loc, str);
2559 loc += charssize;
2560 }
2561 } else {
2562 long v = strtoul(q, &q, 0);
2563 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002564 case 'b':
2565 *loc++ = v;
2566 break;
2567 case 'h':
2568 *(short *) loc = v;
2569 loc += tgt_sizeof_short;
2570 break;
2571 case 'i':
2572 *(int *) loc = v;
2573 loc += tgt_sizeof_int;
2574 break;
2575 case 'l':
2576 *(long *) loc = v;
2577 loc += tgt_sizeof_long;
2578 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002579
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002580 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002581 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002582 }
2583 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002584 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002585 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002586 case '\0':
2587 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002588
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002589 case ' ':
2590 case '\t':
2591 case '\n':
2592 case '\r':
2593 ++q;
2594 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002595
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002596 case ',':
2597 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002598 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002599 }
2600 ++q;
2601 break;
2602
2603 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002604 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002605 }
2606 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002607 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002608 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002609 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002610 }
2611
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002612 argc--;
2613 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002614 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002615}
2616
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002617#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002618static int new_is_module_checksummed(struct obj_file *f)
2619{
2620 const char *p = get_modinfo_value(f, "using_checksums");
2621 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002622 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002623 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002624}
2625
2626/* Get the module's kernel version in the canonical integer form. */
2627
2628static int
2629new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2630{
2631 char *p, *q;
2632 int a, b, c;
2633
2634 p = get_modinfo_value(f, "kernel_version");
2635 if (p == NULL)
2636 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002637 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002638
2639 a = strtoul(p, &p, 10);
2640 if (*p != '.')
2641 return -1;
2642 b = strtoul(p + 1, &p, 10);
2643 if (*p != '.')
2644 return -1;
2645 c = strtoul(p + 1, &q, 10);
2646 if (p + 1 == q)
2647 return -1;
2648
2649 return a << 16 | b << 8 | c;
2650}
2651
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002652#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002653
2654
Eric Andersen9f16d612000-06-12 23:11:16 +00002655/* Fetch the loaded modules, and all currently exported symbols. */
2656
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002657static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002658{
2659 char *module_names, *mn;
2660 struct external_module *modules, *m;
2661 struct new_module_symbol *syms, *s;
2662 size_t ret, bufsize, nmod, nsyms, i, j;
2663
2664 /* Collect the loaded modules. */
2665
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002666 bufsize = 256;
2667 module_names = xmalloc(bufsize);
2668
2669 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002670 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002671 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002672 bufsize = ret;
2673 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002674 goto retry_modules_load;
2675 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002676 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002677 }
2678
2679 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002680
2681 /* Collect the modules' symbols. */
2682
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002683 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002684 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2685 memset(modules, 0, nmod * sizeof(*modules));
2686 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002687 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002688 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002689
Mark Whitley94fd4802001-03-12 23:08:34 +00002690 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2691 if (errno == ENOENT) {
2692 /* The module was removed out from underneath us. */
2693 continue;
2694 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002695 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002696 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002697
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002698 bufsize = 1024;
2699 syms = xmalloc(bufsize);
2700 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002701 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2702 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002703 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002704 bufsize = ret;
2705 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002706 goto retry_mod_sym_load;
2707 case ENOENT:
2708 /* The module was removed out from underneath us. */
2709 continue;
2710 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002711 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002712 }
2713 }
2714 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002715
Mark Whitley94fd4802001-03-12 23:08:34 +00002716 m->name = mn;
2717 m->addr = info.addr;
2718 m->nsyms = nsyms;
2719 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002720
Mark Whitley94fd4802001-03-12 23:08:34 +00002721 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2722 s->name += (unsigned long) syms;
2723 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002724 }
2725 }
2726
2727 /* Collect the kernel's symbols. */
2728
2729 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002730 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002731 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002732 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002733 syms = xrealloc(syms, bufsize = ret);
2734 goto retry_kern_sym_load;
2735 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002736 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002737 }
2738 nksyms = nsyms = ret;
2739 ksyms = syms;
2740
2741 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2742 s->name += (unsigned long) syms;
2743 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002744}
2745
2746
2747/* Return the kernel symbol checksum version, or zero if not used. */
2748
2749static int new_is_kernel_checksummed(void)
2750{
2751 struct new_module_symbol *s;
2752 size_t i;
2753
2754 /* Using_Versions is not the first symbol, but it should be in there. */
2755
2756 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2757 if (strcmp((char *) s->name, "Using_Versions") == 0)
2758 return s->value;
2759
2760 return 0;
2761}
2762
2763
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002764static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002765{
2766 struct obj_section *sec;
2767
2768 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002769 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002770 memset(sec->contents, 0, sizeof(struct new_module));
2771
Miles Baderae28b042002-04-01 09:34:25 +00002772 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002773 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002774 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002775
2776 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002777 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002778}
2779
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002780#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002781/* add an entry to the __ksymtab section, creating it if necessary */
2782static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2783{
2784 struct obj_section *sec;
2785 ElfW(Addr) ofs;
2786
2787 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2788 * If __ksymtab is defined but not marked alloc, x out the first character
2789 * (no obj_delete routine) and create a new __ksymtab with the correct
2790 * characteristics.
2791 */
2792 sec = obj_find_section(f, "__ksymtab");
2793 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2794 *((char *)(sec->name)) = 'x'; /* override const */
2795 sec = NULL;
2796 }
2797 if (!sec)
2798 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002799 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002800 if (!sec)
2801 return;
2802 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002803 /* Empty section might be byte-aligned */
2804 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002805 ofs = sec->header.sh_size;
2806 obj_symbol_patch(f, sec->idx, ofs, sym);
2807 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2808 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2809}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002810#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002811
2812static int new_create_module_ksymtab(struct obj_file *f)
2813{
2814 struct obj_section *sec;
2815 int i;
2816
2817 /* We must always add the module references. */
2818
2819 if (n_ext_modules_used) {
2820 struct new_module_ref *dep;
2821 struct obj_symbol *tm;
2822
2823 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002824 (sizeof(struct new_module_ref)
2825 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002826 if (!sec)
2827 return 0;
2828
Miles Baderae28b042002-04-01 09:34:25 +00002829 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002830 dep = (struct new_module_ref *) sec->contents;
2831 for (i = 0; i < n_ext_modules; ++i)
2832 if (ext_modules[i].used) {
2833 dep->dep = ext_modules[i].addr;
2834 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002835 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002836 dep->next_ref = 0;
2837 ++dep;
2838 }
2839 }
2840
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002841 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002842 size_t nsyms;
2843 int *loaded;
2844
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002845 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002846
2847 /* We don't want to export symbols residing in sections that
2848 aren't loaded. There are a number of these created so that
2849 we make sure certain module options don't appear twice. */
2850
2851 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2852 while (--i >= 0)
2853 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2854
2855 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2856 struct obj_symbol *sym;
2857 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002858 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002859 && sym->secidx <= SHN_HIRESERVE
2860 && (sym->secidx >= SHN_LORESERVE
2861 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002862 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2863
2864 obj_symbol_patch(f, sec->idx, ofs, sym);
2865 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002866 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002867
2868 nsyms++;
2869 }
2870 }
2871
2872 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2873 }
2874
2875 return 1;
2876}
2877
2878
2879static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002880new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002881{
2882 struct new_module *module;
2883 struct obj_section *sec;
2884 void *image;
2885 int ret;
2886 tgt_long m_addr;
2887
2888 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002889 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002890 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002891 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002892 module = (struct new_module *) sec->contents;
2893 m_addr = sec->header.sh_addr;
2894
2895 module->size_of_struct = sizeof(*module);
2896 module->size = m_size;
2897 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2898
2899 sec = obj_find_section(f, "__ksymtab");
2900 if (sec && sec->header.sh_size) {
2901 module->syms = sec->header.sh_addr;
2902 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2903 }
2904
2905 if (n_ext_modules_used) {
2906 sec = obj_find_section(f, ".kmodtab");
2907 module->deps = sec->header.sh_addr;
2908 module->ndeps = n_ext_modules_used;
2909 }
2910
2911 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002912 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002913 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002914 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002915
2916 sec = obj_find_section(f, "__ex_table");
2917 if (sec) {
2918 module->ex_table_start = sec->header.sh_addr;
2919 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2920 }
2921
2922 sec = obj_find_section(f, ".text.init");
2923 if (sec) {
2924 module->runsize = sec->header.sh_addr - m_addr;
2925 }
2926 sec = obj_find_section(f, ".data.init");
2927 if (sec) {
2928 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002929 module->runsize > sec->header.sh_addr - m_addr)
2930 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002931 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002932 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2933 if (sec && sec->header.sh_size) {
2934 module->archdata_start = (void*)sec->header.sh_addr;
2935 module->archdata_end = module->archdata_start + sec->header.sh_size;
2936 }
2937 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2938 if (sec && sec->header.sh_size) {
2939 module->kallsyms_start = (void*)sec->header.sh_addr;
2940 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2941 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002942
Eric Andersen9f16d612000-06-12 23:11:16 +00002943 /* Whew! All of the initialization is complete. Collect the final
2944 module image and give it to the kernel. */
2945
2946 image = xmalloc(m_size);
2947 obj_create_image(f, image);
2948
Eric Andersencb3b9b12004-06-22 11:50:52 +00002949 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002950 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002951 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002952
2953 free(image);
2954
2955 return ret == 0;
2956}
2957
Eric Andersen9f16d612000-06-12 23:11:16 +00002958
2959/*======================================================================*/
2960
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002961static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002962obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2963 const char *string)
2964{
2965 struct obj_string_patch *p;
2966 struct obj_section *strsec;
2967 size_t len = strlen(string) + 1;
2968 char *loc;
2969
2970 p = xmalloc(sizeof(*p));
2971 p->next = f->string_patches;
2972 p->reloc_secidx = secidx;
2973 p->reloc_offset = offset;
2974 f->string_patches = p;
2975
2976 strsec = obj_find_section(f, ".kstrtab");
2977 if (strsec == NULL) {
2978 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2979 p->string_offset = 0;
2980 loc = strsec->contents;
2981 } else {
2982 p->string_offset = strsec->header.sh_size;
2983 loc = obj_extend_section(strsec, len);
2984 }
2985 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002986}
2987
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00002988static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002989obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2990 struct obj_symbol *sym)
2991{
2992 struct obj_symbol_patch *p;
2993
2994 p = xmalloc(sizeof(*p));
2995 p->next = f->symbol_patches;
2996 p->reloc_secidx = secidx;
2997 p->reloc_offset = offset;
2998 p->sym = sym;
2999 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00003000}
3001
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003002static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003003{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003004 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003005
3006 for (i = 0; i < HASH_BUCKETS; ++i) {
3007 struct obj_symbol *sym;
3008 for (sym = f->symtab[i]; sym; sym = sym->next)
3009 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003010 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003011 sym->secidx = SHN_ABS;
3012 sym->value = 0;
3013 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003014 if (!flag_quiet)
3015 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003016 }
3017 }
3018 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003019}
3020
Eric Andersen044228d2001-07-17 01:12:36 +00003021static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003022{
3023 struct common_entry {
3024 struct common_entry *next;
3025 struct obj_symbol *sym;
3026 } *common_head = NULL;
3027
3028 unsigned long i;
3029
3030 for (i = 0; i < HASH_BUCKETS; ++i) {
3031 struct obj_symbol *sym;
3032 for (sym = f->symtab[i]; sym; sym = sym->next)
3033 if (sym->secidx == SHN_COMMON) {
3034 /* Collect all COMMON symbols and sort them by size so as to
3035 minimize space wasted by alignment requirements. */
3036 {
3037 struct common_entry **p, *n;
3038 for (p = &common_head; *p; p = &(*p)->next)
3039 if (sym->size <= (*p)->sym->size)
3040 break;
3041
3042 n = alloca(sizeof(*n));
3043 n->next = *p;
3044 n->sym = sym;
3045 *p = n;
3046 }
3047 }
3048 }
3049
3050 for (i = 1; i < f->local_symtab_size; ++i) {
3051 struct obj_symbol *sym = f->local_symtab[i];
3052 if (sym && sym->secidx == SHN_COMMON) {
3053 struct common_entry **p, *n;
3054 for (p = &common_head; *p; p = &(*p)->next)
3055 if (sym == (*p)->sym)
3056 break;
3057 else if (sym->size < (*p)->sym->size) {
3058 n = alloca(sizeof(*n));
3059 n->next = *p;
3060 n->sym = sym;
3061 *p = n;
3062 break;
3063 }
3064 }
3065 }
3066
3067 if (common_head) {
3068 /* Find the bss section. */
3069 for (i = 0; i < f->header.e_shnum; ++i)
3070 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3071 break;
3072
3073 /* If for some reason there hadn't been one, create one. */
3074 if (i == f->header.e_shnum) {
3075 struct obj_section *sec;
3076
3077 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3078 f->sections[i] = sec = arch_new_section();
3079 f->header.e_shnum = i + 1;
3080
Eric Andersen9f16d612000-06-12 23:11:16 +00003081 sec->header.sh_type = SHT_PROGBITS;
3082 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3083 sec->name = ".bss";
3084 sec->idx = i;
3085 }
3086
3087 /* Allocate the COMMONS. */
3088 {
3089 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3090 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3091 struct common_entry *c;
3092
3093 for (c = common_head; c; c = c->next) {
3094 ElfW(Addr) align = c->sym->value;
3095
3096 if (align > max_align)
3097 max_align = align;
3098 if (bss_size & (align - 1))
3099 bss_size = (bss_size | (align - 1)) + 1;
3100
3101 c->sym->secidx = i;
3102 c->sym->value = bss_size;
3103
3104 bss_size += c->sym->size;
3105 }
3106
3107 f->sections[i]->header.sh_size = bss_size;
3108 f->sections[i]->header.sh_addralign = max_align;
3109 }
3110 }
3111
3112 /* For the sake of patch relocation and parameter initialization,
3113 allocate zeroed data for NOBITS sections now. Note that after
3114 this we cannot assume NOBITS are really empty. */
3115 for (i = 0; i < f->header.e_shnum; ++i) {
3116 struct obj_section *s = f->sections[i];
3117 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003118 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003119 s->contents = memset(xmalloc(s->header.sh_size),
3120 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003121 else
3122 s->contents = NULL;
3123
Eric Andersen9f16d612000-06-12 23:11:16 +00003124 s->header.sh_type = SHT_PROGBITS;
3125 }
3126 }
3127}
3128
Eric Andersen044228d2001-07-17 01:12:36 +00003129static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003130{
3131 unsigned long dot = 0;
3132 struct obj_section *sec;
3133
3134 /* Finalize the positions of the sections relative to one another. */
3135
3136 for (sec = f->load_order; sec; sec = sec->load_next) {
3137 ElfW(Addr) align;
3138
3139 align = sec->header.sh_addralign;
3140 if (align && (dot & (align - 1)))
3141 dot = (dot | (align - 1)) + 1;
3142
3143 sec->header.sh_addr = dot;
3144 dot += sec->header.sh_size;
3145 }
3146
3147 return dot;
3148}
3149
Eric Andersen044228d2001-07-17 01:12:36 +00003150static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003151{
3152 int i, n = f->header.e_shnum;
3153 int ret = 1;
3154
3155 /* Finalize the addresses of the sections. */
3156
3157 f->baseaddr = base;
3158 for (i = 0; i < n; ++i)
3159 f->sections[i]->header.sh_addr += base;
3160
3161 /* And iterate over all of the relocations. */
3162
3163 for (i = 0; i < n; ++i) {
3164 struct obj_section *relsec, *symsec, *targsec, *strsec;
3165 ElfW(RelM) * rel, *relend;
3166 ElfW(Sym) * symtab;
3167 const char *strtab;
3168
3169 relsec = f->sections[i];
3170 if (relsec->header.sh_type != SHT_RELM)
3171 continue;
3172
3173 symsec = f->sections[relsec->header.sh_link];
3174 targsec = f->sections[relsec->header.sh_info];
3175 strsec = f->sections[symsec->header.sh_link];
3176
3177 rel = (ElfW(RelM) *) relsec->contents;
3178 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3179 symtab = (ElfW(Sym) *) symsec->contents;
3180 strtab = (const char *) strsec->contents;
3181
3182 for (; rel < relend; ++rel) {
3183 ElfW(Addr) value = 0;
3184 struct obj_symbol *intsym = NULL;
3185 unsigned long symndx;
3186 ElfW(Sym) * extsym = 0;
3187 const char *errmsg;
3188
3189 /* Attempt to find a value to use for this relocation. */
3190
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003191 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003192 if (symndx) {
3193 /* Note we've already checked for undefined symbols. */
3194
3195 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003196 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003197 /* Local symbols we look up in the local table to be sure
3198 we get the one that is really intended. */
3199 intsym = f->local_symtab[symndx];
3200 } else {
3201 /* Others we look up in the hash table. */
3202 const char *name;
3203 if (extsym->st_name)
3204 name = strtab + extsym->st_name;
3205 else
3206 name = f->sections[extsym->st_shndx]->name;
3207 intsym = obj_find_symbol(f, name);
3208 }
3209
3210 value = obj_symbol_final_value(f, intsym);
3211 intsym->referenced = 1;
3212 }
3213#if SHT_RELM == SHT_RELA
3214#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3215 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3216 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003217 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003218#endif
3219 value += rel->r_addend;
3220#endif
3221
3222 /* Do it! */
3223 switch (arch_apply_relocation
Denis Vlasenko68404f12008-03-17 09:00:54 +00003224 (f, targsec, /*symsec,*/ intsym, rel, value)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003225 ) {
3226 case obj_reloc_ok:
3227 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003228
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003229 case obj_reloc_overflow:
3230 errmsg = "Relocation overflow";
3231 goto bad_reloc;
3232 case obj_reloc_dangerous:
3233 errmsg = "Dangerous relocation";
3234 goto bad_reloc;
3235 case obj_reloc_unhandled:
3236 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003237bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003238 if (extsym) {
3239 bb_error_msg("%s of type %ld for %s", errmsg,
3240 (long) ELF_R_TYPE(rel->r_info),
3241 strtab + extsym->st_name);
3242 } else {
3243 bb_error_msg("%s of type %ld", errmsg,
3244 (long) ELF_R_TYPE(rel->r_info));
3245 }
3246 ret = 0;
3247 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003248 }
3249 }
3250 }
3251
3252 /* Finally, take care of the patches. */
3253
3254 if (f->string_patches) {
3255 struct obj_string_patch *p;
3256 struct obj_section *strsec;
3257 ElfW(Addr) strsec_base;
3258 strsec = obj_find_section(f, ".kstrtab");
3259 strsec_base = strsec->header.sh_addr;
3260
3261 for (p = f->string_patches; p; p = p->next) {
3262 struct obj_section *targsec = f->sections[p->reloc_secidx];
3263 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3264 = strsec_base + p->string_offset;
3265 }
3266 }
3267
3268 if (f->symbol_patches) {
3269 struct obj_symbol_patch *p;
3270
3271 for (p = f->symbol_patches; p; p = p->next) {
3272 struct obj_section *targsec = f->sections[p->reloc_secidx];
3273 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3274 = obj_symbol_final_value(f, p->sym);
3275 }
3276 }
3277
3278 return ret;
3279}
3280
Eric Andersen044228d2001-07-17 01:12:36 +00003281static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003282{
3283 struct obj_section *sec;
3284 ElfW(Addr) base = f->baseaddr;
3285
3286 for (sec = f->load_order; sec; sec = sec->load_next) {
3287 char *secimg;
3288
Eric Andersen2bf658d2001-02-24 20:01:53 +00003289 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003290 continue;
3291
3292 secimg = image + (sec->header.sh_addr - base);
3293
3294 /* Note that we allocated data for NOBITS sections earlier. */
3295 memcpy(secimg, sec->contents, sec->header.sh_size);
3296 }
3297
3298 return 1;
3299}
3300
3301/*======================================================================*/
3302
Denis Vlasenko68404f12008-03-17 09:00:54 +00003303static struct obj_file *obj_load(FILE * fp, int loadprogbits ATTRIBUTE_UNUSED)
Eric Andersen9f16d612000-06-12 23:11:16 +00003304{
3305 struct obj_file *f;
3306 ElfW(Shdr) * section_headers;
3307 int shnum, i;
3308 char *shstrtab;
3309
3310 /* Read the file header. */
3311
3312 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003313 f->symbol_cmp = strcmp;
3314 f->symbol_hash = obj_elf_hash;
3315 f->load_order_search_start = &f->load_order;
3316
3317 fseek(fp, 0, SEEK_SET);
3318 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003319 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003320 }
3321
3322 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003323 || f->header.e_ident[EI_MAG1] != ELFMAG1
3324 || f->header.e_ident[EI_MAG2] != ELFMAG2
3325 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003326 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003327 }
3328 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003329 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003330 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003331 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3332 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003333 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003334 }
3335 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003336 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003337 }
3338
3339 /* Read the section headers. */
3340
3341 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003342 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003343 (unsigned long) f->header.e_shentsize,
3344 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003345 }
3346
3347 shnum = f->header.e_shnum;
3348 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3349 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3350
3351 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3352 fseek(fp, f->header.e_shoff, SEEK_SET);
3353 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003354 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003355 }
3356
3357 /* Read the section data. */
3358
3359 for (i = 0; i < shnum; ++i) {
3360 struct obj_section *sec;
3361
3362 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003363
3364 sec->header = section_headers[i];
3365 sec->idx = i;
3366
Denis Vlasenko51742f42007-04-12 00:32:05 +00003367 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003368 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003369 case SHT_NULL:
3370 case SHT_NOTE:
3371 case SHT_NOBITS:
3372 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003373 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003374
3375 case SHT_PROGBITS:
3376#if LOADBITS
3377 if (!loadprogbits) {
3378 sec->contents = NULL;
3379 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003381#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003382 case SHT_SYMTAB:
3383 case SHT_STRTAB:
3384 case SHT_RELM:
3385 if (sec->header.sh_size > 0) {
3386 sec->contents = xmalloc(sec->header.sh_size);
3387 fseek(fp, sec->header.sh_offset, SEEK_SET);
3388 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003389 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003390 }
3391 } else {
3392 sec->contents = NULL;
3393 }
3394 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003395
3396#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003397 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003398 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003399#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003400 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003401 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003402#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003403 default:
3404 if (sec->header.sh_type >= SHT_LOPROC) {
3405 /* Assume processor specific section types are debug
3406 info and can safely be ignored. If this is ever not
3407 the case (Hello MIPS?), don't put ifdefs here but
3408 create an arch_load_proc_section(). */
3409 break;
3410 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003411
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003412 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003413 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003414 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003415 }
3416 }
3417
3418 /* Do what sort of interpretation as needed by each section. */
3419
3420 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3421
3422 for (i = 0; i < shnum; ++i) {
3423 struct obj_section *sec = f->sections[i];
3424 sec->name = shstrtab + sec->header.sh_name;
3425 }
3426
3427 for (i = 0; i < shnum; ++i) {
3428 struct obj_section *sec = f->sections[i];
3429
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003430 /* .modinfo should be contents only but gcc has no attribute for that.
3431 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3432 */
3433 if (strcmp(sec->name, ".modinfo") == 0)
3434 sec->header.sh_flags &= ~SHF_ALLOC;
3435
Eric Andersen9f16d612000-06-12 23:11:16 +00003436 if (sec->header.sh_flags & SHF_ALLOC)
3437 obj_insert_section_load_order(f, sec);
3438
3439 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003440 case SHT_SYMTAB:
3441 {
3442 unsigned long nsym, j;
3443 char *strtab;
3444 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003445
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003446 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003447 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003448 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003449 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003450 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003451
3452 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3453 strtab = f->sections[sec->header.sh_link]->contents;
3454 sym = (ElfW(Sym) *) sec->contents;
3455
3456 /* Allocate space for a table of local symbols. */
3457 j = f->local_symtab_size = sec->header.sh_info;
3458 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3459
3460 /* Insert all symbols into the hash table. */
3461 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3462 ElfW(Addr) val = sym->st_value;
3463 const char *name;
3464 if (sym->st_name)
3465 name = strtab + sym->st_name;
3466 else if (sym->st_shndx < shnum)
3467 name = f->sections[sym->st_shndx]->name;
3468 else
3469 continue;
3470#if defined(__SH5__)
3471 /*
3472 * For sh64 it is possible that the target of a branch
3473 * requires a mode switch (32 to 16 and back again).
3474 *
3475 * This is implied by the lsb being set in the target
3476 * address for SHmedia mode and clear for SHcompact.
3477 */
3478 val |= sym->st_other & 4;
3479#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003480 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3481 val, sym->st_size);
3482 }
3483 }
3484 break;
3485
3486 case SHT_RELM:
3487 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003488 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003489 (unsigned long) sec->header.sh_entsize,
3490 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003491 }
3492 break;
3493 /* XXX Relocation code from modutils-2.3.19 is not here.
3494 * Why? That's about 20 lines of code from obj/obj_load.c,
3495 * which gets done in a second pass through the sections.
3496 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003497 }
3498 }
3499
3500 return f;
3501}
3502
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003503#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003504/*
3505 * load the unloaded sections directly into the memory allocated by
3506 * kernel for the module
3507 */
3508
Eric Andersenac5dbd12001-08-22 05:26:08 +00003509static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003510{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003511 ElfW(Addr) base = f->baseaddr;
3512 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003513
Eric Andersen8ae319a2001-05-21 16:09:18 +00003514 for (sec = f->load_order; sec; sec = sec->load_next) {
3515
3516 /* section already loaded? */
3517 if (sec->contents != NULL)
3518 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003519
Eric Andersen8ae319a2001-05-21 16:09:18 +00003520 if (sec->header.sh_size == 0)
3521 continue;
3522
3523 sec->contents = imagebase + (sec->header.sh_addr - base);
3524 fseek(fp, sec->header.sh_offset, SEEK_SET);
3525 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003526 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003527 return 0;
3528 }
3529
3530 }
3531 return 1;
3532}
3533#endif
3534
Eric Andersen9f16d612000-06-12 23:11:16 +00003535static void hide_special_symbols(struct obj_file *f)
3536{
3537 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003538 SPFX "cleanup_module",
3539 SPFX "init_module",
3540 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003541 NULL
3542 };
3543
3544 struct obj_symbol *sym;
3545 const char *const *p;
3546
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003547 for (p = specials; *p; ++p) {
3548 sym = obj_find_symbol(f, *p);
3549 if (sym != NULL)
3550 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3551 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003552}
3553
Glenn L McGrath759515c2003-08-30 06:00:33 +00003554
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003555#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003556static int obj_gpl_license(struct obj_file *f, const char **license)
3557{
3558 struct obj_section *sec;
3559 /* This list must match *exactly* the list of allowable licenses in
3560 * linux/include/linux/module.h. Checking for leading "GPL" will not
3561 * work, somebody will use "GPL sucks, this is proprietary".
3562 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003563 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003564 "GPL",
3565 "GPL v2",
3566 "GPL and additional rights",
3567 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003568 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003569 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003570
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003571 sec = obj_find_section(f, ".modinfo");
3572 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003573 const char *value, *ptr, *endptr;
3574 ptr = sec->contents;
3575 endptr = ptr + sec->header.sh_size;
3576 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003577 value = strchr(ptr, '=');
3578 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003579 int i;
3580 if (license)
3581 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003582 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003583 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003584 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003585 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003586 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003587 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003588 ptr = strchr(ptr, '\0');
3589 if (ptr)
3590 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003591 else
3592 ptr = endptr;
3593 }
3594 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003595 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003596}
3597
3598#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003599#define TAINT_PROPRIETORY_MODULE (1 << 0)
3600#define TAINT_FORCED_MODULE (1 << 1)
3601#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003602#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003603
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003604static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003605 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3606{
Denis Vlasenko931de892007-06-21 12:43:45 +00003607 static smallint printed_info;
3608
Eric Andersen166fa462002-09-16 05:30:24 +00003609 char buf[80];
3610 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003611
Eric Andersen166fa462002-09-16 05:30:24 +00003612 if (fd < 0 && !kernel_has_tainted)
3613 return; /* New modutils on old kernel */
3614 printf("Warning: loading %s will taint the kernel: %s%s\n",
3615 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003616 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003617 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003618 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003619 }
3620 if (fd >= 0) {
3621 read(fd, buf, sizeof(buf)-1);
3622 buf[sizeof(buf)-1] = '\0';
3623 oldval = strtoul(buf, NULL, 10);
3624 sprintf(buf, "%d\n", oldval | taint);
3625 write(fd, buf, strlen(buf));
3626 }
3627}
3628
3629/* Check if loading this module will taint the kernel. */
3630static void check_tainted_module(struct obj_file *f, char *m_name)
3631{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003632 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3633
Eric Andersen166fa462002-09-16 05:30:24 +00003634 int fd, kernel_has_tainted;
3635 const char *ptr;
3636
3637 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003638 fd = open(tainted_file, O_RDWR);
3639 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003640 if (errno == ENOENT)
3641 kernel_has_tainted = 0;
3642 else if (errno == EACCES)
3643 kernel_has_tainted = 1;
3644 else {
3645 perror(tainted_file);
3646 kernel_has_tainted = 0;
3647 }
3648 }
3649
3650 switch (obj_gpl_license(f, &ptr)) {
3651 case 0:
3652 break;
3653 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003654 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003655 break;
3656 case 2:
3657 /* The module has a non-GPL license so we pretend that the
3658 * kernel always has a taint flag to get a warning even on
3659 * kernels without the proc flag.
3660 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003661 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003662 break;
3663 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003664 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003665 break;
3666 }
3667
3668 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003669 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003670
3671 if (fd >= 0)
3672 close(fd);
3673}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003674#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003675#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003676#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003677
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003678#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003679/* add module source, timestamp, kernel version and a symbol for the
3680 * start of some sections. this info is used by ksymoops to do better
3681 * debugging.
3682 */
3683static int
3684get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3685{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003686#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003687 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003688#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003689 strncpy(str, "???", sizeof(str));
3690 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003691#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003692}
3693
3694/* add module source, timestamp, kernel version and a symbol for the
3695 * start of some sections. this info is used by ksymoops to do better
3696 * debugging.
3697 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003698static void
Eric Andersen889dd202003-01-23 04:48:34 +00003699add_ksymoops_symbols(struct obj_file *f, const char *filename,
3700 const char *m_name)
3701{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003702 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003703 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003704 ".text",
3705 ".rodata",
3706 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003707 ".bss",
3708 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003709 };
3710
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003711 struct obj_section *sec;
3712 struct obj_symbol *sym;
3713 char *name, *absolute_filename;
3714 char str[STRVERSIONLEN];
3715 int i, l, lm_name, lfilename, use_ksymtab, version;
3716 struct stat statbuf;
3717
3718 /* WARNING: was using realpath, but replaced by readlink to stop using
3719 * lots of stack. But here it seems to be able to cause problems? */
3720 absolute_filename = xmalloc_readlink(filename);
3721 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003722 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003723
3724 lm_name = strlen(m_name);
3725 lfilename = strlen(absolute_filename);
3726
3727 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3728 * are not to be exported. otherwise leave ksymtab alone for now, the
3729 * "export all symbols" compatibility code will export these symbols later.
3730 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003731 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003732
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003733 sec = obj_find_section(f, ".this");
3734 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003735 /* tag the module header with the object name, last modified
3736 * timestamp and module version. worst case for module version
3737 * is 0xffffff, decimal 16777215. putting all three fields in
3738 * one symbol is less readable but saves kernel space.
3739 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003740 l = sizeof(symprefix) + /* "__insmod_" */
3741 lm_name + /* module name */
3742 2 + /* "_O" */
3743 lfilename + /* object filename */
3744 2 + /* "_M" */
3745 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3746 2 + /* "_V" */
3747 8 + /* version in dec */
3748 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003749 name = xmalloc(l);
3750 if (stat(absolute_filename, &statbuf) != 0)
3751 statbuf.st_mtime = 0;
3752 version = get_module_version(f, str); /* -1 if not found */
3753 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003754 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003755 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003756 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003757 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003758 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003759 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003760 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003761 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003762 }
3763 free(absolute_filename);
3764#ifdef _NOT_SUPPORTED_
3765 /* record where the persistent data is going, same address as previous symbol */
3766
3767 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003768 l = sizeof(symprefix) + /* "__insmod_" */
3769 lm_name + /* module name */
3770 2 + /* "_P" */
3771 strlen(f->persist) + /* data store */
3772 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003773 name = xmalloc(l);
3774 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003775 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003776 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003777 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003778 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003779 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003780 }
3781#endif /* _NOT_SUPPORTED_ */
3782 /* tag the desired sections if size is non-zero */
3783
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003784 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003785 sec = obj_find_section(f, section_names[i]);
3786 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003787 l = sizeof(symprefix) + /* "__insmod_" */
3788 lm_name + /* module name */
3789 2 + /* "_S" */
3790 strlen(sec->name) + /* section name */
3791 2 + /* "_L" */
3792 8 + /* length in dec */
3793 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003794 name = xmalloc(l);
3795 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003796 symprefix, m_name, sec->name,
3797 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003798 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003799 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003800 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003801 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003802 }
3803 }
3804}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003805#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003806
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003807#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003808static void print_load_map(struct obj_file *f)
3809{
Eric Andersenbe65c352003-01-23 04:57:35 +00003810 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003811#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3812 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003813 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003814 struct obj_symbol *sym;
3815#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003816 /* Report on the section layout. */
3817
3818 printf("Sections: Size %-*s Align\n",
3819 (int) (2 * sizeof(void *)), "Address");
3820
3821 for (sec = f->load_order; sec; sec = sec->load_next) {
3822 int a;
3823 unsigned long tmp;
3824
3825 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3826 tmp >>= 1;
3827 if (a == -1)
3828 a = 0;
3829
3830 printf("%-15s %08lx %0*lx 2**%d\n",
3831 sec->name,
3832 (long)sec->header.sh_size,
3833 (int) (2 * sizeof(void *)),
3834 (long)sec->header.sh_addr,
3835 a);
3836 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003837#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003838 /* Quick reference which section indicies are loaded. */
3839
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003840 i = f->header.e_shnum;
3841 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003842 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003843 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003844
3845 /* Collect the symbols we'll be listing. */
3846
3847 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3848 for (sym = f->symtab[i]; sym; sym = sym->next)
3849 if (sym->secidx <= SHN_HIRESERVE
3850 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3851 ++nsyms;
3852
3853 all = alloca(nsyms * sizeof(struct obj_symbol *));
3854
3855 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3856 for (sym = f->symtab[i]; sym; sym = sym->next)
3857 if (sym->secidx <= SHN_HIRESERVE
3858 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3859 *p++ = sym;
3860
3861 /* And list them. */
3862 printf("\nSymbols:\n");
3863 for (p = all; p < all + nsyms; ++p) {
3864 char type = '?';
3865 unsigned long value;
3866
3867 sym = *p;
3868 if (sym->secidx == SHN_ABS) {
3869 type = 'A';
3870 value = sym->value;
3871 } else if (sym->secidx == SHN_UNDEF) {
3872 type = 'U';
3873 value = 0;
3874 } else {
3875 sec = f->sections[sym->secidx];
3876
3877 if (sec->header.sh_type == SHT_NOBITS)
3878 type = 'B';
3879 else if (sec->header.sh_flags & SHF_ALLOC) {
3880 if (sec->header.sh_flags & SHF_EXECINSTR)
3881 type = 'T';
3882 else if (sec->header.sh_flags & SHF_WRITE)
3883 type = 'D';
3884 else
3885 type = 'R';
3886 }
3887 value = sym->value + sec->header.sh_addr;
3888 }
3889
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003890 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003891 type = tolower(type);
3892
3893 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3894 type, sym->name);
3895 }
3896#endif
3897}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003898#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003899void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003900#endif
3901
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003902int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3903int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003904{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003905 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003906 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003907 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003908 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003909 unsigned long m_size;
3910 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003911 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003912 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003913 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003914 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003915 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003916#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003917 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003919 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003920#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003921#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003922 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003923#else
3924 FILE *fp;
3925#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003926 int k_version = 0;
3927 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003928
Erik Andersene49d5ec2000-02-08 19:58:47 +00003929 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003930 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003931 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003932 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003933 free(m_name);
3934 m_name = xstrdup(opt_o);
3935 }
Eric Andersen03d80912003-12-19 21:04:19 +00003936
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003937 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003938 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003939 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003940
Erik Andersene49d5ec2000-02-08 19:58:47 +00003941 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003942 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003943 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003944 len = strlen(tmp);
3945
Eric Andersen03d80912003-12-19 21:04:19 +00003946 if (uname(&myuname) == 0) {
3947 if (myuname.release[0] == '2') {
3948 k_version = myuname.release[2] - '0';
3949 }
3950 }
3951
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003952#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003953 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3954 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3955 ) {
3956 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003957 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003958 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003959#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003960 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003961 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003962 tmp[len] = '\0';
3963 }
Eric Andersen2d342152002-06-18 05:16:25 +00003964
Eric Andersen03d80912003-12-19 21:04:19 +00003965
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003966#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003967 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003968 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003969 else
Eric Andersen03d80912003-12-19 21:04:19 +00003970#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003971 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003972
Eric Andersen61f83052002-06-22 17:15:42 +00003973 if (!m_name) {
3974 m_name = tmp;
3975 } else {
3976 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003977 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003978 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003979
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003980 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003981 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3982 || (fp = fopen(arg1, "r")) == NULL
3983 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003984 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3985 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003986 if (k_version) { /* uname succeedd */
3987 char *module_dir;
3988 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00003989
Eric Andersen03d80912003-12-19 21:04:19 +00003990 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003991 /* Jump through hoops in case /lib/modules/`uname -r`
3992 * is a symlink. We do not want recursive_action to
3993 * follow symlinks, but we do want to follow the
3994 * /lib/modules/`uname -r` dir, So resolve it ourselves
3995 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003996 module_dir = xmalloc_readlink(tmdn);
3997 if (!module_dir)
3998 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00003999 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004000 check_module_name_match, NULL, m_fullName, 0);
4001 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004002 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004003 }
4004
4005 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004006 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004007 int r;
4008 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004009
Eric Andersen03d80912003-12-19 21:04:19 +00004010 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004011 m_filename = NULL;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004012 module_dir = xmalloc_readlink(_PATH_MODULES);
4013 if (!module_dir)
4014 module_dir = xstrdup(_PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004015 /* No module found under /lib/modules/`uname -r`, this
4016 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004017 r = recursive_action(module_dir, ACTION_RECURSE,
4018 check_module_name_match, NULL, m_fullName, 0);
4019 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004020 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004021 free(module_dir);
4022 if (m_filename == NULL
4023 || ((fp = fopen(m_filename, "r")) == NULL)
4024 ) {
4025 bb_error_msg_and_die("%s: module not found", m_fullName);
4026 }
Eric Andersen14d35432001-05-14 17:07:32 +00004027 }
Eric Andersen03d80912003-12-19 21:04:19 +00004028 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004029 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004030
Rob Landley999af202005-12-11 20:14:12 +00004031 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004032 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004033
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004034#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004035 if (k_version > 4) {
4036 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004037 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004038 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004039 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004040#endif
4041
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004042 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004043
Eric Andersen9f16d612000-06-12 23:11:16 +00004044 if (get_modinfo_value(f, "kernel_version") == NULL)
4045 m_has_modinfo = 0;
4046 else
4047 m_has_modinfo = 1;
4048
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004049#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004050 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004051 if (!flag_quiet) {
4052 if (uname(&uts_info) < 0)
4053 uts_info.release[0] = '\0';
4054 if (m_has_modinfo) {
4055 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004056 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004057 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004058 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004059 }
4060 }
4061
4062 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004063 bb_error_msg("%skernel-module version mismatch\n"
4064 "\t%s was compiled for kernel version %s\n"
4065 "\twhile this kernel is version %s",
4066 flag_force_load ? "warning: " : "",
4067 m_filename, m_strversion, uts_info.release);
4068 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004069 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004070 }
4071 }
4072 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004073#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004074
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004075 if (query_module(NULL, 0, NULL, 0, NULL))
4076 bb_error_msg_and_die("not configured to support old kernels");
4077 new_get_kernel_symbols();
4078 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004079
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004080#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004081 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004082 if (m_has_modinfo)
4083 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004084
4085 if (m_crcs != k_crcs)
4086 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004087#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004088
Erik Andersene49d5ec2000-02-08 19:58:47 +00004089 /* Let the module know about the kernel symbols. */
4090 add_kernel_symbols(f);
4091
Eric Andersen9f16d612000-06-12 23:11:16 +00004092 /* Allocate common symbols, symbol tables, and string tables. */
4093
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004094 new_create_this_module(f, m_name);
4095 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004096 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004097 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004098
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004099 /* done with the module name, on to the optional var=value arguments */
4100 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004101 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004102 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004103 }
4104
Eric Andersen9f16d612000-06-12 23:11:16 +00004105 arch_create_got(f);
4106 hide_special_symbols(f);
4107
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004108#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004109 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004110#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004111
Eric Andersencb3b9b12004-06-22 11:50:52 +00004112 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004113
Erik Andersene49d5ec2000-02-08 19:58:47 +00004114 /* Find current size of the module */
4115 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004116
Erik Andersene49d5ec2000-02-08 19:58:47 +00004117 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004118 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004119 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004120 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004121 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004122 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004123 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004124 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004125 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004126 }
Erik Andersend387d011999-12-21 02:55:11 +00004127
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004128#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004129 /*
4130 * the PROGBITS section was not loaded by the obj_load
4131 * now we can load them directly into the kernel memory
4132 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004133 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004134 delete_module(m_name);
4135 goto out;
4136 }
Eric Andersen03d80912003-12-19 21:04:19 +00004137#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004138
Eric Andersen9f16d612000-06-12 23:11:16 +00004139 if (!obj_relocate(f, m_addr)) {
4140 delete_module(m_name);
4141 goto out;
4142 }
Erik Andersend387d011999-12-21 02:55:11 +00004143
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004144 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004145 delete_module(m_name);
4146 goto out;
4147 }
4148
Denis Vlasenko51742f42007-04-12 00:32:05 +00004149 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004150 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004151
Matt Kraai3e856ce2000-12-01 02:55:13 +00004152 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004153
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004154 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004155#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004156 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004157 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004158 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004159 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004160 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004161 free(m_filename);
4162#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004163 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004164}
Eric Andersene7047882003-12-11 01:42:13 +00004165
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004166#endif /* ENABLE_FEATURE_2_4_MODULES */
4167/*
4168 * End of big piece of 2.4-specific code
4169 */
Eric Andersene7047882003-12-11 01:42:13 +00004170
4171
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004172#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004173
4174#include <sys/mman.h>
4175#include <asm/unistd.h>
4176#include <sys/syscall.h>
4177
4178/* We use error numbers in a loose translation... */
4179static const char *moderror(int err)
4180{
4181 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004182 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004183 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004184 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004185 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004186 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004187 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004188 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004189 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004190 default:
4191 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004192 }
4193}
4194
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004195#if !ENABLE_FEATURE_2_4_MODULES
4196int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko68404f12008-03-17 09:00:54 +00004197int insmod_main(int argc ATTRIBUTE_UNUSED, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004198#else
Denis Vlasenko68404f12008-03-17 09:00:54 +00004199static int insmod_ng_main(int argc ATTRIBUTE_UNUSED, char **argv)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004200#endif
Eric Andersene7047882003-12-11 01:42:13 +00004201{
Denis Vlasenko92297942006-11-21 11:58:14 +00004202 long ret;
4203 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004204 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004205 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004206 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004207
Denis Vlasenko92297942006-11-21 11:58:14 +00004208 filename = *++argv;
4209 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004210 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004211
4212 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004213 options = xzalloc(1);
4214 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004215 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004216 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004217 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004218 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004219 }
4220
Denis Vlasenko92297942006-11-21 11:58:14 +00004221#if 0
4222 /* Any special reason why mmap? It isn't performace critical... */
4223 int fd;
4224 struct stat st;
4225 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004226 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004227 fstat(fd, &st);
4228 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004229 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004230 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004231 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004232 }
4233
Denis Vlasenko92297942006-11-21 11:58:14 +00004234 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4235 if (map == NULL) {
4236 map = xmalloc(len);
4237 xread(fd, map, len);
4238 }
4239#else
4240 len = MAXINT(ssize_t);
4241 map = xmalloc_open_read_close(filename, &len);
4242#endif
4243
Eric Andersene7047882003-12-11 01:42:13 +00004244 ret = syscall(__NR_init_module, map, len, options);
4245 if (ret != 0) {
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004246 bb_error_msg_and_die("cannot insert '%s': %s",
4247 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004248 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004249
Eric Andersene7047882003-12-11 01:42:13 +00004250 return 0;
4251}
4252
4253#endif