blob: 4620f6f95f88497cbc6d91257f01c987ad26e006 [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,
654 struct obj_section *symsec,
655 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
Eric Andersen14d35432001-05-14 17:07:32 +0000795static int check_module_name_match(const char *filename, struct stat *statbuf,
Denis Vlasenko8c35d652006-10-27 23:42:25 +0000796 void *userdata, int depth)
Eric Andersen9f16d612000-06-12 23:11:16 +0000797{
Eric Andersen14d35432001-05-14 17:07:32 +0000798 char *fullname = (char *) userdata;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000799 char *tmp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000800
Eric Andersen14d35432001-05-14 17:07:32 +0000801 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000802 return FALSE;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000803
804 tmp = bb_get_last_path_component_nostrip(filename);
805 if (strcmp(tmp, fullname) == 0) {
806 /* Stop searching if we find a match */
807 m_filename = xstrdup(filename);
808 return FALSE;
Erik Andersend387d011999-12-21 02:55:11 +0000809 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000810 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000811}
812
Erik Andersen02104321999-12-17 18:57:34 +0000813
Eric Andersen9f16d612000-06-12 23:11:16 +0000814/*======================================================================*/
815
Eric Andersen044228d2001-07-17 01:12:36 +0000816static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000817{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000818 struct arch_file *f;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000819 f = xzalloc(sizeof(*f));
820 return &f->root; /* it's a first member */
Eric Andersen9f16d612000-06-12 23:11:16 +0000821}
822
Eric Andersen044228d2001-07-17 01:12:36 +0000823static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000824{
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000825 return xzalloc(sizeof(struct obj_section));
Eric Andersen9f16d612000-06-12 23:11:16 +0000826}
827
Eric Andersen044228d2001-07-17 01:12:36 +0000828static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000829{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000830 struct arch_symbol *sym;
Denis Vlasenkob68979a2007-11-02 23:31:10 +0000831 sym = xzalloc(sizeof(*sym));
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 return &sym->root;
833}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000834
Eric Andersen044228d2001-07-17 01:12:36 +0000835static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000836arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000837 struct obj_section *targsec,
838 struct obj_section *symsec,
839 struct obj_symbol *sym,
840 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000841{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000842 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000843 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000844 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
845 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000846#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000847 struct arch_symbol *isym = (struct arch_symbol *) sym;
848#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000849#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000850#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000851 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000852#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000853#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000854#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000855 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000856 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000857# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000858 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000859# else
Eric Andersencffd5022002-05-24 06:50:15 +0000860 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000861# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000862#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000863
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000864 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000865
Eric Andersencffd5022002-05-24 06:50:15 +0000866#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000867
Eric Andersen3b1a7442003-12-24 20:30:45 +0000868 case R_ARM_NONE:
869 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000870
Eric Andersen3b1a7442003-12-24 20:30:45 +0000871 case R_ARM_ABS32:
872 *loc += v;
873 break;
Miles Baderae28b042002-04-01 09:34:25 +0000874
Eric Andersen3b1a7442003-12-24 20:30:45 +0000875 case R_ARM_GOT32:
876 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000879 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
880 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000881 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000882
Eric Andersen3b1a7442003-12-24 20:30:45 +0000883 *loc += got - dot;
884 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000885
Eric Andersen3b1a7442003-12-24 20:30:45 +0000886 case R_ARM_PC24:
887 case R_ARM_PLT32:
888 goto bb_use_plt;
889
890 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000891 *loc += v - got;
892 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000893
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000894#elif defined(__cris__)
895
896 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000898
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000899 case R_CRIS_32:
900 /* CRIS keeps the relocation value in the r_addend field and
901 * should not use whats in *loc at all
902 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000903 *loc = v;
904 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000905
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000906#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000907
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000908 case R_H8_DIR24R8:
909 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
910 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000911 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000912 case R_H8_DIR24A8:
913 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000914 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915 case R_H8_DIR32:
916 case R_H8_DIR32A16:
917 *loc += v;
918 break;
919 case R_H8_PCREL16:
920 v -= dot + 2;
921 if ((ElfW(Sword))v > 0x7fff ||
922 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
923 ret = obj_reloc_overflow;
924 else
925 *(unsigned short *)loc = v;
926 break;
927 case R_H8_PCREL8:
928 v -= dot + 1;
929 if ((ElfW(Sword))v > 0x7f ||
930 (ElfW(Sword))v < -(ElfW(Sword))0x80)
931 ret = obj_reloc_overflow;
932 else
933 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000934 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000935
Eric Andersencffd5022002-05-24 06:50:15 +0000936#elif defined(__i386__)
937
Eric Andersen3b1a7442003-12-24 20:30:45 +0000938 case R_386_NONE:
939 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000940
Eric Andersen3b1a7442003-12-24 20:30:45 +0000941 case R_386_32:
942 *loc += v;
943 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000944
Eric Andersen3b1a7442003-12-24 20:30:45 +0000945 case R_386_PLT32:
946 case R_386_PC32:
947 *loc += v - dot;
948 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000949
Eric Andersen3b1a7442003-12-24 20:30:45 +0000950 case R_386_GLOB_DAT:
951 case R_386_JMP_SLOT:
952 *loc = v;
953 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000954
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 case R_386_RELATIVE:
956 *loc += f->baseaddr;
957 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000958
Eric Andersen3b1a7442003-12-24 20:30:45 +0000959 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 *loc += got - dot;
961 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000962
Eric Andersen3b1a7442003-12-24 20:30:45 +0000963 case R_386_GOT32:
964 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000967 *loc += v - got;
968 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000969
Denis Vlasenkoff131b92007-04-10 15:42:06 +0000970#elif defined(__microblaze__)
Mike Frysinger280dae72006-06-06 06:30:32 +0000971 case R_MICROBLAZE_NONE:
972 case R_MICROBLAZE_64_NONE:
973 case R_MICROBLAZE_32_SYM_OP_SYM:
974 case R_MICROBLAZE_32_PCREL:
975 break;
976
977 case R_MICROBLAZE_64_PCREL: {
978 /* dot is the address of the current instruction.
979 * v is the target symbol address.
980 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000981 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000982 * of this instruction.
983 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
984 */
985
986 /* Get split offset stored in code */
987 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
988 (loc[1] & 0xFFFF);
989
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000990 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +0000991 * because dot points to the IMM insn, but branch
992 * is computed relative to the branch instruction itself.
993 */
994 temp += v - dot - 4;
995
996 /* Store back into code */
997 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
998 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
999
1000 break;
1001 }
1002
1003 case R_MICROBLAZE_32:
1004 *loc += v;
1005 break;
1006
1007 case R_MICROBLAZE_64: {
1008 /* Get split pointer stored in code */
1009 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1010 (loc[1] & 0xFFFF);
1011
1012 /* Add reloc offset */
1013 temp1+=v;
1014
1015 /* Store back into code */
1016 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1017 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1018
1019 break;
1020 }
1021
1022 case R_MICROBLAZE_32_PCREL_LO:
1023 case R_MICROBLAZE_32_LO:
1024 case R_MICROBLAZE_SRO32:
1025 case R_MICROBLAZE_SRW32:
1026 ret = obj_reloc_unhandled;
1027 break;
1028
Eric Andersencffd5022002-05-24 06:50:15 +00001029#elif defined(__mc68000__)
1030
Eric Andersen3b1a7442003-12-24 20:30:45 +00001031 case R_68K_NONE:
1032 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001033
Eric Andersen3b1a7442003-12-24 20:30:45 +00001034 case R_68K_32:
1035 *loc += v;
1036 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001037
Eric Andersen3b1a7442003-12-24 20:30:45 +00001038 case R_68K_8:
1039 if (v > 0xff) {
1040 ret = obj_reloc_overflow;
1041 }
1042 *(char *)loc = v;
1043 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001044
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_68K_16:
1046 if (v > 0xffff) {
1047 ret = obj_reloc_overflow;
1048 }
1049 *(short *)loc = v;
1050 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_68K_PC8:
1053 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001054 if ((ElfW(Sword))v > 0x7f ||
1055 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001056 ret = obj_reloc_overflow;
1057 }
1058 *(char *)loc = v;
1059 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001060
Eric Andersen3b1a7442003-12-24 20:30:45 +00001061 case R_68K_PC16:
1062 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001063 if ((ElfW(Sword))v > 0x7fff ||
1064 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001065 ret = obj_reloc_overflow;
1066 }
1067 *(short *)loc = v;
1068 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001069
Eric Andersen3b1a7442003-12-24 20:30:45 +00001070 case R_68K_PC32:
1071 *(int *)loc = v - dot;
1072 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001073
Eric Andersen3b1a7442003-12-24 20:30:45 +00001074 case R_68K_GLOB_DAT:
1075 case R_68K_JMP_SLOT:
1076 *loc = v;
1077 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001078
Eric Andersen3b1a7442003-12-24 20:30:45 +00001079 case R_68K_RELATIVE:
1080 *(int *)loc += f->baseaddr;
1081 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001082
Eric Andersen3b1a7442003-12-24 20:30:45 +00001083 case R_68K_GOT32:
1084 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001085
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001086# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001087 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001088 *loc += v - got;
1089 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001090# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001091
1092#elif defined(__mips__)
1093
Eric Andersen3b1a7442003-12-24 20:30:45 +00001094 case R_MIPS_NONE:
1095 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001096
Eric Andersen3b1a7442003-12-24 20:30:45 +00001097 case R_MIPS_32:
1098 *loc += v;
1099 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001100
Eric Andersen3b1a7442003-12-24 20:30:45 +00001101 case R_MIPS_26:
1102 if (v % 4)
1103 ret = obj_reloc_dangerous;
1104 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1105 ret = obj_reloc_overflow;
1106 *loc =
1107 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1108 0x03ffffff);
1109 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001110
Eric Andersen3b1a7442003-12-24 20:30:45 +00001111 case R_MIPS_HI16:
1112 {
1113 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001114
Eric Andersen3b1a7442003-12-24 20:30:45 +00001115 /* We cannot relocate this one now because we don't know the value
1116 of the carry we need to add. Save the information, and let LO16
1117 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001118 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001119 n->addr = loc;
1120 n->value = v;
1121 n->next = ifile->mips_hi16_list;
1122 ifile->mips_hi16_list = n;
1123 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001124 }
1125
Eric Andersen3b1a7442003-12-24 20:30:45 +00001126 case R_MIPS_LO16:
1127 {
1128 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001129 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001130
1131 /* Sign extend the addend we extract from the lo insn. */
1132 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1133
1134 if (ifile->mips_hi16_list != NULL) {
1135 struct mips_hi16 *l;
1136
1137 l = ifile->mips_hi16_list;
1138 while (l != NULL) {
1139 struct mips_hi16 *next;
1140 unsigned long insn;
1141
Eric Andersen3b1a7442003-12-24 20:30:45 +00001142 /* Do the HI16 relocation. Note that we actually don't
1143 need to know anything about the LO16 itself, except where
1144 to find the low 16 bits of the addend needed by the LO16. */
1145 insn = *l->addr;
1146 val =
1147 ((insn & 0xffff) << 16) +
1148 vallo;
1149 val += v;
1150
1151 /* Account for the sign extension that will happen in the
1152 low bits. */
1153 val =
1154 ((val >> 16) +
1155 ((val & 0x8000) !=
1156 0)) & 0xffff;
1157
1158 insn = (insn & ~0xffff) | val;
1159 *l->addr = insn;
1160
1161 next = l->next;
1162 free(l);
1163 l = next;
1164 }
1165
1166 ifile->mips_hi16_list = NULL;
1167 }
1168
1169 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1170 val = v + vallo;
1171 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1172 *loc = insnlo;
1173 break;
1174 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001175
Mike Frysingerf982d862006-01-04 00:11:26 +00001176#elif defined(__nios2__)
1177
1178 case R_NIOS2_NONE:
1179 break;
1180
1181 case R_NIOS2_BFD_RELOC_32:
1182 *loc += v;
1183 break;
1184
1185 case R_NIOS2_BFD_RELOC_16:
1186 if (v > 0xffff) {
1187 ret = obj_reloc_overflow;
1188 }
1189 *(short *)loc = v;
1190 break;
1191
1192 case R_NIOS2_BFD_RELOC_8:
1193 if (v > 0xff) {
1194 ret = obj_reloc_overflow;
1195 }
1196 *(char *)loc = v;
1197 break;
1198
1199 case R_NIOS2_S16:
1200 {
1201 Elf32_Addr word;
1202
1203 if ((Elf32_Sword)v > 0x7fff ||
1204 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1205 ret = obj_reloc_overflow;
1206 }
1207
1208 word = *loc;
1209 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1210 (word & 0x3f);
1211 }
1212 break;
1213
1214 case R_NIOS2_U16:
1215 {
1216 Elf32_Addr word;
1217
1218 if (v > 0xffff) {
1219 ret = obj_reloc_overflow;
1220 }
1221
1222 word = *loc;
1223 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1224 (word & 0x3f);
1225 }
1226 break;
1227
1228 case R_NIOS2_PCREL16:
1229 {
1230 Elf32_Addr word;
1231
1232 v -= dot + 4;
1233 if ((Elf32_Sword)v > 0x7fff ||
1234 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1235 ret = obj_reloc_overflow;
1236 }
1237
1238 word = *loc;
1239 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1240 }
1241 break;
1242
1243 case R_NIOS2_GPREL:
1244 {
1245 Elf32_Addr word, gp;
1246 /* get _gp */
1247 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1248 v-=gp;
1249 if ((Elf32_Sword)v > 0x7fff ||
1250 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1251 ret = obj_reloc_overflow;
1252 }
1253
1254 word = *loc;
1255 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1256 }
1257 break;
1258
1259 case R_NIOS2_CALL26:
1260 if (v & 3)
1261 ret = obj_reloc_dangerous;
1262 if ((v >> 28) != (dot >> 28))
1263 ret = obj_reloc_overflow;
1264 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1265 break;
1266
1267 case R_NIOS2_IMM5:
1268 {
1269 Elf32_Addr word;
1270
1271 if (v > 0x1f) {
1272 ret = obj_reloc_overflow;
1273 }
1274
1275 word = *loc & ~0x7c0;
1276 *loc = word | ((v & 0x1f) << 6);
1277 }
1278 break;
1279
1280 case R_NIOS2_IMM6:
1281 {
1282 Elf32_Addr word;
1283
1284 if (v > 0x3f) {
1285 ret = obj_reloc_overflow;
1286 }
1287
1288 word = *loc & ~0xfc0;
1289 *loc = word | ((v & 0x3f) << 6);
1290 }
1291 break;
1292
1293 case R_NIOS2_IMM8:
1294 {
1295 Elf32_Addr word;
1296
1297 if (v > 0xff) {
1298 ret = obj_reloc_overflow;
1299 }
1300
1301 word = *loc & ~0x3fc0;
1302 *loc = word | ((v & 0xff) << 6);
1303 }
1304 break;
1305
1306 case R_NIOS2_HI16:
1307 {
1308 Elf32_Addr word;
1309
1310 word = *loc;
1311 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1312 (word & 0x3f);
1313 }
1314 break;
1315
1316 case R_NIOS2_LO16:
1317 {
1318 Elf32_Addr word;
1319
1320 word = *loc;
1321 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1322 (word & 0x3f);
1323 }
1324 break;
1325
1326 case R_NIOS2_HIADJ16:
1327 {
1328 Elf32_Addr word1, word2;
1329
1330 word1 = *loc;
1331 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1332 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1333 (word1 & 0x3f);
1334 }
1335 break;
1336
Mike Frysingerebee0e72006-02-18 06:14:31 +00001337#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001338 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001339
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001340#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001341
Eric Andersen3b1a7442003-12-24 20:30:45 +00001342 case R_PPC_ADDR16_HA:
1343 *(unsigned short *)loc = (v + 0x8000) >> 16;
1344 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001345
Eric Andersen3b1a7442003-12-24 20:30:45 +00001346 case R_PPC_ADDR16_HI:
1347 *(unsigned short *)loc = v >> 16;
1348 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001349
Eric Andersen3b1a7442003-12-24 20:30:45 +00001350 case R_PPC_ADDR16_LO:
1351 *(unsigned short *)loc = v;
1352 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001353
Eric Andersen3b1a7442003-12-24 20:30:45 +00001354 case R_PPC_REL24:
1355 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001356
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 case R_PPC_REL32:
1358 *loc = v - dot;
1359 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001360
Eric Andersen3b1a7442003-12-24 20:30:45 +00001361 case R_PPC_ADDR32:
1362 *loc = v;
1363 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001364
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001365#elif defined(__s390__)
1366
1367 case R_390_32:
1368 *(unsigned int *) loc += v;
1369 break;
1370 case R_390_16:
1371 *(unsigned short *) loc += v;
1372 break;
1373 case R_390_8:
1374 *(unsigned char *) loc += v;
1375 break;
1376
1377 case R_390_PC32:
1378 *(unsigned int *) loc += v - dot;
1379 break;
1380 case R_390_PC16DBL:
1381 *(unsigned short *) loc += (v - dot) >> 1;
1382 break;
1383 case R_390_PC16:
1384 *(unsigned short *) loc += v - dot;
1385 break;
1386
1387 case R_390_PLT32:
1388 case R_390_PLT16DBL:
1389 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001390 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001391 if (pe->inited == 0) {
1392 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1393 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1394 ip[1] = 0x100607f1;
1395 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1396 ip[2] = v - 2;
1397 else
1398 ip[2] = v;
1399 pe->inited = 1;
1400 }
1401
1402 /* Insert relative distance to target. */
1403 v = plt + pe->offset - dot;
1404 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1405 *(unsigned int *) loc = (unsigned int) v;
1406 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1407 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1408 break;
1409
1410 case R_390_GLOB_DAT:
1411 case R_390_JMP_SLOT:
1412 *loc = v;
1413 break;
1414
1415 case R_390_RELATIVE:
1416 *loc += f->baseaddr;
1417 break;
1418
1419 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001420 *(unsigned long *) loc += got - dot;
1421 break;
1422
1423 case R_390_GOT12:
1424 case R_390_GOT16:
1425 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001426 if (!isym->gotent.inited)
1427 {
1428 isym->gotent.inited = 1;
1429 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1430 }
1431 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1432 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1433 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1434 *(unsigned short *) loc += isym->gotent.offset;
1435 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1436 *(unsigned int *) loc += isym->gotent.offset;
1437 break;
1438
1439# ifndef R_390_GOTOFF32
1440# define R_390_GOTOFF32 R_390_GOTOFF
1441# endif
1442 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001443 *loc += v - got;
1444 break;
1445
Eric Andersencffd5022002-05-24 06:50:15 +00001446#elif defined(__sh__)
1447
Eric Andersen3b1a7442003-12-24 20:30:45 +00001448 case R_SH_NONE:
1449 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001450
Eric Andersen3b1a7442003-12-24 20:30:45 +00001451 case R_SH_DIR32:
1452 *loc += v;
1453 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001454
Eric Andersen3b1a7442003-12-24 20:30:45 +00001455 case R_SH_REL32:
1456 *loc += v - dot;
1457 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001458
Eric Andersen3b1a7442003-12-24 20:30:45 +00001459 case R_SH_PLT32:
1460 *loc = v - dot;
1461 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001462
Eric Andersen3b1a7442003-12-24 20:30:45 +00001463 case R_SH_GLOB_DAT:
1464 case R_SH_JMP_SLOT:
1465 *loc = v;
1466 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001467
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 case R_SH_RELATIVE:
1469 *loc = f->baseaddr + rel->r_addend;
1470 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001471
Eric Andersen3b1a7442003-12-24 20:30:45 +00001472 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 *loc = got - dot + rel->r_addend;
1474 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 case R_SH_GOT32:
1477 goto bb_use_got;
1478
1479 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001480 *loc = v - got;
1481 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001482
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001483# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001484 case R_SH_IMM_MEDLOW16:
1485 case R_SH_IMM_LOW16:
1486 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001487 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001488
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001489 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001491
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492 /*
1493 * movi and shori have the format:
1494 *
1495 * | op | imm | reg | reserved |
1496 * 31..26 25..10 9.. 4 3 .. 0
1497 *
1498 * so we simply mask and or in imm.
1499 */
1500 word = *loc & ~0x3fffc00;
1501 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001502
Eric Andersen3b1a7442003-12-24 20:30:45 +00001503 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001504
Eric Andersen3b1a7442003-12-24 20:30:45 +00001505 break;
1506 }
Eric Andersenbf833552003-08-13 19:56:33 +00001507
Eric Andersen3b1a7442003-12-24 20:30:45 +00001508 case R_SH_IMM_MEDLOW16_PCREL:
1509 case R_SH_IMM_LOW16_PCREL:
1510 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001511 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001512
Eric Andersen3b1a7442003-12-24 20:30:45 +00001513 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001514
Eric Andersen3b1a7442003-12-24 20:30:45 +00001515 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001516
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001517 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001518 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001519
Eric Andersen3b1a7442003-12-24 20:30:45 +00001520 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001521
Eric Andersen3b1a7442003-12-24 20:30:45 +00001522 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001523
Eric Andersen3b1a7442003-12-24 20:30:45 +00001524 break;
1525 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001526# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001527
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001528#elif defined(__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001529
Eric Andersen3b1a7442003-12-24 20:30:45 +00001530 case R_V850_NONE:
1531 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001532
Eric Andersen3b1a7442003-12-24 20:30:45 +00001533 case R_V850_32:
1534 /* We write two shorts instead of a long because even
1535 32-bit insns only need half-word alignment, but
1536 32-bit data needs to be long-word aligned. */
1537 v += ((unsigned short *)loc)[0];
1538 v += ((unsigned short *)loc)[1] << 16;
1539 ((unsigned short *)loc)[0] = v & 0xffff;
1540 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1541 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001542
Eric Andersen3b1a7442003-12-24 20:30:45 +00001543 case R_V850_22_PCREL:
1544 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001545
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001546#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001547
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001548 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001549 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001550
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001551 case R_X86_64_64:
1552 *loc += v;
1553 break;
1554
1555 case R_X86_64_32:
1556 *(unsigned int *) loc += v;
1557 if (v > 0xffffffff)
1558 {
1559 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1560 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1561 }
1562 break;
1563
1564 case R_X86_64_32S:
1565 *(signed int *) loc += v;
1566 break;
1567
1568 case R_X86_64_16:
1569 *(unsigned short *) loc += v;
1570 break;
1571
1572 case R_X86_64_8:
1573 *(unsigned char *) loc += v;
1574 break;
1575
1576 case R_X86_64_PC32:
1577 *(unsigned int *) loc += v - dot;
1578 break;
1579
1580 case R_X86_64_PC16:
1581 *(unsigned short *) loc += v - dot;
1582 break;
1583
1584 case R_X86_64_PC8:
1585 *(unsigned char *) loc += v - dot;
1586 break;
1587
1588 case R_X86_64_GLOB_DAT:
1589 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001590 *loc = v;
1591 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001592
1593 case R_X86_64_RELATIVE:
1594 *loc += f->baseaddr;
1595 break;
1596
1597 case R_X86_64_GOT32:
1598 case R_X86_64_GOTPCREL:
1599 goto bb_use_got;
1600# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001601 if (!isym->gotent.reloc_done)
1602 {
1603 isym->gotent.reloc_done = 1;
1604 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1605 }
1606 /* XXX are these really correct? */
1607 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1608 *(unsigned int *) loc += v + isym->gotent.offset;
1609 else
1610 *loc += isym->gotent.offset;
1611 break;
1612# endif
1613
Mike Frysingerf982d862006-01-04 00:11:26 +00001614#else
1615# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001616#endif
1617
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001618 default:
1619 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1620 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001621 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001622
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001623#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001624
Eric Andersen3b1a7442003-12-24 20:30:45 +00001625bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001626
Eric Andersen3b1a7442003-12-24 20:30:45 +00001627 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001628
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001629#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001630 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1631 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001632#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001634#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001635
Eric Andersen3b1a7442003-12-24 20:30:45 +00001636 if (! pe->inited) {
1637 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001638
Eric Andersen3b1a7442003-12-24 20:30:45 +00001639 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001640
1641#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1643 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001644#endif
1645#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001647 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 ip[2] = 0x7d6903a6; /* mtctr r11 */
1649 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001650#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001651#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 /* We have to trash a register, so we assume that any control
1653 transfer more than 21-bits away must be a function call
1654 (so we can use a call-clobbered register). */
1655 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1656 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001657#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001658 pe->inited = 1;
1659 }
Eric Andersen21adca72000-12-06 18:18:26 +00001660
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 /* relative distance to target */
1662 v -= dot;
1663 /* if the target is too far away.... */
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001664#if defined(__arm__) || defined(__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001665 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001666#elif defined(__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001667 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001668#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 /* go via the plt */
1670 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001671
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001672#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001673 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001674#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001676#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001677 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001678
Eric Andersen3b1a7442003-12-24 20:30:45 +00001679 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001680#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001681 /* Convert to words. */
1682 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001683
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001685#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001686#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001687 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001688#endif
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001689#if defined(__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 /* We write two shorts instead of a long because even 32-bit insns
1691 only need half-word alignment, but the 32-bit data write needs
1692 to be long-word aligned. */
1693 ((unsigned short *)loc)[0] =
1694 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1695 | ((v >> 16) & 0x3f); /* offs high part */
1696 ((unsigned short *)loc)[1] =
1697 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001698#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001699 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001700#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001701
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001702#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001703bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001704
Eric Andersen3b1a7442003-12-24 20:30:45 +00001705 /* needs an entry in the .got: set it, once */
1706 if (!isym->gotent.inited) {
1707 isym->gotent.inited = 1;
1708 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1709 }
1710 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001711#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001712 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001713#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001714 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001715#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001716 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001717
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001718#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001719 }
1720
1721 return ret;
1722}
1723
Eric Andersencffd5022002-05-24 06:50:15 +00001724
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001725#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001726
1727static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1728 int offset, int size)
1729{
1730 struct arch_list_entry *pe;
1731
1732 for (pe = *list; pe != NULL; pe = pe->next) {
1733 if (pe->addend == rel->r_addend) {
1734 break;
1735 }
1736 }
1737
1738 if (pe == NULL) {
1739 pe = xmalloc(sizeof(struct arch_list_entry));
1740 pe->next = *list;
1741 pe->addend = rel->r_addend;
1742 pe->offset = offset;
1743 pe->inited = 0;
1744 *list = pe;
1745 return size;
1746 }
1747 return 0;
1748}
1749
1750#endif
1751
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001752#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001753
1754static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1755 int offset, int size)
1756{
1757 if (single->allocated == 0) {
1758 single->allocated = 1;
1759 single->offset = offset;
1760 single->inited = 0;
1761 return size;
1762 }
1763 return 0;
1764}
1765
1766#endif
1767
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001768#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001769
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001770static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001771 int offset, int size)
1772{
1773 struct obj_section *myrelsec = obj_find_section(f, name);
1774
1775 if (offset == 0) {
1776 offset += size;
1777 }
1778
1779 if (myrelsec) {
1780 obj_extend_section(myrelsec, offset);
1781 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001782 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001783 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001784 }
1785
1786 return myrelsec;
1787}
1788
1789#endif
1790
1791static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001792{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001793#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001794 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001795 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001796#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001797 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001798#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001799#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001800 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001801#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001802 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001803 ElfW(RelM) *rel, *relend;
1804 ElfW(Sym) *symtab, *extsym;
1805 const char *strtab, *name;
1806 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001807
Eric Andersen21adca72000-12-06 18:18:26 +00001808 for (i = 0; i < f->header.e_shnum; ++i) {
1809 relsec = f->sections[i];
1810 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001811 continue;
1812
Eric Andersen21adca72000-12-06 18:18:26 +00001813 symsec = f->sections[relsec->header.sh_link];
1814 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001815
Eric Andersen21adca72000-12-06 18:18:26 +00001816 rel = (ElfW(RelM) *) relsec->contents;
1817 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1818 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001819 strtab = (const char *) strsec->contents;
1820
1821 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001822 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001823
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001824#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001825 got_allocate = 0;
1826#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001827#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001828 plt_allocate = 0;
1829#endif
1830
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001831 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001832#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001833 case R_ARM_PC24:
1834 case R_ARM_PLT32:
1835 plt_allocate = 1;
1836 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001837
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001838 case R_ARM_GOTOFF:
1839 case R_ARM_GOTPC:
1840 got_needed = 1;
1841 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001842
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001843 case R_ARM_GOT32:
1844 got_allocate = 1;
1845 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001846
Eric Andersen21adca72000-12-06 18:18:26 +00001847#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001848 case R_386_GOTPC:
1849 case R_386_GOTOFF:
1850 got_needed = 1;
1851 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001852
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001853 case R_386_GOT32:
1854 got_allocate = 1;
1855 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001856
1857#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001858 case R_PPC_REL24:
1859 plt_allocate = 1;
1860 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001861
1862#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001863 case R_68K_GOT32:
1864 got_allocate = 1;
1865 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001866
Eric Andersen16451a02004-03-19 12:16:18 +00001867#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001868 case R_68K_GOTOFF:
1869 got_needed = 1;
1870 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001871#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001872
1873#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001874 case R_SH_GOT32:
1875 got_allocate = 1;
1876 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001877
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001878 case R_SH_GOTPC:
1879 case R_SH_GOTOFF:
1880 got_needed = 1;
1881 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001882
Denis Vlasenkoff131b92007-04-10 15:42:06 +00001883#elif defined(__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001884 case R_V850_22_PCREL:
1885 plt_needed = 1;
1886 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001887
1888#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001889 default:
1890 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001891 }
1892
Eric Andersen21adca72000-12-06 18:18:26 +00001893 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001894 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001895 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001896 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001897 }
1898 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001899#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001900 if (got_allocate) {
1901 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001902 rel, &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001903 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001904
1905 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001906 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001907#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001908#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001909 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001910#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001911 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001912 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001913 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001914#else
1915 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001916 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001917 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001918#endif
1919 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001920 }
1921#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001922 }
Miles Baderae28b042002-04-01 09:34:25 +00001923 }
Eric Andersen21adca72000-12-06 18:18:26 +00001924
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001925#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001926 if (got_needed) {
1927 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001928 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001929 }
Eric Andersen21adca72000-12-06 18:18:26 +00001930#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001931
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001932#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001933 if (plt_needed) {
1934 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001935 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001936 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001937#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001938
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001939#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001940}
1941
Eric Andersen9f16d612000-06-12 23:11:16 +00001942/*======================================================================*/
1943
1944/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001945static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001946{
1947 unsigned long h = 0;
1948 unsigned long g;
1949 unsigned char ch;
1950
1951 while (n > 0) {
1952 ch = *name++;
1953 h = (h << 4) + ch;
Denis Vlasenko1bec1b92007-11-06 02:23:39 +00001954 g = (h & 0xf0000000);
1955 if (g != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001956 h ^= g >> 24;
1957 h &= ~g;
1958 }
1959 n--;
1960 }
1961 return h;
1962}
1963
Eric Andersen044228d2001-07-17 01:12:36 +00001964static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001965{
1966 return obj_elf_hash_n(name, strlen(name));
1967}
1968
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001969#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001970/* String comparison for non-co-versioned kernel and module. */
1971
1972static int ncv_strcmp(const char *a, const char *b)
1973{
1974 size_t alen = strlen(a), blen = strlen(b);
1975
1976 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1977 return strncmp(a, b, alen);
1978 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1979 return strncmp(a, b, blen);
1980 else
1981 return strcmp(a, b);
1982}
1983
1984/* String hashing for non-co-versioned kernel and module. Here
1985 we are simply forced to drop the crc from the hash. */
1986
1987static unsigned long ncv_symbol_hash(const char *str)
1988{
1989 size_t len = strlen(str);
1990 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1991 len -= 10;
1992 return obj_elf_hash_n(str, len);
1993}
1994
Eric Andersen044228d2001-07-17 01:12:36 +00001995static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001996obj_set_symbol_compare(struct obj_file *f,
1997 int (*cmp) (const char *, const char *),
1998 unsigned long (*hash) (const char *))
1999{
2000 if (cmp)
2001 f->symbol_cmp = cmp;
2002 if (hash) {
2003 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2004 int i;
2005
2006 f->symbol_hash = hash;
2007
2008 memcpy(tmptab, f->symtab, sizeof(tmptab));
2009 memset(f->symtab, 0, sizeof(f->symtab));
2010
2011 for (i = 0; i < HASH_BUCKETS; ++i)
2012 for (sym = tmptab[i]; sym; sym = next) {
2013 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2014 next = sym->next;
2015 sym->next = f->symtab[h];
2016 f->symtab[h] = sym;
2017 }
2018 }
2019}
2020
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002021#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002022
Eric Andersen044228d2001-07-17 01:12:36 +00002023static struct obj_symbol *
2024obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002025 unsigned long symidx, int info,
2026 int secidx, ElfW(Addr) value,
2027 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002028{
2029 struct obj_symbol *sym;
2030 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002031 int n_type = ELF_ST_TYPE(info);
2032 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002033
2034 for (sym = f->symtab[hash]; sym; sym = sym->next)
2035 if (f->symbol_cmp(sym->name, name) == 0) {
2036 int o_secidx = sym->secidx;
2037 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002038 int o_type = ELF_ST_TYPE(o_info);
2039 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002040
2041 /* A redefinition! Is it legal? */
2042
2043 if (secidx == SHN_UNDEF)
2044 return sym;
2045 else if (o_secidx == SHN_UNDEF)
2046 goto found;
2047 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2048 /* Cope with local and global symbols of the same name
2049 in the same object file, as might have been created
2050 by ld -r. The only reason locals are now seen at this
2051 level at all is so that we can do semi-sensible things
2052 with parameters. */
2053
2054 struct obj_symbol *nsym, **p;
2055
2056 nsym = arch_new_symbol();
2057 nsym->next = sym->next;
2058 nsym->ksymidx = -1;
2059
2060 /* Excise the old (local) symbol from the hash chain. */
2061 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2062 continue;
2063 *p = sym = nsym;
2064 goto found;
2065 } else if (n_binding == STB_LOCAL) {
2066 /* Another symbol of the same name has already been defined.
2067 Just add this to the local table. */
2068 sym = arch_new_symbol();
2069 sym->next = NULL;
2070 sym->ksymidx = -1;
2071 f->local_symtab[symidx] = sym;
2072 goto found;
2073 } else if (n_binding == STB_WEAK)
2074 return sym;
2075 else if (o_binding == STB_WEAK)
2076 goto found;
2077 /* Don't unify COMMON symbols with object types the programmer
2078 doesn't expect. */
2079 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002080 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002081 return sym;
2082 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002083 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002084 goto found;
2085 else {
2086 /* Don't report an error if the symbol is coming from
2087 the kernel or some external module. */
2088 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002089 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002090 return sym;
2091 }
2092 }
2093
2094 /* Completely new symbol. */
2095 sym = arch_new_symbol();
2096 sym->next = f->symtab[hash];
2097 f->symtab[hash] = sym;
2098 sym->ksymidx = -1;
2099
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002100 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002101 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002102 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002103 name, (long) symidx, (long) f->local_symtab_size);
2104 else
2105 f->local_symtab[symidx] = sym;
2106 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002107
Eric Andersen3b1a7442003-12-24 20:30:45 +00002108found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002109 sym->name = name;
2110 sym->value = value;
2111 sym->size = size;
2112 sym->secidx = secidx;
2113 sym->info = info;
2114
2115 return sym;
2116}
2117
Eric Andersen044228d2001-07-17 01:12:36 +00002118static struct obj_symbol *
2119obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002120{
2121 struct obj_symbol *sym;
2122 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2123
2124 for (sym = f->symtab[hash]; sym; sym = sym->next)
2125 if (f->symbol_cmp(sym->name, name) == 0)
2126 return sym;
2127
2128 return NULL;
2129}
2130
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002131static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002132{
2133 if (sym) {
2134 if (sym->secidx >= SHN_LORESERVE)
2135 return sym->value;
2136
2137 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2138 } else {
2139 /* As a special case, a NULL sym has value zero. */
2140 return 0;
2141 }
2142}
2143
Eric Andersen044228d2001-07-17 01:12:36 +00002144static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002145{
2146 int i, n = f->header.e_shnum;
2147
2148 for (i = 0; i < n; ++i)
2149 if (strcmp(f->sections[i]->name, name) == 0)
2150 return f->sections[i];
2151
2152 return NULL;
2153}
2154
2155static int obj_load_order_prio(struct obj_section *a)
2156{
2157 unsigned long af, ac;
2158
2159 af = a->header.sh_flags;
2160
2161 ac = 0;
2162 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002163 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002164 ac |= 32;
2165 if (af & SHF_ALLOC)
2166 ac |= 16;
2167 if (!(af & SHF_WRITE))
2168 ac |= 8;
2169 if (af & SHF_EXECINSTR)
2170 ac |= 4;
2171 if (a->header.sh_type != SHT_NOBITS)
2172 ac |= 2;
2173
2174 return ac;
2175}
2176
Eric Andersen044228d2001-07-17 01:12:36 +00002177static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002178obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2179{
2180 struct obj_section **p;
2181 int prio = obj_load_order_prio(sec);
2182 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2183 if (obj_load_order_prio(*p) < prio)
2184 break;
2185 sec->load_next = *p;
2186 *p = sec;
2187}
2188
Eric Andersen044228d2001-07-17 01:12:36 +00002189static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002190 const char *name,
2191 unsigned long align,
2192 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002193{
2194 int newidx = f->header.e_shnum++;
2195 struct obj_section *sec;
2196
2197 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2198 f->sections[newidx] = sec = arch_new_section();
2199
Eric Andersen9f16d612000-06-12 23:11:16 +00002200 sec->header.sh_type = SHT_PROGBITS;
2201 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2202 sec->header.sh_size = size;
2203 sec->header.sh_addralign = align;
2204 sec->name = name;
2205 sec->idx = newidx;
2206 if (size)
2207 sec->contents = xmalloc(size);
2208
2209 obj_insert_section_load_order(f, sec);
2210
2211 return sec;
2212}
2213
Eric Andersen044228d2001-07-17 01:12:36 +00002214static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002215 const char *name,
2216 unsigned long align,
2217 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002218{
2219 int newidx = f->header.e_shnum++;
2220 struct obj_section *sec;
2221
2222 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2223 f->sections[newidx] = sec = arch_new_section();
2224
Eric Andersen9f16d612000-06-12 23:11:16 +00002225 sec->header.sh_type = SHT_PROGBITS;
2226 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2227 sec->header.sh_size = size;
2228 sec->header.sh_addralign = align;
2229 sec->name = name;
2230 sec->idx = newidx;
2231 if (size)
2232 sec->contents = xmalloc(size);
2233
2234 sec->load_next = f->load_order;
2235 f->load_order = sec;
2236 if (f->load_order_search_start == &f->load_order)
2237 f->load_order_search_start = &sec->load_next;
2238
2239 return sec;
2240}
2241
Eric Andersen044228d2001-07-17 01:12:36 +00002242static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002243{
2244 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002245 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002246 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2247 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002248 return sec->contents + oldsize;
2249}
2250
2251
Eric Andersen9f16d612000-06-12 23:11:16 +00002252/* Conditionally add the symbols from the given symbol set to the
2253 new module. */
2254
2255static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002256add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002257 int idx, struct new_module_symbol *syms, size_t nsyms)
2258{
2259 struct new_module_symbol *s;
2260 size_t i;
2261 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002262#ifdef SYMBOL_PREFIX
2263 char *name_buf = 0;
2264 size_t name_alloced_size = 0;
2265#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002266#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002267 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002268
Glenn L McGrath759515c2003-08-30 06:00:33 +00002269 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002270#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002271 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002272 /* Only add symbols that are already marked external.
2273 If we override locals we may cause problems for
2274 argument initialization. We will also create a false
2275 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002276 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002277 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002278
Glenn L McGrath759515c2003-08-30 06:00:33 +00002279 /* GPL licensed modules can use symbols exported with
2280 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2281 * exported names. Non-GPL modules never see any GPLONLY_
2282 * symbols so they cannot fudge it by adding the prefix on
2283 * their references.
2284 */
2285 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002286#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002287 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002288 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002289 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002290#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002291 continue;
2292 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002293 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002294
Miles Baderae28b042002-04-01 09:34:25 +00002295#ifdef SYMBOL_PREFIX
2296 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2297 kernel exports `C names', but module object files
2298 reference `linker names'). */
2299 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002300 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002301 if (name_size > name_alloced_size) {
2302 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002303 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002304 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002305 strcpy(name_buf, SYMBOL_PREFIX);
2306 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002307 name = name_buf;
2308#endif /* SYMBOL_PREFIX */
2309
2310 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002311 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002312#ifdef SYMBOL_PREFIX
2313 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002314 name = xmalloc(name_size);
2315 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002316#endif
2317 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002318 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002319 STT_NOTYPE),
2320 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002321 /* Did our symbol just get installed? If so, mark the
2322 module as "used". */
2323 if (sym->secidx == idx)
2324 used = 1;
2325 }
2326 }
2327
2328 return used;
2329}
2330
2331static void add_kernel_symbols(struct obj_file *f)
2332{
2333 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002334 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002335
2336 /* Add module symbols first. */
2337
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002338 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002339 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002340 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2341 ) {
2342 m->used = 1;
2343 ++nused;
2344 }
2345 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002346
2347 n_ext_modules_used = nused;
2348
2349 /* And finally the symbols from the kernel proper. */
2350
2351 if (nksyms)
2352 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2353}
2354
2355static char *get_modinfo_value(struct obj_file *f, const char *key)
2356{
2357 struct obj_section *sec;
2358 char *p, *v, *n, *ep;
2359 size_t klen = strlen(key);
2360
2361 sec = obj_find_section(f, ".modinfo");
2362 if (sec == NULL)
2363 return NULL;
2364 p = sec->contents;
2365 ep = p + sec->header.sh_size;
2366 while (p < ep) {
2367 v = strchr(p, '=');
2368 n = strchr(p, '\0');
2369 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002370 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002371 return v + 1;
2372 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002373 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002374 return n;
2375 }
2376 p = n + 1;
2377 }
2378
2379 return NULL;
2380}
2381
2382
2383/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002384/* Functions relating to module loading after 2.1.18. */
2385
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002386static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002387new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2388{
2389 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002390 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002391 struct obj_symbol *sym;
2392 char *contents, *loc;
2393 int min, max, n;
2394
2395 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002396 q = strchr(p, '=');
2397 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002398 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002400 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002401
2402 key = alloca(q - p + 6);
2403 memcpy(key, "parm_", 5);
2404 memcpy(key + 5, p, q - p);
2405 key[q - p + 5] = 0;
2406
2407 p = get_modinfo_value(f, key);
2408 key += 5;
2409 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002410 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002411 }
2412
Miles Baderae28b042002-04-01 09:34:25 +00002413#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002414 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2415 strcpy(sym_name, SYMBOL_PREFIX);
2416 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002417#else
2418 sym_name = key;
2419#endif
2420 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002421
2422 /* Also check that the parameter was not resolved from the kernel. */
2423 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002424 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002425 }
2426
2427 if (isdigit(*p)) {
2428 min = strtoul(p, &p, 10);
2429 if (*p == '-')
2430 max = strtoul(p + 1, &p, 10);
2431 else
2432 max = min;
2433 } else
2434 min = max = 1;
2435
2436 contents = f->sections[sym->secidx]->contents;
2437 loc = contents + sym->value;
2438 n = (*++q != '\0');
2439
2440 while (1) {
2441 if ((*p == 's') || (*p == 'c')) {
2442 char *str;
2443
2444 /* Do C quoting if we begin with a ", else slurp the lot. */
2445 if (*q == '"') {
2446 char *r;
2447
2448 str = alloca(strlen(q));
2449 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002450 if (*q == '\0')
2451 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002452 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002453 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002454 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002455 case 'a':
2456 *r = '\a';
2457 break;
2458 case 'b':
2459 *r = '\b';
2460 break;
2461 case 'e':
2462 *r = '\033';
2463 break;
2464 case 'f':
2465 *r = '\f';
2466 break;
2467 case 'n':
2468 *r = '\n';
2469 break;
2470 case 'r':
2471 *r = '\r';
2472 break;
2473 case 't':
2474 *r = '\t';
2475 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002476
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002477 case '0':
2478 case '1':
2479 case '2':
2480 case '3':
2481 case '4':
2482 case '5':
2483 case '6':
2484 case '7':
2485 {
2486 int c = *q - '0';
2487 if (q[1] >= '0' && q[1] <= '7') {
2488 c = (c * 8) + *++q - '0';
2489 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002490 c = (c * 8) + *++q - '0';
2491 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002492 *r = c;
2493 }
2494 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002495
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002496 default:
2497 *r = *q;
2498 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002499 }
2500 else
2501 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002502 }
2503 *r = '\0';
2504 ++q;
2505 } else {
2506 char *r;
2507
2508 /* In this case, the string is not quoted. We will break
2509 it using the coma (like for ints). If the user wants to
2510 include comas in a string, he just has to quote it */
2511
2512 /* Search the next coma */
2513 r = strchr(q, ',');
2514
2515 /* Found ? */
2516 if (r != (char *) NULL) {
2517 /* Recopy the current field */
2518 str = alloca(r - q + 1);
2519 memcpy(str, q, r - q);
2520
Eric Andersenaff114c2004-04-14 17:51:38 +00002521 /* I don't know if it is useful, as the previous case
2522 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002523 str[r - q] = '\0';
2524
2525 /* Keep next fields */
2526 q = r;
2527 } else {
2528 /* last string */
2529 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002530 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002531 }
2532 }
2533
2534 if (*p == 's') {
2535 /* Normal string */
2536 obj_string_patch(f, sym->secidx, loc - contents, str);
2537 loc += tgt_sizeof_char_p;
2538 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002539 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002540 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002541
2542 /* Get the size of each member */
2543 /* Probably we should do that outside the loop ? */
2544 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002545 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002546 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002547 }
2548 charssize = strtoul(p + 1, (char **) NULL, 10);
2549
2550 /* Check length */
2551 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002552 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002553 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002554 }
2555
2556 /* Copy to location */
2557 strcpy((char *) loc, str);
2558 loc += charssize;
2559 }
2560 } else {
2561 long v = strtoul(q, &q, 0);
2562 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002563 case 'b':
2564 *loc++ = v;
2565 break;
2566 case 'h':
2567 *(short *) loc = v;
2568 loc += tgt_sizeof_short;
2569 break;
2570 case 'i':
2571 *(int *) loc = v;
2572 loc += tgt_sizeof_int;
2573 break;
2574 case 'l':
2575 *(long *) loc = v;
2576 loc += tgt_sizeof_long;
2577 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002578
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002579 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002580 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002581 }
2582 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002583 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002584 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002585 case '\0':
2586 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002587
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002588 case ' ':
2589 case '\t':
2590 case '\n':
2591 case '\r':
2592 ++q;
2593 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002594
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002595 case ',':
2596 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002597 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002598 }
2599 ++q;
2600 break;
2601
2602 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002603 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002604 }
2605 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002606 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002607 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002608 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002609 }
2610
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002611 argc--;
2612 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002613 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002614}
2615
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002616#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002617static int new_is_module_checksummed(struct obj_file *f)
2618{
2619 const char *p = get_modinfo_value(f, "using_checksums");
2620 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002621 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002622 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002623}
2624
2625/* Get the module's kernel version in the canonical integer form. */
2626
2627static int
2628new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2629{
2630 char *p, *q;
2631 int a, b, c;
2632
2633 p = get_modinfo_value(f, "kernel_version");
2634 if (p == NULL)
2635 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002636 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002637
2638 a = strtoul(p, &p, 10);
2639 if (*p != '.')
2640 return -1;
2641 b = strtoul(p + 1, &p, 10);
2642 if (*p != '.')
2643 return -1;
2644 c = strtoul(p + 1, &q, 10);
2645 if (p + 1 == q)
2646 return -1;
2647
2648 return a << 16 | b << 8 | c;
2649}
2650
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002651#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002652
2653
Eric Andersen9f16d612000-06-12 23:11:16 +00002654/* Fetch the loaded modules, and all currently exported symbols. */
2655
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002656static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002657{
2658 char *module_names, *mn;
2659 struct external_module *modules, *m;
2660 struct new_module_symbol *syms, *s;
2661 size_t ret, bufsize, nmod, nsyms, i, j;
2662
2663 /* Collect the loaded modules. */
2664
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002665 bufsize = 256;
2666 module_names = xmalloc(bufsize);
2667
2668 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002669 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002670 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002671 bufsize = ret;
2672 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002673 goto retry_modules_load;
2674 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002675 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002676 }
2677
2678 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002679
2680 /* Collect the modules' symbols. */
2681
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002682 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002683 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2684 memset(modules, 0, nmod * sizeof(*modules));
2685 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002686 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002687 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002688
Mark Whitley94fd4802001-03-12 23:08:34 +00002689 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2690 if (errno == ENOENT) {
2691 /* The module was removed out from underneath us. */
2692 continue;
2693 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002694 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002695 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002696
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002697 bufsize = 1024;
2698 syms = xmalloc(bufsize);
2699 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002700 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2701 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002702 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002703 bufsize = ret;
2704 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002705 goto retry_mod_sym_load;
2706 case ENOENT:
2707 /* The module was removed out from underneath us. */
2708 continue;
2709 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002710 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002711 }
2712 }
2713 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002714
Mark Whitley94fd4802001-03-12 23:08:34 +00002715 m->name = mn;
2716 m->addr = info.addr;
2717 m->nsyms = nsyms;
2718 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002719
Mark Whitley94fd4802001-03-12 23:08:34 +00002720 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2721 s->name += (unsigned long) syms;
2722 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002723 }
2724 }
2725
2726 /* Collect the kernel's symbols. */
2727
2728 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002729 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002730 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002731 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002732 syms = xrealloc(syms, bufsize = ret);
2733 goto retry_kern_sym_load;
2734 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002735 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002736 }
2737 nksyms = nsyms = ret;
2738 ksyms = syms;
2739
2740 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2741 s->name += (unsigned long) syms;
2742 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002743}
2744
2745
2746/* Return the kernel symbol checksum version, or zero if not used. */
2747
2748static int new_is_kernel_checksummed(void)
2749{
2750 struct new_module_symbol *s;
2751 size_t i;
2752
2753 /* Using_Versions is not the first symbol, but it should be in there. */
2754
2755 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2756 if (strcmp((char *) s->name, "Using_Versions") == 0)
2757 return s->value;
2758
2759 return 0;
2760}
2761
2762
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002763static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002764{
2765 struct obj_section *sec;
2766
2767 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002768 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002769 memset(sec->contents, 0, sizeof(struct new_module));
2770
Miles Baderae28b042002-04-01 09:34:25 +00002771 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002772 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002773 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002774
2775 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002776 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002777}
2778
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002779#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002780/* add an entry to the __ksymtab section, creating it if necessary */
2781static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2782{
2783 struct obj_section *sec;
2784 ElfW(Addr) ofs;
2785
2786 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2787 * If __ksymtab is defined but not marked alloc, x out the first character
2788 * (no obj_delete routine) and create a new __ksymtab with the correct
2789 * characteristics.
2790 */
2791 sec = obj_find_section(f, "__ksymtab");
2792 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2793 *((char *)(sec->name)) = 'x'; /* override const */
2794 sec = NULL;
2795 }
2796 if (!sec)
2797 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002798 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002799 if (!sec)
2800 return;
2801 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002802 /* Empty section might be byte-aligned */
2803 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002804 ofs = sec->header.sh_size;
2805 obj_symbol_patch(f, sec->idx, ofs, sym);
2806 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2807 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2808}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002809#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002810
2811static int new_create_module_ksymtab(struct obj_file *f)
2812{
2813 struct obj_section *sec;
2814 int i;
2815
2816 /* We must always add the module references. */
2817
2818 if (n_ext_modules_used) {
2819 struct new_module_ref *dep;
2820 struct obj_symbol *tm;
2821
2822 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002823 (sizeof(struct new_module_ref)
2824 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002825 if (!sec)
2826 return 0;
2827
Miles Baderae28b042002-04-01 09:34:25 +00002828 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002829 dep = (struct new_module_ref *) sec->contents;
2830 for (i = 0; i < n_ext_modules; ++i)
2831 if (ext_modules[i].used) {
2832 dep->dep = ext_modules[i].addr;
2833 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002834 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002835 dep->next_ref = 0;
2836 ++dep;
2837 }
2838 }
2839
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002840 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002841 size_t nsyms;
2842 int *loaded;
2843
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002844 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002845
2846 /* We don't want to export symbols residing in sections that
2847 aren't loaded. There are a number of these created so that
2848 we make sure certain module options don't appear twice. */
2849
2850 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2851 while (--i >= 0)
2852 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2853
2854 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2855 struct obj_symbol *sym;
2856 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002857 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002858 && sym->secidx <= SHN_HIRESERVE
2859 && (sym->secidx >= SHN_LORESERVE
2860 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002861 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2862
2863 obj_symbol_patch(f, sec->idx, ofs, sym);
2864 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002865 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002866
2867 nsyms++;
2868 }
2869 }
2870
2871 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2872 }
2873
2874 return 1;
2875}
2876
2877
2878static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002879new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002880{
2881 struct new_module *module;
2882 struct obj_section *sec;
2883 void *image;
2884 int ret;
2885 tgt_long m_addr;
2886
2887 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002888 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002889 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002890 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002891 module = (struct new_module *) sec->contents;
2892 m_addr = sec->header.sh_addr;
2893
2894 module->size_of_struct = sizeof(*module);
2895 module->size = m_size;
2896 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2897
2898 sec = obj_find_section(f, "__ksymtab");
2899 if (sec && sec->header.sh_size) {
2900 module->syms = sec->header.sh_addr;
2901 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2902 }
2903
2904 if (n_ext_modules_used) {
2905 sec = obj_find_section(f, ".kmodtab");
2906 module->deps = sec->header.sh_addr;
2907 module->ndeps = n_ext_modules_used;
2908 }
2909
2910 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002911 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002912 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002913 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002914
2915 sec = obj_find_section(f, "__ex_table");
2916 if (sec) {
2917 module->ex_table_start = sec->header.sh_addr;
2918 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2919 }
2920
2921 sec = obj_find_section(f, ".text.init");
2922 if (sec) {
2923 module->runsize = sec->header.sh_addr - m_addr;
2924 }
2925 sec = obj_find_section(f, ".data.init");
2926 if (sec) {
2927 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002928 module->runsize > sec->header.sh_addr - m_addr)
2929 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002931 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2932 if (sec && sec->header.sh_size) {
2933 module->archdata_start = (void*)sec->header.sh_addr;
2934 module->archdata_end = module->archdata_start + sec->header.sh_size;
2935 }
2936 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2937 if (sec && sec->header.sh_size) {
2938 module->kallsyms_start = (void*)sec->header.sh_addr;
2939 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2940 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002941
Eric Andersen9f16d612000-06-12 23:11:16 +00002942 /* Whew! All of the initialization is complete. Collect the final
2943 module image and give it to the kernel. */
2944
2945 image = xmalloc(m_size);
2946 obj_create_image(f, image);
2947
Eric Andersencb3b9b12004-06-22 11:50:52 +00002948 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002949 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002950 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002951
2952 free(image);
2953
2954 return ret == 0;
2955}
2956
Eric Andersen9f16d612000-06-12 23:11:16 +00002957
2958/*======================================================================*/
2959
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002960static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002961obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2962 const char *string)
2963{
2964 struct obj_string_patch *p;
2965 struct obj_section *strsec;
2966 size_t len = strlen(string) + 1;
2967 char *loc;
2968
2969 p = xmalloc(sizeof(*p));
2970 p->next = f->string_patches;
2971 p->reloc_secidx = secidx;
2972 p->reloc_offset = offset;
2973 f->string_patches = p;
2974
2975 strsec = obj_find_section(f, ".kstrtab");
2976 if (strsec == NULL) {
2977 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2978 p->string_offset = 0;
2979 loc = strsec->contents;
2980 } else {
2981 p->string_offset = strsec->header.sh_size;
2982 loc = obj_extend_section(strsec, len);
2983 }
2984 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002985}
2986
Denis Vlasenko6cee58e2007-11-04 15:43:26 +00002987static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002988obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2989 struct obj_symbol *sym)
2990{
2991 struct obj_symbol_patch *p;
2992
2993 p = xmalloc(sizeof(*p));
2994 p->next = f->symbol_patches;
2995 p->reloc_secidx = secidx;
2996 p->reloc_offset = offset;
2997 p->sym = sym;
2998 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00002999}
3000
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003001static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003002{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003003 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003004
3005 for (i = 0; i < HASH_BUCKETS; ++i) {
3006 struct obj_symbol *sym;
3007 for (sym = f->symtab[i]; sym; sym = sym->next)
3008 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003009 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003010 sym->secidx = SHN_ABS;
3011 sym->value = 0;
3012 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003013 if (!flag_quiet)
3014 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003015 }
3016 }
3017 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003018}
3019
Eric Andersen044228d2001-07-17 01:12:36 +00003020static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003021{
3022 struct common_entry {
3023 struct common_entry *next;
3024 struct obj_symbol *sym;
3025 } *common_head = NULL;
3026
3027 unsigned long i;
3028
3029 for (i = 0; i < HASH_BUCKETS; ++i) {
3030 struct obj_symbol *sym;
3031 for (sym = f->symtab[i]; sym; sym = sym->next)
3032 if (sym->secidx == SHN_COMMON) {
3033 /* Collect all COMMON symbols and sort them by size so as to
3034 minimize space wasted by alignment requirements. */
3035 {
3036 struct common_entry **p, *n;
3037 for (p = &common_head; *p; p = &(*p)->next)
3038 if (sym->size <= (*p)->sym->size)
3039 break;
3040
3041 n = alloca(sizeof(*n));
3042 n->next = *p;
3043 n->sym = sym;
3044 *p = n;
3045 }
3046 }
3047 }
3048
3049 for (i = 1; i < f->local_symtab_size; ++i) {
3050 struct obj_symbol *sym = f->local_symtab[i];
3051 if (sym && sym->secidx == SHN_COMMON) {
3052 struct common_entry **p, *n;
3053 for (p = &common_head; *p; p = &(*p)->next)
3054 if (sym == (*p)->sym)
3055 break;
3056 else if (sym->size < (*p)->sym->size) {
3057 n = alloca(sizeof(*n));
3058 n->next = *p;
3059 n->sym = sym;
3060 *p = n;
3061 break;
3062 }
3063 }
3064 }
3065
3066 if (common_head) {
3067 /* Find the bss section. */
3068 for (i = 0; i < f->header.e_shnum; ++i)
3069 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3070 break;
3071
3072 /* If for some reason there hadn't been one, create one. */
3073 if (i == f->header.e_shnum) {
3074 struct obj_section *sec;
3075
3076 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3077 f->sections[i] = sec = arch_new_section();
3078 f->header.e_shnum = i + 1;
3079
Eric Andersen9f16d612000-06-12 23:11:16 +00003080 sec->header.sh_type = SHT_PROGBITS;
3081 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3082 sec->name = ".bss";
3083 sec->idx = i;
3084 }
3085
3086 /* Allocate the COMMONS. */
3087 {
3088 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3089 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3090 struct common_entry *c;
3091
3092 for (c = common_head; c; c = c->next) {
3093 ElfW(Addr) align = c->sym->value;
3094
3095 if (align > max_align)
3096 max_align = align;
3097 if (bss_size & (align - 1))
3098 bss_size = (bss_size | (align - 1)) + 1;
3099
3100 c->sym->secidx = i;
3101 c->sym->value = bss_size;
3102
3103 bss_size += c->sym->size;
3104 }
3105
3106 f->sections[i]->header.sh_size = bss_size;
3107 f->sections[i]->header.sh_addralign = max_align;
3108 }
3109 }
3110
3111 /* For the sake of patch relocation and parameter initialization,
3112 allocate zeroed data for NOBITS sections now. Note that after
3113 this we cannot assume NOBITS are really empty. */
3114 for (i = 0; i < f->header.e_shnum; ++i) {
3115 struct obj_section *s = f->sections[i];
3116 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003117 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003118 s->contents = memset(xmalloc(s->header.sh_size),
3119 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003120 else
3121 s->contents = NULL;
3122
Eric Andersen9f16d612000-06-12 23:11:16 +00003123 s->header.sh_type = SHT_PROGBITS;
3124 }
3125 }
3126}
3127
Eric Andersen044228d2001-07-17 01:12:36 +00003128static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003129{
3130 unsigned long dot = 0;
3131 struct obj_section *sec;
3132
3133 /* Finalize the positions of the sections relative to one another. */
3134
3135 for (sec = f->load_order; sec; sec = sec->load_next) {
3136 ElfW(Addr) align;
3137
3138 align = sec->header.sh_addralign;
3139 if (align && (dot & (align - 1)))
3140 dot = (dot | (align - 1)) + 1;
3141
3142 sec->header.sh_addr = dot;
3143 dot += sec->header.sh_size;
3144 }
3145
3146 return dot;
3147}
3148
Eric Andersen044228d2001-07-17 01:12:36 +00003149static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003150{
3151 int i, n = f->header.e_shnum;
3152 int ret = 1;
3153
3154 /* Finalize the addresses of the sections. */
3155
3156 f->baseaddr = base;
3157 for (i = 0; i < n; ++i)
3158 f->sections[i]->header.sh_addr += base;
3159
3160 /* And iterate over all of the relocations. */
3161
3162 for (i = 0; i < n; ++i) {
3163 struct obj_section *relsec, *symsec, *targsec, *strsec;
3164 ElfW(RelM) * rel, *relend;
3165 ElfW(Sym) * symtab;
3166 const char *strtab;
3167
3168 relsec = f->sections[i];
3169 if (relsec->header.sh_type != SHT_RELM)
3170 continue;
3171
3172 symsec = f->sections[relsec->header.sh_link];
3173 targsec = f->sections[relsec->header.sh_info];
3174 strsec = f->sections[symsec->header.sh_link];
3175
3176 rel = (ElfW(RelM) *) relsec->contents;
3177 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3178 symtab = (ElfW(Sym) *) symsec->contents;
3179 strtab = (const char *) strsec->contents;
3180
3181 for (; rel < relend; ++rel) {
3182 ElfW(Addr) value = 0;
3183 struct obj_symbol *intsym = NULL;
3184 unsigned long symndx;
3185 ElfW(Sym) * extsym = 0;
3186 const char *errmsg;
3187
3188 /* Attempt to find a value to use for this relocation. */
3189
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003190 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003191 if (symndx) {
3192 /* Note we've already checked for undefined symbols. */
3193
3194 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003195 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003196 /* Local symbols we look up in the local table to be sure
3197 we get the one that is really intended. */
3198 intsym = f->local_symtab[symndx];
3199 } else {
3200 /* Others we look up in the hash table. */
3201 const char *name;
3202 if (extsym->st_name)
3203 name = strtab + extsym->st_name;
3204 else
3205 name = f->sections[extsym->st_shndx]->name;
3206 intsym = obj_find_symbol(f, name);
3207 }
3208
3209 value = obj_symbol_final_value(f, intsym);
3210 intsym->referenced = 1;
3211 }
3212#if SHT_RELM == SHT_RELA
3213#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3214 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3215 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003216 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003217#endif
3218 value += rel->r_addend;
3219#endif
3220
3221 /* Do it! */
3222 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003223 (f, targsec, symsec, intsym, rel, value)
3224 ) {
3225 case obj_reloc_ok:
3226 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003227
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003228 case obj_reloc_overflow:
3229 errmsg = "Relocation overflow";
3230 goto bad_reloc;
3231 case obj_reloc_dangerous:
3232 errmsg = "Dangerous relocation";
3233 goto bad_reloc;
3234 case obj_reloc_unhandled:
3235 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003236bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003237 if (extsym) {
3238 bb_error_msg("%s of type %ld for %s", errmsg,
3239 (long) ELF_R_TYPE(rel->r_info),
3240 strtab + extsym->st_name);
3241 } else {
3242 bb_error_msg("%s of type %ld", errmsg,
3243 (long) ELF_R_TYPE(rel->r_info));
3244 }
3245 ret = 0;
3246 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003247 }
3248 }
3249 }
3250
3251 /* Finally, take care of the patches. */
3252
3253 if (f->string_patches) {
3254 struct obj_string_patch *p;
3255 struct obj_section *strsec;
3256 ElfW(Addr) strsec_base;
3257 strsec = obj_find_section(f, ".kstrtab");
3258 strsec_base = strsec->header.sh_addr;
3259
3260 for (p = f->string_patches; p; p = p->next) {
3261 struct obj_section *targsec = f->sections[p->reloc_secidx];
3262 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3263 = strsec_base + p->string_offset;
3264 }
3265 }
3266
3267 if (f->symbol_patches) {
3268 struct obj_symbol_patch *p;
3269
3270 for (p = f->symbol_patches; p; p = p->next) {
3271 struct obj_section *targsec = f->sections[p->reloc_secidx];
3272 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3273 = obj_symbol_final_value(f, p->sym);
3274 }
3275 }
3276
3277 return ret;
3278}
3279
Eric Andersen044228d2001-07-17 01:12:36 +00003280static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003281{
3282 struct obj_section *sec;
3283 ElfW(Addr) base = f->baseaddr;
3284
3285 for (sec = f->load_order; sec; sec = sec->load_next) {
3286 char *secimg;
3287
Eric Andersen2bf658d2001-02-24 20:01:53 +00003288 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003289 continue;
3290
3291 secimg = image + (sec->header.sh_addr - base);
3292
3293 /* Note that we allocated data for NOBITS sections earlier. */
3294 memcpy(secimg, sec->contents, sec->header.sh_size);
3295 }
3296
3297 return 1;
3298}
3299
3300/*======================================================================*/
3301
Eric Andersen044228d2001-07-17 01:12:36 +00003302static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003303{
3304 struct obj_file *f;
3305 ElfW(Shdr) * section_headers;
3306 int shnum, i;
3307 char *shstrtab;
3308
3309 /* Read the file header. */
3310
3311 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003312 f->symbol_cmp = strcmp;
3313 f->symbol_hash = obj_elf_hash;
3314 f->load_order_search_start = &f->load_order;
3315
3316 fseek(fp, 0, SEEK_SET);
3317 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003318 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003319 }
3320
3321 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003322 || f->header.e_ident[EI_MAG1] != ELFMAG1
3323 || f->header.e_ident[EI_MAG2] != ELFMAG2
3324 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003325 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 }
3327 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003328 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003329 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003330 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3331 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003332 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 }
3334 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003335 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003336 }
3337
3338 /* Read the section headers. */
3339
3340 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003341 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003342 (unsigned long) f->header.e_shentsize,
3343 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003344 }
3345
3346 shnum = f->header.e_shnum;
3347 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3348 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3349
3350 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3351 fseek(fp, f->header.e_shoff, SEEK_SET);
3352 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003353 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003354 }
3355
3356 /* Read the section data. */
3357
3358 for (i = 0; i < shnum; ++i) {
3359 struct obj_section *sec;
3360
3361 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003362
3363 sec->header = section_headers[i];
3364 sec->idx = i;
3365
Denis Vlasenko51742f42007-04-12 00:32:05 +00003366 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003367 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003368 case SHT_NULL:
3369 case SHT_NOTE:
3370 case SHT_NOBITS:
3371 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003372 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003373
3374 case SHT_PROGBITS:
3375#if LOADBITS
3376 if (!loadprogbits) {
3377 sec->contents = NULL;
3378 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003379 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003380#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003381 case SHT_SYMTAB:
3382 case SHT_STRTAB:
3383 case SHT_RELM:
3384 if (sec->header.sh_size > 0) {
3385 sec->contents = xmalloc(sec->header.sh_size);
3386 fseek(fp, sec->header.sh_offset, SEEK_SET);
3387 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003388 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003389 }
3390 } else {
3391 sec->contents = NULL;
3392 }
3393 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003394
3395#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003396 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003397 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003398#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003399 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003400 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003401#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003402 default:
3403 if (sec->header.sh_type >= SHT_LOPROC) {
3404 /* Assume processor specific section types are debug
3405 info and can safely be ignored. If this is ever not
3406 the case (Hello MIPS?), don't put ifdefs here but
3407 create an arch_load_proc_section(). */
3408 break;
3409 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003410
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003411 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003412 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003413 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003414 }
3415 }
3416
3417 /* Do what sort of interpretation as needed by each section. */
3418
3419 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3420
3421 for (i = 0; i < shnum; ++i) {
3422 struct obj_section *sec = f->sections[i];
3423 sec->name = shstrtab + sec->header.sh_name;
3424 }
3425
3426 for (i = 0; i < shnum; ++i) {
3427 struct obj_section *sec = f->sections[i];
3428
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003429 /* .modinfo should be contents only but gcc has no attribute for that.
3430 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3431 */
3432 if (strcmp(sec->name, ".modinfo") == 0)
3433 sec->header.sh_flags &= ~SHF_ALLOC;
3434
Eric Andersen9f16d612000-06-12 23:11:16 +00003435 if (sec->header.sh_flags & SHF_ALLOC)
3436 obj_insert_section_load_order(f, sec);
3437
3438 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003439 case SHT_SYMTAB:
3440 {
3441 unsigned long nsym, j;
3442 char *strtab;
3443 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003444
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003445 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003446 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003448 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003449 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003450
3451 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3452 strtab = f->sections[sec->header.sh_link]->contents;
3453 sym = (ElfW(Sym) *) sec->contents;
3454
3455 /* Allocate space for a table of local symbols. */
3456 j = f->local_symtab_size = sec->header.sh_info;
3457 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3458
3459 /* Insert all symbols into the hash table. */
3460 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3461 ElfW(Addr) val = sym->st_value;
3462 const char *name;
3463 if (sym->st_name)
3464 name = strtab + sym->st_name;
3465 else if (sym->st_shndx < shnum)
3466 name = f->sections[sym->st_shndx]->name;
3467 else
3468 continue;
3469#if defined(__SH5__)
3470 /*
3471 * For sh64 it is possible that the target of a branch
3472 * requires a mode switch (32 to 16 and back again).
3473 *
3474 * This is implied by the lsb being set in the target
3475 * address for SHmedia mode and clear for SHcompact.
3476 */
3477 val |= sym->st_other & 4;
3478#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003479 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3480 val, sym->st_size);
3481 }
3482 }
3483 break;
3484
3485 case SHT_RELM:
3486 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003487 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003488 (unsigned long) sec->header.sh_entsize,
3489 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003490 }
3491 break;
3492 /* XXX Relocation code from modutils-2.3.19 is not here.
3493 * Why? That's about 20 lines of code from obj/obj_load.c,
3494 * which gets done in a second pass through the sections.
3495 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003496 }
3497 }
3498
3499 return f;
3500}
3501
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003502#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003503/*
3504 * load the unloaded sections directly into the memory allocated by
3505 * kernel for the module
3506 */
3507
Eric Andersenac5dbd12001-08-22 05:26:08 +00003508static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003509{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003510 ElfW(Addr) base = f->baseaddr;
3511 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003512
Eric Andersen8ae319a2001-05-21 16:09:18 +00003513 for (sec = f->load_order; sec; sec = sec->load_next) {
3514
3515 /* section already loaded? */
3516 if (sec->contents != NULL)
3517 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003518
Eric Andersen8ae319a2001-05-21 16:09:18 +00003519 if (sec->header.sh_size == 0)
3520 continue;
3521
3522 sec->contents = imagebase + (sec->header.sh_addr - base);
3523 fseek(fp, sec->header.sh_offset, SEEK_SET);
3524 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003525 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003526 return 0;
3527 }
3528
3529 }
3530 return 1;
3531}
3532#endif
3533
Eric Andersen9f16d612000-06-12 23:11:16 +00003534static void hide_special_symbols(struct obj_file *f)
3535{
3536 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003537 SPFX "cleanup_module",
3538 SPFX "init_module",
3539 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003540 NULL
3541 };
3542
3543 struct obj_symbol *sym;
3544 const char *const *p;
3545
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003546 for (p = specials; *p; ++p) {
3547 sym = obj_find_symbol(f, *p);
3548 if (sym != NULL)
3549 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3550 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003551}
3552
Glenn L McGrath759515c2003-08-30 06:00:33 +00003553
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003554#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003555static int obj_gpl_license(struct obj_file *f, const char **license)
3556{
3557 struct obj_section *sec;
3558 /* This list must match *exactly* the list of allowable licenses in
3559 * linux/include/linux/module.h. Checking for leading "GPL" will not
3560 * work, somebody will use "GPL sucks, this is proprietary".
3561 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003562 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003563 "GPL",
3564 "GPL v2",
3565 "GPL and additional rights",
3566 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003567 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003568 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003569
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003570 sec = obj_find_section(f, ".modinfo");
3571 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003572 const char *value, *ptr, *endptr;
3573 ptr = sec->contents;
3574 endptr = ptr + sec->header.sh_size;
3575 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003576 value = strchr(ptr, '=');
3577 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003578 int i;
3579 if (license)
3580 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003581 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003582 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003583 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003584 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003585 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003586 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003587 ptr = strchr(ptr, '\0');
3588 if (ptr)
3589 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003590 else
3591 ptr = endptr;
3592 }
3593 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003594 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003595}
3596
3597#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003598#define TAINT_PROPRIETORY_MODULE (1 << 0)
3599#define TAINT_FORCED_MODULE (1 << 1)
3600#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003601#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003602
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003603static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003604 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3605{
Denis Vlasenko931de892007-06-21 12:43:45 +00003606 static smallint printed_info;
3607
Eric Andersen166fa462002-09-16 05:30:24 +00003608 char buf[80];
3609 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003610
Eric Andersen166fa462002-09-16 05:30:24 +00003611 if (fd < 0 && !kernel_has_tainted)
3612 return; /* New modutils on old kernel */
3613 printf("Warning: loading %s will taint the kernel: %s%s\n",
3614 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003615 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003616 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003617 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003618 }
3619 if (fd >= 0) {
3620 read(fd, buf, sizeof(buf)-1);
3621 buf[sizeof(buf)-1] = '\0';
3622 oldval = strtoul(buf, NULL, 10);
3623 sprintf(buf, "%d\n", oldval | taint);
3624 write(fd, buf, strlen(buf));
3625 }
3626}
3627
3628/* Check if loading this module will taint the kernel. */
3629static void check_tainted_module(struct obj_file *f, char *m_name)
3630{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003631 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3632
Eric Andersen166fa462002-09-16 05:30:24 +00003633 int fd, kernel_has_tainted;
3634 const char *ptr;
3635
3636 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003637 fd = open(tainted_file, O_RDWR);
3638 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003639 if (errno == ENOENT)
3640 kernel_has_tainted = 0;
3641 else if (errno == EACCES)
3642 kernel_has_tainted = 1;
3643 else {
3644 perror(tainted_file);
3645 kernel_has_tainted = 0;
3646 }
3647 }
3648
3649 switch (obj_gpl_license(f, &ptr)) {
3650 case 0:
3651 break;
3652 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003653 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003654 break;
3655 case 2:
3656 /* The module has a non-GPL license so we pretend that the
3657 * kernel always has a taint flag to get a warning even on
3658 * kernels without the proc flag.
3659 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003660 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003661 break;
3662 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003663 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003664 break;
3665 }
3666
3667 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003668 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003669
3670 if (fd >= 0)
3671 close(fd);
3672}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003673#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003674#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003675#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003676
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003677#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003678/* add module source, timestamp, kernel version and a symbol for the
3679 * start of some sections. this info is used by ksymoops to do better
3680 * debugging.
3681 */
3682static int
3683get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3684{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003685#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003686 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003687#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003688 strncpy(str, "???", sizeof(str));
3689 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003690#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003691}
3692
3693/* add module source, timestamp, kernel version and a symbol for the
3694 * start of some sections. this info is used by ksymoops to do better
3695 * debugging.
3696 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003697static void
Eric Andersen889dd202003-01-23 04:48:34 +00003698add_ksymoops_symbols(struct obj_file *f, const char *filename,
3699 const char *m_name)
3700{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003701 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003702 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003703 ".text",
3704 ".rodata",
3705 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003706 ".bss",
3707 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003708 };
3709
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003710 struct obj_section *sec;
3711 struct obj_symbol *sym;
3712 char *name, *absolute_filename;
3713 char str[STRVERSIONLEN];
3714 int i, l, lm_name, lfilename, use_ksymtab, version;
3715 struct stat statbuf;
3716
3717 /* WARNING: was using realpath, but replaced by readlink to stop using
3718 * lots of stack. But here it seems to be able to cause problems? */
3719 absolute_filename = xmalloc_readlink(filename);
3720 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003721 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003722
3723 lm_name = strlen(m_name);
3724 lfilename = strlen(absolute_filename);
3725
3726 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3727 * are not to be exported. otherwise leave ksymtab alone for now, the
3728 * "export all symbols" compatibility code will export these symbols later.
3729 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003730 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003731
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003732 sec = obj_find_section(f, ".this");
3733 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003734 /* tag the module header with the object name, last modified
3735 * timestamp and module version. worst case for module version
3736 * is 0xffffff, decimal 16777215. putting all three fields in
3737 * one symbol is less readable but saves kernel space.
3738 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003739 l = sizeof(symprefix) + /* "__insmod_" */
3740 lm_name + /* module name */
3741 2 + /* "_O" */
3742 lfilename + /* object filename */
3743 2 + /* "_M" */
3744 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3745 2 + /* "_V" */
3746 8 + /* version in dec */
3747 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003748 name = xmalloc(l);
3749 if (stat(absolute_filename, &statbuf) != 0)
3750 statbuf.st_mtime = 0;
3751 version = get_module_version(f, str); /* -1 if not found */
3752 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003753 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003754 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003755 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003756 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003757 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003758 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003759 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003760 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003761 }
3762 free(absolute_filename);
3763#ifdef _NOT_SUPPORTED_
3764 /* record where the persistent data is going, same address as previous symbol */
3765
3766 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003767 l = sizeof(symprefix) + /* "__insmod_" */
3768 lm_name + /* module name */
3769 2 + /* "_P" */
3770 strlen(f->persist) + /* data store */
3771 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003772 name = xmalloc(l);
3773 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003774 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003775 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003776 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003777 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003778 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003779 }
3780#endif /* _NOT_SUPPORTED_ */
3781 /* tag the desired sections if size is non-zero */
3782
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003783 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003784 sec = obj_find_section(f, section_names[i]);
3785 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003786 l = sizeof(symprefix) + /* "__insmod_" */
3787 lm_name + /* module name */
3788 2 + /* "_S" */
3789 strlen(sec->name) + /* section name */
3790 2 + /* "_L" */
3791 8 + /* length in dec */
3792 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003793 name = xmalloc(l);
3794 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003795 symprefix, m_name, sec->name,
3796 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003797 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003798 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003799 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003800 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003801 }
3802 }
3803}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003804#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003805
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003806#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003807static void print_load_map(struct obj_file *f)
3808{
Eric Andersenbe65c352003-01-23 04:57:35 +00003809 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003810#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3811 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003812 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003813 struct obj_symbol *sym;
3814#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003815 /* Report on the section layout. */
3816
3817 printf("Sections: Size %-*s Align\n",
3818 (int) (2 * sizeof(void *)), "Address");
3819
3820 for (sec = f->load_order; sec; sec = sec->load_next) {
3821 int a;
3822 unsigned long tmp;
3823
3824 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3825 tmp >>= 1;
3826 if (a == -1)
3827 a = 0;
3828
3829 printf("%-15s %08lx %0*lx 2**%d\n",
3830 sec->name,
3831 (long)sec->header.sh_size,
3832 (int) (2 * sizeof(void *)),
3833 (long)sec->header.sh_addr,
3834 a);
3835 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003836#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003837 /* Quick reference which section indicies are loaded. */
3838
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003839 i = f->header.e_shnum;
3840 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003841 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003842 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003843
3844 /* Collect the symbols we'll be listing. */
3845
3846 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3847 for (sym = f->symtab[i]; sym; sym = sym->next)
3848 if (sym->secidx <= SHN_HIRESERVE
3849 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3850 ++nsyms;
3851
3852 all = alloca(nsyms * sizeof(struct obj_symbol *));
3853
3854 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3855 for (sym = f->symtab[i]; sym; sym = sym->next)
3856 if (sym->secidx <= SHN_HIRESERVE
3857 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3858 *p++ = sym;
3859
3860 /* And list them. */
3861 printf("\nSymbols:\n");
3862 for (p = all; p < all + nsyms; ++p) {
3863 char type = '?';
3864 unsigned long value;
3865
3866 sym = *p;
3867 if (sym->secidx == SHN_ABS) {
3868 type = 'A';
3869 value = sym->value;
3870 } else if (sym->secidx == SHN_UNDEF) {
3871 type = 'U';
3872 value = 0;
3873 } else {
3874 sec = f->sections[sym->secidx];
3875
3876 if (sec->header.sh_type == SHT_NOBITS)
3877 type = 'B';
3878 else if (sec->header.sh_flags & SHF_ALLOC) {
3879 if (sec->header.sh_flags & SHF_EXECINSTR)
3880 type = 'T';
3881 else if (sec->header.sh_flags & SHF_WRITE)
3882 type = 'D';
3883 else
3884 type = 'R';
3885 }
3886 value = sym->value + sec->header.sh_addr;
3887 }
3888
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003889 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003890 type = tolower(type);
3891
3892 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3893 type, sym->name);
3894 }
3895#endif
3896}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003897#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003898void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003899#endif
3900
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003901int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3902int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003903{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003904 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003905 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003906 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003907 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003908 unsigned long m_size;
3909 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003910 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003911 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003912 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003913 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003914 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003915#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003916 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003917 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003918 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003919#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003920#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003921 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003922#else
3923 FILE *fp;
3924#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003925 int k_version = 0;
3926 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003927
Erik Andersene49d5ec2000-02-08 19:58:47 +00003928 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003929 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003930 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003931 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003932 free(m_name);
3933 m_name = xstrdup(opt_o);
3934 }
Eric Andersen03d80912003-12-19 21:04:19 +00003935
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003936 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003937 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003938 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003939
Erik Andersene49d5ec2000-02-08 19:58:47 +00003940 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003941 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003942 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003943 len = strlen(tmp);
3944
Eric Andersen03d80912003-12-19 21:04:19 +00003945 if (uname(&myuname) == 0) {
3946 if (myuname.release[0] == '2') {
3947 k_version = myuname.release[2] - '0';
3948 }
3949 }
3950
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003951#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003952 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3953 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3954 ) {
3955 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003956 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003957 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003958#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003959 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003960 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003961 tmp[len] = '\0';
3962 }
Eric Andersen2d342152002-06-18 05:16:25 +00003963
Eric Andersen03d80912003-12-19 21:04:19 +00003964
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003965#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003966 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003967 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003968 else
Eric Andersen03d80912003-12-19 21:04:19 +00003969#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003970 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003971
Eric Andersen61f83052002-06-22 17:15:42 +00003972 if (!m_name) {
3973 m_name = tmp;
3974 } else {
3975 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003976 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003977 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003978
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003979 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003980 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3981 || (fp = fopen(arg1, "r")) == NULL
3982 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003983 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3984 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003985 if (k_version) { /* uname succeedd */
3986 char *module_dir;
3987 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00003988
Eric Andersen03d80912003-12-19 21:04:19 +00003989 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003990 /* Jump through hoops in case /lib/modules/`uname -r`
3991 * is a symlink. We do not want recursive_action to
3992 * follow symlinks, but we do want to follow the
3993 * /lib/modules/`uname -r` dir, So resolve it ourselves
3994 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003995 module_dir = xmalloc_readlink(tmdn);
3996 if (!module_dir)
3997 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00003998 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003999 check_module_name_match, NULL, m_fullName, 0);
4000 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004001 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004002 }
4003
4004 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004005 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004006 int r;
4007 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004008
Eric Andersen03d80912003-12-19 21:04:19 +00004009 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004010 m_filename = NULL;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004011 module_dir = xmalloc_readlink(_PATH_MODULES);
4012 if (!module_dir)
4013 module_dir = xstrdup(_PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004014 /* No module found under /lib/modules/`uname -r`, this
4015 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004016 r = recursive_action(module_dir, ACTION_RECURSE,
4017 check_module_name_match, NULL, m_fullName, 0);
4018 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004019 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004020 free(module_dir);
4021 if (m_filename == NULL
4022 || ((fp = fopen(m_filename, "r")) == NULL)
4023 ) {
4024 bb_error_msg_and_die("%s: module not found", m_fullName);
4025 }
Eric Andersen14d35432001-05-14 17:07:32 +00004026 }
Eric Andersen03d80912003-12-19 21:04:19 +00004027 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004028 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004029
Rob Landley999af202005-12-11 20:14:12 +00004030 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004031 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004032
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004033#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004034 if (k_version > 4) {
4035 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004036 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004037 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004038 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004039#endif
4040
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004041 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004042
Eric Andersen9f16d612000-06-12 23:11:16 +00004043 if (get_modinfo_value(f, "kernel_version") == NULL)
4044 m_has_modinfo = 0;
4045 else
4046 m_has_modinfo = 1;
4047
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004048#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004049 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004050 if (!flag_quiet) {
4051 if (uname(&uts_info) < 0)
4052 uts_info.release[0] = '\0';
4053 if (m_has_modinfo) {
4054 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004055 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004056 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004057 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004058 }
4059 }
4060
4061 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004062 bb_error_msg("%skernel-module version mismatch\n"
4063 "\t%s was compiled for kernel version %s\n"
4064 "\twhile this kernel is version %s",
4065 flag_force_load ? "warning: " : "",
4066 m_filename, m_strversion, uts_info.release);
4067 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004068 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004069 }
4070 }
4071 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004072#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004073
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004074 if (query_module(NULL, 0, NULL, 0, NULL))
4075 bb_error_msg_and_die("not configured to support old kernels");
4076 new_get_kernel_symbols();
4077 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004079#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004080 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004081 if (m_has_modinfo)
4082 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004083
4084 if (m_crcs != k_crcs)
4085 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004086#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004087
Erik Andersene49d5ec2000-02-08 19:58:47 +00004088 /* Let the module know about the kernel symbols. */
4089 add_kernel_symbols(f);
4090
Eric Andersen9f16d612000-06-12 23:11:16 +00004091 /* Allocate common symbols, symbol tables, and string tables. */
4092
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004093 new_create_this_module(f, m_name);
4094 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004095 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004096 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004097
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004098 /* done with the module name, on to the optional var=value arguments */
4099 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004100 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004101 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004102 }
4103
Eric Andersen9f16d612000-06-12 23:11:16 +00004104 arch_create_got(f);
4105 hide_special_symbols(f);
4106
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004107#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004108 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004109#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004110
Eric Andersencb3b9b12004-06-22 11:50:52 +00004111 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004112
Erik Andersene49d5ec2000-02-08 19:58:47 +00004113 /* Find current size of the module */
4114 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004115
Erik Andersene49d5ec2000-02-08 19:58:47 +00004116 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004117 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004118 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004119 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004120 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004121 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004122 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004123 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004124 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004125 }
Erik Andersend387d011999-12-21 02:55:11 +00004126
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004127#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004128 /*
4129 * the PROGBITS section was not loaded by the obj_load
4130 * now we can load them directly into the kernel memory
4131 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004132 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004133 delete_module(m_name);
4134 goto out;
4135 }
Eric Andersen03d80912003-12-19 21:04:19 +00004136#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004137
Eric Andersen9f16d612000-06-12 23:11:16 +00004138 if (!obj_relocate(f, m_addr)) {
4139 delete_module(m_name);
4140 goto out;
4141 }
Erik Andersend387d011999-12-21 02:55:11 +00004142
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004143 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004144 delete_module(m_name);
4145 goto out;
4146 }
4147
Denis Vlasenko51742f42007-04-12 00:32:05 +00004148 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004149 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004150
Matt Kraai3e856ce2000-12-01 02:55:13 +00004151 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004152
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004153 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004154#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004155 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004156 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004157 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004158 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004159 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004160 free(m_filename);
4161#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004162 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004163}
Eric Andersene7047882003-12-11 01:42:13 +00004164
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004165#endif /* ENABLE_FEATURE_2_4_MODULES */
4166/*
4167 * End of big piece of 2.4-specific code
4168 */
Eric Andersene7047882003-12-11 01:42:13 +00004169
4170
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004171#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004172
4173#include <sys/mman.h>
4174#include <asm/unistd.h>
4175#include <sys/syscall.h>
4176
4177/* We use error numbers in a loose translation... */
4178static const char *moderror(int err)
4179{
4180 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004181 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004182 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004183 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004184 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004185 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004186 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004187 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004188 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004189 default:
4190 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004191 }
4192}
4193
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004194#if !ENABLE_FEATURE_2_4_MODULES
4195int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
4196int insmod_main(int argc, char **argv)
4197#else
4198static int insmod_ng_main(int argc, char **argv)
4199#endif
Eric Andersene7047882003-12-11 01:42:13 +00004200{
Denis Vlasenko92297942006-11-21 11:58:14 +00004201 long ret;
4202 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004203 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004204 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004205 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004206
Denis Vlasenko92297942006-11-21 11:58:14 +00004207 filename = *++argv;
4208 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004209 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004210
4211 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004212 options = xzalloc(1);
4213 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004214 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004215 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004216 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004217 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004218 }
4219
Denis Vlasenko92297942006-11-21 11:58:14 +00004220#if 0
4221 /* Any special reason why mmap? It isn't performace critical... */
4222 int fd;
4223 struct stat st;
4224 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004225 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004226 fstat(fd, &st);
4227 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004228 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004229 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004230 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004231 }
4232
Denis Vlasenko92297942006-11-21 11:58:14 +00004233 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4234 if (map == NULL) {
4235 map = xmalloc(len);
4236 xread(fd, map, len);
4237 }
4238#else
4239 len = MAXINT(ssize_t);
4240 map = xmalloc_open_read_close(filename, &len);
4241#endif
4242
Eric Andersene7047882003-12-11 01:42:13 +00004243 ret = syscall(__NR_init_module, map, len, options);
4244 if (ret != 0) {
Denis Vlasenkoef66d752007-11-06 02:02:45 +00004245 bb_error_msg_and_die("cannot insert '%s': %s",
4246 filename, moderror(errno));
Eric Andersene7047882003-12-11 01:42:13 +00004247 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004248
Eric Andersene7047882003-12-11 01:42:13 +00004249 return 0;
4250}
4251
4252#endif