blob: df75abbfaf853bd86b356214c468173bbfa87472 [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;
1954 if ((g = (h & 0xf0000000)) != 0) {
1955 h ^= g >> 24;
1956 h &= ~g;
1957 }
1958 n--;
1959 }
1960 return h;
1961}
1962
Eric Andersen044228d2001-07-17 01:12:36 +00001963static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001964{
1965 return obj_elf_hash_n(name, strlen(name));
1966}
1967
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001968#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001969/* String comparison for non-co-versioned kernel and module. */
1970
1971static int ncv_strcmp(const char *a, const char *b)
1972{
1973 size_t alen = strlen(a), blen = strlen(b);
1974
1975 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1976 return strncmp(a, b, alen);
1977 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1978 return strncmp(a, b, blen);
1979 else
1980 return strcmp(a, b);
1981}
1982
1983/* String hashing for non-co-versioned kernel and module. Here
1984 we are simply forced to drop the crc from the hash. */
1985
1986static unsigned long ncv_symbol_hash(const char *str)
1987{
1988 size_t len = strlen(str);
1989 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1990 len -= 10;
1991 return obj_elf_hash_n(str, len);
1992}
1993
Eric Andersen044228d2001-07-17 01:12:36 +00001994static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001995obj_set_symbol_compare(struct obj_file *f,
1996 int (*cmp) (const char *, const char *),
1997 unsigned long (*hash) (const char *))
1998{
1999 if (cmp)
2000 f->symbol_cmp = cmp;
2001 if (hash) {
2002 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2003 int i;
2004
2005 f->symbol_hash = hash;
2006
2007 memcpy(tmptab, f->symtab, sizeof(tmptab));
2008 memset(f->symtab, 0, sizeof(f->symtab));
2009
2010 for (i = 0; i < HASH_BUCKETS; ++i)
2011 for (sym = tmptab[i]; sym; sym = next) {
2012 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2013 next = sym->next;
2014 sym->next = f->symtab[h];
2015 f->symtab[h] = sym;
2016 }
2017 }
2018}
2019
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002020#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002021
Eric Andersen044228d2001-07-17 01:12:36 +00002022static struct obj_symbol *
2023obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002024 unsigned long symidx, int info,
2025 int secidx, ElfW(Addr) value,
2026 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002027{
2028 struct obj_symbol *sym;
2029 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002030 int n_type = ELF_ST_TYPE(info);
2031 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002032
2033 for (sym = f->symtab[hash]; sym; sym = sym->next)
2034 if (f->symbol_cmp(sym->name, name) == 0) {
2035 int o_secidx = sym->secidx;
2036 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002037 int o_type = ELF_ST_TYPE(o_info);
2038 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002039
2040 /* A redefinition! Is it legal? */
2041
2042 if (secidx == SHN_UNDEF)
2043 return sym;
2044 else if (o_secidx == SHN_UNDEF)
2045 goto found;
2046 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2047 /* Cope with local and global symbols of the same name
2048 in the same object file, as might have been created
2049 by ld -r. The only reason locals are now seen at this
2050 level at all is so that we can do semi-sensible things
2051 with parameters. */
2052
2053 struct obj_symbol *nsym, **p;
2054
2055 nsym = arch_new_symbol();
2056 nsym->next = sym->next;
2057 nsym->ksymidx = -1;
2058
2059 /* Excise the old (local) symbol from the hash chain. */
2060 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2061 continue;
2062 *p = sym = nsym;
2063 goto found;
2064 } else if (n_binding == STB_LOCAL) {
2065 /* Another symbol of the same name has already been defined.
2066 Just add this to the local table. */
2067 sym = arch_new_symbol();
2068 sym->next = NULL;
2069 sym->ksymidx = -1;
2070 f->local_symtab[symidx] = sym;
2071 goto found;
2072 } else if (n_binding == STB_WEAK)
2073 return sym;
2074 else if (o_binding == STB_WEAK)
2075 goto found;
2076 /* Don't unify COMMON symbols with object types the programmer
2077 doesn't expect. */
2078 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002079 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002080 return sym;
2081 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002082 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002083 goto found;
2084 else {
2085 /* Don't report an error if the symbol is coming from
2086 the kernel or some external module. */
2087 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002088 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002089 return sym;
2090 }
2091 }
2092
2093 /* Completely new symbol. */
2094 sym = arch_new_symbol();
2095 sym->next = f->symtab[hash];
2096 f->symtab[hash] = sym;
2097 sym->ksymidx = -1;
2098
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002099 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002100 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002101 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002102 name, (long) symidx, (long) f->local_symtab_size);
2103 else
2104 f->local_symtab[symidx] = sym;
2105 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002106
Eric Andersen3b1a7442003-12-24 20:30:45 +00002107found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002108 sym->name = name;
2109 sym->value = value;
2110 sym->size = size;
2111 sym->secidx = secidx;
2112 sym->info = info;
2113
2114 return sym;
2115}
2116
Eric Andersen044228d2001-07-17 01:12:36 +00002117static struct obj_symbol *
2118obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002119{
2120 struct obj_symbol *sym;
2121 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2122
2123 for (sym = f->symtab[hash]; sym; sym = sym->next)
2124 if (f->symbol_cmp(sym->name, name) == 0)
2125 return sym;
2126
2127 return NULL;
2128}
2129
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002130static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002131{
2132 if (sym) {
2133 if (sym->secidx >= SHN_LORESERVE)
2134 return sym->value;
2135
2136 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2137 } else {
2138 /* As a special case, a NULL sym has value zero. */
2139 return 0;
2140 }
2141}
2142
Eric Andersen044228d2001-07-17 01:12:36 +00002143static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002144{
2145 int i, n = f->header.e_shnum;
2146
2147 for (i = 0; i < n; ++i)
2148 if (strcmp(f->sections[i]->name, name) == 0)
2149 return f->sections[i];
2150
2151 return NULL;
2152}
2153
2154static int obj_load_order_prio(struct obj_section *a)
2155{
2156 unsigned long af, ac;
2157
2158 af = a->header.sh_flags;
2159
2160 ac = 0;
2161 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002162 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002163 ac |= 32;
2164 if (af & SHF_ALLOC)
2165 ac |= 16;
2166 if (!(af & SHF_WRITE))
2167 ac |= 8;
2168 if (af & SHF_EXECINSTR)
2169 ac |= 4;
2170 if (a->header.sh_type != SHT_NOBITS)
2171 ac |= 2;
2172
2173 return ac;
2174}
2175
Eric Andersen044228d2001-07-17 01:12:36 +00002176static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002177obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2178{
2179 struct obj_section **p;
2180 int prio = obj_load_order_prio(sec);
2181 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2182 if (obj_load_order_prio(*p) < prio)
2183 break;
2184 sec->load_next = *p;
2185 *p = sec;
2186}
2187
Eric Andersen044228d2001-07-17 01:12:36 +00002188static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002189 const char *name,
2190 unsigned long align,
2191 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002192{
2193 int newidx = f->header.e_shnum++;
2194 struct obj_section *sec;
2195
2196 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2197 f->sections[newidx] = sec = arch_new_section();
2198
Eric Andersen9f16d612000-06-12 23:11:16 +00002199 sec->header.sh_type = SHT_PROGBITS;
2200 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2201 sec->header.sh_size = size;
2202 sec->header.sh_addralign = align;
2203 sec->name = name;
2204 sec->idx = newidx;
2205 if (size)
2206 sec->contents = xmalloc(size);
2207
2208 obj_insert_section_load_order(f, sec);
2209
2210 return sec;
2211}
2212
Eric Andersen044228d2001-07-17 01:12:36 +00002213static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002214 const char *name,
2215 unsigned long align,
2216 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002217{
2218 int newidx = f->header.e_shnum++;
2219 struct obj_section *sec;
2220
2221 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2222 f->sections[newidx] = sec = arch_new_section();
2223
Eric Andersen9f16d612000-06-12 23:11:16 +00002224 sec->header.sh_type = SHT_PROGBITS;
2225 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2226 sec->header.sh_size = size;
2227 sec->header.sh_addralign = align;
2228 sec->name = name;
2229 sec->idx = newidx;
2230 if (size)
2231 sec->contents = xmalloc(size);
2232
2233 sec->load_next = f->load_order;
2234 f->load_order = sec;
2235 if (f->load_order_search_start == &f->load_order)
2236 f->load_order_search_start = &sec->load_next;
2237
2238 return sec;
2239}
2240
Eric Andersen044228d2001-07-17 01:12:36 +00002241static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002242{
2243 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002244 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002245 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2246 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002247 return sec->contents + oldsize;
2248}
2249
2250
Eric Andersen9f16d612000-06-12 23:11:16 +00002251/* Conditionally add the symbols from the given symbol set to the
2252 new module. */
2253
2254static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002255add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002256 int idx, struct new_module_symbol *syms, size_t nsyms)
2257{
2258 struct new_module_symbol *s;
2259 size_t i;
2260 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002261#ifdef SYMBOL_PREFIX
2262 char *name_buf = 0;
2263 size_t name_alloced_size = 0;
2264#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002265#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002266 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002267
Glenn L McGrath759515c2003-08-30 06:00:33 +00002268 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002269#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002270 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002271 /* Only add symbols that are already marked external.
2272 If we override locals we may cause problems for
2273 argument initialization. We will also create a false
2274 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002275 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002276 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002277
Glenn L McGrath759515c2003-08-30 06:00:33 +00002278 /* GPL licensed modules can use symbols exported with
2279 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2280 * exported names. Non-GPL modules never see any GPLONLY_
2281 * symbols so they cannot fudge it by adding the prefix on
2282 * their references.
2283 */
2284 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002285#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002286 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002287 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002288 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002289#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002290 continue;
2291 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002292 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002293
Miles Baderae28b042002-04-01 09:34:25 +00002294#ifdef SYMBOL_PREFIX
2295 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2296 kernel exports `C names', but module object files
2297 reference `linker names'). */
2298 size_t extra = sizeof SYMBOL_PREFIX;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002299 size_t name_size = strlen(name) + extra;
Miles Baderae28b042002-04-01 09:34:25 +00002300 if (name_size > name_alloced_size) {
2301 name_alloced_size = name_size * 2;
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002302 name_buf = alloca(name_alloced_size);
Miles Baderae28b042002-04-01 09:34:25 +00002303 }
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002304 strcpy(name_buf, SYMBOL_PREFIX);
2305 strcpy(name_buf + extra - 1, name);
Miles Baderae28b042002-04-01 09:34:25 +00002306 name = name_buf;
2307#endif /* SYMBOL_PREFIX */
2308
2309 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002310 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002311#ifdef SYMBOL_PREFIX
2312 /* Put NAME_BUF into more permanent storage. */
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002313 name = xmalloc(name_size);
2314 strcpy(name, name_buf);
Miles Baderae28b042002-04-01 09:34:25 +00002315#endif
2316 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002317 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002318 STT_NOTYPE),
2319 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002320 /* Did our symbol just get installed? If so, mark the
2321 module as "used". */
2322 if (sym->secidx == idx)
2323 used = 1;
2324 }
2325 }
2326
2327 return used;
2328}
2329
2330static void add_kernel_symbols(struct obj_file *f)
2331{
2332 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002333 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002334
2335 /* Add module symbols first. */
2336
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002337 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002338 if (m->nsyms
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002339 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms, m->nsyms)
2340 ) {
2341 m->used = 1;
2342 ++nused;
2343 }
2344 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002345
2346 n_ext_modules_used = nused;
2347
2348 /* And finally the symbols from the kernel proper. */
2349
2350 if (nksyms)
2351 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2352}
2353
2354static char *get_modinfo_value(struct obj_file *f, const char *key)
2355{
2356 struct obj_section *sec;
2357 char *p, *v, *n, *ep;
2358 size_t klen = strlen(key);
2359
2360 sec = obj_find_section(f, ".modinfo");
2361 if (sec == NULL)
2362 return NULL;
2363 p = sec->contents;
2364 ep = p + sec->header.sh_size;
2365 while (p < ep) {
2366 v = strchr(p, '=');
2367 n = strchr(p, '\0');
2368 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002369 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002370 return v + 1;
2371 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002372 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002373 return n;
2374 }
2375 p = n + 1;
2376 }
2377
2378 return NULL;
2379}
2380
2381
2382/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002383/* Functions relating to module loading after 2.1.18. */
2384
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002385static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002386new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2387{
2388 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002389 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002390 struct obj_symbol *sym;
2391 char *contents, *loc;
2392 int min, max, n;
2393
2394 p = *argv;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002395 q = strchr(p, '=');
2396 if (q == NULL) {
Eric Andersenef40aa82000-06-26 11:16:22 +00002397 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002398 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002399 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002400
2401 key = alloca(q - p + 6);
2402 memcpy(key, "parm_", 5);
2403 memcpy(key + 5, p, q - p);
2404 key[q - p + 5] = 0;
2405
2406 p = get_modinfo_value(f, key);
2407 key += 5;
2408 if (p == NULL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002409 bb_error_msg_and_die("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002410 }
2411
Miles Baderae28b042002-04-01 09:34:25 +00002412#ifdef SYMBOL_PREFIX
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002413 sym_name = alloca(strlen(key) + sizeof SYMBOL_PREFIX);
2414 strcpy(sym_name, SYMBOL_PREFIX);
2415 strcat(sym_name, key);
Miles Baderae28b042002-04-01 09:34:25 +00002416#else
2417 sym_name = key;
2418#endif
2419 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002420
2421 /* Also check that the parameter was not resolved from the kernel. */
2422 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002423 bb_error_msg_and_die("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002424 }
2425
2426 if (isdigit(*p)) {
2427 min = strtoul(p, &p, 10);
2428 if (*p == '-')
2429 max = strtoul(p + 1, &p, 10);
2430 else
2431 max = min;
2432 } else
2433 min = max = 1;
2434
2435 contents = f->sections[sym->secidx]->contents;
2436 loc = contents + sym->value;
2437 n = (*++q != '\0');
2438
2439 while (1) {
2440 if ((*p == 's') || (*p == 'c')) {
2441 char *str;
2442
2443 /* Do C quoting if we begin with a ", else slurp the lot. */
2444 if (*q == '"') {
2445 char *r;
2446
2447 str = alloca(strlen(q));
2448 for (r = str, q++; *q != '"'; ++q, ++r) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002449 if (*q == '\0')
2450 bb_error_msg_and_die("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002451 key);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002452 if (*q == '\\')
Eric Andersen9f16d612000-06-12 23:11:16 +00002453 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002454 case 'a':
2455 *r = '\a';
2456 break;
2457 case 'b':
2458 *r = '\b';
2459 break;
2460 case 'e':
2461 *r = '\033';
2462 break;
2463 case 'f':
2464 *r = '\f';
2465 break;
2466 case 'n':
2467 *r = '\n';
2468 break;
2469 case 'r':
2470 *r = '\r';
2471 break;
2472 case 't':
2473 *r = '\t';
2474 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002475
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002476 case '0':
2477 case '1':
2478 case '2':
2479 case '3':
2480 case '4':
2481 case '5':
2482 case '6':
2483 case '7':
2484 {
2485 int c = *q - '0';
2486 if (q[1] >= '0' && q[1] <= '7') {
2487 c = (c * 8) + *++q - '0';
2488 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002489 c = (c * 8) + *++q - '0';
2490 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002491 *r = c;
2492 }
2493 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002494
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002495 default:
2496 *r = *q;
2497 break;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002498 }
2499 else
2500 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002501 }
2502 *r = '\0';
2503 ++q;
2504 } else {
2505 char *r;
2506
2507 /* In this case, the string is not quoted. We will break
2508 it using the coma (like for ints). If the user wants to
2509 include comas in a string, he just has to quote it */
2510
2511 /* Search the next coma */
2512 r = strchr(q, ',');
2513
2514 /* Found ? */
2515 if (r != (char *) NULL) {
2516 /* Recopy the current field */
2517 str = alloca(r - q + 1);
2518 memcpy(str, q, r - q);
2519
Eric Andersenaff114c2004-04-14 17:51:38 +00002520 /* I don't know if it is useful, as the previous case
2521 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002522 str[r - q] = '\0';
2523
2524 /* Keep next fields */
2525 q = r;
2526 } else {
2527 /* last string */
2528 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002529 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002530 }
2531 }
2532
2533 if (*p == 's') {
2534 /* Normal string */
2535 obj_string_patch(f, sym->secidx, loc - contents, str);
2536 loc += tgt_sizeof_char_p;
2537 } else {
Denis Vlasenko6398cf42007-04-11 17:04:29 +00002538 /* Array of chars (in fact, matrix!) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002539 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002540
2541 /* Get the size of each member */
2542 /* Probably we should do that outside the loop ? */
2543 if (!isdigit(*(p + 1))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002544 bb_error_msg_and_die("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002545 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002546 }
2547 charssize = strtoul(p + 1, (char **) NULL, 10);
2548
2549 /* Check length */
2550 if (strlen(str) >= charssize) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002551 bb_error_msg_and_die("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002552 charssize - 1);
Eric Andersen9f16d612000-06-12 23:11:16 +00002553 }
2554
2555 /* Copy to location */
2556 strcpy((char *) loc, str);
2557 loc += charssize;
2558 }
2559 } else {
2560 long v = strtoul(q, &q, 0);
2561 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002562 case 'b':
2563 *loc++ = v;
2564 break;
2565 case 'h':
2566 *(short *) loc = v;
2567 loc += tgt_sizeof_short;
2568 break;
2569 case 'i':
2570 *(int *) loc = v;
2571 loc += tgt_sizeof_int;
2572 break;
2573 case 'l':
2574 *(long *) loc = v;
2575 loc += tgt_sizeof_long;
2576 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002577
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002578 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002579 bb_error_msg_and_die("unknown parameter type '%c' for %s", *p, key);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002580 }
2581 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002582 retry_end_of_value:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002583 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002584 case '\0':
2585 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002586
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002587 case ' ':
2588 case '\t':
2589 case '\n':
2590 case '\r':
2591 ++q;
2592 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002593
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002594 case ',':
2595 if (++n > max) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002596 bb_error_msg_and_die("too many values for %s (max %d)", key, max);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002597 }
2598 ++q;
2599 break;
2600
2601 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002602 bb_error_msg_and_die("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002603 }
2604 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002605 end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002606 if (n < min) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002607 bb_error_msg_and_die("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002608 }
2609
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002610 argc--;
2611 argv++;
Eric Andersen9f16d612000-06-12 23:11:16 +00002612 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002613}
2614
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002615#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002616static int new_is_module_checksummed(struct obj_file *f)
2617{
2618 const char *p = get_modinfo_value(f, "using_checksums");
2619 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002620 return xatoi(p);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002621 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002622}
2623
2624/* Get the module's kernel version in the canonical integer form. */
2625
2626static int
2627new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2628{
2629 char *p, *q;
2630 int a, b, c;
2631
2632 p = get_modinfo_value(f, "kernel_version");
2633 if (p == NULL)
2634 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002635 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002636
2637 a = strtoul(p, &p, 10);
2638 if (*p != '.')
2639 return -1;
2640 b = strtoul(p + 1, &p, 10);
2641 if (*p != '.')
2642 return -1;
2643 c = strtoul(p + 1, &q, 10);
2644 if (p + 1 == q)
2645 return -1;
2646
2647 return a << 16 | b << 8 | c;
2648}
2649
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002650#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002651
2652
Eric Andersen9f16d612000-06-12 23:11:16 +00002653/* Fetch the loaded modules, and all currently exported symbols. */
2654
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002655static void new_get_kernel_symbols(void)
Eric Andersen9f16d612000-06-12 23:11:16 +00002656{
2657 char *module_names, *mn;
2658 struct external_module *modules, *m;
2659 struct new_module_symbol *syms, *s;
2660 size_t ret, bufsize, nmod, nsyms, i, j;
2661
2662 /* Collect the loaded modules. */
2663
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002664 bufsize = 256;
2665 module_names = xmalloc(bufsize);
2666
2667 retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002668 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002669 if (errno == ENOSPC && bufsize < ret) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002670 bufsize = ret;
2671 module_names = xrealloc(module_names, bufsize);
Eric Andersen9f16d612000-06-12 23:11:16 +00002672 goto retry_modules_load;
2673 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002674 bb_perror_msg_and_die("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002675 }
2676
2677 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002678
2679 /* Collect the modules' symbols. */
2680
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002681 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002682 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2683 memset(modules, 0, nmod * sizeof(*modules));
2684 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002685 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002686 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002687
Mark Whitley94fd4802001-03-12 23:08:34 +00002688 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2689 if (errno == ENOENT) {
2690 /* The module was removed out from underneath us. */
2691 continue;
2692 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002693 bb_perror_msg_and_die("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002694 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002695
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002696 bufsize = 1024;
2697 syms = xmalloc(bufsize);
2698 retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002699 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2700 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002701 case ENOSPC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002702 bufsize = ret;
2703 syms = xrealloc(syms, bufsize);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002704 goto retry_mod_sym_load;
2705 case ENOENT:
2706 /* The module was removed out from underneath us. */
2707 continue;
2708 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002709 bb_perror_msg_and_die("query_module: QM_SYMBOLS: %s", mn);
Mark Whitley94fd4802001-03-12 23:08:34 +00002710 }
2711 }
2712 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002713
Mark Whitley94fd4802001-03-12 23:08:34 +00002714 m->name = mn;
2715 m->addr = info.addr;
2716 m->nsyms = nsyms;
2717 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002718
Mark Whitley94fd4802001-03-12 23:08:34 +00002719 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2720 s->name += (unsigned long) syms;
2721 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002722 }
2723 }
2724
2725 /* Collect the kernel's symbols. */
2726
2727 syms = xmalloc(bufsize = 16 * 1024);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002728 retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002729 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002730 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002731 syms = xrealloc(syms, bufsize = ret);
2732 goto retry_kern_sym_load;
2733 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002734 bb_perror_msg_and_die("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002735 }
2736 nksyms = nsyms = ret;
2737 ksyms = syms;
2738
2739 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2740 s->name += (unsigned long) syms;
2741 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002742}
2743
2744
2745/* Return the kernel symbol checksum version, or zero if not used. */
2746
2747static int new_is_kernel_checksummed(void)
2748{
2749 struct new_module_symbol *s;
2750 size_t i;
2751
2752 /* Using_Versions is not the first symbol, but it should be in there. */
2753
2754 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2755 if (strcmp((char *) s->name, "Using_Versions") == 0)
2756 return s->value;
2757
2758 return 0;
2759}
2760
2761
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002762static void new_create_this_module(struct obj_file *f, const char *m_name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002763{
2764 struct obj_section *sec;
2765
2766 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002767 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002768 memset(sec->contents, 0, sizeof(struct new_module));
2769
Miles Baderae28b042002-04-01 09:34:25 +00002770 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002771 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002772 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002773
2774 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002775 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002776}
2777
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002778#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002779/* add an entry to the __ksymtab section, creating it if necessary */
2780static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2781{
2782 struct obj_section *sec;
2783 ElfW(Addr) ofs;
2784
2785 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2786 * If __ksymtab is defined but not marked alloc, x out the first character
2787 * (no obj_delete routine) and create a new __ksymtab with the correct
2788 * characteristics.
2789 */
2790 sec = obj_find_section(f, "__ksymtab");
2791 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2792 *((char *)(sec->name)) = 'x'; /* override const */
2793 sec = NULL;
2794 }
2795 if (!sec)
2796 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002797 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002798 if (!sec)
2799 return;
2800 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002801 /* Empty section might be byte-aligned */
2802 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002803 ofs = sec->header.sh_size;
2804 obj_symbol_patch(f, sec->idx, ofs, sym);
2805 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2806 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2807}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002808#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002809
2810static int new_create_module_ksymtab(struct obj_file *f)
2811{
2812 struct obj_section *sec;
2813 int i;
2814
2815 /* We must always add the module references. */
2816
2817 if (n_ext_modules_used) {
2818 struct new_module_ref *dep;
2819 struct obj_symbol *tm;
2820
2821 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002822 (sizeof(struct new_module_ref)
2823 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002824 if (!sec)
2825 return 0;
2826
Miles Baderae28b042002-04-01 09:34:25 +00002827 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002828 dep = (struct new_module_ref *) sec->contents;
2829 for (i = 0; i < n_ext_modules; ++i)
2830 if (ext_modules[i].used) {
2831 dep->dep = ext_modules[i].addr;
2832 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002833 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002834 dep->next_ref = 0;
2835 ++dep;
2836 }
2837 }
2838
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002839 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002840 size_t nsyms;
2841 int *loaded;
2842
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002843 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002844
2845 /* We don't want to export symbols residing in sections that
2846 aren't loaded. There are a number of these created so that
2847 we make sure certain module options don't appear twice. */
2848
2849 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2850 while (--i >= 0)
2851 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2852
2853 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2854 struct obj_symbol *sym;
2855 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002856 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002857 && sym->secidx <= SHN_HIRESERVE
2858 && (sym->secidx >= SHN_LORESERVE
2859 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002860 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2861
2862 obj_symbol_patch(f, sec->idx, ofs, sym);
2863 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002864 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002865
2866 nsyms++;
2867 }
2868 }
2869
2870 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2871 }
2872
2873 return 1;
2874}
2875
2876
2877static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002878new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002879{
2880 struct new_module *module;
2881 struct obj_section *sec;
2882 void *image;
2883 int ret;
2884 tgt_long m_addr;
2885
2886 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002887 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002888 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002889 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002890 module = (struct new_module *) sec->contents;
2891 m_addr = sec->header.sh_addr;
2892
2893 module->size_of_struct = sizeof(*module);
2894 module->size = m_size;
2895 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2896
2897 sec = obj_find_section(f, "__ksymtab");
2898 if (sec && sec->header.sh_size) {
2899 module->syms = sec->header.sh_addr;
2900 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2901 }
2902
2903 if (n_ext_modules_used) {
2904 sec = obj_find_section(f, ".kmodtab");
2905 module->deps = sec->header.sh_addr;
2906 module->ndeps = n_ext_modules_used;
2907 }
2908
2909 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002910 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002911 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002912 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002913
2914 sec = obj_find_section(f, "__ex_table");
2915 if (sec) {
2916 module->ex_table_start = sec->header.sh_addr;
2917 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2918 }
2919
2920 sec = obj_find_section(f, ".text.init");
2921 if (sec) {
2922 module->runsize = sec->header.sh_addr - m_addr;
2923 }
2924 sec = obj_find_section(f, ".data.init");
2925 if (sec) {
2926 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002927 module->runsize > sec->header.sh_addr - m_addr)
2928 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002929 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002930 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2931 if (sec && sec->header.sh_size) {
2932 module->archdata_start = (void*)sec->header.sh_addr;
2933 module->archdata_end = module->archdata_start + sec->header.sh_size;
2934 }
2935 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2936 if (sec && sec->header.sh_size) {
2937 module->kallsyms_start = (void*)sec->header.sh_addr;
2938 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2939 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002940
Eric Andersen9f16d612000-06-12 23:11:16 +00002941 /* Whew! All of the initialization is complete. Collect the final
2942 module image and give it to the kernel. */
2943
2944 image = xmalloc(m_size);
2945 obj_create_image(f, image);
2946
Eric Andersencb3b9b12004-06-22 11:50:52 +00002947 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002948 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002949 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002950
2951 free(image);
2952
2953 return ret == 0;
2954}
2955
Eric Andersen9f16d612000-06-12 23:11:16 +00002956
2957/*======================================================================*/
2958
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002959static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002960obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2961 const char *string)
2962{
2963 struct obj_string_patch *p;
2964 struct obj_section *strsec;
2965 size_t len = strlen(string) + 1;
2966 char *loc;
2967
2968 p = xmalloc(sizeof(*p));
2969 p->next = f->string_patches;
2970 p->reloc_secidx = secidx;
2971 p->reloc_offset = offset;
2972 f->string_patches = p;
2973
2974 strsec = obj_find_section(f, ".kstrtab");
2975 if (strsec == NULL) {
2976 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2977 p->string_offset = 0;
2978 loc = strsec->contents;
2979 } else {
2980 p->string_offset = strsec->header.sh_size;
2981 loc = obj_extend_section(strsec, len);
2982 }
2983 memcpy(loc, string, len);
Eric Andersen9f16d612000-06-12 23:11:16 +00002984}
2985
Denis Vlasenkob68979a2007-11-02 23:31:10 +00002986static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002987obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2988 struct obj_symbol *sym)
2989{
2990 struct obj_symbol_patch *p;
2991
2992 p = xmalloc(sizeof(*p));
2993 p->next = f->symbol_patches;
2994 p->reloc_secidx = secidx;
2995 p->reloc_offset = offset;
2996 p->sym = sym;
2997 f->symbol_patches = p;
Eric Andersen9f16d612000-06-12 23:11:16 +00002998}
2999
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003000static void obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003001{
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003002 unsigned i;
Eric Andersen9f16d612000-06-12 23:11:16 +00003003
3004 for (i = 0; i < HASH_BUCKETS; ++i) {
3005 struct obj_symbol *sym;
3006 for (sym = f->symtab[i]; sym; sym = sym->next)
3007 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003008 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003009 sym->secidx = SHN_ABS;
3010 sym->value = 0;
3011 } else {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003012 if (!flag_quiet)
3013 bb_error_msg_and_die("unresolved symbol %s", sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003014 }
3015 }
3016 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003017}
3018
Eric Andersen044228d2001-07-17 01:12:36 +00003019static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003020{
3021 struct common_entry {
3022 struct common_entry *next;
3023 struct obj_symbol *sym;
3024 } *common_head = NULL;
3025
3026 unsigned long i;
3027
3028 for (i = 0; i < HASH_BUCKETS; ++i) {
3029 struct obj_symbol *sym;
3030 for (sym = f->symtab[i]; sym; sym = sym->next)
3031 if (sym->secidx == SHN_COMMON) {
3032 /* Collect all COMMON symbols and sort them by size so as to
3033 minimize space wasted by alignment requirements. */
3034 {
3035 struct common_entry **p, *n;
3036 for (p = &common_head; *p; p = &(*p)->next)
3037 if (sym->size <= (*p)->sym->size)
3038 break;
3039
3040 n = alloca(sizeof(*n));
3041 n->next = *p;
3042 n->sym = sym;
3043 *p = n;
3044 }
3045 }
3046 }
3047
3048 for (i = 1; i < f->local_symtab_size; ++i) {
3049 struct obj_symbol *sym = f->local_symtab[i];
3050 if (sym && sym->secidx == SHN_COMMON) {
3051 struct common_entry **p, *n;
3052 for (p = &common_head; *p; p = &(*p)->next)
3053 if (sym == (*p)->sym)
3054 break;
3055 else if (sym->size < (*p)->sym->size) {
3056 n = alloca(sizeof(*n));
3057 n->next = *p;
3058 n->sym = sym;
3059 *p = n;
3060 break;
3061 }
3062 }
3063 }
3064
3065 if (common_head) {
3066 /* Find the bss section. */
3067 for (i = 0; i < f->header.e_shnum; ++i)
3068 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3069 break;
3070
3071 /* If for some reason there hadn't been one, create one. */
3072 if (i == f->header.e_shnum) {
3073 struct obj_section *sec;
3074
3075 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3076 f->sections[i] = sec = arch_new_section();
3077 f->header.e_shnum = i + 1;
3078
Eric Andersen9f16d612000-06-12 23:11:16 +00003079 sec->header.sh_type = SHT_PROGBITS;
3080 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3081 sec->name = ".bss";
3082 sec->idx = i;
3083 }
3084
3085 /* Allocate the COMMONS. */
3086 {
3087 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3088 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3089 struct common_entry *c;
3090
3091 for (c = common_head; c; c = c->next) {
3092 ElfW(Addr) align = c->sym->value;
3093
3094 if (align > max_align)
3095 max_align = align;
3096 if (bss_size & (align - 1))
3097 bss_size = (bss_size | (align - 1)) + 1;
3098
3099 c->sym->secidx = i;
3100 c->sym->value = bss_size;
3101
3102 bss_size += c->sym->size;
3103 }
3104
3105 f->sections[i]->header.sh_size = bss_size;
3106 f->sections[i]->header.sh_addralign = max_align;
3107 }
3108 }
3109
3110 /* For the sake of patch relocation and parameter initialization,
3111 allocate zeroed data for NOBITS sections now. Note that after
3112 this we cannot assume NOBITS are really empty. */
3113 for (i = 0; i < f->header.e_shnum; ++i) {
3114 struct obj_section *s = f->sections[i];
3115 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003116 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003117 s->contents = memset(xmalloc(s->header.sh_size),
3118 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003119 else
3120 s->contents = NULL;
3121
Eric Andersen9f16d612000-06-12 23:11:16 +00003122 s->header.sh_type = SHT_PROGBITS;
3123 }
3124 }
3125}
3126
Eric Andersen044228d2001-07-17 01:12:36 +00003127static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003128{
3129 unsigned long dot = 0;
3130 struct obj_section *sec;
3131
3132 /* Finalize the positions of the sections relative to one another. */
3133
3134 for (sec = f->load_order; sec; sec = sec->load_next) {
3135 ElfW(Addr) align;
3136
3137 align = sec->header.sh_addralign;
3138 if (align && (dot & (align - 1)))
3139 dot = (dot | (align - 1)) + 1;
3140
3141 sec->header.sh_addr = dot;
3142 dot += sec->header.sh_size;
3143 }
3144
3145 return dot;
3146}
3147
Eric Andersen044228d2001-07-17 01:12:36 +00003148static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003149{
3150 int i, n = f->header.e_shnum;
3151 int ret = 1;
3152
3153 /* Finalize the addresses of the sections. */
3154
3155 f->baseaddr = base;
3156 for (i = 0; i < n; ++i)
3157 f->sections[i]->header.sh_addr += base;
3158
3159 /* And iterate over all of the relocations. */
3160
3161 for (i = 0; i < n; ++i) {
3162 struct obj_section *relsec, *symsec, *targsec, *strsec;
3163 ElfW(RelM) * rel, *relend;
3164 ElfW(Sym) * symtab;
3165 const char *strtab;
3166
3167 relsec = f->sections[i];
3168 if (relsec->header.sh_type != SHT_RELM)
3169 continue;
3170
3171 symsec = f->sections[relsec->header.sh_link];
3172 targsec = f->sections[relsec->header.sh_info];
3173 strsec = f->sections[symsec->header.sh_link];
3174
3175 rel = (ElfW(RelM) *) relsec->contents;
3176 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3177 symtab = (ElfW(Sym) *) symsec->contents;
3178 strtab = (const char *) strsec->contents;
3179
3180 for (; rel < relend; ++rel) {
3181 ElfW(Addr) value = 0;
3182 struct obj_symbol *intsym = NULL;
3183 unsigned long symndx;
3184 ElfW(Sym) * extsym = 0;
3185 const char *errmsg;
3186
3187 /* Attempt to find a value to use for this relocation. */
3188
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003189 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003190 if (symndx) {
3191 /* Note we've already checked for undefined symbols. */
3192
3193 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003194 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003195 /* Local symbols we look up in the local table to be sure
3196 we get the one that is really intended. */
3197 intsym = f->local_symtab[symndx];
3198 } else {
3199 /* Others we look up in the hash table. */
3200 const char *name;
3201 if (extsym->st_name)
3202 name = strtab + extsym->st_name;
3203 else
3204 name = f->sections[extsym->st_shndx]->name;
3205 intsym = obj_find_symbol(f, name);
3206 }
3207
3208 value = obj_symbol_final_value(f, intsym);
3209 intsym->referenced = 1;
3210 }
3211#if SHT_RELM == SHT_RELA
3212#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3213 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3214 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003215 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003216#endif
3217 value += rel->r_addend;
3218#endif
3219
3220 /* Do it! */
3221 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003222 (f, targsec, symsec, intsym, rel, value)
3223 ) {
3224 case obj_reloc_ok:
3225 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003226
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003227 case obj_reloc_overflow:
3228 errmsg = "Relocation overflow";
3229 goto bad_reloc;
3230 case obj_reloc_dangerous:
3231 errmsg = "Dangerous relocation";
3232 goto bad_reloc;
3233 case obj_reloc_unhandled:
3234 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003235bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003236 if (extsym) {
3237 bb_error_msg("%s of type %ld for %s", errmsg,
3238 (long) ELF_R_TYPE(rel->r_info),
3239 strtab + extsym->st_name);
3240 } else {
3241 bb_error_msg("%s of type %ld", errmsg,
3242 (long) ELF_R_TYPE(rel->r_info));
3243 }
3244 ret = 0;
3245 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003246 }
3247 }
3248 }
3249
3250 /* Finally, take care of the patches. */
3251
3252 if (f->string_patches) {
3253 struct obj_string_patch *p;
3254 struct obj_section *strsec;
3255 ElfW(Addr) strsec_base;
3256 strsec = obj_find_section(f, ".kstrtab");
3257 strsec_base = strsec->header.sh_addr;
3258
3259 for (p = f->string_patches; p; p = p->next) {
3260 struct obj_section *targsec = f->sections[p->reloc_secidx];
3261 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3262 = strsec_base + p->string_offset;
3263 }
3264 }
3265
3266 if (f->symbol_patches) {
3267 struct obj_symbol_patch *p;
3268
3269 for (p = f->symbol_patches; p; p = p->next) {
3270 struct obj_section *targsec = f->sections[p->reloc_secidx];
3271 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3272 = obj_symbol_final_value(f, p->sym);
3273 }
3274 }
3275
3276 return ret;
3277}
3278
Eric Andersen044228d2001-07-17 01:12:36 +00003279static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003280{
3281 struct obj_section *sec;
3282 ElfW(Addr) base = f->baseaddr;
3283
3284 for (sec = f->load_order; sec; sec = sec->load_next) {
3285 char *secimg;
3286
Eric Andersen2bf658d2001-02-24 20:01:53 +00003287 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003288 continue;
3289
3290 secimg = image + (sec->header.sh_addr - base);
3291
3292 /* Note that we allocated data for NOBITS sections earlier. */
3293 memcpy(secimg, sec->contents, sec->header.sh_size);
3294 }
3295
3296 return 1;
3297}
3298
3299/*======================================================================*/
3300
Eric Andersen044228d2001-07-17 01:12:36 +00003301static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003302{
3303 struct obj_file *f;
3304 ElfW(Shdr) * section_headers;
3305 int shnum, i;
3306 char *shstrtab;
3307
3308 /* Read the file header. */
3309
3310 f = arch_new_file();
Eric Andersen9f16d612000-06-12 23:11:16 +00003311 f->symbol_cmp = strcmp;
3312 f->symbol_hash = obj_elf_hash;
3313 f->load_order_search_start = &f->load_order;
3314
3315 fseek(fp, 0, SEEK_SET);
3316 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003317 bb_perror_msg_and_die("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003318 }
3319
3320 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003321 || f->header.e_ident[EI_MAG1] != ELFMAG1
3322 || f->header.e_ident[EI_MAG2] != ELFMAG2
3323 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003324 bb_error_msg_and_die("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003325 }
3326 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003327 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003328 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003329 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3330 || !MATCH_MACHINE(f->header.e_machine)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003331 bb_error_msg_and_die("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003332 }
3333 if (f->header.e_type != ET_REL) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003334 bb_error_msg_and_die("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003335 }
3336
3337 /* Read the section headers. */
3338
3339 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003340 bb_error_msg_and_die("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003341 (unsigned long) f->header.e_shentsize,
3342 (unsigned long) sizeof(ElfW(Shdr)));
Eric Andersen9f16d612000-06-12 23:11:16 +00003343 }
3344
3345 shnum = f->header.e_shnum;
3346 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3347 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3348
3349 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3350 fseek(fp, f->header.e_shoff, SEEK_SET);
3351 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003352 bb_perror_msg_and_die("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003353 }
3354
3355 /* Read the section data. */
3356
3357 for (i = 0; i < shnum; ++i) {
3358 struct obj_section *sec;
3359
3360 f->sections[i] = sec = arch_new_section();
Eric Andersen9f16d612000-06-12 23:11:16 +00003361
3362 sec->header = section_headers[i];
3363 sec->idx = i;
3364
Denis Vlasenko51742f42007-04-12 00:32:05 +00003365 if (sec->header.sh_size) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003366 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003367 case SHT_NULL:
3368 case SHT_NOTE:
3369 case SHT_NOBITS:
3370 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003371 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003372
3373 case SHT_PROGBITS:
3374#if LOADBITS
3375 if (!loadprogbits) {
3376 sec->contents = NULL;
3377 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003378 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003379#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003380 case SHT_SYMTAB:
3381 case SHT_STRTAB:
3382 case SHT_RELM:
3383 if (sec->header.sh_size > 0) {
3384 sec->contents = xmalloc(sec->header.sh_size);
3385 fseek(fp, sec->header.sh_offset, SEEK_SET);
3386 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003387 bb_perror_msg_and_die("error reading ELF section data");
Eric Andersen3b1a7442003-12-24 20:30:45 +00003388 }
3389 } else {
3390 sec->contents = NULL;
3391 }
3392 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003393
3394#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003395 case SHT_RELA:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003396 bb_error_msg_and_die("RELA relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003397#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003398 case SHT_REL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003399 bb_error_msg_and_die("REL relocations not supported on this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003400#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003401 default:
3402 if (sec->header.sh_type >= SHT_LOPROC) {
3403 /* Assume processor specific section types are debug
3404 info and can safely be ignored. If this is ever not
3405 the case (Hello MIPS?), don't put ifdefs here but
3406 create an arch_load_proc_section(). */
3407 break;
3408 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003409
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003410 bb_error_msg_and_die("can't handle sections of type %ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003411 (long) sec->header.sh_type);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003412 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003413 }
3414 }
3415
3416 /* Do what sort of interpretation as needed by each section. */
3417
3418 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3419
3420 for (i = 0; i < shnum; ++i) {
3421 struct obj_section *sec = f->sections[i];
3422 sec->name = shstrtab + sec->header.sh_name;
3423 }
3424
3425 for (i = 0; i < shnum; ++i) {
3426 struct obj_section *sec = f->sections[i];
3427
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003428 /* .modinfo should be contents only but gcc has no attribute for that.
3429 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3430 */
3431 if (strcmp(sec->name, ".modinfo") == 0)
3432 sec->header.sh_flags &= ~SHF_ALLOC;
3433
Eric Andersen9f16d612000-06-12 23:11:16 +00003434 if (sec->header.sh_flags & SHF_ALLOC)
3435 obj_insert_section_load_order(f, sec);
3436
3437 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003438 case SHT_SYMTAB:
3439 {
3440 unsigned long nsym, j;
3441 char *strtab;
3442 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003443
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003444 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003445 bb_error_msg_and_die("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003446 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003447 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003448 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003449
3450 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3451 strtab = f->sections[sec->header.sh_link]->contents;
3452 sym = (ElfW(Sym) *) sec->contents;
3453
3454 /* Allocate space for a table of local symbols. */
3455 j = f->local_symtab_size = sec->header.sh_info;
3456 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3457
3458 /* Insert all symbols into the hash table. */
3459 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3460 ElfW(Addr) val = sym->st_value;
3461 const char *name;
3462 if (sym->st_name)
3463 name = strtab + sym->st_name;
3464 else if (sym->st_shndx < shnum)
3465 name = f->sections[sym->st_shndx]->name;
3466 else
3467 continue;
3468#if defined(__SH5__)
3469 /*
3470 * For sh64 it is possible that the target of a branch
3471 * requires a mode switch (32 to 16 and back again).
3472 *
3473 * This is implied by the lsb being set in the target
3474 * address for SHmedia mode and clear for SHcompact.
3475 */
3476 val |= sym->st_other & 4;
3477#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003478 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3479 val, sym->st_size);
3480 }
3481 }
3482 break;
3483
3484 case SHT_RELM:
3485 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003486 bb_error_msg_and_die("relocation entry size mismatch: %lu != %lu",
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003487 (unsigned long) sec->header.sh_entsize,
3488 (unsigned long) sizeof(ElfW(RelM)));
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003489 }
3490 break;
3491 /* XXX Relocation code from modutils-2.3.19 is not here.
3492 * Why? That's about 20 lines of code from obj/obj_load.c,
3493 * which gets done in a second pass through the sections.
3494 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003495 }
3496 }
3497
3498 return f;
3499}
3500
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003501#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003502/*
3503 * load the unloaded sections directly into the memory allocated by
3504 * kernel for the module
3505 */
3506
Eric Andersenac5dbd12001-08-22 05:26:08 +00003507static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003508{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003509 ElfW(Addr) base = f->baseaddr;
3510 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003511
Eric Andersen8ae319a2001-05-21 16:09:18 +00003512 for (sec = f->load_order; sec; sec = sec->load_next) {
3513
3514 /* section already loaded? */
3515 if (sec->contents != NULL)
3516 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003517
Eric Andersen8ae319a2001-05-21 16:09:18 +00003518 if (sec->header.sh_size == 0)
3519 continue;
3520
3521 sec->contents = imagebase + (sec->header.sh_addr - base);
3522 fseek(fp, sec->header.sh_offset, SEEK_SET);
3523 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003524 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003525 return 0;
3526 }
3527
3528 }
3529 return 1;
3530}
3531#endif
3532
Eric Andersen9f16d612000-06-12 23:11:16 +00003533static void hide_special_symbols(struct obj_file *f)
3534{
3535 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003536 SPFX "cleanup_module",
3537 SPFX "init_module",
3538 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003539 NULL
3540 };
3541
3542 struct obj_symbol *sym;
3543 const char *const *p;
3544
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003545 for (p = specials; *p; ++p) {
3546 sym = obj_find_symbol(f, *p);
3547 if (sym != NULL)
3548 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3549 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003550}
3551
Glenn L McGrath759515c2003-08-30 06:00:33 +00003552
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003553#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003554static int obj_gpl_license(struct obj_file *f, const char **license)
3555{
3556 struct obj_section *sec;
3557 /* This list must match *exactly* the list of allowable licenses in
3558 * linux/include/linux/module.h. Checking for leading "GPL" will not
3559 * work, somebody will use "GPL sucks, this is proprietary".
3560 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003561 static const char *const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003562 "GPL",
3563 "GPL v2",
3564 "GPL and additional rights",
3565 "Dual BSD/GPL",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003566 "Dual MPL/GPL"
Eric Andersen166fa462002-09-16 05:30:24 +00003567 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003568
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003569 sec = obj_find_section(f, ".modinfo");
3570 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003571 const char *value, *ptr, *endptr;
3572 ptr = sec->contents;
3573 endptr = ptr + sec->header.sh_size;
3574 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003575 value = strchr(ptr, '=');
3576 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003577 int i;
3578 if (license)
3579 *license = value+1;
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003580 for (i = 0; i < ARRAY_SIZE(gpl_licenses); ++i) {
Eric Andersen166fa462002-09-16 05:30:24 +00003581 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003582 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003583 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003584 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003585 }
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003586 ptr = strchr(ptr, '\0');
3587 if (ptr)
3588 ptr++;
Eric Andersen166fa462002-09-16 05:30:24 +00003589 else
3590 ptr = endptr;
3591 }
3592 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003593 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003594}
3595
3596#define TAINT_FILENAME "/proc/sys/kernel/tainted"
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003597#define TAINT_PROPRIETORY_MODULE (1 << 0)
3598#define TAINT_FORCED_MODULE (1 << 1)
3599#define TAINT_UNSAFE_SMP (1 << 2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003600#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003601
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003602static void set_tainted(int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003603 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3604{
Denis Vlasenko931de892007-06-21 12:43:45 +00003605 static smallint printed_info;
3606
Eric Andersen166fa462002-09-16 05:30:24 +00003607 char buf[80];
3608 int oldval;
Denis Vlasenko931de892007-06-21 12:43:45 +00003609
Eric Andersen166fa462002-09-16 05:30:24 +00003610 if (fd < 0 && !kernel_has_tainted)
3611 return; /* New modutils on old kernel */
3612 printf("Warning: loading %s will taint the kernel: %s%s\n",
3613 m_name, text1, text2);
Denis Vlasenko931de892007-06-21 12:43:45 +00003614 if (!printed_info) {
Eric Andersen166fa462002-09-16 05:30:24 +00003615 printf(" See %s for information about tainted modules\n", TAINT_URL);
Denis Vlasenko931de892007-06-21 12:43:45 +00003616 printed_info = 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003617 }
3618 if (fd >= 0) {
3619 read(fd, buf, sizeof(buf)-1);
3620 buf[sizeof(buf)-1] = '\0';
3621 oldval = strtoul(buf, NULL, 10);
3622 sprintf(buf, "%d\n", oldval | taint);
3623 write(fd, buf, strlen(buf));
3624 }
3625}
3626
3627/* Check if loading this module will taint the kernel. */
3628static void check_tainted_module(struct obj_file *f, char *m_name)
3629{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003630 static const char tainted_file[] ALIGN1 = TAINT_FILENAME;
3631
Eric Andersen166fa462002-09-16 05:30:24 +00003632 int fd, kernel_has_tainted;
3633 const char *ptr;
3634
3635 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003636 fd = open(tainted_file, O_RDWR);
3637 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003638 if (errno == ENOENT)
3639 kernel_has_tainted = 0;
3640 else if (errno == EACCES)
3641 kernel_has_tainted = 1;
3642 else {
3643 perror(tainted_file);
3644 kernel_has_tainted = 0;
3645 }
3646 }
3647
3648 switch (obj_gpl_license(f, &ptr)) {
3649 case 0:
3650 break;
3651 case 1:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003652 set_tainted(fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003653 break;
3654 case 2:
3655 /* The module has a non-GPL license so we pretend that the
3656 * kernel always has a taint flag to get a warning even on
3657 * kernels without the proc flag.
3658 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003659 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
Eric Andersen166fa462002-09-16 05:30:24 +00003660 break;
3661 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003662 set_tainted(fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003663 break;
3664 }
3665
3666 if (flag_force_load)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003667 set_tainted(fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
Eric Andersen166fa462002-09-16 05:30:24 +00003668
3669 if (fd >= 0)
3670 close(fd);
3671}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003672#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003673#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003674#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003675
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003676#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003677/* add module source, timestamp, kernel version and a symbol for the
3678 * start of some sections. this info is used by ksymoops to do better
3679 * debugging.
3680 */
3681static int
3682get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3683{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003684#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003685 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003686#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003687 strncpy(str, "???", sizeof(str));
3688 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003689#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003690}
3691
3692/* add module source, timestamp, kernel version and a symbol for the
3693 * start of some sections. this info is used by ksymoops to do better
3694 * debugging.
3695 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003696static void
Eric Andersen889dd202003-01-23 04:48:34 +00003697add_ksymoops_symbols(struct obj_file *f, const char *filename,
3698 const char *m_name)
3699{
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00003700 static const char symprefix[] ALIGN1 = "__insmod_";
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003701 static const char section_names[][8] = {
Eric Andersen889dd202003-01-23 04:48:34 +00003702 ".text",
3703 ".rodata",
3704 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003705 ".bss",
3706 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003707 };
3708
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003709 struct obj_section *sec;
3710 struct obj_symbol *sym;
3711 char *name, *absolute_filename;
3712 char str[STRVERSIONLEN];
3713 int i, l, lm_name, lfilename, use_ksymtab, version;
3714 struct stat statbuf;
3715
3716 /* WARNING: was using realpath, but replaced by readlink to stop using
3717 * lots of stack. But here it seems to be able to cause problems? */
3718 absolute_filename = xmalloc_readlink(filename);
3719 if (!absolute_filename)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003720 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003721
3722 lm_name = strlen(m_name);
3723 lfilename = strlen(absolute_filename);
3724
3725 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3726 * are not to be exported. otherwise leave ksymtab alone for now, the
3727 * "export all symbols" compatibility code will export these symbols later.
3728 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003729 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003730
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003731 sec = obj_find_section(f, ".this");
3732 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003733 /* tag the module header with the object name, last modified
3734 * timestamp and module version. worst case for module version
3735 * is 0xffffff, decimal 16777215. putting all three fields in
3736 * one symbol is less readable but saves kernel space.
3737 */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003738 l = sizeof(symprefix) + /* "__insmod_" */
3739 lm_name + /* module name */
3740 2 + /* "_O" */
3741 lfilename + /* object filename */
3742 2 + /* "_M" */
3743 2 * sizeof(statbuf.st_mtime) + /* mtime in hex */
3744 2 + /* "_V" */
3745 8 + /* version in dec */
3746 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003747 name = xmalloc(l);
3748 if (stat(absolute_filename, &statbuf) != 0)
3749 statbuf.st_mtime = 0;
3750 version = get_module_version(f, str); /* -1 if not found */
3751 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003752 symprefix, m_name, absolute_filename,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003753 (int)(2 * sizeof(statbuf.st_mtime)), statbuf.st_mtime,
Eric Andersen3b1a7442003-12-24 20:30:45 +00003754 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003755 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003756 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003757 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003758 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003759 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003760 }
3761 free(absolute_filename);
3762#ifdef _NOT_SUPPORTED_
3763 /* record where the persistent data is going, same address as previous symbol */
3764
3765 if (f->persist) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003766 l = sizeof(symprefix) + /* "__insmod_" */
3767 lm_name + /* module name */
3768 2 + /* "_P" */
3769 strlen(f->persist) + /* data store */
3770 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003771 name = xmalloc(l);
3772 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003773 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003774 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003775 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003776 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003777 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003778 }
3779#endif /* _NOT_SUPPORTED_ */
3780 /* tag the desired sections if size is non-zero */
3781
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003782 for (i = 0; i < ARRAY_SIZE(section_names); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003783 sec = obj_find_section(f, section_names[i]);
3784 if (sec && sec->header.sh_size) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003785 l = sizeof(symprefix) + /* "__insmod_" */
3786 lm_name + /* module name */
3787 2 + /* "_S" */
3788 strlen(sec->name) + /* section name */
3789 2 + /* "_L" */
3790 8 + /* length in dec */
3791 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003792 name = xmalloc(l);
3793 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003794 symprefix, m_name, sec->name,
3795 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003796 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003797 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003798 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003799 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003800 }
3801 }
3802}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003803#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003804
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003805#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003806static void print_load_map(struct obj_file *f)
3807{
Eric Andersenbe65c352003-01-23 04:57:35 +00003808 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003809#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3810 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003811 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003812 struct obj_symbol *sym;
3813#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003814 /* Report on the section layout. */
3815
3816 printf("Sections: Size %-*s Align\n",
3817 (int) (2 * sizeof(void *)), "Address");
3818
3819 for (sec = f->load_order; sec; sec = sec->load_next) {
3820 int a;
3821 unsigned long tmp;
3822
3823 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3824 tmp >>= 1;
3825 if (a == -1)
3826 a = 0;
3827
3828 printf("%-15s %08lx %0*lx 2**%d\n",
3829 sec->name,
3830 (long)sec->header.sh_size,
3831 (int) (2 * sizeof(void *)),
3832 (long)sec->header.sh_addr,
3833 a);
3834 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003835#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003836 /* Quick reference which section indicies are loaded. */
3837
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003838 i = f->header.e_shnum;
3839 loaded = alloca(sizeof(int) * i);
Eric Andersenbe65c352003-01-23 04:57:35 +00003840 while (--i >= 0)
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003841 loaded[i] = ((f->sections[i]->header.sh_flags & SHF_ALLOC) != 0);
Eric Andersenbe65c352003-01-23 04:57:35 +00003842
3843 /* Collect the symbols we'll be listing. */
3844
3845 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3846 for (sym = f->symtab[i]; sym; sym = sym->next)
3847 if (sym->secidx <= SHN_HIRESERVE
3848 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3849 ++nsyms;
3850
3851 all = alloca(nsyms * sizeof(struct obj_symbol *));
3852
3853 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3854 for (sym = f->symtab[i]; sym; sym = sym->next)
3855 if (sym->secidx <= SHN_HIRESERVE
3856 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3857 *p++ = sym;
3858
3859 /* And list them. */
3860 printf("\nSymbols:\n");
3861 for (p = all; p < all + nsyms; ++p) {
3862 char type = '?';
3863 unsigned long value;
3864
3865 sym = *p;
3866 if (sym->secidx == SHN_ABS) {
3867 type = 'A';
3868 value = sym->value;
3869 } else if (sym->secidx == SHN_UNDEF) {
3870 type = 'U';
3871 value = 0;
3872 } else {
3873 sec = f->sections[sym->secidx];
3874
3875 if (sec->header.sh_type == SHT_NOBITS)
3876 type = 'B';
3877 else if (sec->header.sh_flags & SHF_ALLOC) {
3878 if (sec->header.sh_flags & SHF_EXECINSTR)
3879 type = 'T';
3880 else if (sec->header.sh_flags & SHF_WRITE)
3881 type = 'D';
3882 else
3883 type = 'R';
3884 }
3885 value = sym->value + sec->header.sh_addr;
3886 }
3887
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003888 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003889 type = tolower(type);
3890
3891 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3892 type, sym->name);
3893 }
3894#endif
3895}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003896#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003897void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003898#endif
3899
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00003900int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
3901int insmod_main(int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003902{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003903 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003904 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003905 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003906 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003907 unsigned long m_size;
3908 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003909 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003910 struct stat st;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003911 char *m_name = NULL;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003912 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003913 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003914#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003915 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003916 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003917 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003919#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003920 FILE *fp = NULL;
Eric Andersen61f83052002-06-22 17:15:42 +00003921#else
3922 FILE *fp;
3923#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003924 int k_version = 0;
3925 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003926
Erik Andersene49d5ec2000-02-08 19:58:47 +00003927 /* Parse any options */
Denis Vlasenkofe7cd642007-08-18 15:32:12 +00003928 getopt32(argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003929 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003930 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003931 free(m_name);
3932 m_name = xstrdup(opt_o);
3933 }
Eric Andersen03d80912003-12-19 21:04:19 +00003934
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003935 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003936 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003937 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003938
Erik Andersene49d5ec2000-02-08 19:58:47 +00003939 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003940 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003941 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003942 len = strlen(tmp);
3943
Eric Andersen03d80912003-12-19 21:04:19 +00003944 if (uname(&myuname) == 0) {
3945 if (myuname.release[0] == '2') {
3946 k_version = myuname.release[2] - '0';
3947 }
3948 }
3949
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003950#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003951 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
3952 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
3953 ) {
3954 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00003955 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003956 } else
Eric Andersen03d80912003-12-19 21:04:19 +00003957#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003958 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003959 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003960 tmp[len] = '\0';
3961 }
Eric Andersen2d342152002-06-18 05:16:25 +00003962
Eric Andersen03d80912003-12-19 21:04:19 +00003963
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003964#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00003965 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00003966 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00003967 else
Eric Andersen03d80912003-12-19 21:04:19 +00003968#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00003969 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00003970
Eric Andersen61f83052002-06-22 17:15:42 +00003971 if (!m_name) {
3972 m_name = tmp;
3973 } else {
3974 free(tmp1);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003975 tmp1 = NULL; /* flag for free(m_name) before exit() */
Eric Andersen61f83052002-06-22 17:15:42 +00003976 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003977
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00003978 /* Get a filedesc for the module. Check that we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003979 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
3980 || (fp = fopen(arg1, "r")) == NULL
3981 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00003982 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
3983 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00003984 if (k_version) { /* uname succeedd */
3985 char *module_dir;
3986 char *tmdn;
Robert Griebld378c312002-07-19 00:05:54 +00003987
Eric Andersen03d80912003-12-19 21:04:19 +00003988 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00003989 /* Jump through hoops in case /lib/modules/`uname -r`
3990 * is a symlink. We do not want recursive_action to
3991 * follow symlinks, but we do want to follow the
3992 * /lib/modules/`uname -r` dir, So resolve it ourselves
3993 * if it is a link... */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003994 module_dir = xmalloc_readlink(tmdn);
3995 if (!module_dir)
3996 module_dir = xstrdup(tmdn);
Denis Vlasenkobbd695d2007-04-08 10:52:28 +00003997 recursive_action(module_dir, ACTION_RECURSE,
Denis Vlasenkob68979a2007-11-02 23:31:10 +00003998 check_module_name_match, NULL, m_fullName, 0);
3999 free(module_dir);
Eric Andersen03d80912003-12-19 21:04:19 +00004000 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004001 }
4002
4003 /* Check if we have found anything yet */
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004004 if (!m_filename || ((fp = fopen(m_filename, "r")) == NULL)) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004005 int r;
4006 char *module_dir;
Robert Griebld378c312002-07-19 00:05:54 +00004007
Eric Andersen03d80912003-12-19 21:04:19 +00004008 free(m_filename);
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004009 m_filename = NULL;
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004010 module_dir = xmalloc_readlink(_PATH_MODULES);
4011 if (!module_dir)
4012 module_dir = xstrdup(_PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004013 /* No module found under /lib/modules/`uname -r`, this
4014 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004015 r = recursive_action(module_dir, ACTION_RECURSE,
4016 check_module_name_match, NULL, m_fullName, 0);
4017 if (r)
Denis Vlasenkod9c6a002007-09-24 19:54:36 +00004018 bb_error_msg_and_die("%s: module not found", m_fullName);
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004019 free(module_dir);
4020 if (m_filename == NULL
4021 || ((fp = fopen(m_filename, "r")) == NULL)
4022 ) {
4023 bb_error_msg_and_die("%s: module not found", m_fullName);
4024 }
Eric Andersen14d35432001-05-14 17:07:32 +00004025 }
Eric Andersen03d80912003-12-19 21:04:19 +00004026 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004027 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004028
Rob Landley999af202005-12-11 20:14:12 +00004029 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004030 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004031
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004032#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004033 if (k_version > 4) {
4034 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004035 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004036 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004037 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004038#endif
4039
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004040 f = obj_load(fp, LOADBITS);
Erik Andersend387d011999-12-21 02:55:11 +00004041
Eric Andersen9f16d612000-06-12 23:11:16 +00004042 if (get_modinfo_value(f, "kernel_version") == NULL)
4043 m_has_modinfo = 0;
4044 else
4045 m_has_modinfo = 1;
4046
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004047#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004048 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004049 if (!flag_quiet) {
4050 if (uname(&uts_info) < 0)
4051 uts_info.release[0] = '\0';
4052 if (m_has_modinfo) {
4053 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004054 if (m_version == -1) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004055 bb_error_msg_and_die("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004056 "compiled for");
Eric Andersenb493dec2002-07-02 19:14:23 +00004057 }
4058 }
4059
4060 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
Denis Vlasenko15611bb2007-06-12 08:52:02 +00004061 bb_error_msg("%skernel-module version mismatch\n"
4062 "\t%s was compiled for kernel version %s\n"
4063 "\twhile this kernel is version %s",
4064 flag_force_load ? "warning: " : "",
4065 m_filename, m_strversion, uts_info.release);
4066 if (!flag_force_load)
Eric Andersenb493dec2002-07-02 19:14:23 +00004067 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004068 }
4069 }
4070 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004071#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004072
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004073 if (query_module(NULL, 0, NULL, 0, NULL))
4074 bb_error_msg_and_die("not configured to support old kernels");
4075 new_get_kernel_symbols();
4076 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004077
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004078#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004079 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004080 if (m_has_modinfo)
4081 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004082
4083 if (m_crcs != k_crcs)
4084 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004085#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004086
Erik Andersene49d5ec2000-02-08 19:58:47 +00004087 /* Let the module know about the kernel symbols. */
4088 add_kernel_symbols(f);
4089
Eric Andersen9f16d612000-06-12 23:11:16 +00004090 /* Allocate common symbols, symbol tables, and string tables. */
4091
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004092 new_create_this_module(f, m_name);
4093 obj_check_undefineds(f);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004094 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004095 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004096
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004097 /* done with the module name, on to the optional var=value arguments */
4098 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004099 if (optind < argc) {
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004100 new_process_module_arguments(f, argc - optind, argv + optind);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004101 }
4102
Eric Andersen9f16d612000-06-12 23:11:16 +00004103 arch_create_got(f);
4104 hide_special_symbols(f);
4105
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004106#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004107 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004108#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004109
Eric Andersencb3b9b12004-06-22 11:50:52 +00004110 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004111
Erik Andersene49d5ec2000-02-08 19:58:47 +00004112 /* Find current size of the module */
4113 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004114
Erik Andersene49d5ec2000-02-08 19:58:47 +00004115 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004116 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004117 case EEXIST:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004118 bb_error_msg_and_die("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004119 case ENOMEM:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004120 bb_error_msg_and_die("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004121 m_size);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004122 default:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004123 bb_perror_msg_and_die("create_module: %s", m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004124 }
Erik Andersend387d011999-12-21 02:55:11 +00004125
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004126#if !LOADBITS
Eric Andersen8ae319a2001-05-21 16:09:18 +00004127 /*
4128 * the PROGBITS section was not loaded by the obj_load
4129 * now we can load them directly into the kernel memory
4130 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004131 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004132 delete_module(m_name);
4133 goto out;
4134 }
Eric Andersen03d80912003-12-19 21:04:19 +00004135#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004136
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 if (!obj_relocate(f, m_addr)) {
4138 delete_module(m_name);
4139 goto out;
4140 }
Erik Andersend387d011999-12-21 02:55:11 +00004141
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004142 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004143 delete_module(m_name);
4144 goto out;
4145 }
4146
Denis Vlasenko51742f42007-04-12 00:32:05 +00004147 if (flag_print_load_map)
Eric Andersenbe65c352003-01-23 04:57:35 +00004148 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004149
Matt Kraai3e856ce2000-12-01 02:55:13 +00004150 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004151
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004152 out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004153#if ENABLE_FEATURE_CLEAN_UP
Denis Vlasenko51742f42007-04-12 00:32:05 +00004154 if (fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004155 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004156 free(tmp1);
Denis Vlasenko51742f42007-04-12 00:32:05 +00004157 if (!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004158 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004159 free(m_filename);
4160#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004161 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004162}
Eric Andersene7047882003-12-11 01:42:13 +00004163
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004164#endif /* ENABLE_FEATURE_2_4_MODULES */
4165/*
4166 * End of big piece of 2.4-specific code
4167 */
Eric Andersene7047882003-12-11 01:42:13 +00004168
4169
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004170#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004171
4172#include <sys/mman.h>
4173#include <asm/unistd.h>
4174#include <sys/syscall.h>
4175
4176/* We use error numbers in a loose translation... */
4177static const char *moderror(int err)
4178{
4179 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004180 case ENOEXEC:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004181 return "invalid module format";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004182 case ENOENT:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004183 return "unknown symbol in module";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004184 case ESRCH:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004185 return "module has wrong symbol version";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004186 case EINVAL:
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004187 return "invalid parameters";
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004188 default:
4189 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004190 }
4191}
4192
Denis Vlasenkob68979a2007-11-02 23:31:10 +00004193#if !ENABLE_FEATURE_2_4_MODULES
4194int insmod_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
4195int insmod_main(int argc, char **argv)
4196#else
4197static int insmod_ng_main(int argc, char **argv)
4198#endif
Eric Andersene7047882003-12-11 01:42:13 +00004199{
Denis Vlasenko92297942006-11-21 11:58:14 +00004200 long ret;
4201 size_t len;
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004202 int optlen;
Eric Andersene7047882003-12-11 01:42:13 +00004203 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004204 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004205
Denis Vlasenko92297942006-11-21 11:58:14 +00004206 filename = *++argv;
4207 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004208 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004209
4210 /* Rest is options */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004211 options = xzalloc(1);
4212 optlen = 0;
Denis Vlasenko92297942006-11-21 11:58:14 +00004213 while (*++argv) {
Denis Vlasenko92297942006-11-21 11:58:14 +00004214 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004215 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenkod67cef22007-06-13 06:47:47 +00004216 optlen += sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004217 }
4218
Denis Vlasenko92297942006-11-21 11:58:14 +00004219#if 0
4220 /* Any special reason why mmap? It isn't performace critical... */
4221 int fd;
4222 struct stat st;
4223 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004224 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004225 fstat(fd, &st);
4226 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004227 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004228 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004229 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004230 }
4231
Denis Vlasenko92297942006-11-21 11:58:14 +00004232 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4233 if (map == NULL) {
4234 map = xmalloc(len);
4235 xread(fd, map, len);
4236 }
4237#else
4238 len = MAXINT(ssize_t);
4239 map = xmalloc_open_read_close(filename, &len);
4240#endif
4241
Eric Andersene7047882003-12-11 01:42:13 +00004242 ret = syscall(__NR_init_module, map, len, options);
4243 if (ret != 0) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004244 bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004245 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004246 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004247
Eric Andersene7047882003-12-11 01:42:13 +00004248 return 0;
4249}
4250
4251#endif