blob: 57092f79a84248d382badc9bc6beb563995bb558 [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
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +000061#include "busybox.h"
Rob Landley519d7df2006-08-09 20:56:23 +000062#include <libgen.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000065#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko3bba5452006-12-30 17:57:03 +000066#undef ENABLE_FEATURE_2_4_MODULES
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000067#define ENABLE_FEATURE_2_4_MODULES 1
Eric Andersene7047882003-12-11 01:42:13 +000068#endif
69
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000070#if !ENABLE_FEATURE_2_4_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000071#define insmod_ng_main insmod_main
72#endif
73
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000074#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000075extern int insmod_ng_main( int argc, char **argv);
76#endif
77
Eric Andersencb3b9b12004-06-22 11:50:52 +000078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000079#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000080
Eric Andersen64c8b172001-04-05 07:33:10 +000081
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000082#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000083#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000084#else
85#define LOADBITS 1
86#endif
87
Eric Andersen90fe7fe2001-02-20 20:47:08 +000088
Mike Frysinger63654c12004-12-26 09:13:32 +000089/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000090#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000091#define MATCH_MACHINE(x) (x == EM_ALPHA)
92#define SHT_RELM SHT_RELA
93#define Elf64_RelM Elf64_Rela
94#define ELFCLASSM ELFCLASS64
95#endif
96
Eric Andersen45a05132004-09-02 23:03:25 +000097/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000103#define USE_PLT_ENTRIES
104#define PLT_ENTRY_SIZE 8
105#define USE_GOT_ENTRIES
106#define GOT_ENTRY_SIZE 8
107#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000108#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000109
Mike Frysingerb306cb72006-06-06 06:15:52 +0000110/* blackfin */
111#if defined(BFIN)
112#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
113#define SHT_RELM SHT_RELA
114#define Elf32_RelM Elf32_Rela
115#define ELFCLASSM ELFCLASS32
116#endif
117
Eric Andersen45a05132004-09-02 23:03:25 +0000118/* CRIS */
119#if defined(__cris__)
120#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000121#define SHT_RELM SHT_RELA
122#define Elf32_RelM Elf32_Rela
123#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000124#ifndef EM_CRIS
125#define EM_CRIS 76
126#define R_CRIS_NONE 0
127#define R_CRIS_32 3
128#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000129#endif
130
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000131/* H8/300 */
132#if defined(__H8300H__) || defined(__H8300S__)
133#define MATCH_MACHINE(x) (x == EM_H8_300)
134#define SHT_RELM SHT_RELA
135#define Elf32_RelM Elf32_Rela
136#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000137#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000138#define SYMBOL_PREFIX "_"
139#endif
140
Mike Frysinger63654c12004-12-26 09:13:32 +0000141/* PA-RISC / HP-PA */
142#if defined(__hppa__)
143#define MATCH_MACHINE(x) (x == EM_PARISC)
144#define SHT_RELM SHT_RELA
145#if defined(__LP64__)
146#define Elf64_RelM Elf64_Rela
147#define ELFCLASSM ELFCLASS64
148#else
149#define Elf32_RelM Elf32_Rela
150#define ELFCLASSM ELFCLASS32
151#endif
152#endif
153
Eric Andersen45a05132004-09-02 23:03:25 +0000154/* x86 */
155#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000156#ifndef EM_486
157#define MATCH_MACHINE(x) (x == EM_386)
158#else
159#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
160#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000161#define SHT_RELM SHT_REL
162#define Elf32_RelM Elf32_Rel
163#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000164#define USE_GOT_ENTRIES
165#define GOT_ENTRY_SIZE 4
166#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* IA64, aka Itanium */
170#if defined(__ia64__)
171#define MATCH_MACHINE(x) (x == EM_IA_64)
172#define SHT_RELM SHT_RELA
173#define Elf64_RelM Elf64_Rela
174#define ELFCLASSM ELFCLASS64
175#endif
176
177/* m68k */
178#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define MATCH_MACHINE(x) (x == EM_68K)
180#define SHT_RELM SHT_RELA
181#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000182#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000183#define USE_GOT_ENTRIES
184#define GOT_ENTRY_SIZE 4
185#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000186#endif
187
Mike Frysingerb306cb72006-06-06 06:15:52 +0000188/* Microblaze */
189#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000190#define USE_SINGLE
Mike Frysingerb306cb72006-06-06 06:15:52 +0000191#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
192#define SHT_RELM SHT_RELA
193#define Elf32_RelM Elf32_Rela
194#define ELFCLASSM ELFCLASS32
195#endif
196
Eric Andersen45a05132004-09-02 23:03:25 +0000197/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000198#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000199#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
200#define SHT_RELM SHT_REL
201#define Elf32_RelM Elf32_Rel
202#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000203/* Account for ELF spec changes. */
204#ifndef EM_MIPS_RS3_LE
205#ifdef EM_MIPS_RS4_BE
206#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
207#else
208#define EM_MIPS_RS3_LE 10
209#endif
210#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000211#define ARCHDATAM "__dbe_table"
212#endif
213
Mike Frysingerf982d862006-01-04 00:11:26 +0000214/* Nios II */
215#if defined(__nios2__)
216#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
217#define SHT_RELM SHT_RELA
218#define Elf32_RelM Elf32_Rela
219#define ELFCLASSM ELFCLASS32
220#endif
221
Eric Andersen45a05132004-09-02 23:03:25 +0000222/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000223#if defined(__powerpc64__)
224#define MATCH_MACHINE(x) (x == EM_PPC64)
225#define SHT_RELM SHT_RELA
226#define Elf64_RelM Elf64_Rela
227#define ELFCLASSM ELFCLASS64
228#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000229#define MATCH_MACHINE(x) (x == EM_PPC)
230#define SHT_RELM SHT_RELA
231#define Elf32_RelM Elf32_Rela
232#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000233#define USE_PLT_ENTRIES
234#define PLT_ENTRY_SIZE 16
235#define USE_PLT_LIST
236#define LIST_ARCHTYPE ElfW(Addr)
237#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000238#define ARCHDATAM "__ftr_fixup"
239#endif
240
Eric Andersen45a05132004-09-02 23:03:25 +0000241/* S390 */
242#if defined(__s390__)
243#define MATCH_MACHINE(x) (x == EM_S390)
244#define SHT_RELM SHT_RELA
245#define Elf32_RelM Elf32_Rela
246#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000247#define USE_PLT_ENTRIES
248#define PLT_ENTRY_SIZE 8
249#define USE_GOT_ENTRIES
250#define GOT_ENTRY_SIZE 8
251#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000252#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000253
Eric Andersen45a05132004-09-02 23:03:25 +0000254/* SuperH */
255#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000256#define MATCH_MACHINE(x) (x == EM_SH)
257#define SHT_RELM SHT_RELA
258#define Elf32_RelM Elf32_Rela
259#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000260#define USE_GOT_ENTRIES
261#define GOT_ENTRY_SIZE 4
262#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000263/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000264/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000265#if defined(__sh__) && BB_BIG_ENDIAN
266# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000267#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000268/* it may or may not work on the SH1/SH2... Error on those also */
269#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000270#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000271#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000272#endif
273
Eric Andersen45a05132004-09-02 23:03:25 +0000274/* Sparc */
275#if defined(__sparc__)
276#define MATCH_MACHINE(x) (x == EM_SPARC)
277#define SHT_RELM SHT_RELA
278#define Elf32_RelM Elf32_Rela
279#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000280#endif
281
Eric Andersen45a05132004-09-02 23:03:25 +0000282/* v850e */
283#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000284#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
285#define SHT_RELM SHT_RELA
286#define Elf32_RelM Elf32_Rela
287#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000288#define USE_PLT_ENTRIES
289#define PLT_ENTRY_SIZE 8
290#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000291#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000292#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000293#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000294#define SYMBOL_PREFIX "_"
295#endif
296
Eric Andersen45a05132004-09-02 23:03:25 +0000297/* X86_64 */
298#if defined(__x86_64__)
299#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000300#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000301#define USE_GOT_ENTRIES
302#define GOT_ENTRY_SIZE 8
303#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000304#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000305#define ELFCLASSM ELFCLASS64
306#endif
307
Eric Andersencffd5022002-05-24 06:50:15 +0000308#ifndef SHT_RELM
309#error Sorry, but insmod.c does not yet support this architecture...
310#endif
311
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313//----------------------------------------------------------------------------
314//--------modutils module.h, lines 45-242
315//----------------------------------------------------------------------------
316
317/* Definitions for the Linux module syscall interface.
318 Copyright 1996, 1997 Linux International.
319
320 Contributed by Richard Henderson <rth@tamu.edu>
321
322 This file is part of the Linux modutils.
323
324 This program is free software; you can redistribute it and/or modify it
325 under the terms of the GNU General Public License as published by the
326 Free Software Foundation; either version 2 of the License, or (at your
327 option) any later version.
328
329 This program is distributed in the hope that it will be useful, but
330 WITHOUT ANY WARRANTY; without even the implied warranty of
331 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 General Public License for more details.
333
334 You should have received a copy of the GNU General Public License
335 along with this program; if not, write to the Free Software Foundation,
336 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
337
338
339#ifndef MODUTILS_MODULE_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000340
Eric Andersen9f16d612000-06-12 23:11:16 +0000341/*======================================================================*/
342/* For sizeof() which are related to the module platform and not to the
343 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
344
345#define tgt_sizeof_char sizeof(char)
346#define tgt_sizeof_short sizeof(short)
347#define tgt_sizeof_int sizeof(int)
348#define tgt_sizeof_long sizeof(long)
349#define tgt_sizeof_char_p sizeof(char *)
350#define tgt_sizeof_void_p sizeof(void *)
351#define tgt_long long
352
353#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
354#undef tgt_sizeof_long
355#undef tgt_sizeof_char_p
356#undef tgt_sizeof_void_p
357#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000358enum {
359 tgt_sizeof_long = 8,
360 tgt_sizeof_char_p = 8,
361 tgt_sizeof_void_p = 8
362};
Eric Andersen9f16d612000-06-12 23:11:16 +0000363#define tgt_long long long
364#endif
365
366/*======================================================================*/
367/* The structures used in Linux 2.1. */
368
369/* Note: new_module_symbol does not use tgt_long intentionally */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000370struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000371 unsigned long value;
372 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000373};
374
375struct new_module_persist;
376
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000377struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000378 unsigned tgt_long dep; /* kernel addresses */
379 unsigned tgt_long ref;
380 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000381};
382
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000383struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000384 unsigned tgt_long size_of_struct; /* == sizeof(module) */
385 unsigned tgt_long next;
386 unsigned tgt_long name;
387 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000388
Eric Andersen3b1a7442003-12-24 20:30:45 +0000389 tgt_long usecount;
390 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000391
Eric Andersen3b1a7442003-12-24 20:30:45 +0000392 unsigned nsyms;
393 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000394
Eric Andersen3b1a7442003-12-24 20:30:45 +0000395 unsigned tgt_long syms;
396 unsigned tgt_long deps;
397 unsigned tgt_long refs;
398 unsigned tgt_long init;
399 unsigned tgt_long cleanup;
400 unsigned tgt_long ex_table_start;
401 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000402#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000403 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 /* Everything after here is extension. */
406 unsigned tgt_long persist_start;
407 unsigned tgt_long persist_end;
408 unsigned tgt_long can_unload;
409 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000410 const char *kallsyms_start; /* All symbols for kernel debugging */
411 const char *kallsyms_end;
412 const char *archdata_start; /* arch specific data for module */
413 const char *archdata_end;
414 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000415};
416
Eric Andersencffd5022002-05-24 06:50:15 +0000417#ifdef ARCHDATAM
418#define ARCHDATA_SEC_NAME ARCHDATAM
419#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000420#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000421#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000422#define KALLSYMS_SEC_NAME "__kallsyms"
423
424
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000425struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000426 unsigned long addr;
427 unsigned long size;
428 unsigned long flags;
429 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000430};
431
432/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000433enum {
434 NEW_MOD_RUNNING = 1,
435 NEW_MOD_DELETED = 2,
436 NEW_MOD_AUTOCLEAN = 4,
437 NEW_MOD_VISITED = 8,
438 NEW_MOD_USED_ONCE = 16
439};
Eric Andersen9f16d612000-06-12 23:11:16 +0000440
Eric Andersencb3b9b12004-06-22 11:50:52 +0000441int init_module(const char *name, const struct new_module *);
442int query_module(const char *name, int which, void *buf,
443 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000444
445/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000446enum {
447 QM_MODULES = 1,
448 QM_DEPS = 2,
449 QM_REFS = 3,
450 QM_SYMBOLS = 4,
451 QM_INFO = 5
452};
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
454/*======================================================================*/
455/* The system calls unchanged between 2.0 and 2.1. */
456
457unsigned long create_module(const char *, size_t);
458int delete_module(const char *);
459
460
461#endif /* module.h */
462
463//----------------------------------------------------------------------------
464//--------end of modutils module.h
465//----------------------------------------------------------------------------
466
467
468
469//----------------------------------------------------------------------------
470//--------modutils obj.h, lines 253-462
471//----------------------------------------------------------------------------
472
473/* Elf object file loading and relocation routines.
474 Copyright 1996, 1997 Linux International.
475
476 Contributed by Richard Henderson <rth@tamu.edu>
477
478 This file is part of the Linux modutils.
479
480 This program is free software; you can redistribute it and/or modify it
481 under the terms of the GNU General Public License as published by the
482 Free Software Foundation; either version 2 of the License, or (at your
483 option) any later version.
484
485 This program is distributed in the hope that it will be useful, but
486 WITHOUT ANY WARRANTY; without even the implied warranty of
487 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
488 General Public License for more details.
489
490 You should have received a copy of the GNU General Public License
491 along with this program; if not, write to the Free Software Foundation,
492 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
493
494
495#ifndef MODUTILS_OBJ_H
Eric Andersen9f16d612000-06-12 23:11:16 +0000496
Eric Andersen9f16d612000-06-12 23:11:16 +0000497/* The relocatable object is manipulated using elfin types. */
498
499#include <stdio.h>
500#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000501#include <endian.h>
502
Eric Andersen9f16d612000-06-12 23:11:16 +0000503#ifndef ElfW
504# if ELFCLASSM == ELFCLASS32
505# define ElfW(x) Elf32_ ## x
506# define ELFW(x) ELF32_ ## x
507# else
508# define ElfW(x) Elf64_ ## x
509# define ELFW(x) ELF64_ ## x
510# endif
511#endif
512
Eric Andersen85e5e722003-07-22 08:56:55 +0000513/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000514#ifndef ELF32_ST_INFO
515# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
516#endif
517
518#ifndef ELF64_ST_INFO
519# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
520#endif
521
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000522#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
523#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
524#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
525#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
526#define ELF_R_SYM(val) ELFW(R_SYM)(val)
527
Eric Andersen9f16d612000-06-12 23:11:16 +0000528struct obj_string_patch;
529struct obj_symbol_patch;
530
531struct obj_section
532{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000533 ElfW(Shdr) header;
534 const char *name;
535 char *contents;
536 struct obj_section *load_next;
537 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000538};
539
540struct obj_symbol
541{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000542 struct obj_symbol *next; /* hash table link */
543 const char *name;
544 unsigned long value;
545 unsigned long size;
546 int secidx; /* the defining section index/module */
547 int info;
548 int ksymidx; /* for export to the kernel symtab */
549 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000550};
551
552/* Hardcode the hash table size. We shouldn't be needing so many
553 symbols that we begin to degrade performance, and we get a big win
554 by giving the compiler a constant divisor. */
555
556#define HASH_BUCKETS 521
557
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000558struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000559 ElfW(Ehdr) header;
560 ElfW(Addr) baseaddr;
561 struct obj_section **sections;
562 struct obj_section *load_order;
563 struct obj_section **load_order_search_start;
564 struct obj_string_patch *string_patches;
565 struct obj_symbol_patch *symbol_patches;
566 int (*symbol_cmp)(const char *, const char *);
567 unsigned long (*symbol_hash)(const char *);
568 unsigned long local_symtab_size;
569 struct obj_symbol **local_symtab;
570 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000571};
572
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000573enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000574 obj_reloc_ok,
575 obj_reloc_overflow,
576 obj_reloc_dangerous,
577 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000578};
579
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000580struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000581 struct obj_string_patch *next;
582 int reloc_secidx;
583 ElfW(Addr) reloc_offset;
584 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000585};
586
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000587struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000588 struct obj_symbol_patch *next;
589 int reloc_secidx;
590 ElfW(Addr) reloc_offset;
591 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000592};
593
594
595/* Generic object manipulation routines. */
596
Eric Andersen044228d2001-07-17 01:12:36 +0000597static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000602 const char *name);
603
Eric Andersen044228d2001-07-17 01:12:36 +0000604static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000605 struct obj_symbol *sym);
606
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000607#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000608static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000609 int (*cmp)(const char *, const char *),
610 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000611#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000612
Eric Andersen044228d2001-07-17 01:12:36 +0000613static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000614 const char *name);
615
Eric Andersen044228d2001-07-17 01:12:36 +0000616static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000617 struct obj_section *sec);
618
Eric Andersen044228d2001-07-17 01:12:36 +0000619static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000620 const char *name,
621 unsigned long align,
622 unsigned long size);
623
Eric Andersen044228d2001-07-17 01:12:36 +0000624static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000625 const char *name,
626 unsigned long align,
627 unsigned long size);
628
Eric Andersen044228d2001-07-17 01:12:36 +0000629static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000630
Eric Andersen044228d2001-07-17 01:12:36 +0000631static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000632 const char *string);
633
Eric Andersen044228d2001-07-17 01:12:36 +0000634static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000635 struct obj_symbol *sym);
636
Eric Andersen044228d2001-07-17 01:12:36 +0000637static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000642
Eric Andersen044228d2001-07-17 01:12:36 +0000643static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000646
Eric Andersen044228d2001-07-17 01:12:36 +0000647static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000648
649/* Architecture specific manipulation routines. */
650
Eric Andersen044228d2001-07-17 01:12:36 +0000651static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000652
Eric Andersen044228d2001-07-17 01:12:36 +0000653static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000658 struct obj_section *targsec,
659 struct obj_section *symsec,
660 struct obj_symbol *sym,
661 ElfW(RelM) *rel, ElfW(Addr) value);
662
Eric Andersencffd5022002-05-24 06:50:15 +0000663static void arch_create_got (struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000664#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000665static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000666#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000667#endif /* obj.h */
668//----------------------------------------------------------------------------
669//--------end of modutils obj.h
670//----------------------------------------------------------------------------
671
672
Miles Baderae28b042002-04-01 09:34:25 +0000673/* SPFX is always a string, so it can be concatenated to string constants. */
674#ifdef SYMBOL_PREFIX
675#define SPFX SYMBOL_PREFIX
676#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000677#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000678#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000679
Erik Andersen02104321999-12-17 18:57:34 +0000680
Erik Andersend387d011999-12-21 02:55:11 +0000681#define _PATH_MODULES "/lib/modules"
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000682enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000683
Eric Andersen9f16d612000-06-12 23:11:16 +0000684/*======================================================================*/
685
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000686#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
687enum {
688 OPT_s = 0x1, // -s /* log to syslog */
689 /* Not supported but kernel needs this for request_module(),
690 as this calls: modprobe -k -s -- <module>
691 so silently ignore this flag */
692 OPT_L = 0x2, // -L /* Stub warning */
693 /* Compatibility with modprobe.
694 In theory, this does locking, but we don't do
695 that. So be careful and plan your life around not
696 loading the same module 50 times concurrently. */
697 OPT_o = 0x4, // -o /* name the output module */
698 OPT_f = 0x8, // -f /* force loading */
699 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
700 OPT_v = 0x20, // -v /* verbose output */
701 OPT_q = 0x40, // -q /* silent */
702 OPT_x = 0x80, // -x /* do not export externs */
703 OPT_m = 0x100, // -m /* print module load map */
704};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000705#define flag_force_load (option_mask32 & OPT_f)
706#define flag_autoclean (option_mask32 & OPT_k)
707#define flag_verbose (option_mask32 & OPT_v)
708#define flag_quiet (option_mask32 & OPT_q)
709#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000710#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000711#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000712#else
713#define flag_print_load_map 0
714#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000715
716/*======================================================================*/
717
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000718#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000719
Eric Andersencffd5022002-05-24 06:50:15 +0000720struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000721{
Eric Andersencffd5022002-05-24 06:50:15 +0000722 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000723 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000724 int offset;
725 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000726};
Eric Andersencffd5022002-05-24 06:50:15 +0000727
Eric Andersen21adca72000-12-06 18:18:26 +0000728#endif
729
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000730#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000731
732struct arch_single_entry
733{
Eric Andersen9f16d612000-06-12 23:11:16 +0000734 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000735 int inited : 1;
736 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000737};
Eric Andersencffd5022002-05-24 06:50:15 +0000738
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000739#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000740
Eric Andersen2bf658d2001-02-24 20:01:53 +0000741#if defined(__mips__)
742struct mips_hi16
743{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000744 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000745 ElfW(Addr) *addr;
746 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000747};
748#endif
749
Eric Andersenfe4208f2000-09-24 03:44:29 +0000750struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000751 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000752#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000753 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000754#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000755#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000756 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000757#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000758#if defined(__mips__)
759 struct mips_hi16 *mips_hi16_list;
760#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000761};
762
Eric Andersenfe4208f2000-09-24 03:44:29 +0000763struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000764 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000765#if defined(USE_PLT_ENTRIES)
766#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000767 struct arch_list_entry *pltent;
768#else
769 struct arch_single_entry pltent;
770#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000771#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000772#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000773 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000774#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000775};
776
777
Eric Andersen9f16d612000-06-12 23:11:16 +0000778struct external_module {
779 const char *name;
780 ElfW(Addr) addr;
781 int used;
782 size_t nsyms;
783 struct new_module_symbol *syms;
784};
785
Eric Andersen044228d2001-07-17 01:12:36 +0000786static struct new_module_symbol *ksyms;
787static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000788
Eric Andersen044228d2001-07-17 01:12:36 +0000789static struct external_module *ext_modules;
790static int n_ext_modules;
791static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000792extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000793
Eric Andersen61f83052002-06-22 17:15:42 +0000794static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000795static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000796
Eric Andersenfe4208f2000-09-24 03:44:29 +0000797
Eric Andersen9f16d612000-06-12 23:11:16 +0000798/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000799
Eric Andersen9f16d612000-06-12 23:11:16 +0000800
Eric Andersen14d35432001-05-14 17:07:32 +0000801static int check_module_name_match(const char *filename, struct stat *statbuf,
Denis Vlasenko8c35d652006-10-27 23:42:25 +0000802 void *userdata, int depth)
Eric Andersen9f16d612000-06-12 23:11:16 +0000803{
Eric Andersen14d35432001-05-14 17:07:32 +0000804 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000805
Eric Andersen14d35432001-05-14 17:07:32 +0000806 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000807 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000808 else {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000809 char *tmp, *tmp1 = xstrdup(filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000810 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000811 if (strcmp(tmp, fullname) == 0) {
812 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000813 /* Stop searching if we find a match */
Rob Landleyd921b2e2006-08-03 15:41:12 +0000814 m_filename = xstrdup(filename);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000815 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000816 }
Eric Andersen14d35432001-05-14 17:07:32 +0000817 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000818 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000819 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000820}
821
Erik Andersen02104321999-12-17 18:57:34 +0000822
Eric Andersen9f16d612000-06-12 23:11:16 +0000823/*======================================================================*/
824
Eric Andersen044228d2001-07-17 01:12:36 +0000825static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000826{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000827 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000828 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000829
Eric Andersencffd5022002-05-24 06:50:15 +0000830 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831
Eric Andersen9f16d612000-06-12 23:11:16 +0000832 return &f->root;
833}
834
Eric Andersen044228d2001-07-17 01:12:36 +0000835static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000836{
837 return xmalloc(sizeof(struct obj_section));
838}
839
Eric Andersen044228d2001-07-17 01:12:36 +0000840static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000841{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000842 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000843 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000844
Eric Andersencffd5022002-05-24 06:50:15 +0000845 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000846
Eric Andersen9f16d612000-06-12 23:11:16 +0000847 return &sym->root;
848}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000849
Eric Andersen044228d2001-07-17 01:12:36 +0000850static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000851arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000852 struct obj_section *targsec,
853 struct obj_section *symsec,
854 struct obj_symbol *sym,
855 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000856{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000857 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000858 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000859 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
860 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000861#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000862 struct arch_symbol *isym = (struct arch_symbol *) sym;
863#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000864#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000865#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000866 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000867#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000868#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000869#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000870 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000871 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000872# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000873 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000874# else
Eric Andersencffd5022002-05-24 06:50:15 +0000875 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000876# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000877#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000878
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000879 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000880
Eric Andersencffd5022002-05-24 06:50:15 +0000881#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000882
Eric Andersen3b1a7442003-12-24 20:30:45 +0000883 case R_ARM_NONE:
884 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000885
Eric Andersen3b1a7442003-12-24 20:30:45 +0000886 case R_ARM_ABS32:
887 *loc += v;
888 break;
Miles Baderae28b042002-04-01 09:34:25 +0000889
Eric Andersen3b1a7442003-12-24 20:30:45 +0000890 case R_ARM_GOT32:
891 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000892
Eric Andersen3b1a7442003-12-24 20:30:45 +0000893 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000894 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
895 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000896 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000897
Eric Andersen3b1a7442003-12-24 20:30:45 +0000898 *loc += got - dot;
899 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000900
Eric Andersen3b1a7442003-12-24 20:30:45 +0000901 case R_ARM_PC24:
902 case R_ARM_PLT32:
903 goto bb_use_plt;
904
905 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000906 *loc += v - got;
907 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000908
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000909#elif defined(__cris__)
910
911 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000913
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000914 case R_CRIS_32:
915 /* CRIS keeps the relocation value in the r_addend field and
916 * should not use whats in *loc at all
917 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000918 *loc = v;
919 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000920
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000921#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000922
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000923 case R_H8_DIR24R8:
924 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
925 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000926 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000927 case R_H8_DIR24A8:
928 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000929 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000930 case R_H8_DIR32:
931 case R_H8_DIR32A16:
932 *loc += v;
933 break;
934 case R_H8_PCREL16:
935 v -= dot + 2;
936 if ((ElfW(Sword))v > 0x7fff ||
937 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
938 ret = obj_reloc_overflow;
939 else
940 *(unsigned short *)loc = v;
941 break;
942 case R_H8_PCREL8:
943 v -= dot + 1;
944 if ((ElfW(Sword))v > 0x7f ||
945 (ElfW(Sword))v < -(ElfW(Sword))0x80)
946 ret = obj_reloc_overflow;
947 else
948 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000949 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000950
Eric Andersencffd5022002-05-24 06:50:15 +0000951#elif defined(__i386__)
952
Eric Andersen3b1a7442003-12-24 20:30:45 +0000953 case R_386_NONE:
954 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000955
Eric Andersen3b1a7442003-12-24 20:30:45 +0000956 case R_386_32:
957 *loc += v;
958 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 case R_386_PLT32:
961 case R_386_PC32:
962 *loc += v - dot;
963 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000964
Eric Andersen3b1a7442003-12-24 20:30:45 +0000965 case R_386_GLOB_DAT:
966 case R_386_JMP_SLOT:
967 *loc = v;
968 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000969
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 case R_386_RELATIVE:
971 *loc += f->baseaddr;
972 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000975 *loc += got - dot;
976 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000977
Eric Andersen3b1a7442003-12-24 20:30:45 +0000978 case R_386_GOT32:
979 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000980
Eric Andersen3b1a7442003-12-24 20:30:45 +0000981 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000982 *loc += v - got;
983 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000984
Mike Frysinger280dae72006-06-06 06:30:32 +0000985#elif defined (__microblaze__)
986 case R_MICROBLAZE_NONE:
987 case R_MICROBLAZE_64_NONE:
988 case R_MICROBLAZE_32_SYM_OP_SYM:
989 case R_MICROBLAZE_32_PCREL:
990 break;
991
992 case R_MICROBLAZE_64_PCREL: {
993 /* dot is the address of the current instruction.
994 * v is the target symbol address.
995 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000996 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000997 * of this instruction.
998 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
999 */
1000
1001 /* Get split offset stored in code */
1002 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
1003 (loc[1] & 0xFFFF);
1004
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001005 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +00001006 * because dot points to the IMM insn, but branch
1007 * is computed relative to the branch instruction itself.
1008 */
1009 temp += v - dot - 4;
1010
1011 /* Store back into code */
1012 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1013 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1014
1015 break;
1016 }
1017
1018 case R_MICROBLAZE_32:
1019 *loc += v;
1020 break;
1021
1022 case R_MICROBLAZE_64: {
1023 /* Get split pointer stored in code */
1024 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1025 (loc[1] & 0xFFFF);
1026
1027 /* Add reloc offset */
1028 temp1+=v;
1029
1030 /* Store back into code */
1031 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1032 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1033
1034 break;
1035 }
1036
1037 case R_MICROBLAZE_32_PCREL_LO:
1038 case R_MICROBLAZE_32_LO:
1039 case R_MICROBLAZE_SRO32:
1040 case R_MICROBLAZE_SRW32:
1041 ret = obj_reloc_unhandled;
1042 break;
1043
Eric Andersencffd5022002-05-24 06:50:15 +00001044#elif defined(__mc68000__)
1045
Eric Andersen3b1a7442003-12-24 20:30:45 +00001046 case R_68K_NONE:
1047 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001048
Eric Andersen3b1a7442003-12-24 20:30:45 +00001049 case R_68K_32:
1050 *loc += v;
1051 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_68K_8:
1054 if (v > 0xff) {
1055 ret = obj_reloc_overflow;
1056 }
1057 *(char *)loc = v;
1058 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001059
Eric Andersen3b1a7442003-12-24 20:30:45 +00001060 case R_68K_16:
1061 if (v > 0xffff) {
1062 ret = obj_reloc_overflow;
1063 }
1064 *(short *)loc = v;
1065 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001066
Eric Andersen3b1a7442003-12-24 20:30:45 +00001067 case R_68K_PC8:
1068 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001069 if ((ElfW(Sword))v > 0x7f ||
1070 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001071 ret = obj_reloc_overflow;
1072 }
1073 *(char *)loc = v;
1074 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001075
Eric Andersen3b1a7442003-12-24 20:30:45 +00001076 case R_68K_PC16:
1077 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001078 if ((ElfW(Sword))v > 0x7fff ||
1079 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001080 ret = obj_reloc_overflow;
1081 }
1082 *(short *)loc = v;
1083 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001084
Eric Andersen3b1a7442003-12-24 20:30:45 +00001085 case R_68K_PC32:
1086 *(int *)loc = v - dot;
1087 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001088
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089 case R_68K_GLOB_DAT:
1090 case R_68K_JMP_SLOT:
1091 *loc = v;
1092 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001093
Eric Andersen3b1a7442003-12-24 20:30:45 +00001094 case R_68K_RELATIVE:
1095 *(int *)loc += f->baseaddr;
1096 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001097
Eric Andersen3b1a7442003-12-24 20:30:45 +00001098 case R_68K_GOT32:
1099 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001100
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001101# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001102 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001103 *loc += v - got;
1104 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001105# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001106
1107#elif defined(__mips__)
1108
Eric Andersen3b1a7442003-12-24 20:30:45 +00001109 case R_MIPS_NONE:
1110 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001111
Eric Andersen3b1a7442003-12-24 20:30:45 +00001112 case R_MIPS_32:
1113 *loc += v;
1114 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001115
Eric Andersen3b1a7442003-12-24 20:30:45 +00001116 case R_MIPS_26:
1117 if (v % 4)
1118 ret = obj_reloc_dangerous;
1119 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1120 ret = obj_reloc_overflow;
1121 *loc =
1122 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1123 0x03ffffff);
1124 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001125
Eric Andersen3b1a7442003-12-24 20:30:45 +00001126 case R_MIPS_HI16:
1127 {
1128 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001129
Eric Andersen3b1a7442003-12-24 20:30:45 +00001130 /* We cannot relocate this one now because we don't know the value
1131 of the carry we need to add. Save the information, and let LO16
1132 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001133 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001134 n->addr = loc;
1135 n->value = v;
1136 n->next = ifile->mips_hi16_list;
1137 ifile->mips_hi16_list = n;
1138 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001139 }
1140
Eric Andersen3b1a7442003-12-24 20:30:45 +00001141 case R_MIPS_LO16:
1142 {
1143 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001144 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001145
1146 /* Sign extend the addend we extract from the lo insn. */
1147 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1148
1149 if (ifile->mips_hi16_list != NULL) {
1150 struct mips_hi16 *l;
1151
1152 l = ifile->mips_hi16_list;
1153 while (l != NULL) {
1154 struct mips_hi16 *next;
1155 unsigned long insn;
1156
Eric Andersen3b1a7442003-12-24 20:30:45 +00001157 /* Do the HI16 relocation. Note that we actually don't
1158 need to know anything about the LO16 itself, except where
1159 to find the low 16 bits of the addend needed by the LO16. */
1160 insn = *l->addr;
1161 val =
1162 ((insn & 0xffff) << 16) +
1163 vallo;
1164 val += v;
1165
1166 /* Account for the sign extension that will happen in the
1167 low bits. */
1168 val =
1169 ((val >> 16) +
1170 ((val & 0x8000) !=
1171 0)) & 0xffff;
1172
1173 insn = (insn & ~0xffff) | val;
1174 *l->addr = insn;
1175
1176 next = l->next;
1177 free(l);
1178 l = next;
1179 }
1180
1181 ifile->mips_hi16_list = NULL;
1182 }
1183
1184 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1185 val = v + vallo;
1186 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1187 *loc = insnlo;
1188 break;
1189 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001190
Mike Frysingerf982d862006-01-04 00:11:26 +00001191#elif defined(__nios2__)
1192
1193 case R_NIOS2_NONE:
1194 break;
1195
1196 case R_NIOS2_BFD_RELOC_32:
1197 *loc += v;
1198 break;
1199
1200 case R_NIOS2_BFD_RELOC_16:
1201 if (v > 0xffff) {
1202 ret = obj_reloc_overflow;
1203 }
1204 *(short *)loc = v;
1205 break;
1206
1207 case R_NIOS2_BFD_RELOC_8:
1208 if (v > 0xff) {
1209 ret = obj_reloc_overflow;
1210 }
1211 *(char *)loc = v;
1212 break;
1213
1214 case R_NIOS2_S16:
1215 {
1216 Elf32_Addr word;
1217
1218 if ((Elf32_Sword)v > 0x7fff ||
1219 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1220 ret = obj_reloc_overflow;
1221 }
1222
1223 word = *loc;
1224 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1225 (word & 0x3f);
1226 }
1227 break;
1228
1229 case R_NIOS2_U16:
1230 {
1231 Elf32_Addr word;
1232
1233 if (v > 0xffff) {
1234 ret = obj_reloc_overflow;
1235 }
1236
1237 word = *loc;
1238 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1239 (word & 0x3f);
1240 }
1241 break;
1242
1243 case R_NIOS2_PCREL16:
1244 {
1245 Elf32_Addr word;
1246
1247 v -= dot + 4;
1248 if ((Elf32_Sword)v > 0x7fff ||
1249 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1250 ret = obj_reloc_overflow;
1251 }
1252
1253 word = *loc;
1254 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1255 }
1256 break;
1257
1258 case R_NIOS2_GPREL:
1259 {
1260 Elf32_Addr word, gp;
1261 /* get _gp */
1262 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1263 v-=gp;
1264 if ((Elf32_Sword)v > 0x7fff ||
1265 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1266 ret = obj_reloc_overflow;
1267 }
1268
1269 word = *loc;
1270 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1271 }
1272 break;
1273
1274 case R_NIOS2_CALL26:
1275 if (v & 3)
1276 ret = obj_reloc_dangerous;
1277 if ((v >> 28) != (dot >> 28))
1278 ret = obj_reloc_overflow;
1279 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1280 break;
1281
1282 case R_NIOS2_IMM5:
1283 {
1284 Elf32_Addr word;
1285
1286 if (v > 0x1f) {
1287 ret = obj_reloc_overflow;
1288 }
1289
1290 word = *loc & ~0x7c0;
1291 *loc = word | ((v & 0x1f) << 6);
1292 }
1293 break;
1294
1295 case R_NIOS2_IMM6:
1296 {
1297 Elf32_Addr word;
1298
1299 if (v > 0x3f) {
1300 ret = obj_reloc_overflow;
1301 }
1302
1303 word = *loc & ~0xfc0;
1304 *loc = word | ((v & 0x3f) << 6);
1305 }
1306 break;
1307
1308 case R_NIOS2_IMM8:
1309 {
1310 Elf32_Addr word;
1311
1312 if (v > 0xff) {
1313 ret = obj_reloc_overflow;
1314 }
1315
1316 word = *loc & ~0x3fc0;
1317 *loc = word | ((v & 0xff) << 6);
1318 }
1319 break;
1320
1321 case R_NIOS2_HI16:
1322 {
1323 Elf32_Addr word;
1324
1325 word = *loc;
1326 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1327 (word & 0x3f);
1328 }
1329 break;
1330
1331 case R_NIOS2_LO16:
1332 {
1333 Elf32_Addr word;
1334
1335 word = *loc;
1336 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1337 (word & 0x3f);
1338 }
1339 break;
1340
1341 case R_NIOS2_HIADJ16:
1342 {
1343 Elf32_Addr word1, word2;
1344
1345 word1 = *loc;
1346 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1347 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1348 (word1 & 0x3f);
1349 }
1350 break;
1351
Mike Frysingerebee0e72006-02-18 06:14:31 +00001352#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001353 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001354
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001355#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001356
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 case R_PPC_ADDR16_HA:
1358 *(unsigned short *)loc = (v + 0x8000) >> 16;
1359 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001360
Eric Andersen3b1a7442003-12-24 20:30:45 +00001361 case R_PPC_ADDR16_HI:
1362 *(unsigned short *)loc = v >> 16;
1363 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001364
Eric Andersen3b1a7442003-12-24 20:30:45 +00001365 case R_PPC_ADDR16_LO:
1366 *(unsigned short *)loc = v;
1367 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001368
Eric Andersen3b1a7442003-12-24 20:30:45 +00001369 case R_PPC_REL24:
1370 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001371
Eric Andersen3b1a7442003-12-24 20:30:45 +00001372 case R_PPC_REL32:
1373 *loc = v - dot;
1374 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001375
Eric Andersen3b1a7442003-12-24 20:30:45 +00001376 case R_PPC_ADDR32:
1377 *loc = v;
1378 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001379
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001380#elif defined(__s390__)
1381
1382 case R_390_32:
1383 *(unsigned int *) loc += v;
1384 break;
1385 case R_390_16:
1386 *(unsigned short *) loc += v;
1387 break;
1388 case R_390_8:
1389 *(unsigned char *) loc += v;
1390 break;
1391
1392 case R_390_PC32:
1393 *(unsigned int *) loc += v - dot;
1394 break;
1395 case R_390_PC16DBL:
1396 *(unsigned short *) loc += (v - dot) >> 1;
1397 break;
1398 case R_390_PC16:
1399 *(unsigned short *) loc += v - dot;
1400 break;
1401
1402 case R_390_PLT32:
1403 case R_390_PLT16DBL:
1404 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001405 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001406 if (pe->inited == 0) {
1407 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1408 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1409 ip[1] = 0x100607f1;
1410 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1411 ip[2] = v - 2;
1412 else
1413 ip[2] = v;
1414 pe->inited = 1;
1415 }
1416
1417 /* Insert relative distance to target. */
1418 v = plt + pe->offset - dot;
1419 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1420 *(unsigned int *) loc = (unsigned int) v;
1421 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1422 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1423 break;
1424
1425 case R_390_GLOB_DAT:
1426 case R_390_JMP_SLOT:
1427 *loc = v;
1428 break;
1429
1430 case R_390_RELATIVE:
1431 *loc += f->baseaddr;
1432 break;
1433
1434 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001435 *(unsigned long *) loc += got - dot;
1436 break;
1437
1438 case R_390_GOT12:
1439 case R_390_GOT16:
1440 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001441 if (!isym->gotent.inited)
1442 {
1443 isym->gotent.inited = 1;
1444 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1445 }
1446 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1447 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1448 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1449 *(unsigned short *) loc += isym->gotent.offset;
1450 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1451 *(unsigned int *) loc += isym->gotent.offset;
1452 break;
1453
1454# ifndef R_390_GOTOFF32
1455# define R_390_GOTOFF32 R_390_GOTOFF
1456# endif
1457 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001458 *loc += v - got;
1459 break;
1460
Eric Andersencffd5022002-05-24 06:50:15 +00001461#elif defined(__sh__)
1462
Eric Andersen3b1a7442003-12-24 20:30:45 +00001463 case R_SH_NONE:
1464 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001465
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 case R_SH_DIR32:
1467 *loc += v;
1468 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001469
Eric Andersen3b1a7442003-12-24 20:30:45 +00001470 case R_SH_REL32:
1471 *loc += v - dot;
1472 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001473
Eric Andersen3b1a7442003-12-24 20:30:45 +00001474 case R_SH_PLT32:
1475 *loc = v - dot;
1476 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001477
Eric Andersen3b1a7442003-12-24 20:30:45 +00001478 case R_SH_GLOB_DAT:
1479 case R_SH_JMP_SLOT:
1480 *loc = v;
1481 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001482
Eric Andersen3b1a7442003-12-24 20:30:45 +00001483 case R_SH_RELATIVE:
1484 *loc = f->baseaddr + rel->r_addend;
1485 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001486
Eric Andersen3b1a7442003-12-24 20:30:45 +00001487 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 *loc = got - dot + rel->r_addend;
1489 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001490
Eric Andersen3b1a7442003-12-24 20:30:45 +00001491 case R_SH_GOT32:
1492 goto bb_use_got;
1493
1494 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001495 *loc = v - got;
1496 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001497
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001498# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001499 case R_SH_IMM_MEDLOW16:
1500 case R_SH_IMM_LOW16:
1501 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001502 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001503
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001504 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001505 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001506
Eric Andersen3b1a7442003-12-24 20:30:45 +00001507 /*
1508 * movi and shori have the format:
1509 *
1510 * | op | imm | reg | reserved |
1511 * 31..26 25..10 9.. 4 3 .. 0
1512 *
1513 * so we simply mask and or in imm.
1514 */
1515 word = *loc & ~0x3fffc00;
1516 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001517
Eric Andersen3b1a7442003-12-24 20:30:45 +00001518 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001519
Eric Andersen3b1a7442003-12-24 20:30:45 +00001520 break;
1521 }
Eric Andersenbf833552003-08-13 19:56:33 +00001522
Eric Andersen3b1a7442003-12-24 20:30:45 +00001523 case R_SH_IMM_MEDLOW16_PCREL:
1524 case R_SH_IMM_LOW16_PCREL:
1525 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001526 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001527
Eric Andersen3b1a7442003-12-24 20:30:45 +00001528 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001529
Eric Andersen3b1a7442003-12-24 20:30:45 +00001530 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001531
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001532 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001533 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001534
Eric Andersen3b1a7442003-12-24 20:30:45 +00001535 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001536
Eric Andersen3b1a7442003-12-24 20:30:45 +00001537 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001538
Eric Andersen3b1a7442003-12-24 20:30:45 +00001539 break;
1540 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001541# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001542
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001543#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001544
Eric Andersen3b1a7442003-12-24 20:30:45 +00001545 case R_V850_NONE:
1546 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001547
Eric Andersen3b1a7442003-12-24 20:30:45 +00001548 case R_V850_32:
1549 /* We write two shorts instead of a long because even
1550 32-bit insns only need half-word alignment, but
1551 32-bit data needs to be long-word aligned. */
1552 v += ((unsigned short *)loc)[0];
1553 v += ((unsigned short *)loc)[1] << 16;
1554 ((unsigned short *)loc)[0] = v & 0xffff;
1555 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1556 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001557
Eric Andersen3b1a7442003-12-24 20:30:45 +00001558 case R_V850_22_PCREL:
1559 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001560
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001561#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001562
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001563 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001564 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001565
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001566 case R_X86_64_64:
1567 *loc += v;
1568 break;
1569
1570 case R_X86_64_32:
1571 *(unsigned int *) loc += v;
1572 if (v > 0xffffffff)
1573 {
1574 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1575 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1576 }
1577 break;
1578
1579 case R_X86_64_32S:
1580 *(signed int *) loc += v;
1581 break;
1582
1583 case R_X86_64_16:
1584 *(unsigned short *) loc += v;
1585 break;
1586
1587 case R_X86_64_8:
1588 *(unsigned char *) loc += v;
1589 break;
1590
1591 case R_X86_64_PC32:
1592 *(unsigned int *) loc += v - dot;
1593 break;
1594
1595 case R_X86_64_PC16:
1596 *(unsigned short *) loc += v - dot;
1597 break;
1598
1599 case R_X86_64_PC8:
1600 *(unsigned char *) loc += v - dot;
1601 break;
1602
1603 case R_X86_64_GLOB_DAT:
1604 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001605 *loc = v;
1606 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001607
1608 case R_X86_64_RELATIVE:
1609 *loc += f->baseaddr;
1610 break;
1611
1612 case R_X86_64_GOT32:
1613 case R_X86_64_GOTPCREL:
1614 goto bb_use_got;
1615# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001616 if (!isym->gotent.reloc_done)
1617 {
1618 isym->gotent.reloc_done = 1;
1619 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1620 }
1621 /* XXX are these really correct? */
1622 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1623 *(unsigned int *) loc += v + isym->gotent.offset;
1624 else
1625 *loc += isym->gotent.offset;
1626 break;
1627# endif
1628
Mike Frysingerf982d862006-01-04 00:11:26 +00001629#else
1630# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001631#endif
1632
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001633 default:
1634 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1635 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001636 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001637
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001638#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001639
Eric Andersen3b1a7442003-12-24 20:30:45 +00001640bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001641
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001643
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001644#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001645 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1646 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001647#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001649#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001650
Eric Andersen3b1a7442003-12-24 20:30:45 +00001651 if (! pe->inited) {
1652 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001653
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001655
1656#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001657 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1658 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001659#endif
1660#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001662 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663 ip[2] = 0x7d6903a6; /* mtctr r11 */
1664 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001665#endif
Miles Baderae28b042002-04-01 09:34:25 +00001666#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001667 /* We have to trash a register, so we assume that any control
1668 transfer more than 21-bits away must be a function call
1669 (so we can use a call-clobbered register). */
1670 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1671 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001672#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001673 pe->inited = 1;
1674 }
Eric Andersen21adca72000-12-06 18:18:26 +00001675
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 /* relative distance to target */
1677 v -= dot;
1678 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001679#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001680 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001681#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001682 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001683#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 /* go via the plt */
1685 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001686
1687#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001689#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001691#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001692 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001693
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001695#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001696 /* Convert to words. */
1697 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001698
Eric Andersen3b1a7442003-12-24 20:30:45 +00001699 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001700#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001701#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001702 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001703#endif
Miles Baderae28b042002-04-01 09:34:25 +00001704#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001705 /* We write two shorts instead of a long because even 32-bit insns
1706 only need half-word alignment, but the 32-bit data write needs
1707 to be long-word aligned. */
1708 ((unsigned short *)loc)[0] =
1709 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1710 | ((v >> 16) & 0x3f); /* offs high part */
1711 ((unsigned short *)loc)[1] =
1712 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001713#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001714 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001715#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001716
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001717#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001718bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001719
Eric Andersen3b1a7442003-12-24 20:30:45 +00001720 /* needs an entry in the .got: set it, once */
1721 if (!isym->gotent.inited) {
1722 isym->gotent.inited = 1;
1723 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1724 }
1725 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001726#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001727 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001728#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001729 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001730#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001731 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001732
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001733#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001734 }
1735
1736 return ret;
1737}
1738
Eric Andersencffd5022002-05-24 06:50:15 +00001739
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001740#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001741
1742static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1743 int offset, int size)
1744{
1745 struct arch_list_entry *pe;
1746
1747 for (pe = *list; pe != NULL; pe = pe->next) {
1748 if (pe->addend == rel->r_addend) {
1749 break;
1750 }
1751 }
1752
1753 if (pe == NULL) {
1754 pe = xmalloc(sizeof(struct arch_list_entry));
1755 pe->next = *list;
1756 pe->addend = rel->r_addend;
1757 pe->offset = offset;
1758 pe->inited = 0;
1759 *list = pe;
1760 return size;
1761 }
1762 return 0;
1763}
1764
1765#endif
1766
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001767#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001768
1769static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1770 int offset, int size)
1771{
1772 if (single->allocated == 0) {
1773 single->allocated = 1;
1774 single->offset = offset;
1775 single->inited = 0;
1776 return size;
1777 }
1778 return 0;
1779}
1780
1781#endif
1782
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001783#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001784
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001785static struct obj_section *arch_xsect_init(struct obj_file *f, const char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001786 int offset, int size)
1787{
1788 struct obj_section *myrelsec = obj_find_section(f, name);
1789
1790 if (offset == 0) {
1791 offset += size;
1792 }
1793
1794 if (myrelsec) {
1795 obj_extend_section(myrelsec, offset);
1796 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001797 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001798 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001799 }
1800
1801 return myrelsec;
1802}
1803
1804#endif
1805
1806static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001807{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001808#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001809 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001810 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001811#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001812 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001813#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001814#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001815 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001816#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001817 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001818 ElfW(RelM) *rel, *relend;
1819 ElfW(Sym) *symtab, *extsym;
1820 const char *strtab, *name;
1821 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001822
Eric Andersen21adca72000-12-06 18:18:26 +00001823 for (i = 0; i < f->header.e_shnum; ++i) {
1824 relsec = f->sections[i];
1825 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001826 continue;
1827
Eric Andersen21adca72000-12-06 18:18:26 +00001828 symsec = f->sections[relsec->header.sh_link];
1829 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001830
Eric Andersen21adca72000-12-06 18:18:26 +00001831 rel = (ElfW(RelM) *) relsec->contents;
1832 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1833 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001834 strtab = (const char *) strsec->contents;
1835
1836 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001837 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001838
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001839#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001840 got_allocate = 0;
1841#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001842#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001843 plt_allocate = 0;
1844#endif
1845
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001846 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001847#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001848 case R_ARM_PC24:
1849 case R_ARM_PLT32:
1850 plt_allocate = 1;
1851 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001852
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001853 case R_ARM_GOTOFF:
1854 case R_ARM_GOTPC:
1855 got_needed = 1;
1856 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001857
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001858 case R_ARM_GOT32:
1859 got_allocate = 1;
1860 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001861
Eric Andersen21adca72000-12-06 18:18:26 +00001862#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001863 case R_386_GOTPC:
1864 case R_386_GOTOFF:
1865 got_needed = 1;
1866 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001867
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001868 case R_386_GOT32:
1869 got_allocate = 1;
1870 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001871
1872#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001873 case R_PPC_REL24:
1874 plt_allocate = 1;
1875 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001876
1877#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001878 case R_68K_GOT32:
1879 got_allocate = 1;
1880 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001881
Eric Andersen16451a02004-03-19 12:16:18 +00001882#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001883 case R_68K_GOTOFF:
1884 got_needed = 1;
1885 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001886#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001887
1888#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001889 case R_SH_GOT32:
1890 got_allocate = 1;
1891 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001892
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001893 case R_SH_GOTPC:
1894 case R_SH_GOTOFF:
1895 got_needed = 1;
1896 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001897
1898#elif defined (__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001899 case R_V850_22_PCREL:
1900 plt_needed = 1;
1901 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001902
1903#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001904 default:
1905 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001906 }
1907
Eric Andersen21adca72000-12-06 18:18:26 +00001908 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001909 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001910 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001911 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001912 }
1913 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001914#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001915 if (got_allocate) {
1916 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001917 rel, &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001918 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001919
1920 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001921 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001922#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001923#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001924 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001925#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001926 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001927 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001928 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001929#else
1930 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001931 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001932 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001933#endif
1934 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001935 }
1936#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001937 }
Miles Baderae28b042002-04-01 09:34:25 +00001938 }
Eric Andersen21adca72000-12-06 18:18:26 +00001939
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001940#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001941 if (got_needed) {
1942 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001943 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001944 }
Eric Andersen21adca72000-12-06 18:18:26 +00001945#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001946
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001947#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001948 if (plt_needed) {
1949 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001950 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001951 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001952#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001953
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001954#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001955}
1956
Eric Andersen9f16d612000-06-12 23:11:16 +00001957/*======================================================================*/
1958
1959/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001960static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001961{
1962 unsigned long h = 0;
1963 unsigned long g;
1964 unsigned char ch;
1965
1966 while (n > 0) {
1967 ch = *name++;
1968 h = (h << 4) + ch;
1969 if ((g = (h & 0xf0000000)) != 0) {
1970 h ^= g >> 24;
1971 h &= ~g;
1972 }
1973 n--;
1974 }
1975 return h;
1976}
1977
Eric Andersen044228d2001-07-17 01:12:36 +00001978static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001979{
1980 return obj_elf_hash_n(name, strlen(name));
1981}
1982
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001983#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001984/* String comparison for non-co-versioned kernel and module. */
1985
1986static int ncv_strcmp(const char *a, const char *b)
1987{
1988 size_t alen = strlen(a), blen = strlen(b);
1989
1990 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1991 return strncmp(a, b, alen);
1992 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1993 return strncmp(a, b, blen);
1994 else
1995 return strcmp(a, b);
1996}
1997
1998/* String hashing for non-co-versioned kernel and module. Here
1999 we are simply forced to drop the crc from the hash. */
2000
2001static unsigned long ncv_symbol_hash(const char *str)
2002{
2003 size_t len = strlen(str);
2004 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2005 len -= 10;
2006 return obj_elf_hash_n(str, len);
2007}
2008
Eric Andersen044228d2001-07-17 01:12:36 +00002009static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002010obj_set_symbol_compare(struct obj_file *f,
2011 int (*cmp) (const char *, const char *),
2012 unsigned long (*hash) (const char *))
2013{
2014 if (cmp)
2015 f->symbol_cmp = cmp;
2016 if (hash) {
2017 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2018 int i;
2019
2020 f->symbol_hash = hash;
2021
2022 memcpy(tmptab, f->symtab, sizeof(tmptab));
2023 memset(f->symtab, 0, sizeof(f->symtab));
2024
2025 for (i = 0; i < HASH_BUCKETS; ++i)
2026 for (sym = tmptab[i]; sym; sym = next) {
2027 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2028 next = sym->next;
2029 sym->next = f->symtab[h];
2030 f->symtab[h] = sym;
2031 }
2032 }
2033}
2034
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002035#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002036
Eric Andersen044228d2001-07-17 01:12:36 +00002037static struct obj_symbol *
2038obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002039 unsigned long symidx, int info,
2040 int secidx, ElfW(Addr) value,
2041 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002042{
2043 struct obj_symbol *sym;
2044 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002045 int n_type = ELF_ST_TYPE(info);
2046 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002047
2048 for (sym = f->symtab[hash]; sym; sym = sym->next)
2049 if (f->symbol_cmp(sym->name, name) == 0) {
2050 int o_secidx = sym->secidx;
2051 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002052 int o_type = ELF_ST_TYPE(o_info);
2053 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002054
2055 /* A redefinition! Is it legal? */
2056
2057 if (secidx == SHN_UNDEF)
2058 return sym;
2059 else if (o_secidx == SHN_UNDEF)
2060 goto found;
2061 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2062 /* Cope with local and global symbols of the same name
2063 in the same object file, as might have been created
2064 by ld -r. The only reason locals are now seen at this
2065 level at all is so that we can do semi-sensible things
2066 with parameters. */
2067
2068 struct obj_symbol *nsym, **p;
2069
2070 nsym = arch_new_symbol();
2071 nsym->next = sym->next;
2072 nsym->ksymidx = -1;
2073
2074 /* Excise the old (local) symbol from the hash chain. */
2075 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2076 continue;
2077 *p = sym = nsym;
2078 goto found;
2079 } else if (n_binding == STB_LOCAL) {
2080 /* Another symbol of the same name has already been defined.
2081 Just add this to the local table. */
2082 sym = arch_new_symbol();
2083 sym->next = NULL;
2084 sym->ksymidx = -1;
2085 f->local_symtab[symidx] = sym;
2086 goto found;
2087 } else if (n_binding == STB_WEAK)
2088 return sym;
2089 else if (o_binding == STB_WEAK)
2090 goto found;
2091 /* Don't unify COMMON symbols with object types the programmer
2092 doesn't expect. */
2093 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002094 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002095 return sym;
2096 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002097 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002098 goto found;
2099 else {
2100 /* Don't report an error if the symbol is coming from
2101 the kernel or some external module. */
2102 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002103 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002104 return sym;
2105 }
2106 }
2107
2108 /* Completely new symbol. */
2109 sym = arch_new_symbol();
2110 sym->next = f->symtab[hash];
2111 f->symtab[hash] = sym;
2112 sym->ksymidx = -1;
2113
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002114 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002115 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002116 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002117 name, (long) symidx, (long) f->local_symtab_size);
2118 else
2119 f->local_symtab[symidx] = sym;
2120 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002121
Eric Andersen3b1a7442003-12-24 20:30:45 +00002122found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002123 sym->name = name;
2124 sym->value = value;
2125 sym->size = size;
2126 sym->secidx = secidx;
2127 sym->info = info;
2128
2129 return sym;
2130}
2131
Eric Andersen044228d2001-07-17 01:12:36 +00002132static struct obj_symbol *
2133obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002134{
2135 struct obj_symbol *sym;
2136 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2137
2138 for (sym = f->symtab[hash]; sym; sym = sym->next)
2139 if (f->symbol_cmp(sym->name, name) == 0)
2140 return sym;
2141
2142 return NULL;
2143}
2144
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002145static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002146{
2147 if (sym) {
2148 if (sym->secidx >= SHN_LORESERVE)
2149 return sym->value;
2150
2151 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2152 } else {
2153 /* As a special case, a NULL sym has value zero. */
2154 return 0;
2155 }
2156}
2157
Eric Andersen044228d2001-07-17 01:12:36 +00002158static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002159{
2160 int i, n = f->header.e_shnum;
2161
2162 for (i = 0; i < n; ++i)
2163 if (strcmp(f->sections[i]->name, name) == 0)
2164 return f->sections[i];
2165
2166 return NULL;
2167}
2168
2169static int obj_load_order_prio(struct obj_section *a)
2170{
2171 unsigned long af, ac;
2172
2173 af = a->header.sh_flags;
2174
2175 ac = 0;
2176 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002177 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002178 ac |= 32;
2179 if (af & SHF_ALLOC)
2180 ac |= 16;
2181 if (!(af & SHF_WRITE))
2182 ac |= 8;
2183 if (af & SHF_EXECINSTR)
2184 ac |= 4;
2185 if (a->header.sh_type != SHT_NOBITS)
2186 ac |= 2;
2187
2188 return ac;
2189}
2190
Eric Andersen044228d2001-07-17 01:12:36 +00002191static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002192obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2193{
2194 struct obj_section **p;
2195 int prio = obj_load_order_prio(sec);
2196 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2197 if (obj_load_order_prio(*p) < prio)
2198 break;
2199 sec->load_next = *p;
2200 *p = sec;
2201}
2202
Eric Andersen044228d2001-07-17 01:12:36 +00002203static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002204 const char *name,
2205 unsigned long align,
2206 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002207{
2208 int newidx = f->header.e_shnum++;
2209 struct obj_section *sec;
2210
2211 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2212 f->sections[newidx] = sec = arch_new_section();
2213
2214 memset(sec, 0, sizeof(*sec));
2215 sec->header.sh_type = SHT_PROGBITS;
2216 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2217 sec->header.sh_size = size;
2218 sec->header.sh_addralign = align;
2219 sec->name = name;
2220 sec->idx = newidx;
2221 if (size)
2222 sec->contents = xmalloc(size);
2223
2224 obj_insert_section_load_order(f, sec);
2225
2226 return sec;
2227}
2228
Eric Andersen044228d2001-07-17 01:12:36 +00002229static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002230 const char *name,
2231 unsigned long align,
2232 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002233{
2234 int newidx = f->header.e_shnum++;
2235 struct obj_section *sec;
2236
2237 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2238 f->sections[newidx] = sec = arch_new_section();
2239
2240 memset(sec, 0, sizeof(*sec));
2241 sec->header.sh_type = SHT_PROGBITS;
2242 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2243 sec->header.sh_size = size;
2244 sec->header.sh_addralign = align;
2245 sec->name = name;
2246 sec->idx = newidx;
2247 if (size)
2248 sec->contents = xmalloc(size);
2249
2250 sec->load_next = f->load_order;
2251 f->load_order = sec;
2252 if (f->load_order_search_start == &f->load_order)
2253 f->load_order_search_start = &sec->load_next;
2254
2255 return sec;
2256}
2257
Eric Andersen044228d2001-07-17 01:12:36 +00002258static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002259{
2260 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002261 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002262 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2263 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002264 return sec->contents + oldsize;
2265}
2266
2267
Eric Andersen9f16d612000-06-12 23:11:16 +00002268/* Conditionally add the symbols from the given symbol set to the
2269 new module. */
2270
2271static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002272add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002273 int idx, struct new_module_symbol *syms, size_t nsyms)
2274{
2275 struct new_module_symbol *s;
2276 size_t i;
2277 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002278#ifdef SYMBOL_PREFIX
2279 char *name_buf = 0;
2280 size_t name_alloced_size = 0;
2281#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002282#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002283 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002284
Glenn L McGrath759515c2003-08-30 06:00:33 +00002285 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002286#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002287 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002288 /* Only add symbols that are already marked external.
2289 If we override locals we may cause problems for
2290 argument initialization. We will also create a false
2291 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002292 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002293 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002294
Glenn L McGrath759515c2003-08-30 06:00:33 +00002295 /* GPL licensed modules can use symbols exported with
2296 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2297 * exported names. Non-GPL modules never see any GPLONLY_
2298 * symbols so they cannot fudge it by adding the prefix on
2299 * their references.
2300 */
2301 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002302#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002303 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002304 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002305 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002306#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002307 continue;
2308 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002309 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002310
Miles Baderae28b042002-04-01 09:34:25 +00002311#ifdef SYMBOL_PREFIX
2312 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2313 kernel exports `C names', but module object files
2314 reference `linker names'). */
2315 size_t extra = sizeof SYMBOL_PREFIX;
2316 size_t name_size = strlen (name) + extra;
2317 if (name_size > name_alloced_size) {
2318 name_alloced_size = name_size * 2;
2319 name_buf = alloca (name_alloced_size);
2320 }
2321 strcpy (name_buf, SYMBOL_PREFIX);
2322 strcpy (name_buf + extra - 1, name);
2323 name = name_buf;
2324#endif /* SYMBOL_PREFIX */
2325
2326 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002327 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002328#ifdef SYMBOL_PREFIX
2329 /* Put NAME_BUF into more permanent storage. */
2330 name = xmalloc (name_size);
2331 strcpy (name, name_buf);
2332#endif
2333 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002334 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002335 STT_NOTYPE),
2336 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002337 /* Did our symbol just get installed? If so, mark the
2338 module as "used". */
2339 if (sym->secidx == idx)
2340 used = 1;
2341 }
2342 }
2343
2344 return used;
2345}
2346
2347static void add_kernel_symbols(struct obj_file *f)
2348{
2349 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002350 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002351
2352 /* Add module symbols first. */
2353
2354 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2355 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002356 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2357 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002358
2359 n_ext_modules_used = nused;
2360
2361 /* And finally the symbols from the kernel proper. */
2362
2363 if (nksyms)
2364 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2365}
2366
2367static char *get_modinfo_value(struct obj_file *f, const char *key)
2368{
2369 struct obj_section *sec;
2370 char *p, *v, *n, *ep;
2371 size_t klen = strlen(key);
2372
2373 sec = obj_find_section(f, ".modinfo");
2374 if (sec == NULL)
2375 return NULL;
2376 p = sec->contents;
2377 ep = p + sec->header.sh_size;
2378 while (p < ep) {
2379 v = strchr(p, '=');
2380 n = strchr(p, '\0');
2381 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002382 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002383 return v + 1;
2384 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002385 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002386 return n;
2387 }
2388 p = n + 1;
2389 }
2390
2391 return NULL;
2392}
2393
2394
2395/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002396/* Functions relating to module loading after 2.1.18. */
2397
2398static int
2399new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2400{
2401 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002402 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002403 struct obj_symbol *sym;
2404 char *contents, *loc;
2405 int min, max, n;
2406
2407 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002408 if ((q = strchr(p, '=')) == NULL) {
2409 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002410 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002411 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002412
2413 key = alloca(q - p + 6);
2414 memcpy(key, "parm_", 5);
2415 memcpy(key + 5, p, q - p);
2416 key[q - p + 5] = 0;
2417
2418 p = get_modinfo_value(f, key);
2419 key += 5;
2420 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002421 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002422 return 0;
2423 }
2424
Miles Baderae28b042002-04-01 09:34:25 +00002425#ifdef SYMBOL_PREFIX
2426 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2427 strcpy (sym_name, SYMBOL_PREFIX);
2428 strcat (sym_name, key);
2429#else
2430 sym_name = key;
2431#endif
2432 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002433
2434 /* Also check that the parameter was not resolved from the kernel. */
2435 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002436 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002437 return 0;
2438 }
2439
2440 if (isdigit(*p)) {
2441 min = strtoul(p, &p, 10);
2442 if (*p == '-')
2443 max = strtoul(p + 1, &p, 10);
2444 else
2445 max = min;
2446 } else
2447 min = max = 1;
2448
2449 contents = f->sections[sym->secidx]->contents;
2450 loc = contents + sym->value;
2451 n = (*++q != '\0');
2452
2453 while (1) {
2454 if ((*p == 's') || (*p == 'c')) {
2455 char *str;
2456
2457 /* Do C quoting if we begin with a ", else slurp the lot. */
2458 if (*q == '"') {
2459 char *r;
2460
2461 str = alloca(strlen(q));
2462 for (r = str, q++; *q != '"'; ++q, ++r) {
2463 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002464 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002465 key);
2466 return 0;
2467 } else if (*q == '\\')
2468 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002469 case 'a':
2470 *r = '\a';
2471 break;
2472 case 'b':
2473 *r = '\b';
2474 break;
2475 case 'e':
2476 *r = '\033';
2477 break;
2478 case 'f':
2479 *r = '\f';
2480 break;
2481 case 'n':
2482 *r = '\n';
2483 break;
2484 case 'r':
2485 *r = '\r';
2486 break;
2487 case 't':
2488 *r = '\t';
2489 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002490
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002491 case '0':
2492 case '1':
2493 case '2':
2494 case '3':
2495 case '4':
2496 case '5':
2497 case '6':
2498 case '7':
2499 {
2500 int c = *q - '0';
2501 if (q[1] >= '0' && q[1] <= '7') {
2502 c = (c * 8) + *++q - '0';
2503 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002504 c = (c * 8) + *++q - '0';
2505 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002506 *r = c;
2507 }
2508 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002509
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002510 default:
2511 *r = *q;
2512 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002513 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002514 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002515 }
2516 *r = '\0';
2517 ++q;
2518 } else {
2519 char *r;
2520
2521 /* In this case, the string is not quoted. We will break
2522 it using the coma (like for ints). If the user wants to
2523 include comas in a string, he just has to quote it */
2524
2525 /* Search the next coma */
2526 r = strchr(q, ',');
2527
2528 /* Found ? */
2529 if (r != (char *) NULL) {
2530 /* Recopy the current field */
2531 str = alloca(r - q + 1);
2532 memcpy(str, q, r - q);
2533
Eric Andersenaff114c2004-04-14 17:51:38 +00002534 /* I don't know if it is useful, as the previous case
2535 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002536 str[r - q] = '\0';
2537
2538 /* Keep next fields */
2539 q = r;
2540 } else {
2541 /* last string */
2542 str = q;
Denis Vlasenkoab2aea42007-01-29 22:51:58 +00002543 q = (char*)"";
Eric Andersen9f16d612000-06-12 23:11:16 +00002544 }
2545 }
2546
2547 if (*p == 's') {
2548 /* Normal string */
2549 obj_string_patch(f, sym->secidx, loc - contents, str);
2550 loc += tgt_sizeof_char_p;
2551 } else {
2552 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002553 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002554
2555 /* Get the size of each member */
2556 /* Probably we should do that outside the loop ? */
2557 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002558 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002559 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 return 0;
2561 }
2562 charssize = strtoul(p + 1, (char **) NULL, 10);
2563
2564 /* Check length */
2565 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002566 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002567 charssize - 1);
2568 return 0;
2569 }
2570
2571 /* Copy to location */
2572 strcpy((char *) loc, str);
2573 loc += charssize;
2574 }
2575 } else {
2576 long v = strtoul(q, &q, 0);
2577 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002578 case 'b':
2579 *loc++ = v;
2580 break;
2581 case 'h':
2582 *(short *) loc = v;
2583 loc += tgt_sizeof_short;
2584 break;
2585 case 'i':
2586 *(int *) loc = v;
2587 loc += tgt_sizeof_int;
2588 break;
2589 case 'l':
2590 *(long *) loc = v;
2591 loc += tgt_sizeof_long;
2592 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002593
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002594 default:
2595 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2596 return 0;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002597 }
2598 }
2599
2600retry_end_of_value:
2601 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002602 case '\0':
2603 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002604
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002605 case ' ':
2606 case '\t':
2607 case '\n':
2608 case '\r':
2609 ++q;
2610 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002611
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002612 case ',':
2613 if (++n > max) {
2614 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002615 return 0;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002616 }
2617 ++q;
2618 break;
2619
2620 default:
2621 bb_error_msg("invalid argument syntax for %s", key);
2622 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002623 }
2624 }
2625
Eric Andersen3b1a7442003-12-24 20:30:45 +00002626end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002627 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002628 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002629 return 0;
2630 }
2631
2632 argc--, argv++;
2633 }
2634
2635 return 1;
2636}
2637
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002638#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002639static int new_is_module_checksummed(struct obj_file *f)
2640{
2641 const char *p = get_modinfo_value(f, "using_checksums");
2642 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002643 return xatoi(p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002644 else
2645 return 0;
2646}
2647
2648/* Get the module's kernel version in the canonical integer form. */
2649
2650static int
2651new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2652{
2653 char *p, *q;
2654 int a, b, c;
2655
2656 p = get_modinfo_value(f, "kernel_version");
2657 if (p == NULL)
2658 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002659 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002660
2661 a = strtoul(p, &p, 10);
2662 if (*p != '.')
2663 return -1;
2664 b = strtoul(p + 1, &p, 10);
2665 if (*p != '.')
2666 return -1;
2667 c = strtoul(p + 1, &q, 10);
2668 if (p + 1 == q)
2669 return -1;
2670
2671 return a << 16 | b << 8 | c;
2672}
2673
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002674#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002675
2676
Eric Andersen9f16d612000-06-12 23:11:16 +00002677/* Fetch the loaded modules, and all currently exported symbols. */
2678
2679static int new_get_kernel_symbols(void)
2680{
2681 char *module_names, *mn;
2682 struct external_module *modules, *m;
2683 struct new_module_symbol *syms, *s;
2684 size_t ret, bufsize, nmod, nsyms, i, j;
2685
2686 /* Collect the loaded modules. */
2687
2688 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002689retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002690 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002691 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002692 module_names = xrealloc(module_names, bufsize = ret);
2693 goto retry_modules_load;
2694 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002695 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002696 return 0;
2697 }
2698
2699 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002700
2701 /* Collect the modules' symbols. */
2702
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002703 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002704 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2705 memset(modules, 0, nmod * sizeof(*modules));
2706 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002707 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002708 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002709
Mark Whitley94fd4802001-03-12 23:08:34 +00002710 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2711 if (errno == ENOENT) {
2712 /* The module was removed out from underneath us. */
2713 continue;
2714 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002715 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 return 0;
2717 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002718
Mark Whitley94fd4802001-03-12 23:08:34 +00002719 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002720retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002721 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2722 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002723 case ENOSPC:
2724 syms = xrealloc(syms, bufsize = ret);
2725 goto retry_mod_sym_load;
2726 case ENOENT:
2727 /* The module was removed out from underneath us. */
2728 continue;
2729 default:
2730 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2731 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002732 }
2733 }
2734 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002735
Mark Whitley94fd4802001-03-12 23:08:34 +00002736 m->name = mn;
2737 m->addr = info.addr;
2738 m->nsyms = nsyms;
2739 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002740
Mark Whitley94fd4802001-03-12 23:08:34 +00002741 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2742 s->name += (unsigned long) syms;
2743 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002744 }
2745 }
2746
2747 /* Collect the kernel's symbols. */
2748
2749 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002750retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002751 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002752 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002753 syms = xrealloc(syms, bufsize = ret);
2754 goto retry_kern_sym_load;
2755 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002756 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002757 return 0;
2758 }
2759 nksyms = nsyms = ret;
2760 ksyms = syms;
2761
2762 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2763 s->name += (unsigned long) syms;
2764 }
2765 return 1;
2766}
2767
2768
2769/* Return the kernel symbol checksum version, or zero if not used. */
2770
2771static int new_is_kernel_checksummed(void)
2772{
2773 struct new_module_symbol *s;
2774 size_t i;
2775
2776 /* Using_Versions is not the first symbol, but it should be in there. */
2777
2778 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2779 if (strcmp((char *) s->name, "Using_Versions") == 0)
2780 return s->value;
2781
2782 return 0;
2783}
2784
2785
2786static int new_create_this_module(struct obj_file *f, const char *m_name)
2787{
2788 struct obj_section *sec;
2789
2790 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002791 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002792 memset(sec->contents, 0, sizeof(struct new_module));
2793
Miles Baderae28b042002-04-01 09:34:25 +00002794 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002795 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002796 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002797
2798 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002799 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002800
2801 return 1;
2802}
2803
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002804#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002805/* add an entry to the __ksymtab section, creating it if necessary */
2806static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2807{
2808 struct obj_section *sec;
2809 ElfW(Addr) ofs;
2810
2811 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2812 * If __ksymtab is defined but not marked alloc, x out the first character
2813 * (no obj_delete routine) and create a new __ksymtab with the correct
2814 * characteristics.
2815 */
2816 sec = obj_find_section(f, "__ksymtab");
2817 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2818 *((char *)(sec->name)) = 'x'; /* override const */
2819 sec = NULL;
2820 }
2821 if (!sec)
2822 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002823 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002824 if (!sec)
2825 return;
2826 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002827 /* Empty section might be byte-aligned */
2828 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002829 ofs = sec->header.sh_size;
2830 obj_symbol_patch(f, sec->idx, ofs, sym);
2831 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2832 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2833}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002834#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002835
2836static int new_create_module_ksymtab(struct obj_file *f)
2837{
2838 struct obj_section *sec;
2839 int i;
2840
2841 /* We must always add the module references. */
2842
2843 if (n_ext_modules_used) {
2844 struct new_module_ref *dep;
2845 struct obj_symbol *tm;
2846
2847 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002848 (sizeof(struct new_module_ref)
2849 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002850 if (!sec)
2851 return 0;
2852
Miles Baderae28b042002-04-01 09:34:25 +00002853 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002854 dep = (struct new_module_ref *) sec->contents;
2855 for (i = 0; i < n_ext_modules; ++i)
2856 if (ext_modules[i].used) {
2857 dep->dep = ext_modules[i].addr;
2858 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002859 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002860 dep->next_ref = 0;
2861 ++dep;
2862 }
2863 }
2864
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002865 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002866 size_t nsyms;
2867 int *loaded;
2868
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002869 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002870
2871 /* We don't want to export symbols residing in sections that
2872 aren't loaded. There are a number of these created so that
2873 we make sure certain module options don't appear twice. */
2874
2875 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2876 while (--i >= 0)
2877 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2878
2879 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2880 struct obj_symbol *sym;
2881 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002882 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002883 && sym->secidx <= SHN_HIRESERVE
2884 && (sym->secidx >= SHN_LORESERVE
2885 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002886 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2887
2888 obj_symbol_patch(f, sec->idx, ofs, sym);
2889 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002890 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002891
2892 nsyms++;
2893 }
2894 }
2895
2896 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2897 }
2898
2899 return 1;
2900}
2901
2902
2903static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002904new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002905{
2906 struct new_module *module;
2907 struct obj_section *sec;
2908 void *image;
2909 int ret;
2910 tgt_long m_addr;
2911
2912 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002913 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002914 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002915 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002916 module = (struct new_module *) sec->contents;
2917 m_addr = sec->header.sh_addr;
2918
2919 module->size_of_struct = sizeof(*module);
2920 module->size = m_size;
2921 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2922
2923 sec = obj_find_section(f, "__ksymtab");
2924 if (sec && sec->header.sh_size) {
2925 module->syms = sec->header.sh_addr;
2926 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2927 }
2928
2929 if (n_ext_modules_used) {
2930 sec = obj_find_section(f, ".kmodtab");
2931 module->deps = sec->header.sh_addr;
2932 module->ndeps = n_ext_modules_used;
2933 }
2934
2935 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002936 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002937 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002938 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002939
2940 sec = obj_find_section(f, "__ex_table");
2941 if (sec) {
2942 module->ex_table_start = sec->header.sh_addr;
2943 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2944 }
2945
2946 sec = obj_find_section(f, ".text.init");
2947 if (sec) {
2948 module->runsize = sec->header.sh_addr - m_addr;
2949 }
2950 sec = obj_find_section(f, ".data.init");
2951 if (sec) {
2952 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002953 module->runsize > sec->header.sh_addr - m_addr)
2954 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002955 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002956 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2957 if (sec && sec->header.sh_size) {
2958 module->archdata_start = (void*)sec->header.sh_addr;
2959 module->archdata_end = module->archdata_start + sec->header.sh_size;
2960 }
2961 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2962 if (sec && sec->header.sh_size) {
2963 module->kallsyms_start = (void*)sec->header.sh_addr;
2964 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2965 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002966
Eric Andersen9f16d612000-06-12 23:11:16 +00002967 /* Whew! All of the initialization is complete. Collect the final
2968 module image and give it to the kernel. */
2969
2970 image = xmalloc(m_size);
2971 obj_create_image(f, image);
2972
Eric Andersencb3b9b12004-06-22 11:50:52 +00002973 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002974 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002975 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002976
2977 free(image);
2978
2979 return ret == 0;
2980}
2981
Eric Andersen9f16d612000-06-12 23:11:16 +00002982
2983/*======================================================================*/
2984
Eric Andersen044228d2001-07-17 01:12:36 +00002985static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002986obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2987 const char *string)
2988{
2989 struct obj_string_patch *p;
2990 struct obj_section *strsec;
2991 size_t len = strlen(string) + 1;
2992 char *loc;
2993
2994 p = xmalloc(sizeof(*p));
2995 p->next = f->string_patches;
2996 p->reloc_secidx = secidx;
2997 p->reloc_offset = offset;
2998 f->string_patches = p;
2999
3000 strsec = obj_find_section(f, ".kstrtab");
3001 if (strsec == NULL) {
3002 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3003 p->string_offset = 0;
3004 loc = strsec->contents;
3005 } else {
3006 p->string_offset = strsec->header.sh_size;
3007 loc = obj_extend_section(strsec, len);
3008 }
3009 memcpy(loc, string, len);
3010
3011 return 1;
3012}
3013
Eric Andersen044228d2001-07-17 01:12:36 +00003014static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003015obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3016 struct obj_symbol *sym)
3017{
3018 struct obj_symbol_patch *p;
3019
3020 p = xmalloc(sizeof(*p));
3021 p->next = f->symbol_patches;
3022 p->reloc_secidx = secidx;
3023 p->reloc_offset = offset;
3024 p->sym = sym;
3025 f->symbol_patches = p;
3026
3027 return 1;
3028}
3029
Eric Andersen044228d2001-07-17 01:12:36 +00003030static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003031{
3032 unsigned long i;
3033 int ret = 1;
3034
3035 for (i = 0; i < HASH_BUCKETS; ++i) {
3036 struct obj_symbol *sym;
3037 for (sym = f->symtab[i]; sym; sym = sym->next)
3038 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003039 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003040 sym->secidx = SHN_ABS;
3041 sym->value = 0;
3042 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003043 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003044 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003045 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003046 ret = 0;
3047 }
3048 }
3049 }
3050
3051 return ret;
3052}
3053
Eric Andersen044228d2001-07-17 01:12:36 +00003054static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003055{
3056 struct common_entry {
3057 struct common_entry *next;
3058 struct obj_symbol *sym;
3059 } *common_head = NULL;
3060
3061 unsigned long i;
3062
3063 for (i = 0; i < HASH_BUCKETS; ++i) {
3064 struct obj_symbol *sym;
3065 for (sym = f->symtab[i]; sym; sym = sym->next)
3066 if (sym->secidx == SHN_COMMON) {
3067 /* Collect all COMMON symbols and sort them by size so as to
3068 minimize space wasted by alignment requirements. */
3069 {
3070 struct common_entry **p, *n;
3071 for (p = &common_head; *p; p = &(*p)->next)
3072 if (sym->size <= (*p)->sym->size)
3073 break;
3074
3075 n = alloca(sizeof(*n));
3076 n->next = *p;
3077 n->sym = sym;
3078 *p = n;
3079 }
3080 }
3081 }
3082
3083 for (i = 1; i < f->local_symtab_size; ++i) {
3084 struct obj_symbol *sym = f->local_symtab[i];
3085 if (sym && sym->secidx == SHN_COMMON) {
3086 struct common_entry **p, *n;
3087 for (p = &common_head; *p; p = &(*p)->next)
3088 if (sym == (*p)->sym)
3089 break;
3090 else if (sym->size < (*p)->sym->size) {
3091 n = alloca(sizeof(*n));
3092 n->next = *p;
3093 n->sym = sym;
3094 *p = n;
3095 break;
3096 }
3097 }
3098 }
3099
3100 if (common_head) {
3101 /* Find the bss section. */
3102 for (i = 0; i < f->header.e_shnum; ++i)
3103 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3104 break;
3105
3106 /* If for some reason there hadn't been one, create one. */
3107 if (i == f->header.e_shnum) {
3108 struct obj_section *sec;
3109
3110 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3111 f->sections[i] = sec = arch_new_section();
3112 f->header.e_shnum = i + 1;
3113
3114 memset(sec, 0, sizeof(*sec));
3115 sec->header.sh_type = SHT_PROGBITS;
3116 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3117 sec->name = ".bss";
3118 sec->idx = i;
3119 }
3120
3121 /* Allocate the COMMONS. */
3122 {
3123 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3124 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3125 struct common_entry *c;
3126
3127 for (c = common_head; c; c = c->next) {
3128 ElfW(Addr) align = c->sym->value;
3129
3130 if (align > max_align)
3131 max_align = align;
3132 if (bss_size & (align - 1))
3133 bss_size = (bss_size | (align - 1)) + 1;
3134
3135 c->sym->secidx = i;
3136 c->sym->value = bss_size;
3137
3138 bss_size += c->sym->size;
3139 }
3140
3141 f->sections[i]->header.sh_size = bss_size;
3142 f->sections[i]->header.sh_addralign = max_align;
3143 }
3144 }
3145
3146 /* For the sake of patch relocation and parameter initialization,
3147 allocate zeroed data for NOBITS sections now. Note that after
3148 this we cannot assume NOBITS are really empty. */
3149 for (i = 0; i < f->header.e_shnum; ++i) {
3150 struct obj_section *s = f->sections[i];
3151 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003152 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003153 s->contents = memset(xmalloc(s->header.sh_size),
3154 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003155 else
3156 s->contents = NULL;
3157
Eric Andersen9f16d612000-06-12 23:11:16 +00003158 s->header.sh_type = SHT_PROGBITS;
3159 }
3160 }
3161}
3162
Eric Andersen044228d2001-07-17 01:12:36 +00003163static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003164{
3165 unsigned long dot = 0;
3166 struct obj_section *sec;
3167
3168 /* Finalize the positions of the sections relative to one another. */
3169
3170 for (sec = f->load_order; sec; sec = sec->load_next) {
3171 ElfW(Addr) align;
3172
3173 align = sec->header.sh_addralign;
3174 if (align && (dot & (align - 1)))
3175 dot = (dot | (align - 1)) + 1;
3176
3177 sec->header.sh_addr = dot;
3178 dot += sec->header.sh_size;
3179 }
3180
3181 return dot;
3182}
3183
Eric Andersen044228d2001-07-17 01:12:36 +00003184static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003185{
3186 int i, n = f->header.e_shnum;
3187 int ret = 1;
3188
3189 /* Finalize the addresses of the sections. */
3190
3191 f->baseaddr = base;
3192 for (i = 0; i < n; ++i)
3193 f->sections[i]->header.sh_addr += base;
3194
3195 /* And iterate over all of the relocations. */
3196
3197 for (i = 0; i < n; ++i) {
3198 struct obj_section *relsec, *symsec, *targsec, *strsec;
3199 ElfW(RelM) * rel, *relend;
3200 ElfW(Sym) * symtab;
3201 const char *strtab;
3202
3203 relsec = f->sections[i];
3204 if (relsec->header.sh_type != SHT_RELM)
3205 continue;
3206
3207 symsec = f->sections[relsec->header.sh_link];
3208 targsec = f->sections[relsec->header.sh_info];
3209 strsec = f->sections[symsec->header.sh_link];
3210
3211 rel = (ElfW(RelM) *) relsec->contents;
3212 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3213 symtab = (ElfW(Sym) *) symsec->contents;
3214 strtab = (const char *) strsec->contents;
3215
3216 for (; rel < relend; ++rel) {
3217 ElfW(Addr) value = 0;
3218 struct obj_symbol *intsym = NULL;
3219 unsigned long symndx;
3220 ElfW(Sym) * extsym = 0;
3221 const char *errmsg;
3222
3223 /* Attempt to find a value to use for this relocation. */
3224
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003225 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003226 if (symndx) {
3227 /* Note we've already checked for undefined symbols. */
3228
3229 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003230 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003231 /* Local symbols we look up in the local table to be sure
3232 we get the one that is really intended. */
3233 intsym = f->local_symtab[symndx];
3234 } else {
3235 /* Others we look up in the hash table. */
3236 const char *name;
3237 if (extsym->st_name)
3238 name = strtab + extsym->st_name;
3239 else
3240 name = f->sections[extsym->st_shndx]->name;
3241 intsym = obj_find_symbol(f, name);
3242 }
3243
3244 value = obj_symbol_final_value(f, intsym);
3245 intsym->referenced = 1;
3246 }
3247#if SHT_RELM == SHT_RELA
3248#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3249 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3250 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003251 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003252#endif
3253 value += rel->r_addend;
3254#endif
3255
3256 /* Do it! */
3257 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003258 (f, targsec, symsec, intsym, rel, value)
3259 ) {
3260 case obj_reloc_ok:
3261 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003262
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003263 case obj_reloc_overflow:
3264 errmsg = "Relocation overflow";
3265 goto bad_reloc;
3266 case obj_reloc_dangerous:
3267 errmsg = "Dangerous relocation";
3268 goto bad_reloc;
3269 case obj_reloc_unhandled:
3270 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003271bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003272 if (extsym) {
3273 bb_error_msg("%s of type %ld for %s", errmsg,
3274 (long) ELF_R_TYPE(rel->r_info),
3275 strtab + extsym->st_name);
3276 } else {
3277 bb_error_msg("%s of type %ld", errmsg,
3278 (long) ELF_R_TYPE(rel->r_info));
3279 }
3280 ret = 0;
3281 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003282 }
3283 }
3284 }
3285
3286 /* Finally, take care of the patches. */
3287
3288 if (f->string_patches) {
3289 struct obj_string_patch *p;
3290 struct obj_section *strsec;
3291 ElfW(Addr) strsec_base;
3292 strsec = obj_find_section(f, ".kstrtab");
3293 strsec_base = strsec->header.sh_addr;
3294
3295 for (p = f->string_patches; p; p = p->next) {
3296 struct obj_section *targsec = f->sections[p->reloc_secidx];
3297 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3298 = strsec_base + p->string_offset;
3299 }
3300 }
3301
3302 if (f->symbol_patches) {
3303 struct obj_symbol_patch *p;
3304
3305 for (p = f->symbol_patches; p; p = p->next) {
3306 struct obj_section *targsec = f->sections[p->reloc_secidx];
3307 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3308 = obj_symbol_final_value(f, p->sym);
3309 }
3310 }
3311
3312 return ret;
3313}
3314
Eric Andersen044228d2001-07-17 01:12:36 +00003315static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003316{
3317 struct obj_section *sec;
3318 ElfW(Addr) base = f->baseaddr;
3319
3320 for (sec = f->load_order; sec; sec = sec->load_next) {
3321 char *secimg;
3322
Eric Andersen2bf658d2001-02-24 20:01:53 +00003323 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003324 continue;
3325
3326 secimg = image + (sec->header.sh_addr - base);
3327
3328 /* Note that we allocated data for NOBITS sections earlier. */
3329 memcpy(secimg, sec->contents, sec->header.sh_size);
3330 }
3331
3332 return 1;
3333}
3334
3335/*======================================================================*/
3336
Eric Andersen044228d2001-07-17 01:12:36 +00003337static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003338{
3339 struct obj_file *f;
3340 ElfW(Shdr) * section_headers;
3341 int shnum, i;
3342 char *shstrtab;
3343
3344 /* Read the file header. */
3345
3346 f = arch_new_file();
3347 memset(f, 0, sizeof(*f));
3348 f->symbol_cmp = strcmp;
3349 f->symbol_hash = obj_elf_hash;
3350 f->load_order_search_start = &f->load_order;
3351
3352 fseek(fp, 0, SEEK_SET);
3353 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003354 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003355 return NULL;
3356 }
3357
3358 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003359 || f->header.e_ident[EI_MAG1] != ELFMAG1
3360 || f->header.e_ident[EI_MAG2] != ELFMAG2
3361 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003362 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003363 return NULL;
3364 }
3365 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003366 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003367 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003368 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3369 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003370 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003371 return NULL;
3372 }
3373 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003374 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003375 return NULL;
3376 }
3377
3378 /* Read the section headers. */
3379
3380 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003381 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003382 (unsigned long) f->header.e_shentsize,
3383 (unsigned long) sizeof(ElfW(Shdr)));
3384 return NULL;
3385 }
3386
3387 shnum = f->header.e_shnum;
3388 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3389 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3390
3391 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3392 fseek(fp, f->header.e_shoff, SEEK_SET);
3393 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003394 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003395 return NULL;
3396 }
3397
3398 /* Read the section data. */
3399
3400 for (i = 0; i < shnum; ++i) {
3401 struct obj_section *sec;
3402
3403 f->sections[i] = sec = arch_new_section();
3404 memset(sec, 0, sizeof(*sec));
3405
3406 sec->header = section_headers[i];
3407 sec->idx = i;
3408
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003409 if(sec->header.sh_size) {
3410 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003411 case SHT_NULL:
3412 case SHT_NOTE:
3413 case SHT_NOBITS:
3414 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003415 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003416
3417 case SHT_PROGBITS:
3418#if LOADBITS
3419 if (!loadprogbits) {
3420 sec->contents = NULL;
3421 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003422 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003423#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003424 case SHT_SYMTAB:
3425 case SHT_STRTAB:
3426 case SHT_RELM:
3427 if (sec->header.sh_size > 0) {
3428 sec->contents = xmalloc(sec->header.sh_size);
3429 fseek(fp, sec->header.sh_offset, SEEK_SET);
3430 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3431 bb_perror_msg("error reading ELF section data");
3432 return NULL;
3433 }
3434 } else {
3435 sec->contents = NULL;
3436 }
3437 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003438
3439#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003440 case SHT_RELA:
3441 bb_error_msg("RELA relocations not supported on this architecture");
3442 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003443#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003444 case SHT_REL:
3445 bb_error_msg("REL relocations not supported on this architecture");
3446 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003447#endif
3448
Eric Andersen3b1a7442003-12-24 20:30:45 +00003449 default:
3450 if (sec->header.sh_type >= SHT_LOPROC) {
3451 /* Assume processor specific section types are debug
3452 info and can safely be ignored. If this is ever not
3453 the case (Hello MIPS?), don't put ifdefs here but
3454 create an arch_load_proc_section(). */
3455 break;
3456 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003457
Eric Andersen3b1a7442003-12-24 20:30:45 +00003458 bb_error_msg("can't handle sections of type %ld",
3459 (long) sec->header.sh_type);
3460 return NULL;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003461 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003462 }
3463 }
3464
3465 /* Do what sort of interpretation as needed by each section. */
3466
3467 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3468
3469 for (i = 0; i < shnum; ++i) {
3470 struct obj_section *sec = f->sections[i];
3471 sec->name = shstrtab + sec->header.sh_name;
3472 }
3473
3474 for (i = 0; i < shnum; ++i) {
3475 struct obj_section *sec = f->sections[i];
3476
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003477 /* .modinfo should be contents only but gcc has no attribute for that.
3478 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3479 */
3480 if (strcmp(sec->name, ".modinfo") == 0)
3481 sec->header.sh_flags &= ~SHF_ALLOC;
3482
Eric Andersen9f16d612000-06-12 23:11:16 +00003483 if (sec->header.sh_flags & SHF_ALLOC)
3484 obj_insert_section_load_order(f, sec);
3485
3486 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003487 case SHT_SYMTAB:
3488 {
3489 unsigned long nsym, j;
3490 char *strtab;
3491 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003492
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003493 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3494 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003495 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003496 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003497 return NULL;
3498 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003499
3500 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3501 strtab = f->sections[sec->header.sh_link]->contents;
3502 sym = (ElfW(Sym) *) sec->contents;
3503
3504 /* Allocate space for a table of local symbols. */
3505 j = f->local_symtab_size = sec->header.sh_info;
3506 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3507
3508 /* Insert all symbols into the hash table. */
3509 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3510 ElfW(Addr) val = sym->st_value;
3511 const char *name;
3512 if (sym->st_name)
3513 name = strtab + sym->st_name;
3514 else if (sym->st_shndx < shnum)
3515 name = f->sections[sym->st_shndx]->name;
3516 else
3517 continue;
3518#if defined(__SH5__)
3519 /*
3520 * For sh64 it is possible that the target of a branch
3521 * requires a mode switch (32 to 16 and back again).
3522 *
3523 * This is implied by the lsb being set in the target
3524 * address for SHmedia mode and clear for SHcompact.
3525 */
3526 val |= sym->st_other & 4;
3527#endif
3528
3529 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3530 val, sym->st_size);
3531 }
3532 }
3533 break;
3534
3535 case SHT_RELM:
3536 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3537 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3538 (unsigned long) sec->header.sh_entsize,
3539 (unsigned long) sizeof(ElfW(RelM)));
3540 return NULL;
3541 }
3542 break;
3543 /* XXX Relocation code from modutils-2.3.19 is not here.
3544 * Why? That's about 20 lines of code from obj/obj_load.c,
3545 * which gets done in a second pass through the sections.
3546 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003547 }
3548 }
3549
3550 return f;
3551}
3552
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003553#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003554/*
3555 * load the unloaded sections directly into the memory allocated by
3556 * kernel for the module
3557 */
3558
Eric Andersenac5dbd12001-08-22 05:26:08 +00003559static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003560{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003561 ElfW(Addr) base = f->baseaddr;
3562 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003563
Eric Andersen8ae319a2001-05-21 16:09:18 +00003564 for (sec = f->load_order; sec; sec = sec->load_next) {
3565
3566 /* section already loaded? */
3567 if (sec->contents != NULL)
3568 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003569
Eric Andersen8ae319a2001-05-21 16:09:18 +00003570 if (sec->header.sh_size == 0)
3571 continue;
3572
3573 sec->contents = imagebase + (sec->header.sh_addr - base);
3574 fseek(fp, sec->header.sh_offset, SEEK_SET);
3575 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003576 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003577 return 0;
3578 }
3579
3580 }
3581 return 1;
3582}
3583#endif
3584
Eric Andersen9f16d612000-06-12 23:11:16 +00003585static void hide_special_symbols(struct obj_file *f)
3586{
3587 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003588 SPFX "cleanup_module",
3589 SPFX "init_module",
3590 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003591 NULL
3592 };
3593
3594 struct obj_symbol *sym;
3595 const char *const *p;
3596
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003597 for (p = specials; *p; ++p) {
3598 sym = obj_find_symbol(f, *p);
3599 if (sym != NULL)
3600 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3601 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003602}
3603
Glenn L McGrath759515c2003-08-30 06:00:33 +00003604
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003605#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003606static int obj_gpl_license(struct obj_file *f, const char **license)
3607{
3608 struct obj_section *sec;
3609 /* This list must match *exactly* the list of allowable licenses in
3610 * linux/include/linux/module.h. Checking for leading "GPL" will not
3611 * work, somebody will use "GPL sucks, this is proprietary".
3612 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003613 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003614 "GPL",
3615 "GPL v2",
3616 "GPL and additional rights",
3617 "Dual BSD/GPL",
3618 "Dual MPL/GPL",
3619 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003620
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003621 sec = obj_find_section(f, ".modinfo");
3622 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003623 const char *value, *ptr, *endptr;
3624 ptr = sec->contents;
3625 endptr = ptr + sec->header.sh_size;
3626 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003627 value = strchr(ptr, '=');
3628 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003629 int i;
3630 if (license)
3631 *license = value+1;
3632 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3633 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003634 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003635 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003636 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003637 }
3638 if (strchr(ptr, '\0'))
3639 ptr = strchr(ptr, '\0') + 1;
3640 else
3641 ptr = endptr;
3642 }
3643 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003644 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003645}
3646
3647#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3648#define TAINT_PROPRIETORY_MODULE (1<<0)
3649#define TAINT_FORCED_MODULE (1<<1)
3650#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003651#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003652
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003653static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003654 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3655{
3656 char buf[80];
3657 int oldval;
3658 static int first = 1;
3659 if (fd < 0 && !kernel_has_tainted)
3660 return; /* New modutils on old kernel */
3661 printf("Warning: loading %s will taint the kernel: %s%s\n",
3662 m_name, text1, text2);
3663 if (first) {
3664 printf(" See %s for information about tainted modules\n", TAINT_URL);
3665 first = 0;
3666 }
3667 if (fd >= 0) {
3668 read(fd, buf, sizeof(buf)-1);
3669 buf[sizeof(buf)-1] = '\0';
3670 oldval = strtoul(buf, NULL, 10);
3671 sprintf(buf, "%d\n", oldval | taint);
3672 write(fd, buf, strlen(buf));
3673 }
3674}
3675
3676/* Check if loading this module will taint the kernel. */
3677static void check_tainted_module(struct obj_file *f, char *m_name)
3678{
3679 static const char tainted_file[] = TAINT_FILENAME;
3680 int fd, kernel_has_tainted;
3681 const char *ptr;
3682
3683 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003684 fd = open(tainted_file, O_RDWR);
3685 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003686 if (errno == ENOENT)
3687 kernel_has_tainted = 0;
3688 else if (errno == EACCES)
3689 kernel_has_tainted = 1;
3690 else {
3691 perror(tainted_file);
3692 kernel_has_tainted = 0;
3693 }
3694 }
3695
3696 switch (obj_gpl_license(f, &ptr)) {
3697 case 0:
3698 break;
3699 case 1:
3700 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3701 break;
3702 case 2:
3703 /* The module has a non-GPL license so we pretend that the
3704 * kernel always has a taint flag to get a warning even on
3705 * kernels without the proc flag.
3706 */
3707 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3708 break;
3709 default:
3710 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3711 break;
3712 }
3713
3714 if (flag_force_load)
3715 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3716
3717 if (fd >= 0)
3718 close(fd);
3719}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003720#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003721#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003722#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003723
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003724#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003725/* add module source, timestamp, kernel version and a symbol for the
3726 * start of some sections. this info is used by ksymoops to do better
3727 * debugging.
3728 */
3729static int
3730get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3731{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003732#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003733 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003734#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003735 strncpy(str, "???", sizeof(str));
3736 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003737#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003738}
3739
3740/* add module source, timestamp, kernel version and a symbol for the
3741 * start of some sections. this info is used by ksymoops to do better
3742 * debugging.
3743 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003744static void
Eric Andersen889dd202003-01-23 04:48:34 +00003745add_ksymoops_symbols(struct obj_file *f, const char *filename,
3746 const char *m_name)
3747{
3748 static const char symprefix[] = "__insmod_";
3749 struct obj_section *sec;
3750 struct obj_symbol *sym;
3751 char *name, *absolute_filename;
3752 char str[STRVERSIONLEN], real[PATH_MAX];
3753 int i, l, lm_name, lfilename, use_ksymtab, version;
3754 struct stat statbuf;
3755
3756 static const char *section_names[] = {
3757 ".text",
3758 ".rodata",
3759 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003760 ".bss",
3761 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003762 };
3763
3764 if (realpath(filename, real)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +00003765 absolute_filename = xstrdup(real);
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003766 } else {
3767 bb_perror_msg("cannot get realpath for %s", filename);
Rob Landleyd921b2e2006-08-03 15:41:12 +00003768 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003769 }
3770
3771 lm_name = strlen(m_name);
3772 lfilename = strlen(absolute_filename);
3773
3774 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3775 * are not to be exported. otherwise leave ksymtab alone for now, the
3776 * "export all symbols" compatibility code will export these symbols later.
3777 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003778 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003779
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003780 sec = obj_find_section(f, ".this");
3781 if (sec) {
Eric Andersen889dd202003-01-23 04:48:34 +00003782 /* tag the module header with the object name, last modified
3783 * timestamp and module version. worst case for module version
3784 * is 0xffffff, decimal 16777215. putting all three fields in
3785 * one symbol is less readable but saves kernel space.
3786 */
3787 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003788 lm_name+ /* module name */
3789 2+ /* "_O" */
3790 lfilename+ /* object filename */
3791 2+ /* "_M" */
3792 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3793 2+ /* "_V" */
3794 8+ /* version in dec */
3795 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003796 name = xmalloc(l);
3797 if (stat(absolute_filename, &statbuf) != 0)
3798 statbuf.st_mtime = 0;
3799 version = get_module_version(f, str); /* -1 if not found */
3800 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003801 symprefix, m_name, absolute_filename,
3802 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3803 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003804 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003805 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003806 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003807 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003809 }
3810 free(absolute_filename);
3811#ifdef _NOT_SUPPORTED_
3812 /* record where the persistent data is going, same address as previous symbol */
3813
3814 if (f->persist) {
3815 l = sizeof(symprefix)+ /* "__insmod_" */
3816 lm_name+ /* module name */
3817 2+ /* "_P" */
3818 strlen(f->persist)+ /* data store */
3819 1; /* nul */
3820 name = xmalloc(l);
3821 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003822 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003823 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003824 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003825 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003826 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003827 }
3828#endif /* _NOT_SUPPORTED_ */
3829 /* tag the desired sections if size is non-zero */
3830
3831 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
Denis Vlasenko98ee06d2006-12-31 18:57:37 +00003832 sec = obj_find_section(f, section_names[i]);
3833 if (sec && sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003834 l = sizeof(symprefix)+ /* "__insmod_" */
3835 lm_name+ /* module name */
3836 2+ /* "_S" */
3837 strlen(sec->name)+ /* section name */
3838 2+ /* "_L" */
3839 8+ /* length in dec */
3840 1; /* nul */
3841 name = xmalloc(l);
3842 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003843 symprefix, m_name, sec->name,
3844 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003845 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003846 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003847 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003848 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003849 }
3850 }
3851}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003852#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003853
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003854#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003855static void print_load_map(struct obj_file *f)
3856{
Eric Andersenbe65c352003-01-23 04:57:35 +00003857 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003858#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3859 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003860 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003861 struct obj_symbol *sym;
3862#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003863 /* Report on the section layout. */
3864
3865 printf("Sections: Size %-*s Align\n",
3866 (int) (2 * sizeof(void *)), "Address");
3867
3868 for (sec = f->load_order; sec; sec = sec->load_next) {
3869 int a;
3870 unsigned long tmp;
3871
3872 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3873 tmp >>= 1;
3874 if (a == -1)
3875 a = 0;
3876
3877 printf("%-15s %08lx %0*lx 2**%d\n",
3878 sec->name,
3879 (long)sec->header.sh_size,
3880 (int) (2 * sizeof(void *)),
3881 (long)sec->header.sh_addr,
3882 a);
3883 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003884#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003885 /* Quick reference which section indicies are loaded. */
3886
3887 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3888 while (--i >= 0)
3889 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3890
3891 /* Collect the symbols we'll be listing. */
3892
3893 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3894 for (sym = f->symtab[i]; sym; sym = sym->next)
3895 if (sym->secidx <= SHN_HIRESERVE
3896 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3897 ++nsyms;
3898
3899 all = alloca(nsyms * sizeof(struct obj_symbol *));
3900
3901 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3902 for (sym = f->symtab[i]; sym; sym = sym->next)
3903 if (sym->secidx <= SHN_HIRESERVE
3904 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3905 *p++ = sym;
3906
3907 /* And list them. */
3908 printf("\nSymbols:\n");
3909 for (p = all; p < all + nsyms; ++p) {
3910 char type = '?';
3911 unsigned long value;
3912
3913 sym = *p;
3914 if (sym->secidx == SHN_ABS) {
3915 type = 'A';
3916 value = sym->value;
3917 } else if (sym->secidx == SHN_UNDEF) {
3918 type = 'U';
3919 value = 0;
3920 } else {
3921 sec = f->sections[sym->secidx];
3922
3923 if (sec->header.sh_type == SHT_NOBITS)
3924 type = 'B';
3925 else if (sec->header.sh_flags & SHF_ALLOC) {
3926 if (sec->header.sh_flags & SHF_EXECINSTR)
3927 type = 'T';
3928 else if (sec->header.sh_flags & SHF_WRITE)
3929 type = 'D';
3930 else
3931 type = 'R';
3932 }
3933 value = sym->value + sec->header.sh_addr;
3934 }
3935
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003936 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003937 type = tolower(type);
3938
3939 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3940 type, sym->name);
3941 }
3942#endif
3943}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003944#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003945void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003946#endif
3947
Denis Vlasenko06af2162007-02-03 17:28:39 +00003948int insmod_main( int argc, char **argv);
Rob Landleydfba7412006-03-06 20:47:33 +00003949int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003950{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003951 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003952 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003953 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003954 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003955 unsigned long m_size;
3956 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003957 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003958 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003959 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003960 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003961 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003962#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003963 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003964 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003965 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003966#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003967#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00003968 FILE *fp = 0;
3969#else
3970 FILE *fp;
3971#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003972 int k_version = 0;
3973 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003974
Erik Andersene49d5ec2000-02-08 19:58:47 +00003975 /* Parse any options */
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003976 getopt32(argc, argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003977 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003978 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003979 free(m_name);
3980 m_name = xstrdup(opt_o);
3981 }
Eric Andersen03d80912003-12-19 21:04:19 +00003982
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003983 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003984 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003985 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003986
Erik Andersene49d5ec2000-02-08 19:58:47 +00003987 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003988 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003989 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003990 len = strlen(tmp);
3991
Eric Andersen03d80912003-12-19 21:04:19 +00003992 if (uname(&myuname) == 0) {
3993 if (myuname.release[0] == '2') {
3994 k_version = myuname.release[2] - '0';
3995 }
3996 }
3997
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003998#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003999 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
4000 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
4001 ) {
4002 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00004003 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004004 } else
Eric Andersen03d80912003-12-19 21:04:19 +00004005#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004006 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004007 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004008 tmp[len] = '\0';
4009 }
Eric Andersen2d342152002-06-18 05:16:25 +00004010
Eric Andersen03d80912003-12-19 21:04:19 +00004011
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004012#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004013 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00004014 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004015 else
Eric Andersen03d80912003-12-19 21:04:19 +00004016#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00004017 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004018
Eric Andersen61f83052002-06-22 17:15:42 +00004019 if (!m_name) {
4020 m_name = tmp;
4021 } else {
4022 free(tmp1);
4023 tmp1 = 0; /* flag for free(m_name) before exit() */
4024 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004025
Eric Andersen14d35432001-05-14 17:07:32 +00004026 /* Get a filedesc for the module. Check we we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004027 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
4028 || (fp = fopen(arg1, "r")) == NULL
4029 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00004030 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4031 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004032 if (k_version) { /* uname succeedd */
4033 char *module_dir;
4034 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004035 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004036
Eric Andersen03d80912003-12-19 21:04:19 +00004037 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004038 /* Jump through hoops in case /lib/modules/`uname -r`
4039 * is a symlink. We do not want recursive_action to
4040 * follow symlinks, but we do want to follow the
4041 * /lib/modules/`uname -r` dir, So resolve it ourselves
4042 * if it is a link... */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004043 if (realpath(tmdn, real_module_dir) == NULL)
Eric Andersen03d80912003-12-19 21:04:19 +00004044 module_dir = tmdn;
4045 else
4046 module_dir = real_module_dir;
4047 recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004048 check_module_name_match, 0, m_fullName, 0);
Eric Andersen03d80912003-12-19 21:04:19 +00004049 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004050 }
4051
4052 /* Check if we have found anything yet */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004053 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004054 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004055
Eric Andersen03d80912003-12-19 21:04:19 +00004056 free(m_filename);
4057 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004058 if (realpath (_PATH_MODULES, module_dir) == NULL)
4059 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004060 /* No module found under /lib/modules/`uname -r`, this
4061 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004062 if (!recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004063 check_module_name_match, 0, m_fullName, 0)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004064 ) {
Eric Andersen61f83052002-06-22 17:15:42 +00004065 if (m_filename == 0
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004066 || ((fp = fopen(m_filename, "r")) == NULL)
4067 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004068 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004069 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004070 }
4071 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004072 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004073 }
Eric Andersen03d80912003-12-19 21:04:19 +00004074 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004075 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004076
Rob Landley999af202005-12-11 20:14:12 +00004077 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004078 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004079
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004080#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004081 if (k_version > 4) {
4082 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004083 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004084 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004085 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004086#endif
4087
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004088 f = obj_load(fp, LOADBITS);
4089 if (f == NULL)
4090 bb_perror_msg_and_die("cannot load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004091
Eric Andersen9f16d612000-06-12 23:11:16 +00004092 if (get_modinfo_value(f, "kernel_version") == NULL)
4093 m_has_modinfo = 0;
4094 else
4095 m_has_modinfo = 1;
4096
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004097#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004098 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004099 if (!flag_quiet) {
4100 if (uname(&uts_info) < 0)
4101 uts_info.release[0] = '\0';
4102 if (m_has_modinfo) {
4103 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004104 if (m_version == -1) {
Denis Vlasenkoa9595882006-09-29 21:30:43 +00004105 bb_error_msg("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004106 "compiled for");
4107 goto out;
4108 }
4109 }
4110
4111 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4112 if (flag_force_load) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004113 bb_error_msg("warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004114 "\t%s was compiled for kernel version %s\n"
4115 "\twhile this kernel is version %s",
4116 m_filename, m_strversion, uts_info.release);
4117 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004118 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004119 "\t%s was compiled for kernel version %s\n"
4120 "\twhile this kernel is version %s.",
4121 m_filename, m_strversion, uts_info.release);
4122 goto out;
4123 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004124 }
4125 }
4126 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004127#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004128
Eric Andersencb3b9b12004-06-22 11:50:52 +00004129 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004130 if (!new_get_kernel_symbols())
4131 goto out;
4132 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004133 } else {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004134 bb_error_msg("not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004135 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004136 }
4137
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004138#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004139 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004140 if (m_has_modinfo)
4141 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004142
4143 if (m_crcs != k_crcs)
4144 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004145#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004146
Erik Andersene49d5ec2000-02-08 19:58:47 +00004147 /* Let the module know about the kernel symbols. */
4148 add_kernel_symbols(f);
4149
Eric Andersen9f16d612000-06-12 23:11:16 +00004150 /* Allocate common symbols, symbol tables, and string tables. */
4151
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004152 if (!new_create_this_module(f, m_name)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004153 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004154 }
4155
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 if (!obj_check_undefineds(f)) {
4157 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004158 }
4159 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004160 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004161
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004162 /* done with the module name, on to the optional var=value arguments */
4163 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004164 if (optind < argc) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004165 if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004166 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004167 }
4168 }
4169
Eric Andersen9f16d612000-06-12 23:11:16 +00004170 arch_create_got(f);
4171 hide_special_symbols(f);
4172
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004173#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004174 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004175#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004176
Eric Andersencb3b9b12004-06-22 11:50:52 +00004177 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004178
Erik Andersene49d5ec2000-02-08 19:58:47 +00004179 /* Find current size of the module */
4180 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004181
4182
Erik Andersene49d5ec2000-02-08 19:58:47 +00004183 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004184 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004185 case EEXIST:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004186 bb_error_msg("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004187 goto out;
4188 case ENOMEM:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004189 bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004190 m_size);
4191 goto out;
4192 default:
4193 bb_perror_msg("create_module: %s", m_name);
4194 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004195 }
Erik Andersend387d011999-12-21 02:55:11 +00004196
Eric Andersen8ae319a2001-05-21 16:09:18 +00004197#if !LOADBITS
4198 /*
4199 * the PROGBITS section was not loaded by the obj_load
4200 * now we can load them directly into the kernel memory
4201 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004202 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004203 delete_module(m_name);
4204 goto out;
4205 }
Eric Andersen03d80912003-12-19 21:04:19 +00004206#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004207
Eric Andersen9f16d612000-06-12 23:11:16 +00004208 if (!obj_relocate(f, m_addr)) {
4209 delete_module(m_name);
4210 goto out;
4211 }
Erik Andersend387d011999-12-21 02:55:11 +00004212
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004213 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004214 delete_module(m_name);
4215 goto out;
4216 }
4217
Eric Andersenbe65c352003-01-23 04:57:35 +00004218 if(flag_print_load_map)
4219 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004220
Matt Kraai3e856ce2000-12-01 02:55:13 +00004221 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004222
4223out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004224#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00004225 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004226 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004227 free(tmp1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004228 if(!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004229 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004230 free(m_filename);
4231#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004232 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004233}
Eric Andersene7047882003-12-11 01:42:13 +00004234
4235
4236#endif
4237
4238
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004239#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004240
4241#include <sys/mman.h>
4242#include <asm/unistd.h>
4243#include <sys/syscall.h>
4244
4245/* We use error numbers in a loose translation... */
4246static const char *moderror(int err)
4247{
4248 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004249 case ENOEXEC:
4250 return "Invalid module format";
4251 case ENOENT:
4252 return "Unknown symbol in module";
4253 case ESRCH:
4254 return "Module has wrong symbol version";
4255 case EINVAL:
4256 return "Invalid parameters";
4257 default:
4258 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004259 }
4260}
4261
Denis Vlasenko06af2162007-02-03 17:28:39 +00004262int insmod_ng_main(int argc, char **argv);
Denis Vlasenko92297942006-11-21 11:58:14 +00004263int insmod_ng_main(int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004264{
Denis Vlasenko92297942006-11-21 11:58:14 +00004265 long ret;
4266 size_t len;
Eric Andersene7047882003-12-11 01:42:13 +00004267 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004268 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004269
Denis Vlasenko92297942006-11-21 11:58:14 +00004270 filename = *++argv;
4271 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004272 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004273
4274 /* Rest is options */
Denis Vlasenko92297942006-11-21 11:58:14 +00004275 options = xstrdup("");
4276 while (*++argv) {
4277 int optlen = strlen(options);
4278 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004279 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenko92297942006-11-21 11:58:14 +00004280 sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004281 }
4282
Denis Vlasenko92297942006-11-21 11:58:14 +00004283#if 0
4284 /* Any special reason why mmap? It isn't performace critical... */
4285 int fd;
4286 struct stat st;
4287 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004288 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004289 fstat(fd, &st);
4290 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004291 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004292 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004293 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004294 }
4295
Denis Vlasenko92297942006-11-21 11:58:14 +00004296 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4297 if (map == NULL) {
4298 map = xmalloc(len);
4299 xread(fd, map, len);
4300 }
4301#else
4302 len = MAXINT(ssize_t);
4303 map = xmalloc_open_read_close(filename, &len);
4304#endif
4305
Eric Andersene7047882003-12-11 01:42:13 +00004306 ret = syscall(__NR_init_module, map, len, options);
4307 if (ret != 0) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004308 bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004309 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004310 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004311
Eric Andersene7047882003-12-11 01:42:13 +00004312 return 0;
4313}
4314
4315#endif