blob: 7ed4cdb30270a50a83c882aa0f2fcf4b5f2ca430 [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.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000043 * Did some cleanup and added CONFIG_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"
Erik Andersen02104321999-12-17 18:57:34 +000062#include <stdlib.h>
63#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000065#include <errno.h>
66#include <unistd.h>
67#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000068#include <ctype.h>
69#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000070#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000071#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000072#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000073#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000074
Eric Andersene7047882003-12-11 01:42:13 +000075#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
Eric Andersene7047882003-12-11 01:42:13 +000076 !defined(CONFIG_FEATURE_2_6_MODULES)
77#define CONFIG_FEATURE_2_4_MODULES
78#endif
79
Eric Andersencb3b9b12004-06-22 11:50:52 +000080#if !defined(CONFIG_FEATURE_2_4_MODULES)
Eric Andersene7047882003-12-11 01:42:13 +000081#define insmod_ng_main insmod_main
82#endif
83
Eric Andersene7047882003-12-11 01:42:13 +000084#if defined(CONFIG_FEATURE_2_6_MODULES)
85extern int insmod_ng_main( int argc, char **argv);
86#endif
87
Eric Andersencb3b9b12004-06-22 11:50:52 +000088
89#if defined(CONFIG_FEATURE_2_4_MODULES)
90
Eric Andersen64c8b172001-04-05 07:33:10 +000091
Eric Andersenbdfd0d72001-10-24 05:00:29 +000092#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000093#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000094#else
95#define LOADBITS 1
96#endif
97
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098
Mike Frysinger63654c12004-12-26 09:13:32 +000099/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000100#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +0000101#define MATCH_MACHINE(x) (x == EM_ALPHA)
102#define SHT_RELM SHT_RELA
103#define Elf64_RelM Elf64_Rela
104#define ELFCLASSM ELFCLASS64
105#endif
106
Eric Andersen45a05132004-09-02 23:03:25 +0000107/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000108#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +0000109#define MATCH_MACHINE(x) (x == EM_ARM)
110#define SHT_RELM SHT_REL
111#define Elf32_RelM Elf32_Rel
112#define ELFCLASSM ELFCLASS32
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000113#define CONFIG_USE_PLT_ENTRIES
114#define CONFIG_PLT_ENTRY_SIZE 8
115#define CONFIG_USE_GOT_ENTRIES
116#define CONFIG_GOT_ENTRY_SIZE 8
117#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000118#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000119
Mike Frysingerb306cb72006-06-06 06:15:52 +0000120/* blackfin */
121#if defined(BFIN)
122#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
123#define SHT_RELM SHT_RELA
124#define Elf32_RelM Elf32_Rela
125#define ELFCLASSM ELFCLASS32
126#endif
127
Eric Andersen45a05132004-09-02 23:03:25 +0000128/* CRIS */
129#if defined(__cris__)
130#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000131#define SHT_RELM SHT_RELA
132#define Elf32_RelM Elf32_Rela
133#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000134#ifndef EM_CRIS
135#define EM_CRIS 76
136#define R_CRIS_NONE 0
137#define R_CRIS_32 3
138#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000139#endif
140
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000141/* H8/300 */
142#if defined(__H8300H__) || defined(__H8300S__)
143#define MATCH_MACHINE(x) (x == EM_H8_300)
144#define SHT_RELM SHT_RELA
145#define Elf32_RelM Elf32_Rela
146#define ELFCLASSM ELFCLASS32
147#define CONFIG_USE_SINGLE
148#define SYMBOL_PREFIX "_"
149#endif
150
Mike Frysinger63654c12004-12-26 09:13:32 +0000151/* PA-RISC / HP-PA */
152#if defined(__hppa__)
153#define MATCH_MACHINE(x) (x == EM_PARISC)
154#define SHT_RELM SHT_RELA
155#if defined(__LP64__)
156#define Elf64_RelM Elf64_Rela
157#define ELFCLASSM ELFCLASS64
158#else
159#define Elf32_RelM Elf32_Rela
160#define ELFCLASSM ELFCLASS32
161#endif
162#endif
163
Eric Andersen45a05132004-09-02 23:03:25 +0000164/* x86 */
165#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000166#ifndef EM_486
167#define MATCH_MACHINE(x) (x == EM_386)
168#else
169#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
170#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000171#define SHT_RELM SHT_REL
172#define Elf32_RelM Elf32_Rel
173#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000174#define CONFIG_USE_GOT_ENTRIES
175#define CONFIG_GOT_ENTRY_SIZE 4
176#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000177#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000178
Eric Andersen45a05132004-09-02 23:03:25 +0000179/* IA64, aka Itanium */
180#if defined(__ia64__)
181#define MATCH_MACHINE(x) (x == EM_IA_64)
182#define SHT_RELM SHT_RELA
183#define Elf64_RelM Elf64_Rela
184#define ELFCLASSM ELFCLASS64
185#endif
186
187/* m68k */
188#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000189#define MATCH_MACHINE(x) (x == EM_68K)
190#define SHT_RELM SHT_RELA
191#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000192#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000193#define CONFIG_USE_GOT_ENTRIES
194#define CONFIG_GOT_ENTRY_SIZE 4
195#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000196#endif
197
Mike Frysingerb306cb72006-06-06 06:15:52 +0000198/* Microblaze */
199#if defined(__microblaze__)
200#define CONFIG_USE_SINGLE
201#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
202#define SHT_RELM SHT_RELA
203#define Elf32_RelM Elf32_Rela
204#define ELFCLASSM ELFCLASS32
205#endif
206
Eric Andersen45a05132004-09-02 23:03:25 +0000207/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000208#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000209#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
210#define SHT_RELM SHT_REL
211#define Elf32_RelM Elf32_Rel
212#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000213/* Account for ELF spec changes. */
214#ifndef EM_MIPS_RS3_LE
215#ifdef EM_MIPS_RS4_BE
216#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
217#else
218#define EM_MIPS_RS3_LE 10
219#endif
220#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000221#define ARCHDATAM "__dbe_table"
222#endif
223
Mike Frysingerf982d862006-01-04 00:11:26 +0000224/* Nios II */
225#if defined(__nios2__)
226#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
227#define SHT_RELM SHT_RELA
228#define Elf32_RelM Elf32_Rela
229#define ELFCLASSM ELFCLASS32
230#endif
231
Eric Andersen45a05132004-09-02 23:03:25 +0000232/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000233#if defined(__powerpc64__)
234#define MATCH_MACHINE(x) (x == EM_PPC64)
235#define SHT_RELM SHT_RELA
236#define Elf64_RelM Elf64_Rela
237#define ELFCLASSM ELFCLASS64
238#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000239#define MATCH_MACHINE(x) (x == EM_PPC)
240#define SHT_RELM SHT_RELA
241#define Elf32_RelM Elf32_Rela
242#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000243#define CONFIG_USE_PLT_ENTRIES
244#define CONFIG_PLT_ENTRY_SIZE 16
245#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000246#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000247#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000248#define ARCHDATAM "__ftr_fixup"
249#endif
250
Eric Andersen45a05132004-09-02 23:03:25 +0000251/* S390 */
252#if defined(__s390__)
253#define MATCH_MACHINE(x) (x == EM_S390)
254#define SHT_RELM SHT_RELA
255#define Elf32_RelM Elf32_Rela
256#define ELFCLASSM ELFCLASS32
257#define CONFIG_USE_PLT_ENTRIES
258#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000259#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000260#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000261#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000262#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000263
Eric Andersen45a05132004-09-02 23:03:25 +0000264/* SuperH */
265#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000266#define MATCH_MACHINE(x) (x == EM_SH)
267#define SHT_RELM SHT_RELA
268#define Elf32_RelM Elf32_Rela
269#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000270#define CONFIG_USE_GOT_ENTRIES
271#define CONFIG_GOT_ENTRY_SIZE 4
272#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000273/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000274/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000275#if defined(__sh__) && BB_BIG_ENDIAN
276# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000277#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000278/* it may or may not work on the SH1/SH2... Error on those also */
279#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000280#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000281#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000282#endif
283
Eric Andersen45a05132004-09-02 23:03:25 +0000284/* Sparc */
285#if defined(__sparc__)
286#define MATCH_MACHINE(x) (x == EM_SPARC)
287#define SHT_RELM SHT_RELA
288#define Elf32_RelM Elf32_Rela
289#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000290#endif
291
Eric Andersen45a05132004-09-02 23:03:25 +0000292/* v850e */
293#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000294#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
295#define SHT_RELM SHT_RELA
296#define Elf32_RelM Elf32_Rela
297#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000298#define CONFIG_USE_PLT_ENTRIES
299#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000300#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000301#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000302#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000303#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000304#define SYMBOL_PREFIX "_"
305#endif
306
Eric Andersen45a05132004-09-02 23:03:25 +0000307/* X86_64 */
308#if defined(__x86_64__)
309#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000310#define SHT_RELM SHT_RELA
Mike Frysinger91fbdac2005-10-02 06:44:39 +0000311#define CONFIG_USE_GOT_ENTRIES
312#define CONFIG_GOT_ENTRY_SIZE 8
313#define CONFIG_USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000314#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000315#define ELFCLASSM ELFCLASS64
316#endif
317
Eric Andersencffd5022002-05-24 06:50:15 +0000318#ifndef SHT_RELM
319#error Sorry, but insmod.c does not yet support this architecture...
320#endif
321
322
Eric Andersen9f16d612000-06-12 23:11:16 +0000323//----------------------------------------------------------------------------
324//--------modutils module.h, lines 45-242
325//----------------------------------------------------------------------------
326
327/* Definitions for the Linux module syscall interface.
328 Copyright 1996, 1997 Linux International.
329
330 Contributed by Richard Henderson <rth@tamu.edu>
331
332 This file is part of the Linux modutils.
333
334 This program is free software; you can redistribute it and/or modify it
335 under the terms of the GNU General Public License as published by the
336 Free Software Foundation; either version 2 of the License, or (at your
337 option) any later version.
338
339 This program is distributed in the hope that it will be useful, but
340 WITHOUT ANY WARRANTY; without even the implied warranty of
341 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
342 General Public License for more details.
343
344 You should have received a copy of the GNU General Public License
345 along with this program; if not, write to the Free Software Foundation,
346 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
347
348
349#ifndef MODUTILS_MODULE_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000350/* Why? static const int MODUTILS_MODULE_H = 1;*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000351
Mike Frysinger63654c12004-12-26 09:13:32 +0000352#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000353
354/*======================================================================*/
355/* For sizeof() which are related to the module platform and not to the
356 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
357
358#define tgt_sizeof_char sizeof(char)
359#define tgt_sizeof_short sizeof(short)
360#define tgt_sizeof_int sizeof(int)
361#define tgt_sizeof_long sizeof(long)
362#define tgt_sizeof_char_p sizeof(char *)
363#define tgt_sizeof_void_p sizeof(void *)
364#define tgt_long long
365
366#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
367#undef tgt_sizeof_long
368#undef tgt_sizeof_char_p
369#undef tgt_sizeof_void_p
370#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000371enum {
372 tgt_sizeof_long = 8,
373 tgt_sizeof_char_p = 8,
374 tgt_sizeof_void_p = 8
375};
Eric Andersen9f16d612000-06-12 23:11:16 +0000376#define tgt_long long long
377#endif
378
379/*======================================================================*/
380/* The structures used in Linux 2.1. */
381
382/* Note: new_module_symbol does not use tgt_long intentionally */
383struct new_module_symbol
384{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000385 unsigned long value;
386 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000387};
388
389struct new_module_persist;
390
391struct new_module_ref
392{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000393 unsigned tgt_long dep; /* kernel addresses */
394 unsigned tgt_long ref;
395 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000396};
397
398struct new_module
399{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000400 unsigned tgt_long size_of_struct; /* == sizeof(module) */
401 unsigned tgt_long next;
402 unsigned tgt_long name;
403 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000404
Eric Andersen3b1a7442003-12-24 20:30:45 +0000405 tgt_long usecount;
406 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000407
Eric Andersen3b1a7442003-12-24 20:30:45 +0000408 unsigned nsyms;
409 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000410
Eric Andersen3b1a7442003-12-24 20:30:45 +0000411 unsigned tgt_long syms;
412 unsigned tgt_long deps;
413 unsigned tgt_long refs;
414 unsigned tgt_long init;
415 unsigned tgt_long cleanup;
416 unsigned tgt_long ex_table_start;
417 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000418#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000419 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000420#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000421 /* Everything after here is extension. */
422 unsigned tgt_long persist_start;
423 unsigned tgt_long persist_end;
424 unsigned tgt_long can_unload;
425 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000426 const char *kallsyms_start; /* All symbols for kernel debugging */
427 const char *kallsyms_end;
428 const char *archdata_start; /* arch specific data for module */
429 const char *archdata_end;
430 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000431};
432
Eric Andersencffd5022002-05-24 06:50:15 +0000433#ifdef ARCHDATAM
434#define ARCHDATA_SEC_NAME ARCHDATAM
435#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000436#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000437#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000438#define KALLSYMS_SEC_NAME "__kallsyms"
439
440
Eric Andersen9f16d612000-06-12 23:11:16 +0000441struct new_module_info
442{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000443 unsigned long addr;
444 unsigned long size;
445 unsigned long flags;
446 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000447};
448
449/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000450enum {
451 NEW_MOD_RUNNING = 1,
452 NEW_MOD_DELETED = 2,
453 NEW_MOD_AUTOCLEAN = 4,
454 NEW_MOD_VISITED = 8,
455 NEW_MOD_USED_ONCE = 16
456};
Eric Andersen9f16d612000-06-12 23:11:16 +0000457
Eric Andersencb3b9b12004-06-22 11:50:52 +0000458int init_module(const char *name, const struct new_module *);
459int query_module(const char *name, int which, void *buf,
460 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000461
462/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000463enum {
464 QM_MODULES = 1,
465 QM_DEPS = 2,
466 QM_REFS = 3,
467 QM_SYMBOLS = 4,
468 QM_INFO = 5
469};
Eric Andersen9f16d612000-06-12 23:11:16 +0000470
471/*======================================================================*/
472/* The system calls unchanged between 2.0 and 2.1. */
473
474unsigned long create_module(const char *, size_t);
475int delete_module(const char *);
476
477
478#endif /* module.h */
479
480//----------------------------------------------------------------------------
481//--------end of modutils module.h
482//----------------------------------------------------------------------------
483
484
485
486//----------------------------------------------------------------------------
487//--------modutils obj.h, lines 253-462
488//----------------------------------------------------------------------------
489
490/* Elf object file loading and relocation routines.
491 Copyright 1996, 1997 Linux International.
492
493 Contributed by Richard Henderson <rth@tamu.edu>
494
495 This file is part of the Linux modutils.
496
497 This program is free software; you can redistribute it and/or modify it
498 under the terms of the GNU General Public License as published by the
499 Free Software Foundation; either version 2 of the License, or (at your
500 option) any later version.
501
502 This program is distributed in the hope that it will be useful, but
503 WITHOUT ANY WARRANTY; without even the implied warranty of
504 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
505 General Public License for more details.
506
507 You should have received a copy of the GNU General Public License
508 along with this program; if not, write to the Free Software Foundation,
509 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
510
511
512#ifndef MODUTILS_OBJ_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000513/* Why? static const int MODUTILS_OBJ_H = 1; */
Eric Andersen9f16d612000-06-12 23:11:16 +0000514
Mike Frysinger63654c12004-12-26 09:13:32 +0000515#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000516
517/* The relocatable object is manipulated using elfin types. */
518
519#include <stdio.h>
520#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000521#include <endian.h>
522
Eric Andersen9f16d612000-06-12 23:11:16 +0000523#ifndef ElfW
524# if ELFCLASSM == ELFCLASS32
525# define ElfW(x) Elf32_ ## x
526# define ELFW(x) ELF32_ ## x
527# else
528# define ElfW(x) Elf64_ ## x
529# define ELFW(x) ELF64_ ## x
530# endif
531#endif
532
Eric Andersen85e5e722003-07-22 08:56:55 +0000533/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000534#ifndef ELF32_ST_INFO
535# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
536#endif
537
538#ifndef ELF64_ST_INFO
539# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
540#endif
541
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000542#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
543#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
544#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
545#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
546#define ELF_R_SYM(val) ELFW(R_SYM)(val)
547
Eric Andersen9f16d612000-06-12 23:11:16 +0000548struct obj_string_patch;
549struct obj_symbol_patch;
550
551struct obj_section
552{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000553 ElfW(Shdr) header;
554 const char *name;
555 char *contents;
556 struct obj_section *load_next;
557 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000558};
559
560struct obj_symbol
561{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000562 struct obj_symbol *next; /* hash table link */
563 const char *name;
564 unsigned long value;
565 unsigned long size;
566 int secidx; /* the defining section index/module */
567 int info;
568 int ksymidx; /* for export to the kernel symtab */
569 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000570};
571
572/* Hardcode the hash table size. We shouldn't be needing so many
573 symbols that we begin to degrade performance, and we get a big win
574 by giving the compiler a constant divisor. */
575
576#define HASH_BUCKETS 521
577
578struct obj_file
579{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000580 ElfW(Ehdr) header;
581 ElfW(Addr) baseaddr;
582 struct obj_section **sections;
583 struct obj_section *load_order;
584 struct obj_section **load_order_search_start;
585 struct obj_string_patch *string_patches;
586 struct obj_symbol_patch *symbol_patches;
587 int (*symbol_cmp)(const char *, const char *);
588 unsigned long (*symbol_hash)(const char *);
589 unsigned long local_symtab_size;
590 struct obj_symbol **local_symtab;
591 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000592};
593
594enum obj_reloc
595{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000596 obj_reloc_ok,
597 obj_reloc_overflow,
598 obj_reloc_dangerous,
599 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000600};
601
602struct obj_string_patch
603{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000604 struct obj_string_patch *next;
605 int reloc_secidx;
606 ElfW(Addr) reloc_offset;
607 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000608};
609
610struct obj_symbol_patch
611{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000612 struct obj_symbol_patch *next;
613 int reloc_secidx;
614 ElfW(Addr) reloc_offset;
615 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000616};
617
618
619/* Generic object manipulation routines. */
620
Eric Andersen044228d2001-07-17 01:12:36 +0000621static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000624
Eric Andersen044228d2001-07-17 01:12:36 +0000625static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000626 const char *name);
627
Eric Andersen044228d2001-07-17 01:12:36 +0000628static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000629 struct obj_symbol *sym);
630
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000631#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000632static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000633 int (*cmp)(const char *, const char *),
634 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000635#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000636
Eric Andersen044228d2001-07-17 01:12:36 +0000637static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000638 const char *name);
639
Eric Andersen044228d2001-07-17 01:12:36 +0000640static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000641 struct obj_section *sec);
642
Eric Andersen044228d2001-07-17 01:12:36 +0000643static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000644 const char *name,
645 unsigned long align,
646 unsigned long size);
647
Eric Andersen044228d2001-07-17 01:12:36 +0000648static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000649 const char *name,
650 unsigned long align,
651 unsigned long size);
652
Eric Andersen044228d2001-07-17 01:12:36 +0000653static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000656 const char *string);
657
Eric Andersen044228d2001-07-17 01:12:36 +0000658static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000659 struct obj_symbol *sym);
660
Eric Andersen044228d2001-07-17 01:12:36 +0000661static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000662
Eric Andersen044228d2001-07-17 01:12:36 +0000663static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000664
Eric Andersen044228d2001-07-17 01:12:36 +0000665static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000666
Eric Andersen044228d2001-07-17 01:12:36 +0000667static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000668
Eric Andersen044228d2001-07-17 01:12:36 +0000669static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000670
Eric Andersen044228d2001-07-17 01:12:36 +0000671static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000672
673/* Architecture specific manipulation routines. */
674
Eric Andersen044228d2001-07-17 01:12:36 +0000675static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000676
Eric Andersen044228d2001-07-17 01:12:36 +0000677static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000678
Eric Andersen044228d2001-07-17 01:12:36 +0000679static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000680
Eric Andersen044228d2001-07-17 01:12:36 +0000681static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000682 struct obj_section *targsec,
683 struct obj_section *symsec,
684 struct obj_symbol *sym,
685 ElfW(RelM) *rel, ElfW(Addr) value);
686
Eric Andersencffd5022002-05-24 06:50:15 +0000687static void arch_create_got (struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000688#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000689static int obj_gpl_license(struct obj_file *f, const char **license);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000690#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000691#endif /* obj.h */
692//----------------------------------------------------------------------------
693//--------end of modutils obj.h
694//----------------------------------------------------------------------------
695
696
Miles Baderae28b042002-04-01 09:34:25 +0000697/* SPFX is always a string, so it can be concatenated to string constants. */
698#ifdef SYMBOL_PREFIX
699#define SPFX SYMBOL_PREFIX
700#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000701#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000702#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000703
Erik Andersen02104321999-12-17 18:57:34 +0000704
Erik Andersend387d011999-12-21 02:55:11 +0000705#define _PATH_MODULES "/lib/modules"
Rob Landleybc68cd12006-03-10 19:22:06 +0000706enum { STRVERSIONLEN = 32 };
Erik Andersend387d011999-12-21 02:55:11 +0000707
Eric Andersen9f16d612000-06-12 23:11:16 +0000708/*======================================================================*/
709
Eric Andersen044228d2001-07-17 01:12:36 +0000710static int flag_force_load = 0;
711static int flag_autoclean = 0;
712static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000713static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000714static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000715
716
717/*======================================================================*/
718
Eric Andersencffd5022002-05-24 06:50:15 +0000719#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000720
Eric Andersencffd5022002-05-24 06:50:15 +0000721struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000722{
Eric Andersencffd5022002-05-24 06:50:15 +0000723 struct arch_list_entry *next;
724 CONFIG_LIST_ARCHTYPE addend;
725 int offset;
726 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000727};
Eric Andersencffd5022002-05-24 06:50:15 +0000728
Eric Andersen21adca72000-12-06 18:18:26 +0000729#endif
730
Eric Andersencffd5022002-05-24 06:50:15 +0000731#if defined(CONFIG_USE_SINGLE)
732
733struct arch_single_entry
734{
Eric Andersen9f16d612000-06-12 23:11:16 +0000735 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000736 int inited : 1;
737 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000738};
Eric Andersencffd5022002-05-24 06:50:15 +0000739
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000740#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000741
Eric Andersen2bf658d2001-02-24 20:01:53 +0000742#if defined(__mips__)
743struct mips_hi16
744{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000745 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000746 ElfW(Addr) *addr;
747 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000748};
749#endif
750
Eric Andersenfe4208f2000-09-24 03:44:29 +0000751struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000752 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000753#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000754 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000755#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000756#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000757 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000758#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000759#if defined(__mips__)
760 struct mips_hi16 *mips_hi16_list;
761#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000762};
763
Eric Andersenfe4208f2000-09-24 03:44:29 +0000764struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000765 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000766#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000767#if defined(CONFIG_USE_PLT_LIST)
768 struct arch_list_entry *pltent;
769#else
770 struct arch_single_entry pltent;
771#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000772#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000773#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000774 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000775#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000776};
777
778
Eric Andersen9f16d612000-06-12 23:11:16 +0000779struct external_module {
780 const char *name;
781 ElfW(Addr) addr;
782 int used;
783 size_t nsyms;
784 struct new_module_symbol *syms;
785};
786
Eric Andersen044228d2001-07-17 01:12:36 +0000787static struct new_module_symbol *ksyms;
788static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000789
Eric Andersen044228d2001-07-17 01:12:36 +0000790static struct external_module *ext_modules;
791static int n_ext_modules;
792static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000793extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000794
Eric Andersen61f83052002-06-22 17:15:42 +0000795static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000796static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000797
Eric Andersenfe4208f2000-09-24 03:44:29 +0000798
Erik Andersen02104321999-12-17 18:57:34 +0000799
Eric Andersen9f16d612000-06-12 23:11:16 +0000800/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000801
Eric Andersen9f16d612000-06-12 23:11:16 +0000802
Eric Andersen14d35432001-05-14 17:07:32 +0000803static int check_module_name_match(const char *filename, struct stat *statbuf,
804 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000805{
Eric Andersen14d35432001-05-14 17:07:32 +0000806 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000807
Eric Andersen14d35432001-05-14 17:07:32 +0000808 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000809 return (FALSE);
810 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000811 char *tmp, *tmp1 = bb_xstrdup(filename);
812 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000813 if (strcmp(tmp, fullname) == 0) {
814 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000815 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000816 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000817 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000818 }
Eric Andersen14d35432001-05-14 17:07:32 +0000819 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000820 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000821 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000822}
823
Erik Andersen02104321999-12-17 18:57:34 +0000824
Eric Andersen9f16d612000-06-12 23:11:16 +0000825/*======================================================================*/
826
Eric Andersen044228d2001-07-17 01:12:36 +0000827static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000828{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000829 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000830 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831
Eric Andersencffd5022002-05-24 06:50:15 +0000832 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833
Eric Andersen9f16d612000-06-12 23:11:16 +0000834 return &f->root;
835}
836
Eric Andersen044228d2001-07-17 01:12:36 +0000837static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000838{
839 return xmalloc(sizeof(struct obj_section));
840}
841
Eric Andersen044228d2001-07-17 01:12:36 +0000842static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000843{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000844 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000846
Eric Andersencffd5022002-05-24 06:50:15 +0000847 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000848
Eric Andersen9f16d612000-06-12 23:11:16 +0000849 return &sym->root;
850}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000851
Eric Andersen044228d2001-07-17 01:12:36 +0000852static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000853arch_apply_relocation(struct obj_file *f,
854 struct obj_section *targsec,
855 struct obj_section *symsec,
856 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000857 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000858{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000859 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000860 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000861 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
862 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000863#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
864 struct arch_symbol *isym = (struct arch_symbol *) sym;
865#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000866#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000867#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000868 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000869#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000870#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000871#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000872 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000873 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000874# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000875 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000876# else
Eric Andersencffd5022002-05-24 06:50:15 +0000877 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000878# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000879#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000880
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000881 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000882
Eric Andersencffd5022002-05-24 06:50:15 +0000883#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000884
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 case R_ARM_NONE:
886 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000887
Eric Andersen3b1a7442003-12-24 20:30:45 +0000888 case R_ARM_ABS32:
889 *loc += v;
890 break;
Miles Baderae28b042002-04-01 09:34:25 +0000891
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 case R_ARM_GOT32:
893 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000896 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
897 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000898 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000899
Eric Andersen3496fdc2006-01-30 23:09:20 +0000900 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000901 *loc += got - dot;
902 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000903
Eric Andersen3b1a7442003-12-24 20:30:45 +0000904 case R_ARM_PC24:
905 case R_ARM_PLT32:
906 goto bb_use_plt;
907
908 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3496fdc2006-01-30 23:09:20 +0000909 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000910 *loc += v - got;
911 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000912
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000913#elif defined(__cris__)
914
915 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000916 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000917
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000918 case R_CRIS_32:
919 /* CRIS keeps the relocation value in the r_addend field and
920 * should not use whats in *loc at all
921 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000922 *loc = v;
923 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000924
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000925#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000926
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000927 case R_H8_DIR24R8:
928 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
929 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000930 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000931 case R_H8_DIR24A8:
932 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000933 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000934 case R_H8_DIR32:
935 case R_H8_DIR32A16:
936 *loc += v;
937 break;
938 case R_H8_PCREL16:
939 v -= dot + 2;
940 if ((ElfW(Sword))v > 0x7fff ||
941 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
942 ret = obj_reloc_overflow;
943 else
944 *(unsigned short *)loc = v;
945 break;
946 case R_H8_PCREL8:
947 v -= dot + 1;
948 if ((ElfW(Sword))v > 0x7f ||
949 (ElfW(Sword))v < -(ElfW(Sword))0x80)
950 ret = obj_reloc_overflow;
951 else
952 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000953 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000954
Eric Andersencffd5022002-05-24 06:50:15 +0000955#elif defined(__i386__)
956
Eric Andersen3b1a7442003-12-24 20:30:45 +0000957 case R_386_NONE:
958 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 case R_386_32:
961 *loc += v;
962 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000963
Eric Andersen3b1a7442003-12-24 20:30:45 +0000964 case R_386_PLT32:
965 case R_386_PC32:
966 *loc += v - dot;
967 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_GLOB_DAT:
970 case R_386_JMP_SLOT:
971 *loc = v;
972 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_386_RELATIVE:
975 *loc += f->baseaddr;
976 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000977
Eric Andersen3b1a7442003-12-24 20:30:45 +0000978 case R_386_GOTPC:
979 assert(got != 0);
980 *loc += got - dot;
981 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000982
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 case R_386_GOT32:
984 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000985
Eric Andersen3b1a7442003-12-24 20:30:45 +0000986 case R_386_GOTOFF:
987 assert(got != 0);
988 *loc += v - got;
989 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000990
Mike Frysinger280dae72006-06-06 06:30:32 +0000991#elif defined (__microblaze__)
992 case R_MICROBLAZE_NONE:
993 case R_MICROBLAZE_64_NONE:
994 case R_MICROBLAZE_32_SYM_OP_SYM:
995 case R_MICROBLAZE_32_PCREL:
996 break;
997
998 case R_MICROBLAZE_64_PCREL: {
999 /* dot is the address of the current instruction.
1000 * v is the target symbol address.
1001 * So we need to extract the offset in the code,
1002 * adding v, then subtrating the current address
1003 * of this instruction.
1004 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
1005 */
1006
1007 /* Get split offset stored in code */
1008 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
1009 (loc[1] & 0xFFFF);
1010
1011 /* Adjust relative offset. -4 adjustment required
1012 * because dot points to the IMM insn, but branch
1013 * is computed relative to the branch instruction itself.
1014 */
1015 temp += v - dot - 4;
1016
1017 /* Store back into code */
1018 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1019 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1020
1021 break;
1022 }
1023
1024 case R_MICROBLAZE_32:
1025 *loc += v;
1026 break;
1027
1028 case R_MICROBLAZE_64: {
1029 /* Get split pointer stored in code */
1030 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1031 (loc[1] & 0xFFFF);
1032
1033 /* Add reloc offset */
1034 temp1+=v;
1035
1036 /* Store back into code */
1037 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1038 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1039
1040 break;
1041 }
1042
1043 case R_MICROBLAZE_32_PCREL_LO:
1044 case R_MICROBLAZE_32_LO:
1045 case R_MICROBLAZE_SRO32:
1046 case R_MICROBLAZE_SRW32:
1047 ret = obj_reloc_unhandled;
1048 break;
1049
Eric Andersencffd5022002-05-24 06:50:15 +00001050#elif defined(__mc68000__)
1051
Eric Andersen3b1a7442003-12-24 20:30:45 +00001052 case R_68K_NONE:
1053 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001054
Eric Andersen3b1a7442003-12-24 20:30:45 +00001055 case R_68K_32:
1056 *loc += v;
1057 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001058
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 case R_68K_8:
1060 if (v > 0xff) {
1061 ret = obj_reloc_overflow;
1062 }
1063 *(char *)loc = v;
1064 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001065
Eric Andersen3b1a7442003-12-24 20:30:45 +00001066 case R_68K_16:
1067 if (v > 0xffff) {
1068 ret = obj_reloc_overflow;
1069 }
1070 *(short *)loc = v;
1071 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001072
Eric Andersen3b1a7442003-12-24 20:30:45 +00001073 case R_68K_PC8:
1074 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001075 if ((ElfW(Sword))v > 0x7f ||
1076 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001077 ret = obj_reloc_overflow;
1078 }
1079 *(char *)loc = v;
1080 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001081
Eric Andersen3b1a7442003-12-24 20:30:45 +00001082 case R_68K_PC16:
1083 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001084 if ((ElfW(Sword))v > 0x7fff ||
1085 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 ret = obj_reloc_overflow;
1087 }
1088 *(short *)loc = v;
1089 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001090
Eric Andersen3b1a7442003-12-24 20:30:45 +00001091 case R_68K_PC32:
1092 *(int *)loc = v - dot;
1093 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001094
Eric Andersen3b1a7442003-12-24 20:30:45 +00001095 case R_68K_GLOB_DAT:
1096 case R_68K_JMP_SLOT:
1097 *loc = v;
1098 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001099
Eric Andersen3b1a7442003-12-24 20:30:45 +00001100 case R_68K_RELATIVE:
1101 *(int *)loc += f->baseaddr;
1102 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001103
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 case R_68K_GOT32:
1105 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001106
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001107# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001108 case R_68K_GOTOFF:
1109 assert(got != 0);
1110 *loc += v - got;
1111 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001112# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001113
1114#elif defined(__mips__)
1115
Eric Andersen3b1a7442003-12-24 20:30:45 +00001116 case R_MIPS_NONE:
1117 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001118
Eric Andersen3b1a7442003-12-24 20:30:45 +00001119 case R_MIPS_32:
1120 *loc += v;
1121 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001122
Eric Andersen3b1a7442003-12-24 20:30:45 +00001123 case R_MIPS_26:
1124 if (v % 4)
1125 ret = obj_reloc_dangerous;
1126 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1127 ret = obj_reloc_overflow;
1128 *loc =
1129 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1130 0x03ffffff);
1131 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001132
Eric Andersen3b1a7442003-12-24 20:30:45 +00001133 case R_MIPS_HI16:
1134 {
1135 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001136
Eric Andersen3b1a7442003-12-24 20:30:45 +00001137 /* We cannot relocate this one now because we don't know the value
1138 of the carry we need to add. Save the information, and let LO16
1139 do the actual relocation. */
1140 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1141 n->addr = loc;
1142 n->value = v;
1143 n->next = ifile->mips_hi16_list;
1144 ifile->mips_hi16_list = n;
1145 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001146 }
1147
Eric Andersen3b1a7442003-12-24 20:30:45 +00001148 case R_MIPS_LO16:
1149 {
1150 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001151 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001152
1153 /* Sign extend the addend we extract from the lo insn. */
1154 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1155
1156 if (ifile->mips_hi16_list != NULL) {
1157 struct mips_hi16 *l;
1158
1159 l = ifile->mips_hi16_list;
1160 while (l != NULL) {
1161 struct mips_hi16 *next;
1162 unsigned long insn;
1163
1164 /* The value for the HI16 had best be the same. */
1165 assert(v == l->value);
1166
1167 /* Do the HI16 relocation. Note that we actually don't
1168 need to know anything about the LO16 itself, except where
1169 to find the low 16 bits of the addend needed by the LO16. */
1170 insn = *l->addr;
1171 val =
1172 ((insn & 0xffff) << 16) +
1173 vallo;
1174 val += v;
1175
1176 /* Account for the sign extension that will happen in the
1177 low bits. */
1178 val =
1179 ((val >> 16) +
1180 ((val & 0x8000) !=
1181 0)) & 0xffff;
1182
1183 insn = (insn & ~0xffff) | val;
1184 *l->addr = insn;
1185
1186 next = l->next;
1187 free(l);
1188 l = next;
1189 }
1190
1191 ifile->mips_hi16_list = NULL;
1192 }
1193
1194 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1195 val = v + vallo;
1196 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1197 *loc = insnlo;
1198 break;
1199 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001200
Mike Frysingerf982d862006-01-04 00:11:26 +00001201#elif defined(__nios2__)
1202
1203 case R_NIOS2_NONE:
1204 break;
1205
1206 case R_NIOS2_BFD_RELOC_32:
1207 *loc += v;
1208 break;
1209
1210 case R_NIOS2_BFD_RELOC_16:
1211 if (v > 0xffff) {
1212 ret = obj_reloc_overflow;
1213 }
1214 *(short *)loc = v;
1215 break;
1216
1217 case R_NIOS2_BFD_RELOC_8:
1218 if (v > 0xff) {
1219 ret = obj_reloc_overflow;
1220 }
1221 *(char *)loc = v;
1222 break;
1223
1224 case R_NIOS2_S16:
1225 {
1226 Elf32_Addr word;
1227
1228 if ((Elf32_Sword)v > 0x7fff ||
1229 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1230 ret = obj_reloc_overflow;
1231 }
1232
1233 word = *loc;
1234 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1235 (word & 0x3f);
1236 }
1237 break;
1238
1239 case R_NIOS2_U16:
1240 {
1241 Elf32_Addr word;
1242
1243 if (v > 0xffff) {
1244 ret = obj_reloc_overflow;
1245 }
1246
1247 word = *loc;
1248 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1249 (word & 0x3f);
1250 }
1251 break;
1252
1253 case R_NIOS2_PCREL16:
1254 {
1255 Elf32_Addr word;
1256
1257 v -= dot + 4;
1258 if ((Elf32_Sword)v > 0x7fff ||
1259 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1260 ret = obj_reloc_overflow;
1261 }
1262
1263 word = *loc;
1264 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1265 }
1266 break;
1267
1268 case R_NIOS2_GPREL:
1269 {
1270 Elf32_Addr word, gp;
1271 /* get _gp */
1272 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1273 v-=gp;
1274 if ((Elf32_Sword)v > 0x7fff ||
1275 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1276 ret = obj_reloc_overflow;
1277 }
1278
1279 word = *loc;
1280 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1281 }
1282 break;
1283
1284 case R_NIOS2_CALL26:
1285 if (v & 3)
1286 ret = obj_reloc_dangerous;
1287 if ((v >> 28) != (dot >> 28))
1288 ret = obj_reloc_overflow;
1289 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1290 break;
1291
1292 case R_NIOS2_IMM5:
1293 {
1294 Elf32_Addr word;
1295
1296 if (v > 0x1f) {
1297 ret = obj_reloc_overflow;
1298 }
1299
1300 word = *loc & ~0x7c0;
1301 *loc = word | ((v & 0x1f) << 6);
1302 }
1303 break;
1304
1305 case R_NIOS2_IMM6:
1306 {
1307 Elf32_Addr word;
1308
1309 if (v > 0x3f) {
1310 ret = obj_reloc_overflow;
1311 }
1312
1313 word = *loc & ~0xfc0;
1314 *loc = word | ((v & 0x3f) << 6);
1315 }
1316 break;
1317
1318 case R_NIOS2_IMM8:
1319 {
1320 Elf32_Addr word;
1321
1322 if (v > 0xff) {
1323 ret = obj_reloc_overflow;
1324 }
1325
1326 word = *loc & ~0x3fc0;
1327 *loc = word | ((v & 0xff) << 6);
1328 }
1329 break;
1330
1331 case R_NIOS2_HI16:
1332 {
1333 Elf32_Addr word;
1334
1335 word = *loc;
1336 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1337 (word & 0x3f);
1338 }
1339 break;
1340
1341 case R_NIOS2_LO16:
1342 {
1343 Elf32_Addr word;
1344
1345 word = *loc;
1346 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1347 (word & 0x3f);
1348 }
1349 break;
1350
1351 case R_NIOS2_HIADJ16:
1352 {
1353 Elf32_Addr word1, word2;
1354
1355 word1 = *loc;
1356 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1357 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1358 (word1 & 0x3f);
1359 }
1360 break;
1361
Mike Frysingerebee0e72006-02-18 06:14:31 +00001362#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001363 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001364
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001365#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001366
Eric Andersen3b1a7442003-12-24 20:30:45 +00001367 case R_PPC_ADDR16_HA:
1368 *(unsigned short *)loc = (v + 0x8000) >> 16;
1369 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001370
Eric Andersen3b1a7442003-12-24 20:30:45 +00001371 case R_PPC_ADDR16_HI:
1372 *(unsigned short *)loc = v >> 16;
1373 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001374
Eric Andersen3b1a7442003-12-24 20:30:45 +00001375 case R_PPC_ADDR16_LO:
1376 *(unsigned short *)loc = v;
1377 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001378
Eric Andersen3b1a7442003-12-24 20:30:45 +00001379 case R_PPC_REL24:
1380 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001381
Eric Andersen3b1a7442003-12-24 20:30:45 +00001382 case R_PPC_REL32:
1383 *loc = v - dot;
1384 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001385
Eric Andersen3b1a7442003-12-24 20:30:45 +00001386 case R_PPC_ADDR32:
1387 *loc = v;
1388 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001389
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001390#elif defined(__s390__)
1391
1392 case R_390_32:
1393 *(unsigned int *) loc += v;
1394 break;
1395 case R_390_16:
1396 *(unsigned short *) loc += v;
1397 break;
1398 case R_390_8:
1399 *(unsigned char *) loc += v;
1400 break;
1401
1402 case R_390_PC32:
1403 *(unsigned int *) loc += v - dot;
1404 break;
1405 case R_390_PC16DBL:
1406 *(unsigned short *) loc += (v - dot) >> 1;
1407 break;
1408 case R_390_PC16:
1409 *(unsigned short *) loc += v - dot;
1410 break;
1411
1412 case R_390_PLT32:
1413 case R_390_PLT16DBL:
1414 /* find the plt entry and initialize it. */
1415 assert(isym != NULL);
1416 pe = (struct arch_single_entry *) &isym->pltent;
1417 assert(pe->allocated);
1418 if (pe->inited == 0) {
1419 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1420 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1421 ip[1] = 0x100607f1;
1422 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1423 ip[2] = v - 2;
1424 else
1425 ip[2] = v;
1426 pe->inited = 1;
1427 }
1428
1429 /* Insert relative distance to target. */
1430 v = plt + pe->offset - dot;
1431 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1432 *(unsigned int *) loc = (unsigned int) v;
1433 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1434 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1435 break;
1436
1437 case R_390_GLOB_DAT:
1438 case R_390_JMP_SLOT:
1439 *loc = v;
1440 break;
1441
1442 case R_390_RELATIVE:
1443 *loc += f->baseaddr;
1444 break;
1445
1446 case R_390_GOTPC:
1447 assert(got != 0);
1448 *(unsigned long *) loc += got - dot;
1449 break;
1450
1451 case R_390_GOT12:
1452 case R_390_GOT16:
1453 case R_390_GOT32:
1454 assert(isym != NULL);
1455 assert(got != 0);
1456 if (!isym->gotent.inited)
1457 {
1458 isym->gotent.inited = 1;
1459 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1460 }
1461 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1462 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1463 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1464 *(unsigned short *) loc += isym->gotent.offset;
1465 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1466 *(unsigned int *) loc += isym->gotent.offset;
1467 break;
1468
1469# ifndef R_390_GOTOFF32
1470# define R_390_GOTOFF32 R_390_GOTOFF
1471# endif
1472 case R_390_GOTOFF32:
1473 assert(got != 0);
1474 *loc += v - got;
1475 break;
1476
Eric Andersencffd5022002-05-24 06:50:15 +00001477#elif defined(__sh__)
1478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 case R_SH_NONE:
1480 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001481
Eric Andersen3b1a7442003-12-24 20:30:45 +00001482 case R_SH_DIR32:
1483 *loc += v;
1484 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001485
Eric Andersen3b1a7442003-12-24 20:30:45 +00001486 case R_SH_REL32:
1487 *loc += v - dot;
1488 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 case R_SH_PLT32:
1491 *loc = v - dot;
1492 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001493
Eric Andersen3b1a7442003-12-24 20:30:45 +00001494 case R_SH_GLOB_DAT:
1495 case R_SH_JMP_SLOT:
1496 *loc = v;
1497 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001498
Eric Andersen3b1a7442003-12-24 20:30:45 +00001499 case R_SH_RELATIVE:
1500 *loc = f->baseaddr + rel->r_addend;
1501 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001502
Eric Andersen3b1a7442003-12-24 20:30:45 +00001503 case R_SH_GOTPC:
1504 assert(got != 0);
1505 *loc = got - dot + rel->r_addend;
1506 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001507
Eric Andersen3b1a7442003-12-24 20:30:45 +00001508 case R_SH_GOT32:
1509 goto bb_use_got;
1510
1511 case R_SH_GOTOFF:
1512 assert(got != 0);
1513 *loc = v - got;
1514 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001515
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001516# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001517 case R_SH_IMM_MEDLOW16:
1518 case R_SH_IMM_LOW16:
1519 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001520 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001521
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001522 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001523 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001524
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 /*
1526 * movi and shori have the format:
1527 *
1528 * | op | imm | reg | reserved |
1529 * 31..26 25..10 9.. 4 3 .. 0
1530 *
1531 * so we simply mask and or in imm.
1532 */
1533 word = *loc & ~0x3fffc00;
1534 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001535
Eric Andersen3b1a7442003-12-24 20:30:45 +00001536 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001537
Eric Andersen3b1a7442003-12-24 20:30:45 +00001538 break;
1539 }
Eric Andersenbf833552003-08-13 19:56:33 +00001540
Eric Andersen3b1a7442003-12-24 20:30:45 +00001541 case R_SH_IMM_MEDLOW16_PCREL:
1542 case R_SH_IMM_LOW16_PCREL:
1543 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001544 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001545
Eric Andersen3b1a7442003-12-24 20:30:45 +00001546 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001547
Eric Andersen3b1a7442003-12-24 20:30:45 +00001548 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001549
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001550 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001551 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001552
Eric Andersen3b1a7442003-12-24 20:30:45 +00001553 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001554
Eric Andersen3b1a7442003-12-24 20:30:45 +00001555 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001556
Eric Andersen3b1a7442003-12-24 20:30:45 +00001557 break;
1558 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001559# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001560
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001561#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001562
Eric Andersen3b1a7442003-12-24 20:30:45 +00001563 case R_V850_NONE:
1564 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001565
Eric Andersen3b1a7442003-12-24 20:30:45 +00001566 case R_V850_32:
1567 /* We write two shorts instead of a long because even
1568 32-bit insns only need half-word alignment, but
1569 32-bit data needs to be long-word aligned. */
1570 v += ((unsigned short *)loc)[0];
1571 v += ((unsigned short *)loc)[1] << 16;
1572 ((unsigned short *)loc)[0] = v & 0xffff;
1573 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1574 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001575
Eric Andersen3b1a7442003-12-24 20:30:45 +00001576 case R_V850_22_PCREL:
1577 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001578
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001579#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001580
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001581 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001582 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001583
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001584 case R_X86_64_64:
1585 *loc += v;
1586 break;
1587
1588 case R_X86_64_32:
1589 *(unsigned int *) loc += v;
1590 if (v > 0xffffffff)
1591 {
1592 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1593 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1594 }
1595 break;
1596
1597 case R_X86_64_32S:
1598 *(signed int *) loc += v;
1599 break;
1600
1601 case R_X86_64_16:
1602 *(unsigned short *) loc += v;
1603 break;
1604
1605 case R_X86_64_8:
1606 *(unsigned char *) loc += v;
1607 break;
1608
1609 case R_X86_64_PC32:
1610 *(unsigned int *) loc += v - dot;
1611 break;
1612
1613 case R_X86_64_PC16:
1614 *(unsigned short *) loc += v - dot;
1615 break;
1616
1617 case R_X86_64_PC8:
1618 *(unsigned char *) loc += v - dot;
1619 break;
1620
1621 case R_X86_64_GLOB_DAT:
1622 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001623 *loc = v;
1624 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001625
1626 case R_X86_64_RELATIVE:
1627 *loc += f->baseaddr;
1628 break;
1629
1630 case R_X86_64_GOT32:
1631 case R_X86_64_GOTPCREL:
1632 goto bb_use_got;
1633# if 0
1634 assert(isym != NULL);
1635 if (!isym->gotent.reloc_done)
1636 {
1637 isym->gotent.reloc_done = 1;
1638 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1639 }
1640 /* XXX are these really correct? */
1641 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1642 *(unsigned int *) loc += v + isym->gotent.offset;
1643 else
1644 *loc += isym->gotent.offset;
1645 break;
1646# endif
1647
Mike Frysingerf982d862006-01-04 00:11:26 +00001648#else
1649# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001650#endif
1651
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001652 default:
1653 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1654 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001655 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001656
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001657#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001658
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001660
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 /* find the plt entry and initialize it if necessary */
1662 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001663
Eric Andersencffd5022002-05-24 06:50:15 +00001664#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1666 pe = pe->next;
1667 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001668#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001670#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001671
Eric Andersen3b1a7442003-12-24 20:30:45 +00001672 if (! pe->inited) {
1673 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001674
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001676
1677#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1679 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001680#endif
1681#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001683 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 ip[2] = 0x7d6903a6; /* mtctr r11 */
1685 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001686#endif
Miles Baderae28b042002-04-01 09:34:25 +00001687#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 /* We have to trash a register, so we assume that any control
1689 transfer more than 21-bits away must be a function call
1690 (so we can use a call-clobbered register). */
1691 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1692 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001693#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 pe->inited = 1;
1695 }
Eric Andersen21adca72000-12-06 18:18:26 +00001696
Eric Andersen3b1a7442003-12-24 20:30:45 +00001697 /* relative distance to target */
1698 v -= dot;
1699 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001700#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001701 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001702#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001703 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001704#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001705 /* go via the plt */
1706 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001707
1708#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001709 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001710#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001711 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001712#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001713 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001714
Eric Andersen3b1a7442003-12-24 20:30:45 +00001715 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001716#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001717 /* Convert to words. */
1718 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001719
Eric Andersen3b1a7442003-12-24 20:30:45 +00001720 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001721#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001722#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001723 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001724#endif
Miles Baderae28b042002-04-01 09:34:25 +00001725#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001726 /* We write two shorts instead of a long because even 32-bit insns
1727 only need half-word alignment, but the 32-bit data write needs
1728 to be long-word aligned. */
1729 ((unsigned short *)loc)[0] =
1730 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1731 | ((v >> 16) & 0x3f); /* offs high part */
1732 ((unsigned short *)loc)[1] =
1733 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001734#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001735 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001736#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001737
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001738#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001739bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001740
Eric Andersen3b1a7442003-12-24 20:30:45 +00001741 assert(isym != NULL);
1742 /* needs an entry in the .got: set it, once */
1743 if (!isym->gotent.inited) {
1744 isym->gotent.inited = 1;
1745 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1746 }
1747 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001748#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001749 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001750#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001751 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001752#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001753 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001754
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001755#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001756 }
1757
1758 return ret;
1759}
1760
Eric Andersencffd5022002-05-24 06:50:15 +00001761
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001762#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001763
1764static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1765 int offset, int size)
1766{
1767 struct arch_list_entry *pe;
1768
1769 for (pe = *list; pe != NULL; pe = pe->next) {
1770 if (pe->addend == rel->r_addend) {
1771 break;
1772 }
1773 }
1774
1775 if (pe == NULL) {
1776 pe = xmalloc(sizeof(struct arch_list_entry));
1777 pe->next = *list;
1778 pe->addend = rel->r_addend;
1779 pe->offset = offset;
1780 pe->inited = 0;
1781 *list = pe;
1782 return size;
1783 }
1784 return 0;
1785}
1786
1787#endif
1788
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001789#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001790
1791static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1792 int offset, int size)
1793{
1794 if (single->allocated == 0) {
1795 single->allocated = 1;
1796 single->offset = offset;
1797 single->inited = 0;
1798 return size;
1799 }
1800 return 0;
1801}
1802
1803#endif
1804
1805#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1806
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001807static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001808 int offset, int size)
1809{
1810 struct obj_section *myrelsec = obj_find_section(f, name);
1811
1812 if (offset == 0) {
1813 offset += size;
1814 }
1815
1816 if (myrelsec) {
1817 obj_extend_section(myrelsec, offset);
1818 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001819 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001820 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001821 assert(myrelsec);
1822 }
1823
1824 return myrelsec;
1825}
1826
1827#endif
1828
1829static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001830{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001831#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001832 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001833 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001834#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001835 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001836#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001837#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001838 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001839#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001840 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001841 ElfW(RelM) *rel, *relend;
1842 ElfW(Sym) *symtab, *extsym;
1843 const char *strtab, *name;
1844 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001845
Eric Andersen21adca72000-12-06 18:18:26 +00001846 for (i = 0; i < f->header.e_shnum; ++i) {
1847 relsec = f->sections[i];
1848 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001849 continue;
1850
Eric Andersen21adca72000-12-06 18:18:26 +00001851 symsec = f->sections[relsec->header.sh_link];
1852 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001853
Eric Andersen21adca72000-12-06 18:18:26 +00001854 rel = (ElfW(RelM) *) relsec->contents;
1855 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1856 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001857 strtab = (const char *) strsec->contents;
1858
1859 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001860 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001861
Eric Andersencffd5022002-05-24 06:50:15 +00001862#if defined(CONFIG_USE_GOT_ENTRIES)
1863 got_allocate = 0;
1864#endif
1865#if defined(CONFIG_USE_PLT_ENTRIES)
1866 plt_allocate = 0;
1867#endif
1868
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001869 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001870#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001871 case R_ARM_PC24:
1872 case R_ARM_PLT32:
1873 plt_allocate = 1;
1874 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001875
Eric Andersen3b1a7442003-12-24 20:30:45 +00001876 case R_ARM_GOTOFF:
1877 case R_ARM_GOTPC:
1878 got_needed = 1;
1879 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001880
Eric Andersen3b1a7442003-12-24 20:30:45 +00001881 case R_ARM_GOT32:
1882 got_allocate = 1;
1883 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001884
Eric Andersen21adca72000-12-06 18:18:26 +00001885#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001886 case R_386_GOTPC:
1887 case R_386_GOTOFF:
1888 got_needed = 1;
1889 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001890
Eric Andersen3b1a7442003-12-24 20:30:45 +00001891 case R_386_GOT32:
1892 got_allocate = 1;
1893 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001894
1895#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001896 case R_PPC_REL24:
1897 plt_allocate = 1;
1898 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001899
1900#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001901 case R_68K_GOT32:
1902 got_allocate = 1;
1903 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001904
Eric Andersen16451a02004-03-19 12:16:18 +00001905#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001906 case R_68K_GOTOFF:
1907 got_needed = 1;
1908 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001909#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001910
1911#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001912 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001913 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001914 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001915
Eric Andersen3b1a7442003-12-24 20:30:45 +00001916 case R_SH_GOTPC:
1917 case R_SH_GOTOFF:
1918 got_needed = 1;
1919 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001920
1921#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001922 case R_V850_22_PCREL:
1923 plt_needed = 1;
1924 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001925
1926#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001927 default:
1928 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001929 }
1930
Eric Andersen21adca72000-12-06 18:18:26 +00001931 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001932 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001933 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001934 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001935 }
1936 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001937#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001938 if (got_allocate) {
1939 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001940 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001941 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001942
1943 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001944 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001945#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001946#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001947 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001948#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001949 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001950 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001951 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001952#else
1953 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001954 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001955 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001956#endif
1957 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001958 }
1959#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001960 }
Miles Baderae28b042002-04-01 09:34:25 +00001961 }
Eric Andersen21adca72000-12-06 18:18:26 +00001962
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001963#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001964 if (got_needed) {
1965 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001966 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001967 }
Eric Andersen21adca72000-12-06 18:18:26 +00001968#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001969
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001970#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001971 if (plt_needed) {
1972 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001973 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001974 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001975#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001976
1977#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001978}
1979
Eric Andersen9f16d612000-06-12 23:11:16 +00001980/*======================================================================*/
1981
1982/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001983static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001984{
1985 unsigned long h = 0;
1986 unsigned long g;
1987 unsigned char ch;
1988
1989 while (n > 0) {
1990 ch = *name++;
1991 h = (h << 4) + ch;
1992 if ((g = (h & 0xf0000000)) != 0) {
1993 h ^= g >> 24;
1994 h &= ~g;
1995 }
1996 n--;
1997 }
1998 return h;
1999}
2000
Eric Andersen044228d2001-07-17 01:12:36 +00002001static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002002{
2003 return obj_elf_hash_n(name, strlen(name));
2004}
2005
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002006#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002007/* String comparison for non-co-versioned kernel and module. */
2008
2009static int ncv_strcmp(const char *a, const char *b)
2010{
2011 size_t alen = strlen(a), blen = strlen(b);
2012
2013 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
2014 return strncmp(a, b, alen);
2015 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
2016 return strncmp(a, b, blen);
2017 else
2018 return strcmp(a, b);
2019}
2020
2021/* String hashing for non-co-versioned kernel and module. Here
2022 we are simply forced to drop the crc from the hash. */
2023
2024static unsigned long ncv_symbol_hash(const char *str)
2025{
2026 size_t len = strlen(str);
2027 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2028 len -= 10;
2029 return obj_elf_hash_n(str, len);
2030}
2031
Eric Andersen044228d2001-07-17 01:12:36 +00002032static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002033obj_set_symbol_compare(struct obj_file *f,
2034 int (*cmp) (const char *, const char *),
2035 unsigned long (*hash) (const char *))
2036{
2037 if (cmp)
2038 f->symbol_cmp = cmp;
2039 if (hash) {
2040 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2041 int i;
2042
2043 f->symbol_hash = hash;
2044
2045 memcpy(tmptab, f->symtab, sizeof(tmptab));
2046 memset(f->symtab, 0, sizeof(f->symtab));
2047
2048 for (i = 0; i < HASH_BUCKETS; ++i)
2049 for (sym = tmptab[i]; sym; sym = next) {
2050 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2051 next = sym->next;
2052 sym->next = f->symtab[h];
2053 f->symtab[h] = sym;
2054 }
2055 }
2056}
2057
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002058#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002059
Eric Andersen044228d2001-07-17 01:12:36 +00002060static struct obj_symbol *
2061obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00002062 unsigned long symidx, int info,
2063 int secidx, ElfW(Addr) value,
2064 unsigned long size)
2065{
2066 struct obj_symbol *sym;
2067 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002068 int n_type = ELF_ST_TYPE(info);
2069 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002070
2071 for (sym = f->symtab[hash]; sym; sym = sym->next)
2072 if (f->symbol_cmp(sym->name, name) == 0) {
2073 int o_secidx = sym->secidx;
2074 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002075 int o_type = ELF_ST_TYPE(o_info);
2076 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002077
2078 /* A redefinition! Is it legal? */
2079
2080 if (secidx == SHN_UNDEF)
2081 return sym;
2082 else if (o_secidx == SHN_UNDEF)
2083 goto found;
2084 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2085 /* Cope with local and global symbols of the same name
2086 in the same object file, as might have been created
2087 by ld -r. The only reason locals are now seen at this
2088 level at all is so that we can do semi-sensible things
2089 with parameters. */
2090
2091 struct obj_symbol *nsym, **p;
2092
2093 nsym = arch_new_symbol();
2094 nsym->next = sym->next;
2095 nsym->ksymidx = -1;
2096
2097 /* Excise the old (local) symbol from the hash chain. */
2098 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2099 continue;
2100 *p = sym = nsym;
2101 goto found;
2102 } else if (n_binding == STB_LOCAL) {
2103 /* Another symbol of the same name has already been defined.
2104 Just add this to the local table. */
2105 sym = arch_new_symbol();
2106 sym->next = NULL;
2107 sym->ksymidx = -1;
2108 f->local_symtab[symidx] = sym;
2109 goto found;
2110 } else if (n_binding == STB_WEAK)
2111 return sym;
2112 else if (o_binding == STB_WEAK)
2113 goto found;
2114 /* Don't unify COMMON symbols with object types the programmer
2115 doesn't expect. */
2116 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002117 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002118 return sym;
2119 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002120 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002121 goto found;
2122 else {
2123 /* Don't report an error if the symbol is coming from
2124 the kernel or some external module. */
2125 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002126 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002127 return sym;
2128 }
2129 }
2130
2131 /* Completely new symbol. */
2132 sym = arch_new_symbol();
2133 sym->next = f->symtab[hash];
2134 f->symtab[hash] = sym;
2135 sym->ksymidx = -1;
2136
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002137 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002138 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002139 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002140 name, (long) symidx, (long) f->local_symtab_size);
2141 else
2142 f->local_symtab[symidx] = sym;
2143 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002144
Eric Andersen3b1a7442003-12-24 20:30:45 +00002145found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002146 sym->name = name;
2147 sym->value = value;
2148 sym->size = size;
2149 sym->secidx = secidx;
2150 sym->info = info;
2151
2152 return sym;
2153}
2154
Eric Andersen044228d2001-07-17 01:12:36 +00002155static struct obj_symbol *
2156obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002157{
2158 struct obj_symbol *sym;
2159 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2160
2161 for (sym = f->symtab[hash]; sym; sym = sym->next)
2162 if (f->symbol_cmp(sym->name, name) == 0)
2163 return sym;
2164
2165 return NULL;
2166}
2167
Eric Andersen044228d2001-07-17 01:12:36 +00002168static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002169 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2170{
2171 if (sym) {
2172 if (sym->secidx >= SHN_LORESERVE)
2173 return sym->value;
2174
2175 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2176 } else {
2177 /* As a special case, a NULL sym has value zero. */
2178 return 0;
2179 }
2180}
2181
Eric Andersen044228d2001-07-17 01:12:36 +00002182static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002183{
2184 int i, n = f->header.e_shnum;
2185
2186 for (i = 0; i < n; ++i)
2187 if (strcmp(f->sections[i]->name, name) == 0)
2188 return f->sections[i];
2189
2190 return NULL;
2191}
2192
2193static int obj_load_order_prio(struct obj_section *a)
2194{
2195 unsigned long af, ac;
2196
2197 af = a->header.sh_flags;
2198
2199 ac = 0;
2200 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002201 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002202 ac |= 32;
2203 if (af & SHF_ALLOC)
2204 ac |= 16;
2205 if (!(af & SHF_WRITE))
2206 ac |= 8;
2207 if (af & SHF_EXECINSTR)
2208 ac |= 4;
2209 if (a->header.sh_type != SHT_NOBITS)
2210 ac |= 2;
2211
2212 return ac;
2213}
2214
Eric Andersen044228d2001-07-17 01:12:36 +00002215static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002216obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2217{
2218 struct obj_section **p;
2219 int prio = obj_load_order_prio(sec);
2220 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2221 if (obj_load_order_prio(*p) < prio)
2222 break;
2223 sec->load_next = *p;
2224 *p = sec;
2225}
2226
Eric Andersen044228d2001-07-17 01:12:36 +00002227static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002228 const char *name,
2229 unsigned long align,
2230 unsigned long size)
2231{
2232 int newidx = f->header.e_shnum++;
2233 struct obj_section *sec;
2234
2235 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2236 f->sections[newidx] = sec = arch_new_section();
2237
2238 memset(sec, 0, sizeof(*sec));
2239 sec->header.sh_type = SHT_PROGBITS;
2240 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2241 sec->header.sh_size = size;
2242 sec->header.sh_addralign = align;
2243 sec->name = name;
2244 sec->idx = newidx;
2245 if (size)
2246 sec->contents = xmalloc(size);
2247
2248 obj_insert_section_load_order(f, sec);
2249
2250 return sec;
2251}
2252
Eric Andersen044228d2001-07-17 01:12:36 +00002253static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002254 const char *name,
2255 unsigned long align,
2256 unsigned long size)
2257{
2258 int newidx = f->header.e_shnum++;
2259 struct obj_section *sec;
2260
2261 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2262 f->sections[newidx] = sec = arch_new_section();
2263
2264 memset(sec, 0, sizeof(*sec));
2265 sec->header.sh_type = SHT_PROGBITS;
2266 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2267 sec->header.sh_size = size;
2268 sec->header.sh_addralign = align;
2269 sec->name = name;
2270 sec->idx = newidx;
2271 if (size)
2272 sec->contents = xmalloc(size);
2273
2274 sec->load_next = f->load_order;
2275 f->load_order = sec;
2276 if (f->load_order_search_start == &f->load_order)
2277 f->load_order_search_start = &sec->load_next;
2278
2279 return sec;
2280}
2281
Eric Andersen044228d2001-07-17 01:12:36 +00002282static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002283{
2284 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002285 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002286 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2287 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002288 return sec->contents + oldsize;
2289}
2290
2291
Eric Andersen9f16d612000-06-12 23:11:16 +00002292/* Conditionally add the symbols from the given symbol set to the
2293 new module. */
2294
2295static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002296add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002297 int idx, struct new_module_symbol *syms, size_t nsyms)
2298{
2299 struct new_module_symbol *s;
2300 size_t i;
2301 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002302#ifdef SYMBOL_PREFIX
2303 char *name_buf = 0;
2304 size_t name_alloced_size = 0;
2305#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002306#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2307 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002308
Glenn L McGrath759515c2003-08-30 06:00:33 +00002309 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002310#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002311 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002312 /* Only add symbols that are already marked external.
2313 If we override locals we may cause problems for
2314 argument initialization. We will also create a false
2315 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002316 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002317 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002318
Glenn L McGrath759515c2003-08-30 06:00:33 +00002319 /* GPL licensed modules can use symbols exported with
2320 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2321 * exported names. Non-GPL modules never see any GPLONLY_
2322 * symbols so they cannot fudge it by adding the prefix on
2323 * their references.
2324 */
2325 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002326#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002327 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002328 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002329 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002330#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002331 continue;
2332 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002333 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002334
Miles Baderae28b042002-04-01 09:34:25 +00002335#ifdef SYMBOL_PREFIX
2336 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2337 kernel exports `C names', but module object files
2338 reference `linker names'). */
2339 size_t extra = sizeof SYMBOL_PREFIX;
2340 size_t name_size = strlen (name) + extra;
2341 if (name_size > name_alloced_size) {
2342 name_alloced_size = name_size * 2;
2343 name_buf = alloca (name_alloced_size);
2344 }
2345 strcpy (name_buf, SYMBOL_PREFIX);
2346 strcpy (name_buf + extra - 1, name);
2347 name = name_buf;
2348#endif /* SYMBOL_PREFIX */
2349
2350 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002351 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002352#ifdef SYMBOL_PREFIX
2353 /* Put NAME_BUF into more permanent storage. */
2354 name = xmalloc (name_size);
2355 strcpy (name, name_buf);
2356#endif
2357 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002358 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002359 STT_NOTYPE),
2360 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002361 /* Did our symbol just get installed? If so, mark the
2362 module as "used". */
2363 if (sym->secidx == idx)
2364 used = 1;
2365 }
2366 }
2367
2368 return used;
2369}
2370
2371static void add_kernel_symbols(struct obj_file *f)
2372{
2373 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002374 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002375
2376 /* Add module symbols first. */
2377
2378 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2379 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002380 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2381 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002382
2383 n_ext_modules_used = nused;
2384
2385 /* And finally the symbols from the kernel proper. */
2386
2387 if (nksyms)
2388 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2389}
2390
2391static char *get_modinfo_value(struct obj_file *f, const char *key)
2392{
2393 struct obj_section *sec;
2394 char *p, *v, *n, *ep;
2395 size_t klen = strlen(key);
2396
2397 sec = obj_find_section(f, ".modinfo");
2398 if (sec == NULL)
2399 return NULL;
2400 p = sec->contents;
2401 ep = p + sec->header.sh_size;
2402 while (p < ep) {
2403 v = strchr(p, '=');
2404 n = strchr(p, '\0');
2405 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002406 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002407 return v + 1;
2408 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002409 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002410 return n;
2411 }
2412 p = n + 1;
2413 }
2414
2415 return NULL;
2416}
2417
2418
2419/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002420/* Functions relating to module loading after 2.1.18. */
2421
2422static int
2423new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2424{
2425 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002426 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002427 struct obj_symbol *sym;
2428 char *contents, *loc;
2429 int min, max, n;
2430
2431 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002432 if ((q = strchr(p, '=')) == NULL) {
2433 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002434 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002435 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002436
2437 key = alloca(q - p + 6);
2438 memcpy(key, "parm_", 5);
2439 memcpy(key + 5, p, q - p);
2440 key[q - p + 5] = 0;
2441
2442 p = get_modinfo_value(f, key);
2443 key += 5;
2444 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002445 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002446 return 0;
2447 }
2448
Miles Baderae28b042002-04-01 09:34:25 +00002449#ifdef SYMBOL_PREFIX
2450 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2451 strcpy (sym_name, SYMBOL_PREFIX);
2452 strcat (sym_name, key);
2453#else
2454 sym_name = key;
2455#endif
2456 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002457
2458 /* Also check that the parameter was not resolved from the kernel. */
2459 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002460 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002461 return 0;
2462 }
2463
2464 if (isdigit(*p)) {
2465 min = strtoul(p, &p, 10);
2466 if (*p == '-')
2467 max = strtoul(p + 1, &p, 10);
2468 else
2469 max = min;
2470 } else
2471 min = max = 1;
2472
2473 contents = f->sections[sym->secidx]->contents;
2474 loc = contents + sym->value;
2475 n = (*++q != '\0');
2476
2477 while (1) {
2478 if ((*p == 's') || (*p == 'c')) {
2479 char *str;
2480
2481 /* Do C quoting if we begin with a ", else slurp the lot. */
2482 if (*q == '"') {
2483 char *r;
2484
2485 str = alloca(strlen(q));
2486 for (r = str, q++; *q != '"'; ++q, ++r) {
2487 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002488 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002489 key);
2490 return 0;
2491 } else if (*q == '\\')
2492 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002493 case 'a':
2494 *r = '\a';
2495 break;
2496 case 'b':
2497 *r = '\b';
2498 break;
2499 case 'e':
2500 *r = '\033';
2501 break;
2502 case 'f':
2503 *r = '\f';
2504 break;
2505 case 'n':
2506 *r = '\n';
2507 break;
2508 case 'r':
2509 *r = '\r';
2510 break;
2511 case 't':
2512 *r = '\t';
2513 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002514
Eric Andersen3b1a7442003-12-24 20:30:45 +00002515 case '0':
2516 case '1':
2517 case '2':
2518 case '3':
2519 case '4':
2520 case '5':
2521 case '6':
2522 case '7':
2523 {
2524 int c = *q - '0';
2525 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002526 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002527 if (q[1] >= '0' && q[1] <= '7')
2528 c = (c * 8) + *++q - '0';
2529 }
2530 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002531 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002532 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002533
Eric Andersen3b1a7442003-12-24 20:30:45 +00002534 default:
2535 *r = *q;
2536 break;
2537 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002538 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002539 }
2540 *r = '\0';
2541 ++q;
2542 } else {
2543 char *r;
2544
2545 /* In this case, the string is not quoted. We will break
2546 it using the coma (like for ints). If the user wants to
2547 include comas in a string, he just has to quote it */
2548
2549 /* Search the next coma */
2550 r = strchr(q, ',');
2551
2552 /* Found ? */
2553 if (r != (char *) NULL) {
2554 /* Recopy the current field */
2555 str = alloca(r - q + 1);
2556 memcpy(str, q, r - q);
2557
Eric Andersenaff114c2004-04-14 17:51:38 +00002558 /* I don't know if it is useful, as the previous case
2559 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002560 str[r - q] = '\0';
2561
2562 /* Keep next fields */
2563 q = r;
2564 } else {
2565 /* last string */
2566 str = q;
2567 q = "";
2568 }
2569 }
2570
2571 if (*p == 's') {
2572 /* Normal string */
2573 obj_string_patch(f, sym->secidx, loc - contents, str);
2574 loc += tgt_sizeof_char_p;
2575 } else {
2576 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002577 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002578
2579 /* Get the size of each member */
2580 /* Probably we should do that outside the loop ? */
2581 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002582 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002583 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002584 return 0;
2585 }
2586 charssize = strtoul(p + 1, (char **) NULL, 10);
2587
2588 /* Check length */
2589 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002590 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002591 charssize - 1);
2592 return 0;
2593 }
2594
2595 /* Copy to location */
2596 strcpy((char *) loc, str);
2597 loc += charssize;
2598 }
2599 } else {
2600 long v = strtoul(q, &q, 0);
2601 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002602 case 'b':
2603 *loc++ = v;
2604 break;
2605 case 'h':
2606 *(short *) loc = v;
2607 loc += tgt_sizeof_short;
2608 break;
2609 case 'i':
2610 *(int *) loc = v;
2611 loc += tgt_sizeof_int;
2612 break;
2613 case 'l':
2614 *(long *) loc = v;
2615 loc += tgt_sizeof_long;
2616 break;
2617
2618 default:
2619 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2620 return 0;
2621 }
2622 }
2623
2624retry_end_of_value:
2625 switch (*q) {
2626 case '\0':
2627 goto end_of_arg;
2628
2629 case ' ':
2630 case '\t':
2631 case '\n':
2632 case '\r':
2633 ++q;
2634 goto retry_end_of_value;
2635
2636 case ',':
2637 if (++n > max) {
2638 bb_error_msg("too many values for %s (max %d)", key, max);
2639 return 0;
2640 }
2641 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002642 break;
2643
2644 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002645 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002646 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002647 }
2648 }
2649
Eric Andersen3b1a7442003-12-24 20:30:45 +00002650end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002651 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002652 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002653 return 0;
2654 }
2655
2656 argc--, argv++;
2657 }
2658
2659 return 1;
2660}
2661
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002662#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002663static int new_is_module_checksummed(struct obj_file *f)
2664{
2665 const char *p = get_modinfo_value(f, "using_checksums");
2666 if (p)
2667 return atoi(p);
2668 else
2669 return 0;
2670}
2671
2672/* Get the module's kernel version in the canonical integer form. */
2673
2674static int
2675new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2676{
2677 char *p, *q;
2678 int a, b, c;
2679
2680 p = get_modinfo_value(f, "kernel_version");
2681 if (p == NULL)
2682 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002683 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002684
2685 a = strtoul(p, &p, 10);
2686 if (*p != '.')
2687 return -1;
2688 b = strtoul(p + 1, &p, 10);
2689 if (*p != '.')
2690 return -1;
2691 c = strtoul(p + 1, &q, 10);
2692 if (p + 1 == q)
2693 return -1;
2694
2695 return a << 16 | b << 8 | c;
2696}
2697
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002698#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002699
2700
Eric Andersen9f16d612000-06-12 23:11:16 +00002701/* Fetch the loaded modules, and all currently exported symbols. */
2702
2703static int new_get_kernel_symbols(void)
2704{
2705 char *module_names, *mn;
2706 struct external_module *modules, *m;
2707 struct new_module_symbol *syms, *s;
2708 size_t ret, bufsize, nmod, nsyms, i, j;
2709
2710 /* Collect the loaded modules. */
2711
2712 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002713retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002714 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002715 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002716 module_names = xrealloc(module_names, bufsize = ret);
2717 goto retry_modules_load;
2718 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002719 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002720 return 0;
2721 }
2722
2723 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002724
2725 /* Collect the modules' symbols. */
2726
Mark Whitley94fd4802001-03-12 23:08:34 +00002727 if (nmod){
2728 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2729 memset(modules, 0, nmod * sizeof(*modules));
2730 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002731 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002732 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002733
Mark Whitley94fd4802001-03-12 23:08:34 +00002734 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2735 if (errno == ENOENT) {
2736 /* The module was removed out from underneath us. */
2737 continue;
2738 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002739 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002740 return 0;
2741 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002742
Mark Whitley94fd4802001-03-12 23:08:34 +00002743 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002744retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002745 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2746 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002747 case ENOSPC:
2748 syms = xrealloc(syms, bufsize = ret);
2749 goto retry_mod_sym_load;
2750 case ENOENT:
2751 /* The module was removed out from underneath us. */
2752 continue;
2753 default:
2754 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2755 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002756 }
2757 }
2758 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002759
Mark Whitley94fd4802001-03-12 23:08:34 +00002760 m->name = mn;
2761 m->addr = info.addr;
2762 m->nsyms = nsyms;
2763 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002764
Mark Whitley94fd4802001-03-12 23:08:34 +00002765 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2766 s->name += (unsigned long) syms;
2767 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002768 }
2769 }
2770
2771 /* Collect the kernel's symbols. */
2772
2773 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002774retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002775 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002776 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002777 syms = xrealloc(syms, bufsize = ret);
2778 goto retry_kern_sym_load;
2779 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002780 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002781 return 0;
2782 }
2783 nksyms = nsyms = ret;
2784 ksyms = syms;
2785
2786 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2787 s->name += (unsigned long) syms;
2788 }
2789 return 1;
2790}
2791
2792
2793/* Return the kernel symbol checksum version, or zero if not used. */
2794
2795static int new_is_kernel_checksummed(void)
2796{
2797 struct new_module_symbol *s;
2798 size_t i;
2799
2800 /* Using_Versions is not the first symbol, but it should be in there. */
2801
2802 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2803 if (strcmp((char *) s->name, "Using_Versions") == 0)
2804 return s->value;
2805
2806 return 0;
2807}
2808
2809
2810static int new_create_this_module(struct obj_file *f, const char *m_name)
2811{
2812 struct obj_section *sec;
2813
2814 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002815 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002816 memset(sec->contents, 0, sizeof(struct new_module));
2817
Miles Baderae28b042002-04-01 09:34:25 +00002818 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002819 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002820 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002821
2822 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002823 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002824
2825 return 1;
2826}
2827
Eric Andersen889dd202003-01-23 04:48:34 +00002828#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2829/* add an entry to the __ksymtab section, creating it if necessary */
2830static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2831{
2832 struct obj_section *sec;
2833 ElfW(Addr) ofs;
2834
2835 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2836 * If __ksymtab is defined but not marked alloc, x out the first character
2837 * (no obj_delete routine) and create a new __ksymtab with the correct
2838 * characteristics.
2839 */
2840 sec = obj_find_section(f, "__ksymtab");
2841 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2842 *((char *)(sec->name)) = 'x'; /* override const */
2843 sec = NULL;
2844 }
2845 if (!sec)
2846 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002847 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002848 if (!sec)
2849 return;
2850 sec->header.sh_flags |= SHF_ALLOC;
2851 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002852 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002853 ofs = sec->header.sh_size;
2854 obj_symbol_patch(f, sec->idx, ofs, sym);
2855 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2856 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2857}
2858#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002859
2860static int new_create_module_ksymtab(struct obj_file *f)
2861{
2862 struct obj_section *sec;
2863 int i;
2864
2865 /* We must always add the module references. */
2866
2867 if (n_ext_modules_used) {
2868 struct new_module_ref *dep;
2869 struct obj_symbol *tm;
2870
2871 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002872 (sizeof(struct new_module_ref)
2873 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002874 if (!sec)
2875 return 0;
2876
Miles Baderae28b042002-04-01 09:34:25 +00002877 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002878 dep = (struct new_module_ref *) sec->contents;
2879 for (i = 0; i < n_ext_modules; ++i)
2880 if (ext_modules[i].used) {
2881 dep->dep = ext_modules[i].addr;
2882 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002883 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002884 dep->next_ref = 0;
2885 ++dep;
2886 }
2887 }
2888
2889 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2890 size_t nsyms;
2891 int *loaded;
2892
2893 sec =
2894 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002895 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002896
2897 /* We don't want to export symbols residing in sections that
2898 aren't loaded. There are a number of these created so that
2899 we make sure certain module options don't appear twice. */
2900
2901 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2902 while (--i >= 0)
2903 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2904
2905 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2906 struct obj_symbol *sym;
2907 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002908 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002909 && sym->secidx <= SHN_HIRESERVE
2910 && (sym->secidx >= SHN_LORESERVE
2911 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002912 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2913
2914 obj_symbol_patch(f, sec->idx, ofs, sym);
2915 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002916 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002917
2918 nsyms++;
2919 }
2920 }
2921
2922 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2923 }
2924
2925 return 1;
2926}
2927
2928
2929static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002930new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002931{
2932 struct new_module *module;
2933 struct obj_section *sec;
2934 void *image;
2935 int ret;
2936 tgt_long m_addr;
2937
2938 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002939 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002940 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002941 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002942 module = (struct new_module *) sec->contents;
2943 m_addr = sec->header.sh_addr;
2944
2945 module->size_of_struct = sizeof(*module);
2946 module->size = m_size;
2947 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2948
2949 sec = obj_find_section(f, "__ksymtab");
2950 if (sec && sec->header.sh_size) {
2951 module->syms = sec->header.sh_addr;
2952 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2953 }
2954
2955 if (n_ext_modules_used) {
2956 sec = obj_find_section(f, ".kmodtab");
2957 module->deps = sec->header.sh_addr;
2958 module->ndeps = n_ext_modules_used;
2959 }
2960
2961 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002962 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002963 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002964 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002965
2966 sec = obj_find_section(f, "__ex_table");
2967 if (sec) {
2968 module->ex_table_start = sec->header.sh_addr;
2969 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2970 }
2971
2972 sec = obj_find_section(f, ".text.init");
2973 if (sec) {
2974 module->runsize = sec->header.sh_addr - m_addr;
2975 }
2976 sec = obj_find_section(f, ".data.init");
2977 if (sec) {
2978 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002979 module->runsize > sec->header.sh_addr - m_addr)
2980 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002981 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002982 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2983 if (sec && sec->header.sh_size) {
2984 module->archdata_start = (void*)sec->header.sh_addr;
2985 module->archdata_end = module->archdata_start + sec->header.sh_size;
2986 }
2987 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2988 if (sec && sec->header.sh_size) {
2989 module->kallsyms_start = (void*)sec->header.sh_addr;
2990 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2991 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002992
Eric Andersen9f16d612000-06-12 23:11:16 +00002993 /* Whew! All of the initialization is complete. Collect the final
2994 module image and give it to the kernel. */
2995
2996 image = xmalloc(m_size);
2997 obj_create_image(f, image);
2998
Eric Andersencb3b9b12004-06-22 11:50:52 +00002999 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00003000 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00003001 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00003002
3003 free(image);
3004
3005 return ret == 0;
3006}
3007
Eric Andersen9f16d612000-06-12 23:11:16 +00003008
3009/*======================================================================*/
3010
Eric Andersen044228d2001-07-17 01:12:36 +00003011static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003012obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3013 const char *string)
3014{
3015 struct obj_string_patch *p;
3016 struct obj_section *strsec;
3017 size_t len = strlen(string) + 1;
3018 char *loc;
3019
3020 p = xmalloc(sizeof(*p));
3021 p->next = f->string_patches;
3022 p->reloc_secidx = secidx;
3023 p->reloc_offset = offset;
3024 f->string_patches = p;
3025
3026 strsec = obj_find_section(f, ".kstrtab");
3027 if (strsec == NULL) {
3028 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3029 p->string_offset = 0;
3030 loc = strsec->contents;
3031 } else {
3032 p->string_offset = strsec->header.sh_size;
3033 loc = obj_extend_section(strsec, len);
3034 }
3035 memcpy(loc, string, len);
3036
3037 return 1;
3038}
3039
Eric Andersen044228d2001-07-17 01:12:36 +00003040static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003041obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3042 struct obj_symbol *sym)
3043{
3044 struct obj_symbol_patch *p;
3045
3046 p = xmalloc(sizeof(*p));
3047 p->next = f->symbol_patches;
3048 p->reloc_secidx = secidx;
3049 p->reloc_offset = offset;
3050 p->sym = sym;
3051 f->symbol_patches = p;
3052
3053 return 1;
3054}
3055
Eric Andersen044228d2001-07-17 01:12:36 +00003056static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003057{
3058 unsigned long i;
3059 int ret = 1;
3060
3061 for (i = 0; i < HASH_BUCKETS; ++i) {
3062 struct obj_symbol *sym;
3063 for (sym = f->symtab[i]; sym; sym = sym->next)
3064 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003065 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003066 sym->secidx = SHN_ABS;
3067 sym->value = 0;
3068 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003069 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003070 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003071 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003072 ret = 0;
3073 }
3074 }
3075 }
3076
3077 return ret;
3078}
3079
Eric Andersen044228d2001-07-17 01:12:36 +00003080static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003081{
3082 struct common_entry {
3083 struct common_entry *next;
3084 struct obj_symbol *sym;
3085 } *common_head = NULL;
3086
3087 unsigned long i;
3088
3089 for (i = 0; i < HASH_BUCKETS; ++i) {
3090 struct obj_symbol *sym;
3091 for (sym = f->symtab[i]; sym; sym = sym->next)
3092 if (sym->secidx == SHN_COMMON) {
3093 /* Collect all COMMON symbols and sort them by size so as to
3094 minimize space wasted by alignment requirements. */
3095 {
3096 struct common_entry **p, *n;
3097 for (p = &common_head; *p; p = &(*p)->next)
3098 if (sym->size <= (*p)->sym->size)
3099 break;
3100
3101 n = alloca(sizeof(*n));
3102 n->next = *p;
3103 n->sym = sym;
3104 *p = n;
3105 }
3106 }
3107 }
3108
3109 for (i = 1; i < f->local_symtab_size; ++i) {
3110 struct obj_symbol *sym = f->local_symtab[i];
3111 if (sym && sym->secidx == SHN_COMMON) {
3112 struct common_entry **p, *n;
3113 for (p = &common_head; *p; p = &(*p)->next)
3114 if (sym == (*p)->sym)
3115 break;
3116 else if (sym->size < (*p)->sym->size) {
3117 n = alloca(sizeof(*n));
3118 n->next = *p;
3119 n->sym = sym;
3120 *p = n;
3121 break;
3122 }
3123 }
3124 }
3125
3126 if (common_head) {
3127 /* Find the bss section. */
3128 for (i = 0; i < f->header.e_shnum; ++i)
3129 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3130 break;
3131
3132 /* If for some reason there hadn't been one, create one. */
3133 if (i == f->header.e_shnum) {
3134 struct obj_section *sec;
3135
3136 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3137 f->sections[i] = sec = arch_new_section();
3138 f->header.e_shnum = i + 1;
3139
3140 memset(sec, 0, sizeof(*sec));
3141 sec->header.sh_type = SHT_PROGBITS;
3142 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3143 sec->name = ".bss";
3144 sec->idx = i;
3145 }
3146
3147 /* Allocate the COMMONS. */
3148 {
3149 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3150 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3151 struct common_entry *c;
3152
3153 for (c = common_head; c; c = c->next) {
3154 ElfW(Addr) align = c->sym->value;
3155
3156 if (align > max_align)
3157 max_align = align;
3158 if (bss_size & (align - 1))
3159 bss_size = (bss_size | (align - 1)) + 1;
3160
3161 c->sym->secidx = i;
3162 c->sym->value = bss_size;
3163
3164 bss_size += c->sym->size;
3165 }
3166
3167 f->sections[i]->header.sh_size = bss_size;
3168 f->sections[i]->header.sh_addralign = max_align;
3169 }
3170 }
3171
3172 /* For the sake of patch relocation and parameter initialization,
3173 allocate zeroed data for NOBITS sections now. Note that after
3174 this we cannot assume NOBITS are really empty. */
3175 for (i = 0; i < f->header.e_shnum; ++i) {
3176 struct obj_section *s = f->sections[i];
3177 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003178 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003179 s->contents = memset(xmalloc(s->header.sh_size),
3180 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003181 else
3182 s->contents = NULL;
3183
Eric Andersen9f16d612000-06-12 23:11:16 +00003184 s->header.sh_type = SHT_PROGBITS;
3185 }
3186 }
3187}
3188
Eric Andersen044228d2001-07-17 01:12:36 +00003189static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003190{
3191 unsigned long dot = 0;
3192 struct obj_section *sec;
3193
3194 /* Finalize the positions of the sections relative to one another. */
3195
3196 for (sec = f->load_order; sec; sec = sec->load_next) {
3197 ElfW(Addr) align;
3198
3199 align = sec->header.sh_addralign;
3200 if (align && (dot & (align - 1)))
3201 dot = (dot | (align - 1)) + 1;
3202
3203 sec->header.sh_addr = dot;
3204 dot += sec->header.sh_size;
3205 }
3206
3207 return dot;
3208}
3209
Eric Andersen044228d2001-07-17 01:12:36 +00003210static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003211{
3212 int i, n = f->header.e_shnum;
3213 int ret = 1;
3214
3215 /* Finalize the addresses of the sections. */
3216
3217 f->baseaddr = base;
3218 for (i = 0; i < n; ++i)
3219 f->sections[i]->header.sh_addr += base;
3220
3221 /* And iterate over all of the relocations. */
3222
3223 for (i = 0; i < n; ++i) {
3224 struct obj_section *relsec, *symsec, *targsec, *strsec;
3225 ElfW(RelM) * rel, *relend;
3226 ElfW(Sym) * symtab;
3227 const char *strtab;
3228
3229 relsec = f->sections[i];
3230 if (relsec->header.sh_type != SHT_RELM)
3231 continue;
3232
3233 symsec = f->sections[relsec->header.sh_link];
3234 targsec = f->sections[relsec->header.sh_info];
3235 strsec = f->sections[symsec->header.sh_link];
3236
3237 rel = (ElfW(RelM) *) relsec->contents;
3238 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3239 symtab = (ElfW(Sym) *) symsec->contents;
3240 strtab = (const char *) strsec->contents;
3241
3242 for (; rel < relend; ++rel) {
3243 ElfW(Addr) value = 0;
3244 struct obj_symbol *intsym = NULL;
3245 unsigned long symndx;
3246 ElfW(Sym) * extsym = 0;
3247 const char *errmsg;
3248
3249 /* Attempt to find a value to use for this relocation. */
3250
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003251 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003252 if (symndx) {
3253 /* Note we've already checked for undefined symbols. */
3254
3255 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003256 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003257 /* Local symbols we look up in the local table to be sure
3258 we get the one that is really intended. */
3259 intsym = f->local_symtab[symndx];
3260 } else {
3261 /* Others we look up in the hash table. */
3262 const char *name;
3263 if (extsym->st_name)
3264 name = strtab + extsym->st_name;
3265 else
3266 name = f->sections[extsym->st_shndx]->name;
3267 intsym = obj_find_symbol(f, name);
3268 }
3269
3270 value = obj_symbol_final_value(f, intsym);
3271 intsym->referenced = 1;
3272 }
3273#if SHT_RELM == SHT_RELA
3274#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3275 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3276 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003277 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003278#endif
3279 value += rel->r_addend;
3280#endif
3281
3282 /* Do it! */
3283 switch (arch_apply_relocation
3284 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003285 case obj_reloc_ok:
3286 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003287
Eric Andersen3b1a7442003-12-24 20:30:45 +00003288 case obj_reloc_overflow:
3289 errmsg = "Relocation overflow";
3290 goto bad_reloc;
3291 case obj_reloc_dangerous:
3292 errmsg = "Dangerous relocation";
3293 goto bad_reloc;
3294 case obj_reloc_unhandled:
3295 errmsg = "Unhandled relocation";
3296bad_reloc:
3297 if (extsym) {
3298 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003299 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003300 strtab + extsym->st_name);
3301 } else {
3302 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003303 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003304 }
3305 ret = 0;
3306 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003307 }
3308 }
3309 }
3310
3311 /* Finally, take care of the patches. */
3312
3313 if (f->string_patches) {
3314 struct obj_string_patch *p;
3315 struct obj_section *strsec;
3316 ElfW(Addr) strsec_base;
3317 strsec = obj_find_section(f, ".kstrtab");
3318 strsec_base = strsec->header.sh_addr;
3319
3320 for (p = f->string_patches; p; p = p->next) {
3321 struct obj_section *targsec = f->sections[p->reloc_secidx];
3322 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3323 = strsec_base + p->string_offset;
3324 }
3325 }
3326
3327 if (f->symbol_patches) {
3328 struct obj_symbol_patch *p;
3329
3330 for (p = f->symbol_patches; p; p = p->next) {
3331 struct obj_section *targsec = f->sections[p->reloc_secidx];
3332 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3333 = obj_symbol_final_value(f, p->sym);
3334 }
3335 }
3336
3337 return ret;
3338}
3339
Eric Andersen044228d2001-07-17 01:12:36 +00003340static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003341{
3342 struct obj_section *sec;
3343 ElfW(Addr) base = f->baseaddr;
3344
3345 for (sec = f->load_order; sec; sec = sec->load_next) {
3346 char *secimg;
3347
Eric Andersen2bf658d2001-02-24 20:01:53 +00003348 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003349 continue;
3350
3351 secimg = image + (sec->header.sh_addr - base);
3352
3353 /* Note that we allocated data for NOBITS sections earlier. */
3354 memcpy(secimg, sec->contents, sec->header.sh_size);
3355 }
3356
3357 return 1;
3358}
3359
3360/*======================================================================*/
3361
Eric Andersen044228d2001-07-17 01:12:36 +00003362static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003363{
3364 struct obj_file *f;
3365 ElfW(Shdr) * section_headers;
3366 int shnum, i;
3367 char *shstrtab;
3368
3369 /* Read the file header. */
3370
3371 f = arch_new_file();
3372 memset(f, 0, sizeof(*f));
3373 f->symbol_cmp = strcmp;
3374 f->symbol_hash = obj_elf_hash;
3375 f->load_order_search_start = &f->load_order;
3376
3377 fseek(fp, 0, SEEK_SET);
3378 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003379 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003380 return NULL;
3381 }
3382
3383 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003384 || f->header.e_ident[EI_MAG1] != ELFMAG1
3385 || f->header.e_ident[EI_MAG2] != ELFMAG2
3386 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003387 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003388 return NULL;
3389 }
3390 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003391 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003392 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003393 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3394 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003395 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003396 return NULL;
3397 }
3398 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003399 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003400 return NULL;
3401 }
3402
3403 /* Read the section headers. */
3404
3405 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003406 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003407 (unsigned long) f->header.e_shentsize,
3408 (unsigned long) sizeof(ElfW(Shdr)));
3409 return NULL;
3410 }
3411
3412 shnum = f->header.e_shnum;
3413 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3414 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3415
3416 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3417 fseek(fp, f->header.e_shoff, SEEK_SET);
3418 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003419 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003420 return NULL;
3421 }
3422
3423 /* Read the section data. */
3424
3425 for (i = 0; i < shnum; ++i) {
3426 struct obj_section *sec;
3427
3428 f->sections[i] = sec = arch_new_section();
3429 memset(sec, 0, sizeof(*sec));
3430
3431 sec->header = section_headers[i];
3432 sec->idx = i;
3433
Eric Andersen2bf658d2001-02-24 20:01:53 +00003434 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003435 case SHT_NULL:
3436 case SHT_NOTE:
3437 case SHT_NOBITS:
3438 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003439 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003440
3441 case SHT_PROGBITS:
3442#if LOADBITS
3443 if (!loadprogbits) {
3444 sec->contents = NULL;
3445 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003446 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003447#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003448 case SHT_SYMTAB:
3449 case SHT_STRTAB:
3450 case SHT_RELM:
3451 if (sec->header.sh_size > 0) {
3452 sec->contents = xmalloc(sec->header.sh_size);
3453 fseek(fp, sec->header.sh_offset, SEEK_SET);
3454 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3455 bb_perror_msg("error reading ELF section data");
3456 return NULL;
3457 }
3458 } else {
3459 sec->contents = NULL;
3460 }
3461 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003462
3463#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003464 case SHT_RELA:
3465 bb_error_msg("RELA relocations not supported on this architecture");
3466 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003467#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003468 case SHT_REL:
3469 bb_error_msg("REL relocations not supported on this architecture");
3470 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003471#endif
3472
Eric Andersen3b1a7442003-12-24 20:30:45 +00003473 default:
3474 if (sec->header.sh_type >= SHT_LOPROC) {
3475 /* Assume processor specific section types are debug
3476 info and can safely be ignored. If this is ever not
3477 the case (Hello MIPS?), don't put ifdefs here but
3478 create an arch_load_proc_section(). */
3479 break;
3480 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003481
Eric Andersen3b1a7442003-12-24 20:30:45 +00003482 bb_error_msg("can't handle sections of type %ld",
3483 (long) sec->header.sh_type);
3484 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003485 }
3486 }
3487
3488 /* Do what sort of interpretation as needed by each section. */
3489
3490 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3491
3492 for (i = 0; i < shnum; ++i) {
3493 struct obj_section *sec = f->sections[i];
3494 sec->name = shstrtab + sec->header.sh_name;
3495 }
3496
3497 for (i = 0; i < shnum; ++i) {
3498 struct obj_section *sec = f->sections[i];
3499
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003500 /* .modinfo should be contents only but gcc has no attribute for that.
3501 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3502 */
3503 if (strcmp(sec->name, ".modinfo") == 0)
3504 sec->header.sh_flags &= ~SHF_ALLOC;
3505
Eric Andersen9f16d612000-06-12 23:11:16 +00003506 if (sec->header.sh_flags & SHF_ALLOC)
3507 obj_insert_section_load_order(f, sec);
3508
3509 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003510 case SHT_SYMTAB:
3511 {
3512 unsigned long nsym, j;
3513 char *strtab;
3514 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003515
Eric Andersen3b1a7442003-12-24 20:30:45 +00003516 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3517 bb_error_msg("symbol size mismatch: %lu != %lu",
3518 (unsigned long) sec->header.sh_entsize,
3519 (unsigned long) sizeof(ElfW(Sym)));
3520 return NULL;
3521 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003522
Eric Andersen3b1a7442003-12-24 20:30:45 +00003523 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3524 strtab = f->sections[sec->header.sh_link]->contents;
3525 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003526
Eric Andersen3b1a7442003-12-24 20:30:45 +00003527 /* Allocate space for a table of local symbols. */
3528 j = f->local_symtab_size = sec->header.sh_info;
3529 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003530
Eric Andersen3b1a7442003-12-24 20:30:45 +00003531 /* Insert all symbols into the hash table. */
3532 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3533 ElfW(Addr) val = sym->st_value;
3534 const char *name;
3535 if (sym->st_name)
3536 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003537 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003538 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003539 else
3540 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003541
Eric Andersenbf833552003-08-13 19:56:33 +00003542#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003543 /*
3544 * For sh64 it is possible that the target of a branch
3545 * requires a mode switch (32 to 16 and back again).
3546 *
3547 * This is implied by the lsb being set in the target
3548 * address for SHmedia mode and clear for SHcompact.
3549 */
3550 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003551#endif
3552
Eric Andersen3b1a7442003-12-24 20:30:45 +00003553 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3554 val, sym->st_size);
3555 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003556 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003557 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003558
Eric Andersen3b1a7442003-12-24 20:30:45 +00003559 case SHT_RELM:
3560 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3561 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3562 (unsigned long) sec->header.sh_entsize,
3563 (unsigned long) sizeof(ElfW(RelM)));
3564 return NULL;
3565 }
3566 break;
3567 /* XXX Relocation code from modutils-2.3.19 is not here.
3568 * Why? That's about 20 lines of code from obj/obj_load.c,
3569 * which gets done in a second pass through the sections.
3570 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003571 }
3572 }
3573
3574 return f;
3575}
3576
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003577#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003578/*
3579 * load the unloaded sections directly into the memory allocated by
3580 * kernel for the module
3581 */
3582
Eric Andersenac5dbd12001-08-22 05:26:08 +00003583static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003584{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003585 ElfW(Addr) base = f->baseaddr;
3586 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003587
Eric Andersen8ae319a2001-05-21 16:09:18 +00003588 for (sec = f->load_order; sec; sec = sec->load_next) {
3589
3590 /* section already loaded? */
3591 if (sec->contents != NULL)
3592 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003593
Eric Andersen8ae319a2001-05-21 16:09:18 +00003594 if (sec->header.sh_size == 0)
3595 continue;
3596
3597 sec->contents = imagebase + (sec->header.sh_addr - base);
3598 fseek(fp, sec->header.sh_offset, SEEK_SET);
3599 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003600 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003601 return 0;
3602 }
3603
3604 }
3605 return 1;
3606}
3607#endif
3608
Eric Andersen9f16d612000-06-12 23:11:16 +00003609static void hide_special_symbols(struct obj_file *f)
3610{
3611 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003612 SPFX "cleanup_module",
3613 SPFX "init_module",
3614 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003615 NULL
3616 };
3617
3618 struct obj_symbol *sym;
3619 const char *const *p;
3620
3621 for (p = specials; *p; ++p)
3622 if ((sym = obj_find_symbol(f, *p)) != NULL)
3623 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003624 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003625}
3626
Glenn L McGrath759515c2003-08-30 06:00:33 +00003627
Eric Andersen71ae64b2002-10-10 04:20:21 +00003628#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003629static int obj_gpl_license(struct obj_file *f, const char **license)
3630{
3631 struct obj_section *sec;
3632 /* This list must match *exactly* the list of allowable licenses in
3633 * linux/include/linux/module.h. Checking for leading "GPL" will not
3634 * work, somebody will use "GPL sucks, this is proprietary".
3635 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003636 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003637 "GPL",
3638 "GPL v2",
3639 "GPL and additional rights",
3640 "Dual BSD/GPL",
3641 "Dual MPL/GPL",
3642 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003643
Eric Andersen166fa462002-09-16 05:30:24 +00003644 if ((sec = obj_find_section(f, ".modinfo"))) {
3645 const char *value, *ptr, *endptr;
3646 ptr = sec->contents;
3647 endptr = ptr + sec->header.sh_size;
3648 while (ptr < endptr) {
3649 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3650 int i;
3651 if (license)
3652 *license = value+1;
3653 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3654 if (strcmp(value+1, gpl_licenses[i]) == 0)
3655 return(0);
3656 }
3657 return(2);
3658 }
3659 if (strchr(ptr, '\0'))
3660 ptr = strchr(ptr, '\0') + 1;
3661 else
3662 ptr = endptr;
3663 }
3664 }
3665 return(1);
3666}
3667
3668#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3669#define TAINT_PROPRIETORY_MODULE (1<<0)
3670#define TAINT_FORCED_MODULE (1<<1)
3671#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003672#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003673
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003674static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003675 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3676{
3677 char buf[80];
3678 int oldval;
3679 static int first = 1;
3680 if (fd < 0 && !kernel_has_tainted)
3681 return; /* New modutils on old kernel */
3682 printf("Warning: loading %s will taint the kernel: %s%s\n",
3683 m_name, text1, text2);
3684 if (first) {
3685 printf(" See %s for information about tainted modules\n", TAINT_URL);
3686 first = 0;
3687 }
3688 if (fd >= 0) {
3689 read(fd, buf, sizeof(buf)-1);
3690 buf[sizeof(buf)-1] = '\0';
3691 oldval = strtoul(buf, NULL, 10);
3692 sprintf(buf, "%d\n", oldval | taint);
3693 write(fd, buf, strlen(buf));
3694 }
3695}
3696
3697/* Check if loading this module will taint the kernel. */
3698static void check_tainted_module(struct obj_file *f, char *m_name)
3699{
3700 static const char tainted_file[] = TAINT_FILENAME;
3701 int fd, kernel_has_tainted;
3702 const char *ptr;
3703
3704 kernel_has_tainted = 1;
3705 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3706 if (errno == ENOENT)
3707 kernel_has_tainted = 0;
3708 else if (errno == EACCES)
3709 kernel_has_tainted = 1;
3710 else {
3711 perror(tainted_file);
3712 kernel_has_tainted = 0;
3713 }
3714 }
3715
3716 switch (obj_gpl_license(f, &ptr)) {
3717 case 0:
3718 break;
3719 case 1:
3720 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3721 break;
3722 case 2:
3723 /* The module has a non-GPL license so we pretend that the
3724 * kernel always has a taint flag to get a warning even on
3725 * kernels without the proc flag.
3726 */
3727 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3728 break;
3729 default:
3730 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3731 break;
3732 }
3733
3734 if (flag_force_load)
3735 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3736
3737 if (fd >= 0)
3738 close(fd);
3739}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003740#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3741#define check_tainted_module(x, y) do { } while(0);
3742#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003743
Eric Andersen889dd202003-01-23 04:48:34 +00003744#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3745/* add module source, timestamp, kernel version and a symbol for the
3746 * start of some sections. this info is used by ksymoops to do better
3747 * debugging.
3748 */
3749static int
3750get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3751{
3752#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003753 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003754#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003755 strncpy(str, "???", sizeof(str));
3756 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003757#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3758}
3759
3760/* add module source, timestamp, kernel version and a symbol for the
3761 * start of some sections. this info is used by ksymoops to do better
3762 * debugging.
3763 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003764static void
Eric Andersen889dd202003-01-23 04:48:34 +00003765add_ksymoops_symbols(struct obj_file *f, const char *filename,
3766 const char *m_name)
3767{
3768 static const char symprefix[] = "__insmod_";
3769 struct obj_section *sec;
3770 struct obj_symbol *sym;
3771 char *name, *absolute_filename;
3772 char str[STRVERSIONLEN], real[PATH_MAX];
3773 int i, l, lm_name, lfilename, use_ksymtab, version;
3774 struct stat statbuf;
3775
3776 static const char *section_names[] = {
3777 ".text",
3778 ".rodata",
3779 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003780 ".bss",
3781 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003782 };
3783
3784 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003785 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003786 }
3787 else {
3788 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003789 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003790 errno = save_errno;
3791 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003792 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003793 }
3794
3795 lm_name = strlen(m_name);
3796 lfilename = strlen(absolute_filename);
3797
3798 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3799 * are not to be exported. otherwise leave ksymtab alone for now, the
3800 * "export all symbols" compatibility code will export these symbols later.
3801 */
3802 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3803
3804 if ((sec = obj_find_section(f, ".this"))) {
3805 /* tag the module header with the object name, last modified
3806 * timestamp and module version. worst case for module version
3807 * is 0xffffff, decimal 16777215. putting all three fields in
3808 * one symbol is less readable but saves kernel space.
3809 */
3810 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003811 lm_name+ /* module name */
3812 2+ /* "_O" */
3813 lfilename+ /* object filename */
3814 2+ /* "_M" */
3815 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3816 2+ /* "_V" */
3817 8+ /* version in dec */
3818 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003819 name = xmalloc(l);
3820 if (stat(absolute_filename, &statbuf) != 0)
3821 statbuf.st_mtime = 0;
3822 version = get_module_version(f, str); /* -1 if not found */
3823 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003824 symprefix, m_name, absolute_filename,
3825 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3826 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003827 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003828 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003829 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003830 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003831 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003832 }
3833 free(absolute_filename);
3834#ifdef _NOT_SUPPORTED_
3835 /* record where the persistent data is going, same address as previous symbol */
3836
3837 if (f->persist) {
3838 l = sizeof(symprefix)+ /* "__insmod_" */
3839 lm_name+ /* module name */
3840 2+ /* "_P" */
3841 strlen(f->persist)+ /* data store */
3842 1; /* nul */
3843 name = xmalloc(l);
3844 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003845 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003846 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003847 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003848 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003849 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003850 }
3851#endif /* _NOT_SUPPORTED_ */
3852 /* tag the desired sections if size is non-zero */
3853
3854 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3855 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003856 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003857 l = sizeof(symprefix)+ /* "__insmod_" */
3858 lm_name+ /* module name */
3859 2+ /* "_S" */
3860 strlen(sec->name)+ /* section name */
3861 2+ /* "_L" */
3862 8+ /* length in dec */
3863 1; /* nul */
3864 name = xmalloc(l);
3865 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003866 symprefix, m_name, sec->name,
3867 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003868 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003869 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003870 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003871 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003872 }
3873 }
3874}
3875#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3876
Eric Andersenbe65c352003-01-23 04:57:35 +00003877#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3878static void print_load_map(struct obj_file *f)
3879{
3880 struct obj_symbol *sym;
3881 struct obj_symbol **all, **p;
3882 struct obj_section *sec;
3883 int i, nsyms, *loaded;
3884
3885 /* Report on the section layout. */
3886
3887 printf("Sections: Size %-*s Align\n",
3888 (int) (2 * sizeof(void *)), "Address");
3889
3890 for (sec = f->load_order; sec; sec = sec->load_next) {
3891 int a;
3892 unsigned long tmp;
3893
3894 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3895 tmp >>= 1;
3896 if (a == -1)
3897 a = 0;
3898
3899 printf("%-15s %08lx %0*lx 2**%d\n",
3900 sec->name,
3901 (long)sec->header.sh_size,
3902 (int) (2 * sizeof(void *)),
3903 (long)sec->header.sh_addr,
3904 a);
3905 }
3906#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3907 /* Quick reference which section indicies are loaded. */
3908
3909 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3910 while (--i >= 0)
3911 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3912
3913 /* Collect the symbols we'll be listing. */
3914
3915 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3916 for (sym = f->symtab[i]; sym; sym = sym->next)
3917 if (sym->secidx <= SHN_HIRESERVE
3918 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3919 ++nsyms;
3920
3921 all = alloca(nsyms * sizeof(struct obj_symbol *));
3922
3923 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3924 for (sym = f->symtab[i]; sym; sym = sym->next)
3925 if (sym->secidx <= SHN_HIRESERVE
3926 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3927 *p++ = sym;
3928
3929 /* And list them. */
3930 printf("\nSymbols:\n");
3931 for (p = all; p < all + nsyms; ++p) {
3932 char type = '?';
3933 unsigned long value;
3934
3935 sym = *p;
3936 if (sym->secidx == SHN_ABS) {
3937 type = 'A';
3938 value = sym->value;
3939 } else if (sym->secidx == SHN_UNDEF) {
3940 type = 'U';
3941 value = 0;
3942 } else {
3943 sec = f->sections[sym->secidx];
3944
3945 if (sec->header.sh_type == SHT_NOBITS)
3946 type = 'B';
3947 else if (sec->header.sh_flags & SHF_ALLOC) {
3948 if (sec->header.sh_flags & SHF_EXECINSTR)
3949 type = 'T';
3950 else if (sec->header.sh_flags & SHF_WRITE)
3951 type = 'D';
3952 else
3953 type = 'R';
3954 }
3955 value = sym->value + sec->header.sh_addr;
3956 }
3957
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003958 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003959 type = tolower(type);
3960
3961 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3962 type, sym->name);
3963 }
3964#endif
3965}
3966
3967#endif
3968
Rob Landleydfba7412006-03-06 20:47:33 +00003969int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003970{
Eric Andersena18aaf12001-01-24 19:07:09 +00003971 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003972 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003973 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003974 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003975 unsigned long m_size;
3976 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003977 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003978 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003979 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003980 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003981 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003982#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003983 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003984 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003985 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003986#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003987#ifdef CONFIG_FEATURE_CLEAN_UP
3988 FILE *fp = 0;
3989#else
3990 FILE *fp;
3991#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003992#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3993 int flag_print_load_map = 0;
3994#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003995 int k_version = 0;
3996 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003997
Erik Andersene49d5ec2000-02-08 19:58:47 +00003998 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003999#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004000 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004001#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004002 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00004003#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004004 {
4005 switch (opt) {
4006 case 'f': /* force loading */
4007 flag_force_load = 1;
4008 break;
4009 case 'k': /* module loaded by kerneld, auto-cleanable */
4010 flag_autoclean = 1;
4011 break;
4012 case 's': /* log to syslog */
4013 /* log to syslog -- not supported */
4014 /* but kernel needs this for request_module(), */
4015 /* as this calls: modprobe -k -s -- <module> */
4016 /* so silently ignore this flag */
4017 break;
4018 case 'v': /* verbose output */
4019 flag_verbose = 1;
4020 break;
4021 case 'q': /* silent */
4022 flag_quiet = 1;
4023 break;
4024 case 'x': /* do not export externs */
4025 flag_export = 0;
4026 break;
4027 case 'o': /* name the output module */
4028 free(m_name);
4029 m_name = bb_xstrdup(optarg);
4030 break;
4031 case 'L': /* Stub warning */
4032 /* This is needed for compatibility with modprobe.
4033 * In theory, this does locking, but we don't do
4034 * that. So be careful and plan your life around not
4035 * loading the same module 50 times concurrently. */
4036 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004037#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004038 case 'm': /* print module load map */
4039 flag_print_load_map = 1;
4040 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004041#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004042 default:
4043 bb_show_usage();
4044 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004045 }
Eric Andersen03d80912003-12-19 21:04:19 +00004046
Eric Andersena18aaf12001-01-24 19:07:09 +00004047 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004048 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00004049 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004050
Erik Andersene49d5ec2000-02-08 19:58:47 +00004051 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00004052 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00004053 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004054 len = strlen(tmp);
4055
Eric Andersen03d80912003-12-19 21:04:19 +00004056 if (uname(&myuname) == 0) {
4057 if (myuname.release[0] == '2') {
4058 k_version = myuname.release[2] - '0';
4059 }
4060 }
4061
4062#if defined(CONFIG_FEATURE_2_6_MODULES)
4063 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004064 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004065 len-=3;
4066 tmp[len] = '\0';
4067 }
4068 else
4069#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004070 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4071 len-=2;
4072 tmp[len] = '\0';
4073 }
Eric Andersen2d342152002-06-18 05:16:25 +00004074
Eric Andersen03d80912003-12-19 21:04:19 +00004075
4076#if defined(CONFIG_FEATURE_2_6_MODULES)
4077 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004078 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004079 else
Eric Andersen03d80912003-12-19 21:04:19 +00004080#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004081 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004082
Eric Andersen61f83052002-06-22 17:15:42 +00004083 if (!m_name) {
4084 m_name = tmp;
4085 } else {
4086 free(tmp1);
4087 tmp1 = 0; /* flag for free(m_name) before exit() */
4088 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004089
Eric Andersen14d35432001-05-14 17:07:32 +00004090 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004091 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4092 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004093 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4094 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004095 if (k_version) { /* uname succeedd */
4096 char *module_dir;
4097 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004098 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004099
Eric Andersen03d80912003-12-19 21:04:19 +00004100 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004101 /* Jump through hoops in case /lib/modules/`uname -r`
4102 * is a symlink. We do not want recursive_action to
4103 * follow symlinks, but we do want to follow the
4104 * /lib/modules/`uname -r` dir, So resolve it ourselves
4105 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004106 if (realpath (tmdn, real_module_dir) == NULL)
4107 module_dir = tmdn;
4108 else
4109 module_dir = real_module_dir;
4110 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004111 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004112 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004113 }
4114
4115 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004116 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004117 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004118 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004119
Eric Andersen03d80912003-12-19 21:04:19 +00004120 free(m_filename);
4121 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004122 if (realpath (_PATH_MODULES, module_dir) == NULL)
4123 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004124 /* No module found under /lib/modules/`uname -r`, this
4125 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004126 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004127 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004128 {
Eric Andersen61f83052002-06-22 17:15:42 +00004129 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004130 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004131 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004132 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004133 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004134 }
4135 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004136 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004137 }
Eric Andersen03d80912003-12-19 21:04:19 +00004138 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004139 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004140
Rob Landley999af202005-12-11 20:14:12 +00004141 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004142 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004143
Eric Andersene7047882003-12-11 01:42:13 +00004144#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004145 if (k_version > 4)
4146 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004147 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004148 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004149 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004150 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004151#endif
4152
Eric Andersen8ae319a2001-05-21 16:09:18 +00004153 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004154 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004155
Eric Andersen9f16d612000-06-12 23:11:16 +00004156 if (get_modinfo_value(f, "kernel_version") == NULL)
4157 m_has_modinfo = 0;
4158 else
4159 m_has_modinfo = 1;
4160
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004161#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004162 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004163 if (!flag_quiet) {
4164 if (uname(&uts_info) < 0)
4165 uts_info.release[0] = '\0';
4166 if (m_has_modinfo) {
4167 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004168 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004169 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004170 "compiled for");
4171 goto out;
4172 }
4173 }
4174
4175 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4176 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004177 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004178 "\t%s was compiled for kernel version %s\n"
4179 "\twhile this kernel is version %s",
4180 m_filename, m_strversion, uts_info.release);
4181 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004182 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004183 "\t%s was compiled for kernel version %s\n"
4184 "\twhile this kernel is version %s.",
4185 m_filename, m_strversion, uts_info.release);
4186 goto out;
4187 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004188 }
4189 }
4190 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004191#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004192
Eric Andersencb3b9b12004-06-22 11:50:52 +00004193 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004194 if (!new_get_kernel_symbols())
4195 goto out;
4196 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004197 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004198 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004199 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004200 }
4201
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004202#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004203 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004204 if (m_has_modinfo)
4205 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004206
4207 if (m_crcs != k_crcs)
4208 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004209#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004210
Erik Andersene49d5ec2000-02-08 19:58:47 +00004211 /* Let the module know about the kernel symbols. */
4212 add_kernel_symbols(f);
4213
Eric Andersen9f16d612000-06-12 23:11:16 +00004214 /* Allocate common symbols, symbol tables, and string tables. */
4215
Eric Andersencb3b9b12004-06-22 11:50:52 +00004216 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004217 {
4218 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004219 }
4220
Eric Andersen9f16d612000-06-12 23:11:16 +00004221 if (!obj_check_undefineds(f)) {
4222 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004223 }
4224 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004225 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004226
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004227 /* done with the module name, on to the optional var=value arguments */
4228 ++optind;
4229
Eric Andersen9f16d612000-06-12 23:11:16 +00004230 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004231 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004232 {
4233 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004234 }
4235 }
4236
Eric Andersen9f16d612000-06-12 23:11:16 +00004237 arch_create_got(f);
4238 hide_special_symbols(f);
4239
Eric Andersen889dd202003-01-23 04:48:34 +00004240#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4241 add_ksymoops_symbols(f, m_filename, m_name);
4242#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4243
Eric Andersencb3b9b12004-06-22 11:50:52 +00004244 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004245
Erik Andersene49d5ec2000-02-08 19:58:47 +00004246 /* Find current size of the module */
4247 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004248
4249
Erik Andersene49d5ec2000-02-08 19:58:47 +00004250 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004251 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004252 case EEXIST:
4253 bb_error_msg("A module named %s already exists", m_name);
4254 goto out;
4255 case ENOMEM:
4256 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4257 m_size);
4258 goto out;
4259 default:
4260 bb_perror_msg("create_module: %s", m_name);
4261 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004262 }
Erik Andersend387d011999-12-21 02:55:11 +00004263
Eric Andersen8ae319a2001-05-21 16:09:18 +00004264#if !LOADBITS
4265 /*
4266 * the PROGBITS section was not loaded by the obj_load
4267 * now we can load them directly into the kernel memory
4268 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004269 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004270 delete_module(m_name);
4271 goto out;
4272 }
Eric Andersen03d80912003-12-19 21:04:19 +00004273#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004274
Eric Andersen9f16d612000-06-12 23:11:16 +00004275 if (!obj_relocate(f, m_addr)) {
4276 delete_module(m_name);
4277 goto out;
4278 }
Erik Andersend387d011999-12-21 02:55:11 +00004279
Eric Andersencb3b9b12004-06-22 11:50:52 +00004280 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004281 {
4282 delete_module(m_name);
4283 goto out;
4284 }
4285
Eric Andersenbe65c352003-01-23 04:57:35 +00004286#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4287 if(flag_print_load_map)
4288 print_load_map(f);
4289#endif
4290
Matt Kraai3e856ce2000-12-01 02:55:13 +00004291 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004292
4293out:
Eric Andersen61f83052002-06-22 17:15:42 +00004294#ifdef CONFIG_FEATURE_CLEAN_UP
4295 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004296 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004297 free(tmp1);
4298 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004299 free(m_name);
4300 }
4301 free(m_filename);
4302#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004303 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004304}
Eric Andersene7047882003-12-11 01:42:13 +00004305
4306
4307#endif
4308
4309
4310#ifdef CONFIG_FEATURE_2_6_MODULES
4311
4312#include <sys/mman.h>
4313#include <asm/unistd.h>
4314#include <sys/syscall.h>
4315
4316/* We use error numbers in a loose translation... */
4317static const char *moderror(int err)
4318{
4319 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004320 case ENOEXEC:
4321 return "Invalid module format";
4322 case ENOENT:
4323 return "Unknown symbol in module";
4324 case ESRCH:
4325 return "Module has wrong symbol version";
4326 case EINVAL:
4327 return "Invalid parameters";
4328 default:
4329 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004330 }
4331}
4332
Rob Landleydfba7412006-03-06 20:47:33 +00004333int insmod_ng_main( int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004334{
4335 int i;
4336 int fd;
4337 long int ret;
4338 struct stat st;
4339 unsigned long len;
4340 void *map;
4341 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004342
Eric Andersene7047882003-12-11 01:42:13 +00004343 filename = argv[1];
4344 if (!filename) {
4345 bb_show_usage();
4346 return -1;
4347 }
4348
4349 /* Rest is options */
4350 for (i = 2; i < argc; i++) {
4351 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4352 /* Spaces handled by "" pairs, but no way of escaping quotes */
4353 if (strchr(argv[i], ' ')) {
4354 strcat(options, "\"");
4355 strcat(options, argv[i]);
4356 strcat(options, "\"");
4357 } else {
4358 strcat(options, argv[i]);
4359 }
4360 strcat(options, " ");
4361 }
4362
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +00004363 fd = bb_xopen3(filename, O_RDONLY, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004364
4365 fstat(fd, &st);
4366 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004367 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004368 if (map == MAP_FAILED) {
4369 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4370 }
4371
4372 ret = syscall(__NR_init_module, map, len, options);
4373 if (ret != 0) {
4374 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004375 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004376 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004377
Eric Andersene7047882003-12-11 01:42:13 +00004378 return 0;
4379}
4380
4381#endif