blob: 3aabadd26060d51127b887bfb866d601d2bca739 [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"
Rob Landley519d7df2006-08-09 20:56:23 +000062#include <libgen.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Eric Andersene7047882003-12-11 01:42:13 +000065#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
Eric Andersene7047882003-12-11 01:42:13 +000066 !defined(CONFIG_FEATURE_2_6_MODULES)
67#define CONFIG_FEATURE_2_4_MODULES
68#endif
69
Eric Andersencb3b9b12004-06-22 11:50:52 +000070#if !defined(CONFIG_FEATURE_2_4_MODULES)
Eric Andersene7047882003-12-11 01:42:13 +000071#define insmod_ng_main insmod_main
72#endif
73
Eric Andersene7047882003-12-11 01:42:13 +000074#if defined(CONFIG_FEATURE_2_6_MODULES)
75extern int insmod_ng_main( int argc, char **argv);
76#endif
77
Eric Andersencb3b9b12004-06-22 11:50:52 +000078
79#if defined(CONFIG_FEATURE_2_4_MODULES)
80
Eric Andersen64c8b172001-04-05 07:33:10 +000081
Eric Andersenbdfd0d72001-10-24 05:00:29 +000082#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000083#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000084#else
85#define LOADBITS 1
86#endif
87
Eric Andersen90fe7fe2001-02-20 20:47:08 +000088
Mike Frysinger63654c12004-12-26 09:13:32 +000089/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000090#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000091#define MATCH_MACHINE(x) (x == EM_ALPHA)
92#define SHT_RELM SHT_RELA
93#define Elf64_RelM Elf64_Rela
94#define ELFCLASSM ELFCLASS64
95#endif
96
Eric Andersen45a05132004-09-02 23:03:25 +000097/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000103#define CONFIG_USE_PLT_ENTRIES
104#define CONFIG_PLT_ENTRY_SIZE 8
105#define CONFIG_USE_GOT_ENTRIES
106#define CONFIG_GOT_ENTRY_SIZE 8
107#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000108#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000109
Mike Frysingerb306cb72006-06-06 06:15:52 +0000110/* blackfin */
111#if defined(BFIN)
112#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
113#define SHT_RELM SHT_RELA
114#define Elf32_RelM Elf32_Rela
115#define ELFCLASSM ELFCLASS32
116#endif
117
Eric Andersen45a05132004-09-02 23:03:25 +0000118/* CRIS */
119#if defined(__cris__)
120#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000121#define SHT_RELM SHT_RELA
122#define Elf32_RelM Elf32_Rela
123#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000124#ifndef EM_CRIS
125#define EM_CRIS 76
126#define R_CRIS_NONE 0
127#define R_CRIS_32 3
128#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000129#endif
130
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000131/* H8/300 */
132#if defined(__H8300H__) || defined(__H8300S__)
133#define MATCH_MACHINE(x) (x == EM_H8_300)
134#define SHT_RELM SHT_RELA
135#define Elf32_RelM Elf32_Rela
136#define ELFCLASSM ELFCLASS32
137#define CONFIG_USE_SINGLE
138#define SYMBOL_PREFIX "_"
139#endif
140
Mike Frysinger63654c12004-12-26 09:13:32 +0000141/* PA-RISC / HP-PA */
142#if defined(__hppa__)
143#define MATCH_MACHINE(x) (x == EM_PARISC)
144#define SHT_RELM SHT_RELA
145#if defined(__LP64__)
146#define Elf64_RelM Elf64_Rela
147#define ELFCLASSM ELFCLASS64
148#else
149#define Elf32_RelM Elf32_Rela
150#define ELFCLASSM ELFCLASS32
151#endif
152#endif
153
Eric Andersen45a05132004-09-02 23:03:25 +0000154/* x86 */
155#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000156#ifndef EM_486
157#define MATCH_MACHINE(x) (x == EM_386)
158#else
159#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
160#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000161#define SHT_RELM SHT_REL
162#define Elf32_RelM Elf32_Rel
163#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000164#define CONFIG_USE_GOT_ENTRIES
165#define CONFIG_GOT_ENTRY_SIZE 4
166#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* IA64, aka Itanium */
170#if defined(__ia64__)
171#define MATCH_MACHINE(x) (x == EM_IA_64)
172#define SHT_RELM SHT_RELA
173#define Elf64_RelM Elf64_Rela
174#define ELFCLASSM ELFCLASS64
175#endif
176
177/* m68k */
178#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define MATCH_MACHINE(x) (x == EM_68K)
180#define SHT_RELM SHT_RELA
181#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000182#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000183#define CONFIG_USE_GOT_ENTRIES
184#define CONFIG_GOT_ENTRY_SIZE 4
185#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000186#endif
187
Mike Frysingerb306cb72006-06-06 06:15:52 +0000188/* Microblaze */
189#if defined(__microblaze__)
190#define CONFIG_USE_SINGLE
191#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
192#define SHT_RELM SHT_RELA
193#define Elf32_RelM Elf32_Rela
194#define ELFCLASSM ELFCLASS32
195#endif
196
Eric Andersen45a05132004-09-02 23:03:25 +0000197/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000198#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000199#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
200#define SHT_RELM SHT_REL
201#define Elf32_RelM Elf32_Rel
202#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000203/* Account for ELF spec changes. */
204#ifndef EM_MIPS_RS3_LE
205#ifdef EM_MIPS_RS4_BE
206#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
207#else
208#define EM_MIPS_RS3_LE 10
209#endif
210#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000211#define ARCHDATAM "__dbe_table"
212#endif
213
Mike Frysingerf982d862006-01-04 00:11:26 +0000214/* Nios II */
215#if defined(__nios2__)
216#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
217#define SHT_RELM SHT_RELA
218#define Elf32_RelM Elf32_Rela
219#define ELFCLASSM ELFCLASS32
220#endif
221
Eric Andersen45a05132004-09-02 23:03:25 +0000222/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000223#if defined(__powerpc64__)
224#define MATCH_MACHINE(x) (x == EM_PPC64)
225#define SHT_RELM SHT_RELA
226#define Elf64_RelM Elf64_Rela
227#define ELFCLASSM ELFCLASS64
228#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000229#define MATCH_MACHINE(x) (x == EM_PPC)
230#define SHT_RELM SHT_RELA
231#define Elf32_RelM Elf32_Rela
232#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000233#define CONFIG_USE_PLT_ENTRIES
234#define CONFIG_PLT_ENTRY_SIZE 16
235#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000236#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000237#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000238#define ARCHDATAM "__ftr_fixup"
239#endif
240
Eric Andersen45a05132004-09-02 23:03:25 +0000241/* S390 */
242#if defined(__s390__)
243#define MATCH_MACHINE(x) (x == EM_S390)
244#define SHT_RELM SHT_RELA
245#define Elf32_RelM Elf32_Rela
246#define ELFCLASSM ELFCLASS32
247#define CONFIG_USE_PLT_ENTRIES
248#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000249#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000250#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000251#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000252#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000253
Eric Andersen45a05132004-09-02 23:03:25 +0000254/* SuperH */
255#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000256#define MATCH_MACHINE(x) (x == EM_SH)
257#define SHT_RELM SHT_RELA
258#define Elf32_RelM Elf32_Rela
259#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000260#define CONFIG_USE_GOT_ENTRIES
261#define CONFIG_GOT_ENTRY_SIZE 4
262#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000263/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000264/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000265#if defined(__sh__) && BB_BIG_ENDIAN
266# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000267#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000268/* it may or may not work on the SH1/SH2... Error on those also */
269#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000270#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000271#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000272#endif
273
Eric Andersen45a05132004-09-02 23:03:25 +0000274/* Sparc */
275#if defined(__sparc__)
276#define MATCH_MACHINE(x) (x == EM_SPARC)
277#define SHT_RELM SHT_RELA
278#define Elf32_RelM Elf32_Rela
279#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000280#endif
281
Eric Andersen45a05132004-09-02 23:03:25 +0000282/* v850e */
283#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000284#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
285#define SHT_RELM SHT_RELA
286#define Elf32_RelM Elf32_Rela
287#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000288#define CONFIG_USE_PLT_ENTRIES
289#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000290#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000291#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000292#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000293#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000294#define SYMBOL_PREFIX "_"
295#endif
296
Eric Andersen45a05132004-09-02 23:03:25 +0000297/* X86_64 */
298#if defined(__x86_64__)
299#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000300#define SHT_RELM SHT_RELA
Mike Frysinger91fbdac2005-10-02 06:44:39 +0000301#define CONFIG_USE_GOT_ENTRIES
302#define CONFIG_GOT_ENTRY_SIZE 8
303#define CONFIG_USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000304#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000305#define ELFCLASSM ELFCLASS64
306#endif
307
Eric Andersencffd5022002-05-24 06:50:15 +0000308#ifndef SHT_RELM
309#error Sorry, but insmod.c does not yet support this architecture...
310#endif
311
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313//----------------------------------------------------------------------------
314//--------modutils module.h, lines 45-242
315//----------------------------------------------------------------------------
316
317/* Definitions for the Linux module syscall interface.
318 Copyright 1996, 1997 Linux International.
319
320 Contributed by Richard Henderson <rth@tamu.edu>
321
322 This file is part of the Linux modutils.
323
324 This program is free software; you can redistribute it and/or modify it
325 under the terms of the GNU General Public License as published by the
326 Free Software Foundation; either version 2 of the License, or (at your
327 option) any later version.
328
329 This program is distributed in the hope that it will be useful, but
330 WITHOUT ANY WARRANTY; without even the implied warranty of
331 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 General Public License for more details.
333
334 You should have received a copy of the GNU General Public License
335 along with this program; if not, write to the Free Software Foundation,
336 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
337
338
339#ifndef MODUTILS_MODULE_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000340/* Why? static const int MODUTILS_MODULE_H = 1;*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000341
Eric Andersen9f16d612000-06-12 23:11:16 +0000342/*======================================================================*/
343/* For sizeof() which are related to the module platform and not to the
344 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
345
346#define tgt_sizeof_char sizeof(char)
347#define tgt_sizeof_short sizeof(short)
348#define tgt_sizeof_int sizeof(int)
349#define tgt_sizeof_long sizeof(long)
350#define tgt_sizeof_char_p sizeof(char *)
351#define tgt_sizeof_void_p sizeof(void *)
352#define tgt_long long
353
354#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
355#undef tgt_sizeof_long
356#undef tgt_sizeof_char_p
357#undef tgt_sizeof_void_p
358#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000359enum {
360 tgt_sizeof_long = 8,
361 tgt_sizeof_char_p = 8,
362 tgt_sizeof_void_p = 8
363};
Eric Andersen9f16d612000-06-12 23:11:16 +0000364#define tgt_long long long
365#endif
366
367/*======================================================================*/
368/* The structures used in Linux 2.1. */
369
370/* Note: new_module_symbol does not use tgt_long intentionally */
371struct new_module_symbol
372{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000373 unsigned long value;
374 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000375};
376
377struct new_module_persist;
378
379struct new_module_ref
380{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000381 unsigned tgt_long dep; /* kernel addresses */
382 unsigned tgt_long ref;
383 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000384};
385
386struct new_module
387{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000388 unsigned tgt_long size_of_struct; /* == sizeof(module) */
389 unsigned tgt_long next;
390 unsigned tgt_long name;
391 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000392
Eric Andersen3b1a7442003-12-24 20:30:45 +0000393 tgt_long usecount;
394 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000395
Eric Andersen3b1a7442003-12-24 20:30:45 +0000396 unsigned nsyms;
397 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000398
Eric Andersen3b1a7442003-12-24 20:30:45 +0000399 unsigned tgt_long syms;
400 unsigned tgt_long deps;
401 unsigned tgt_long refs;
402 unsigned tgt_long init;
403 unsigned tgt_long cleanup;
404 unsigned tgt_long ex_table_start;
405 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000406#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000407 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000408#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000409 /* Everything after here is extension. */
410 unsigned tgt_long persist_start;
411 unsigned tgt_long persist_end;
412 unsigned tgt_long can_unload;
413 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000414 const char *kallsyms_start; /* All symbols for kernel debugging */
415 const char *kallsyms_end;
416 const char *archdata_start; /* arch specific data for module */
417 const char *archdata_end;
418 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000419};
420
Eric Andersencffd5022002-05-24 06:50:15 +0000421#ifdef ARCHDATAM
422#define ARCHDATA_SEC_NAME ARCHDATAM
423#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000424#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000425#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000426#define KALLSYMS_SEC_NAME "__kallsyms"
427
428
Eric Andersen9f16d612000-06-12 23:11:16 +0000429struct new_module_info
430{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000431 unsigned long addr;
432 unsigned long size;
433 unsigned long flags;
434 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000435};
436
437/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000438enum {
439 NEW_MOD_RUNNING = 1,
440 NEW_MOD_DELETED = 2,
441 NEW_MOD_AUTOCLEAN = 4,
442 NEW_MOD_VISITED = 8,
443 NEW_MOD_USED_ONCE = 16
444};
Eric Andersen9f16d612000-06-12 23:11:16 +0000445
Eric Andersencb3b9b12004-06-22 11:50:52 +0000446int init_module(const char *name, const struct new_module *);
447int query_module(const char *name, int which, void *buf,
448 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000449
450/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000451enum {
452 QM_MODULES = 1,
453 QM_DEPS = 2,
454 QM_REFS = 3,
455 QM_SYMBOLS = 4,
456 QM_INFO = 5
457};
Eric Andersen9f16d612000-06-12 23:11:16 +0000458
459/*======================================================================*/
460/* The system calls unchanged between 2.0 and 2.1. */
461
462unsigned long create_module(const char *, size_t);
463int delete_module(const char *);
464
465
466#endif /* module.h */
467
468//----------------------------------------------------------------------------
469//--------end of modutils module.h
470//----------------------------------------------------------------------------
471
472
473
474//----------------------------------------------------------------------------
475//--------modutils obj.h, lines 253-462
476//----------------------------------------------------------------------------
477
478/* Elf object file loading and relocation routines.
479 Copyright 1996, 1997 Linux International.
480
481 Contributed by Richard Henderson <rth@tamu.edu>
482
483 This file is part of the Linux modutils.
484
485 This program is free software; you can redistribute it and/or modify it
486 under the terms of the GNU General Public License as published by the
487 Free Software Foundation; either version 2 of the License, or (at your
488 option) any later version.
489
490 This program is distributed in the hope that it will be useful, but
491 WITHOUT ANY WARRANTY; without even the implied warranty of
492 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
493 General Public License for more details.
494
495 You should have received a copy of the GNU General Public License
496 along with this program; if not, write to the Free Software Foundation,
497 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
498
499
500#ifndef MODUTILS_OBJ_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000501/* Why? static const int MODUTILS_OBJ_H = 1; */
Eric Andersen9f16d612000-06-12 23:11:16 +0000502
Eric Andersen9f16d612000-06-12 23:11:16 +0000503/* The relocatable object is manipulated using elfin types. */
504
505#include <stdio.h>
506#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000507#include <endian.h>
508
Eric Andersen9f16d612000-06-12 23:11:16 +0000509#ifndef ElfW
510# if ELFCLASSM == ELFCLASS32
511# define ElfW(x) Elf32_ ## x
512# define ELFW(x) ELF32_ ## x
513# else
514# define ElfW(x) Elf64_ ## x
515# define ELFW(x) ELF64_ ## x
516# endif
517#endif
518
Eric Andersen85e5e722003-07-22 08:56:55 +0000519/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000520#ifndef ELF32_ST_INFO
521# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
522#endif
523
524#ifndef ELF64_ST_INFO
525# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
526#endif
527
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000528#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
529#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
530#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
531#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
532#define ELF_R_SYM(val) ELFW(R_SYM)(val)
533
Eric Andersen9f16d612000-06-12 23:11:16 +0000534struct obj_string_patch;
535struct obj_symbol_patch;
536
537struct obj_section
538{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000539 ElfW(Shdr) header;
540 const char *name;
541 char *contents;
542 struct obj_section *load_next;
543 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000544};
545
546struct obj_symbol
547{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000548 struct obj_symbol *next; /* hash table link */
549 const char *name;
550 unsigned long value;
551 unsigned long size;
552 int secidx; /* the defining section index/module */
553 int info;
554 int ksymidx; /* for export to the kernel symtab */
555 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000556};
557
558/* Hardcode the hash table size. We shouldn't be needing so many
559 symbols that we begin to degrade performance, and we get a big win
560 by giving the compiler a constant divisor. */
561
562#define HASH_BUCKETS 521
563
564struct obj_file
565{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000566 ElfW(Ehdr) header;
567 ElfW(Addr) baseaddr;
568 struct obj_section **sections;
569 struct obj_section *load_order;
570 struct obj_section **load_order_search_start;
571 struct obj_string_patch *string_patches;
572 struct obj_symbol_patch *symbol_patches;
573 int (*symbol_cmp)(const char *, const char *);
574 unsigned long (*symbol_hash)(const char *);
575 unsigned long local_symtab_size;
576 struct obj_symbol **local_symtab;
577 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000578};
579
580enum obj_reloc
581{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000582 obj_reloc_ok,
583 obj_reloc_overflow,
584 obj_reloc_dangerous,
585 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000586};
587
588struct obj_string_patch
589{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000590 struct obj_string_patch *next;
591 int reloc_secidx;
592 ElfW(Addr) reloc_offset;
593 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000594};
595
596struct obj_symbol_patch
597{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000598 struct obj_symbol_patch *next;
599 int reloc_secidx;
600 ElfW(Addr) reloc_offset;
601 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000602};
603
604
605/* Generic object manipulation routines. */
606
Eric Andersen044228d2001-07-17 01:12:36 +0000607static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000608
Eric Andersen044228d2001-07-17 01:12:36 +0000609static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000610
Eric Andersen044228d2001-07-17 01:12:36 +0000611static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000612 const char *name);
613
Eric Andersen044228d2001-07-17 01:12:36 +0000614static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000615 struct obj_symbol *sym);
616
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000617#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000618static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000619 int (*cmp)(const char *, const char *),
620 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000621#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000622
Eric Andersen044228d2001-07-17 01:12:36 +0000623static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000624 const char *name);
625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 struct obj_section *sec);
628
Eric Andersen044228d2001-07-17 01:12:36 +0000629static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000630 const char *name,
631 unsigned long align,
632 unsigned long size);
633
Eric Andersen044228d2001-07-17 01:12:36 +0000634static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000635 const char *name,
636 unsigned long align,
637 unsigned long size);
638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000642 const char *string);
643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000645 struct obj_symbol *sym);
646
Eric Andersen044228d2001-07-17 01:12:36 +0000647static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000648
Eric Andersen044228d2001-07-17 01:12:36 +0000649static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
Eric Andersen044228d2001-07-17 01:12:36 +0000651static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000652
Eric Andersen044228d2001-07-17 01:12:36 +0000653static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000658
659/* Architecture specific manipulation routines. */
660
Eric Andersen044228d2001-07-17 01:12:36 +0000661static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000662
Eric Andersen044228d2001-07-17 01:12:36 +0000663static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000664
Eric Andersen044228d2001-07-17 01:12:36 +0000665static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000666
Eric Andersen044228d2001-07-17 01:12:36 +0000667static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000668 struct obj_section *targsec,
669 struct obj_section *symsec,
670 struct obj_symbol *sym,
671 ElfW(RelM) *rel, ElfW(Addr) value);
672
Eric Andersencffd5022002-05-24 06:50:15 +0000673static void arch_create_got (struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000674#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000675static int obj_gpl_license(struct obj_file *f, const char **license);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000676#endif /* ENABLE_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000677#endif /* obj.h */
678//----------------------------------------------------------------------------
679//--------end of modutils obj.h
680//----------------------------------------------------------------------------
681
682
Miles Baderae28b042002-04-01 09:34:25 +0000683/* SPFX is always a string, so it can be concatenated to string constants. */
684#ifdef SYMBOL_PREFIX
685#define SPFX SYMBOL_PREFIX
686#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000687#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000688#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000689
Erik Andersen02104321999-12-17 18:57:34 +0000690
Erik Andersend387d011999-12-21 02:55:11 +0000691#define _PATH_MODULES "/lib/modules"
Rob Landleybc68cd12006-03-10 19:22:06 +0000692enum { STRVERSIONLEN = 32 };
Erik Andersend387d011999-12-21 02:55:11 +0000693
Eric Andersen9f16d612000-06-12 23:11:16 +0000694/*======================================================================*/
695
Eric Andersen044228d2001-07-17 01:12:36 +0000696static int flag_force_load = 0;
697static int flag_autoclean = 0;
698static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000699static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000700static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000701
702
703/*======================================================================*/
704
Eric Andersencffd5022002-05-24 06:50:15 +0000705#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000706
Eric Andersencffd5022002-05-24 06:50:15 +0000707struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000708{
Eric Andersencffd5022002-05-24 06:50:15 +0000709 struct arch_list_entry *next;
710 CONFIG_LIST_ARCHTYPE addend;
711 int offset;
712 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000713};
Eric Andersencffd5022002-05-24 06:50:15 +0000714
Eric Andersen21adca72000-12-06 18:18:26 +0000715#endif
716
Eric Andersencffd5022002-05-24 06:50:15 +0000717#if defined(CONFIG_USE_SINGLE)
718
719struct arch_single_entry
720{
Eric Andersen9f16d612000-06-12 23:11:16 +0000721 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000722 int inited : 1;
723 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000724};
Eric Andersencffd5022002-05-24 06:50:15 +0000725
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000726#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000727
Eric Andersen2bf658d2001-02-24 20:01:53 +0000728#if defined(__mips__)
729struct mips_hi16
730{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000731 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000732 ElfW(Addr) *addr;
733 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000734};
735#endif
736
Eric Andersenfe4208f2000-09-24 03:44:29 +0000737struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000738 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000739#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000740 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000741#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000742#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000743 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000744#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000745#if defined(__mips__)
746 struct mips_hi16 *mips_hi16_list;
747#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000748};
749
Eric Andersenfe4208f2000-09-24 03:44:29 +0000750struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000751 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000752#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000753#if defined(CONFIG_USE_PLT_LIST)
754 struct arch_list_entry *pltent;
755#else
756 struct arch_single_entry pltent;
757#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000758#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000759#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000760 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000761#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000762};
763
764
Eric Andersen9f16d612000-06-12 23:11:16 +0000765struct external_module {
766 const char *name;
767 ElfW(Addr) addr;
768 int used;
769 size_t nsyms;
770 struct new_module_symbol *syms;
771};
772
Eric Andersen044228d2001-07-17 01:12:36 +0000773static struct new_module_symbol *ksyms;
774static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000775
Eric Andersen044228d2001-07-17 01:12:36 +0000776static struct external_module *ext_modules;
777static int n_ext_modules;
778static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000779extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000780
Eric Andersen61f83052002-06-22 17:15:42 +0000781static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000782static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000783
Eric Andersenfe4208f2000-09-24 03:44:29 +0000784
Erik Andersen02104321999-12-17 18:57:34 +0000785
Eric Andersen9f16d612000-06-12 23:11:16 +0000786/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000787
Eric Andersen9f16d612000-06-12 23:11:16 +0000788
Eric Andersen14d35432001-05-14 17:07:32 +0000789static int check_module_name_match(const char *filename, struct stat *statbuf,
790 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000791{
Eric Andersen14d35432001-05-14 17:07:32 +0000792 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000793
Eric Andersen14d35432001-05-14 17:07:32 +0000794 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000795 return (FALSE);
796 else {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000797 char *tmp, *tmp1 = xstrdup(filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000798 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000799 if (strcmp(tmp, fullname) == 0) {
800 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000801 /* Stop searching if we find a match */
Rob Landleyd921b2e2006-08-03 15:41:12 +0000802 m_filename = xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000803 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000804 }
Eric Andersen14d35432001-05-14 17:07:32 +0000805 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000806 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000807 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000808}
809
Erik Andersen02104321999-12-17 18:57:34 +0000810
Eric Andersen9f16d612000-06-12 23:11:16 +0000811/*======================================================================*/
812
Eric Andersen044228d2001-07-17 01:12:36 +0000813static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000814{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000815 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000816 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000817
Eric Andersencffd5022002-05-24 06:50:15 +0000818 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000819
Eric Andersen9f16d612000-06-12 23:11:16 +0000820 return &f->root;
821}
822
Eric Andersen044228d2001-07-17 01:12:36 +0000823static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000824{
825 return xmalloc(sizeof(struct obj_section));
826}
827
Eric Andersen044228d2001-07-17 01:12:36 +0000828static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000829{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000830 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000831 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000832
Eric Andersencffd5022002-05-24 06:50:15 +0000833 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000834
Eric Andersen9f16d612000-06-12 23:11:16 +0000835 return &sym->root;
836}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000837
Eric Andersen044228d2001-07-17 01:12:36 +0000838static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000839arch_apply_relocation(struct obj_file *f,
840 struct obj_section *targsec,
841 struct obj_section *symsec,
842 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000843 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000844{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000845 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000846 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000847 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
848 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000849#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
850 struct arch_symbol *isym = (struct arch_symbol *) sym;
851#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000852#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000853#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000854 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000855#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000856#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000857#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000858 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000859 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000860# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000861 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000862# else
Eric Andersencffd5022002-05-24 06:50:15 +0000863 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000864# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000865#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000866
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000867 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000868
Eric Andersencffd5022002-05-24 06:50:15 +0000869#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000870
Eric Andersen3b1a7442003-12-24 20:30:45 +0000871 case R_ARM_NONE:
872 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000873
Eric Andersen3b1a7442003-12-24 20:30:45 +0000874 case R_ARM_ABS32:
875 *loc += v;
876 break;
Miles Baderae28b042002-04-01 09:34:25 +0000877
Eric Andersen3b1a7442003-12-24 20:30:45 +0000878 case R_ARM_GOT32:
879 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000880
Eric Andersen3b1a7442003-12-24 20:30:45 +0000881 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000882 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
883 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000885
Eric Andersen3b1a7442003-12-24 20:30:45 +0000886 *loc += got - dot;
887 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000888
Eric Andersen3b1a7442003-12-24 20:30:45 +0000889 case R_ARM_PC24:
890 case R_ARM_PLT32:
891 goto bb_use_plt;
892
893 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 *loc += v - got;
895 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000896
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000897#elif defined(__cris__)
898
899 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000901
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000902 case R_CRIS_32:
903 /* CRIS keeps the relocation value in the r_addend field and
904 * should not use whats in *loc at all
905 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000906 *loc = v;
907 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000908
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000909#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000910
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000911 case R_H8_DIR24R8:
912 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
913 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000914 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000915 case R_H8_DIR24A8:
916 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000917 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000918 case R_H8_DIR32:
919 case R_H8_DIR32A16:
920 *loc += v;
921 break;
922 case R_H8_PCREL16:
923 v -= dot + 2;
924 if ((ElfW(Sword))v > 0x7fff ||
925 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
926 ret = obj_reloc_overflow;
927 else
928 *(unsigned short *)loc = v;
929 break;
930 case R_H8_PCREL8:
931 v -= dot + 1;
932 if ((ElfW(Sword))v > 0x7f ||
933 (ElfW(Sword))v < -(ElfW(Sword))0x80)
934 ret = obj_reloc_overflow;
935 else
936 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000937 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000938
Eric Andersencffd5022002-05-24 06:50:15 +0000939#elif defined(__i386__)
940
Eric Andersen3b1a7442003-12-24 20:30:45 +0000941 case R_386_NONE:
942 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000943
Eric Andersen3b1a7442003-12-24 20:30:45 +0000944 case R_386_32:
945 *loc += v;
946 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000947
Eric Andersen3b1a7442003-12-24 20:30:45 +0000948 case R_386_PLT32:
949 case R_386_PC32:
950 *loc += v - dot;
951 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000952
Eric Andersen3b1a7442003-12-24 20:30:45 +0000953 case R_386_GLOB_DAT:
954 case R_386_JMP_SLOT:
955 *loc = v;
956 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000957
Eric Andersen3b1a7442003-12-24 20:30:45 +0000958 case R_386_RELATIVE:
959 *loc += f->baseaddr;
960 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000961
Eric Andersen3b1a7442003-12-24 20:30:45 +0000962 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000963 *loc += got - dot;
964 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000965
Eric Andersen3b1a7442003-12-24 20:30:45 +0000966 case R_386_GOT32:
967 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000968
Eric Andersen3b1a7442003-12-24 20:30:45 +0000969 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 *loc += v - got;
971 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000972
Mike Frysinger280dae72006-06-06 06:30:32 +0000973#elif defined (__microblaze__)
974 case R_MICROBLAZE_NONE:
975 case R_MICROBLAZE_64_NONE:
976 case R_MICROBLAZE_32_SYM_OP_SYM:
977 case R_MICROBLAZE_32_PCREL:
978 break;
979
980 case R_MICROBLAZE_64_PCREL: {
981 /* dot is the address of the current instruction.
982 * v is the target symbol address.
983 * So we need to extract the offset in the code,
984 * adding v, then subtrating the current address
985 * of this instruction.
986 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
987 */
988
989 /* Get split offset stored in code */
990 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
991 (loc[1] & 0xFFFF);
992
993 /* Adjust relative offset. -4 adjustment required
994 * because dot points to the IMM insn, but branch
995 * is computed relative to the branch instruction itself.
996 */
997 temp += v - dot - 4;
998
999 /* Store back into code */
1000 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1001 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1002
1003 break;
1004 }
1005
1006 case R_MICROBLAZE_32:
1007 *loc += v;
1008 break;
1009
1010 case R_MICROBLAZE_64: {
1011 /* Get split pointer stored in code */
1012 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1013 (loc[1] & 0xFFFF);
1014
1015 /* Add reloc offset */
1016 temp1+=v;
1017
1018 /* Store back into code */
1019 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1020 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1021
1022 break;
1023 }
1024
1025 case R_MICROBLAZE_32_PCREL_LO:
1026 case R_MICROBLAZE_32_LO:
1027 case R_MICROBLAZE_SRO32:
1028 case R_MICROBLAZE_SRW32:
1029 ret = obj_reloc_unhandled;
1030 break;
1031
Eric Andersencffd5022002-05-24 06:50:15 +00001032#elif defined(__mc68000__)
1033
Eric Andersen3b1a7442003-12-24 20:30:45 +00001034 case R_68K_NONE:
1035 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001036
Eric Andersen3b1a7442003-12-24 20:30:45 +00001037 case R_68K_32:
1038 *loc += v;
1039 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001040
Eric Andersen3b1a7442003-12-24 20:30:45 +00001041 case R_68K_8:
1042 if (v > 0xff) {
1043 ret = obj_reloc_overflow;
1044 }
1045 *(char *)loc = v;
1046 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001047
Eric Andersen3b1a7442003-12-24 20:30:45 +00001048 case R_68K_16:
1049 if (v > 0xffff) {
1050 ret = obj_reloc_overflow;
1051 }
1052 *(short *)loc = v;
1053 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001054
Eric Andersen3b1a7442003-12-24 20:30:45 +00001055 case R_68K_PC8:
1056 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001057 if ((ElfW(Sword))v > 0x7f ||
1058 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001059 ret = obj_reloc_overflow;
1060 }
1061 *(char *)loc = v;
1062 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001063
Eric Andersen3b1a7442003-12-24 20:30:45 +00001064 case R_68K_PC16:
1065 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001066 if ((ElfW(Sword))v > 0x7fff ||
1067 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001068 ret = obj_reloc_overflow;
1069 }
1070 *(short *)loc = v;
1071 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001072
Eric Andersen3b1a7442003-12-24 20:30:45 +00001073 case R_68K_PC32:
1074 *(int *)loc = v - dot;
1075 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001076
Eric Andersen3b1a7442003-12-24 20:30:45 +00001077 case R_68K_GLOB_DAT:
1078 case R_68K_JMP_SLOT:
1079 *loc = v;
1080 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001081
Eric Andersen3b1a7442003-12-24 20:30:45 +00001082 case R_68K_RELATIVE:
1083 *(int *)loc += f->baseaddr;
1084 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001085
Eric Andersen3b1a7442003-12-24 20:30:45 +00001086 case R_68K_GOT32:
1087 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001088
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001089# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001090 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001091 *loc += v - got;
1092 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001093# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001094
1095#elif defined(__mips__)
1096
Eric Andersen3b1a7442003-12-24 20:30:45 +00001097 case R_MIPS_NONE:
1098 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001099
Eric Andersen3b1a7442003-12-24 20:30:45 +00001100 case R_MIPS_32:
1101 *loc += v;
1102 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001103
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 case R_MIPS_26:
1105 if (v % 4)
1106 ret = obj_reloc_dangerous;
1107 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1108 ret = obj_reloc_overflow;
1109 *loc =
1110 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1111 0x03ffffff);
1112 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001113
Eric Andersen3b1a7442003-12-24 20:30:45 +00001114 case R_MIPS_HI16:
1115 {
1116 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001117
Eric Andersen3b1a7442003-12-24 20:30:45 +00001118 /* We cannot relocate this one now because we don't know the value
1119 of the carry we need to add. Save the information, and let LO16
1120 do the actual relocation. */
1121 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1122 n->addr = loc;
1123 n->value = v;
1124 n->next = ifile->mips_hi16_list;
1125 ifile->mips_hi16_list = n;
1126 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001127 }
1128
Eric Andersen3b1a7442003-12-24 20:30:45 +00001129 case R_MIPS_LO16:
1130 {
1131 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001132 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001133
1134 /* Sign extend the addend we extract from the lo insn. */
1135 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1136
1137 if (ifile->mips_hi16_list != NULL) {
1138 struct mips_hi16 *l;
1139
1140 l = ifile->mips_hi16_list;
1141 while (l != NULL) {
1142 struct mips_hi16 *next;
1143 unsigned long insn;
1144
Eric Andersen3b1a7442003-12-24 20:30:45 +00001145 /* Do the HI16 relocation. Note that we actually don't
1146 need to know anything about the LO16 itself, except where
1147 to find the low 16 bits of the addend needed by the LO16. */
1148 insn = *l->addr;
1149 val =
1150 ((insn & 0xffff) << 16) +
1151 vallo;
1152 val += v;
1153
1154 /* Account for the sign extension that will happen in the
1155 low bits. */
1156 val =
1157 ((val >> 16) +
1158 ((val & 0x8000) !=
1159 0)) & 0xffff;
1160
1161 insn = (insn & ~0xffff) | val;
1162 *l->addr = insn;
1163
1164 next = l->next;
1165 free(l);
1166 l = next;
1167 }
1168
1169 ifile->mips_hi16_list = NULL;
1170 }
1171
1172 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1173 val = v + vallo;
1174 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1175 *loc = insnlo;
1176 break;
1177 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001178
Mike Frysingerf982d862006-01-04 00:11:26 +00001179#elif defined(__nios2__)
1180
1181 case R_NIOS2_NONE:
1182 break;
1183
1184 case R_NIOS2_BFD_RELOC_32:
1185 *loc += v;
1186 break;
1187
1188 case R_NIOS2_BFD_RELOC_16:
1189 if (v > 0xffff) {
1190 ret = obj_reloc_overflow;
1191 }
1192 *(short *)loc = v;
1193 break;
1194
1195 case R_NIOS2_BFD_RELOC_8:
1196 if (v > 0xff) {
1197 ret = obj_reloc_overflow;
1198 }
1199 *(char *)loc = v;
1200 break;
1201
1202 case R_NIOS2_S16:
1203 {
1204 Elf32_Addr word;
1205
1206 if ((Elf32_Sword)v > 0x7fff ||
1207 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1208 ret = obj_reloc_overflow;
1209 }
1210
1211 word = *loc;
1212 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1213 (word & 0x3f);
1214 }
1215 break;
1216
1217 case R_NIOS2_U16:
1218 {
1219 Elf32_Addr word;
1220
1221 if (v > 0xffff) {
1222 ret = obj_reloc_overflow;
1223 }
1224
1225 word = *loc;
1226 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1227 (word & 0x3f);
1228 }
1229 break;
1230
1231 case R_NIOS2_PCREL16:
1232 {
1233 Elf32_Addr word;
1234
1235 v -= dot + 4;
1236 if ((Elf32_Sword)v > 0x7fff ||
1237 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1238 ret = obj_reloc_overflow;
1239 }
1240
1241 word = *loc;
1242 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1243 }
1244 break;
1245
1246 case R_NIOS2_GPREL:
1247 {
1248 Elf32_Addr word, gp;
1249 /* get _gp */
1250 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1251 v-=gp;
1252 if ((Elf32_Sword)v > 0x7fff ||
1253 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1254 ret = obj_reloc_overflow;
1255 }
1256
1257 word = *loc;
1258 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1259 }
1260 break;
1261
1262 case R_NIOS2_CALL26:
1263 if (v & 3)
1264 ret = obj_reloc_dangerous;
1265 if ((v >> 28) != (dot >> 28))
1266 ret = obj_reloc_overflow;
1267 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1268 break;
1269
1270 case R_NIOS2_IMM5:
1271 {
1272 Elf32_Addr word;
1273
1274 if (v > 0x1f) {
1275 ret = obj_reloc_overflow;
1276 }
1277
1278 word = *loc & ~0x7c0;
1279 *loc = word | ((v & 0x1f) << 6);
1280 }
1281 break;
1282
1283 case R_NIOS2_IMM6:
1284 {
1285 Elf32_Addr word;
1286
1287 if (v > 0x3f) {
1288 ret = obj_reloc_overflow;
1289 }
1290
1291 word = *loc & ~0xfc0;
1292 *loc = word | ((v & 0x3f) << 6);
1293 }
1294 break;
1295
1296 case R_NIOS2_IMM8:
1297 {
1298 Elf32_Addr word;
1299
1300 if (v > 0xff) {
1301 ret = obj_reloc_overflow;
1302 }
1303
1304 word = *loc & ~0x3fc0;
1305 *loc = word | ((v & 0xff) << 6);
1306 }
1307 break;
1308
1309 case R_NIOS2_HI16:
1310 {
1311 Elf32_Addr word;
1312
1313 word = *loc;
1314 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1315 (word & 0x3f);
1316 }
1317 break;
1318
1319 case R_NIOS2_LO16:
1320 {
1321 Elf32_Addr word;
1322
1323 word = *loc;
1324 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1325 (word & 0x3f);
1326 }
1327 break;
1328
1329 case R_NIOS2_HIADJ16:
1330 {
1331 Elf32_Addr word1, word2;
1332
1333 word1 = *loc;
1334 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1335 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1336 (word1 & 0x3f);
1337 }
1338 break;
1339
Mike Frysingerebee0e72006-02-18 06:14:31 +00001340#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001341 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001342
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001343#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001344
Eric Andersen3b1a7442003-12-24 20:30:45 +00001345 case R_PPC_ADDR16_HA:
1346 *(unsigned short *)loc = (v + 0x8000) >> 16;
1347 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001348
Eric Andersen3b1a7442003-12-24 20:30:45 +00001349 case R_PPC_ADDR16_HI:
1350 *(unsigned short *)loc = v >> 16;
1351 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001352
Eric Andersen3b1a7442003-12-24 20:30:45 +00001353 case R_PPC_ADDR16_LO:
1354 *(unsigned short *)loc = v;
1355 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001356
Eric Andersen3b1a7442003-12-24 20:30:45 +00001357 case R_PPC_REL24:
1358 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001359
Eric Andersen3b1a7442003-12-24 20:30:45 +00001360 case R_PPC_REL32:
1361 *loc = v - dot;
1362 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001363
Eric Andersen3b1a7442003-12-24 20:30:45 +00001364 case R_PPC_ADDR32:
1365 *loc = v;
1366 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001367
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001368#elif defined(__s390__)
1369
1370 case R_390_32:
1371 *(unsigned int *) loc += v;
1372 break;
1373 case R_390_16:
1374 *(unsigned short *) loc += v;
1375 break;
1376 case R_390_8:
1377 *(unsigned char *) loc += v;
1378 break;
1379
1380 case R_390_PC32:
1381 *(unsigned int *) loc += v - dot;
1382 break;
1383 case R_390_PC16DBL:
1384 *(unsigned short *) loc += (v - dot) >> 1;
1385 break;
1386 case R_390_PC16:
1387 *(unsigned short *) loc += v - dot;
1388 break;
1389
1390 case R_390_PLT32:
1391 case R_390_PLT16DBL:
1392 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001393 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001394 if (pe->inited == 0) {
1395 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1396 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1397 ip[1] = 0x100607f1;
1398 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1399 ip[2] = v - 2;
1400 else
1401 ip[2] = v;
1402 pe->inited = 1;
1403 }
1404
1405 /* Insert relative distance to target. */
1406 v = plt + pe->offset - dot;
1407 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1408 *(unsigned int *) loc = (unsigned int) v;
1409 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1410 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1411 break;
1412
1413 case R_390_GLOB_DAT:
1414 case R_390_JMP_SLOT:
1415 *loc = v;
1416 break;
1417
1418 case R_390_RELATIVE:
1419 *loc += f->baseaddr;
1420 break;
1421
1422 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001423 *(unsigned long *) loc += got - dot;
1424 break;
1425
1426 case R_390_GOT12:
1427 case R_390_GOT16:
1428 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001429 if (!isym->gotent.inited)
1430 {
1431 isym->gotent.inited = 1;
1432 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1433 }
1434 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1435 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1436 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1437 *(unsigned short *) loc += isym->gotent.offset;
1438 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1439 *(unsigned int *) loc += isym->gotent.offset;
1440 break;
1441
1442# ifndef R_390_GOTOFF32
1443# define R_390_GOTOFF32 R_390_GOTOFF
1444# endif
1445 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001446 *loc += v - got;
1447 break;
1448
Eric Andersencffd5022002-05-24 06:50:15 +00001449#elif defined(__sh__)
1450
Eric Andersen3b1a7442003-12-24 20:30:45 +00001451 case R_SH_NONE:
1452 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001453
Eric Andersen3b1a7442003-12-24 20:30:45 +00001454 case R_SH_DIR32:
1455 *loc += v;
1456 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001457
Eric Andersen3b1a7442003-12-24 20:30:45 +00001458 case R_SH_REL32:
1459 *loc += v - dot;
1460 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001461
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 case R_SH_PLT32:
1463 *loc = v - dot;
1464 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001465
Eric Andersen3b1a7442003-12-24 20:30:45 +00001466 case R_SH_GLOB_DAT:
1467 case R_SH_JMP_SLOT:
1468 *loc = v;
1469 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001470
Eric Andersen3b1a7442003-12-24 20:30:45 +00001471 case R_SH_RELATIVE:
1472 *loc = f->baseaddr + rel->r_addend;
1473 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001474
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 *loc = got - dot + rel->r_addend;
1477 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001478
Eric Andersen3b1a7442003-12-24 20:30:45 +00001479 case R_SH_GOT32:
1480 goto bb_use_got;
1481
1482 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001483 *loc = v - got;
1484 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001485
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001486# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001487 case R_SH_IMM_MEDLOW16:
1488 case R_SH_IMM_LOW16:
1489 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001490 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001491
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001492 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001493 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001494
Eric Andersen3b1a7442003-12-24 20:30:45 +00001495 /*
1496 * movi and shori have the format:
1497 *
1498 * | op | imm | reg | reserved |
1499 * 31..26 25..10 9.. 4 3 .. 0
1500 *
1501 * so we simply mask and or in imm.
1502 */
1503 word = *loc & ~0x3fffc00;
1504 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001505
Eric Andersen3b1a7442003-12-24 20:30:45 +00001506 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001507
Eric Andersen3b1a7442003-12-24 20:30:45 +00001508 break;
1509 }
Eric Andersenbf833552003-08-13 19:56:33 +00001510
Eric Andersen3b1a7442003-12-24 20:30:45 +00001511 case R_SH_IMM_MEDLOW16_PCREL:
1512 case R_SH_IMM_LOW16_PCREL:
1513 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001514 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001515
Eric Andersen3b1a7442003-12-24 20:30:45 +00001516 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001517
Eric Andersen3b1a7442003-12-24 20:30:45 +00001518 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001519
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001520 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001521 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001522
Eric Andersen3b1a7442003-12-24 20:30:45 +00001523 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001524
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001526
Eric Andersen3b1a7442003-12-24 20:30:45 +00001527 break;
1528 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001529# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001530
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001531#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001532
Eric Andersen3b1a7442003-12-24 20:30:45 +00001533 case R_V850_NONE:
1534 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001535
Eric Andersen3b1a7442003-12-24 20:30:45 +00001536 case R_V850_32:
1537 /* We write two shorts instead of a long because even
1538 32-bit insns only need half-word alignment, but
1539 32-bit data needs to be long-word aligned. */
1540 v += ((unsigned short *)loc)[0];
1541 v += ((unsigned short *)loc)[1] << 16;
1542 ((unsigned short *)loc)[0] = v & 0xffff;
1543 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1544 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001545
Eric Andersen3b1a7442003-12-24 20:30:45 +00001546 case R_V850_22_PCREL:
1547 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001548
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001549#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001550
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001551 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001552 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001553
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001554 case R_X86_64_64:
1555 *loc += v;
1556 break;
1557
1558 case R_X86_64_32:
1559 *(unsigned int *) loc += v;
1560 if (v > 0xffffffff)
1561 {
1562 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1563 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1564 }
1565 break;
1566
1567 case R_X86_64_32S:
1568 *(signed int *) loc += v;
1569 break;
1570
1571 case R_X86_64_16:
1572 *(unsigned short *) loc += v;
1573 break;
1574
1575 case R_X86_64_8:
1576 *(unsigned char *) loc += v;
1577 break;
1578
1579 case R_X86_64_PC32:
1580 *(unsigned int *) loc += v - dot;
1581 break;
1582
1583 case R_X86_64_PC16:
1584 *(unsigned short *) loc += v - dot;
1585 break;
1586
1587 case R_X86_64_PC8:
1588 *(unsigned char *) loc += v - dot;
1589 break;
1590
1591 case R_X86_64_GLOB_DAT:
1592 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001593 *loc = v;
1594 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001595
1596 case R_X86_64_RELATIVE:
1597 *loc += f->baseaddr;
1598 break;
1599
1600 case R_X86_64_GOT32:
1601 case R_X86_64_GOTPCREL:
1602 goto bb_use_got;
1603# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001604 if (!isym->gotent.reloc_done)
1605 {
1606 isym->gotent.reloc_done = 1;
1607 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1608 }
1609 /* XXX are these really correct? */
1610 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1611 *(unsigned int *) loc += v + isym->gotent.offset;
1612 else
1613 *loc += isym->gotent.offset;
1614 break;
1615# endif
1616
Mike Frysingerf982d862006-01-04 00:11:26 +00001617#else
1618# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001619#endif
1620
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001621 default:
1622 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1623 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001624 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001625
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001626#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001627
Eric Andersen3b1a7442003-12-24 20:30:45 +00001628bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001629
Eric Andersen3b1a7442003-12-24 20:30:45 +00001630 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001631
Eric Andersencffd5022002-05-24 06:50:15 +00001632#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001633 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1634 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001635#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001636 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001637#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001638
Eric Andersen3b1a7442003-12-24 20:30:45 +00001639 if (! pe->inited) {
1640 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001641
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001643
1644#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001645 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1646 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001647#endif
1648#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001649 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001650 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001651 ip[2] = 0x7d6903a6; /* mtctr r11 */
1652 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001653#endif
Miles Baderae28b042002-04-01 09:34:25 +00001654#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001655 /* We have to trash a register, so we assume that any control
1656 transfer more than 21-bits away must be a function call
1657 (so we can use a call-clobbered register). */
1658 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1659 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001660#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001661 pe->inited = 1;
1662 }
Eric Andersen21adca72000-12-06 18:18:26 +00001663
Eric Andersen3b1a7442003-12-24 20:30:45 +00001664 /* relative distance to target */
1665 v -= dot;
1666 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001667#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001668 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001669#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001670 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001671#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001672 /* go via the plt */
1673 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001674
1675#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001677#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001679#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001680 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001681
Eric Andersen3b1a7442003-12-24 20:30:45 +00001682 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001683#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001684 /* Convert to words. */
1685 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001686
Eric Andersen3b1a7442003-12-24 20:30:45 +00001687 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001688#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001689#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001691#endif
Miles Baderae28b042002-04-01 09:34:25 +00001692#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001693 /* We write two shorts instead of a long because even 32-bit insns
1694 only need half-word alignment, but the 32-bit data write needs
1695 to be long-word aligned. */
1696 ((unsigned short *)loc)[0] =
1697 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1698 | ((v >> 16) & 0x3f); /* offs high part */
1699 ((unsigned short *)loc)[1] =
1700 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001701#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001702 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001703#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001704
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001705#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001706bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001707
Eric Andersen3b1a7442003-12-24 20:30:45 +00001708 /* needs an entry in the .got: set it, once */
1709 if (!isym->gotent.inited) {
1710 isym->gotent.inited = 1;
1711 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1712 }
1713 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001714#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001715 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001716#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001717 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001718#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001719 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001720
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001721#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001722 }
1723
1724 return ret;
1725}
1726
Eric Andersencffd5022002-05-24 06:50:15 +00001727
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001728#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001729
1730static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1731 int offset, int size)
1732{
1733 struct arch_list_entry *pe;
1734
1735 for (pe = *list; pe != NULL; pe = pe->next) {
1736 if (pe->addend == rel->r_addend) {
1737 break;
1738 }
1739 }
1740
1741 if (pe == NULL) {
1742 pe = xmalloc(sizeof(struct arch_list_entry));
1743 pe->next = *list;
1744 pe->addend = rel->r_addend;
1745 pe->offset = offset;
1746 pe->inited = 0;
1747 *list = pe;
1748 return size;
1749 }
1750 return 0;
1751}
1752
1753#endif
1754
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001755#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001756
1757static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1758 int offset, int size)
1759{
1760 if (single->allocated == 0) {
1761 single->allocated = 1;
1762 single->offset = offset;
1763 single->inited = 0;
1764 return size;
1765 }
1766 return 0;
1767}
1768
1769#endif
1770
1771#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1772
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001773static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001774 int offset, int size)
1775{
1776 struct obj_section *myrelsec = obj_find_section(f, name);
1777
1778 if (offset == 0) {
1779 offset += size;
1780 }
1781
1782 if (myrelsec) {
1783 obj_extend_section(myrelsec, offset);
1784 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001785 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001786 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001787 }
1788
1789 return myrelsec;
1790}
1791
1792#endif
1793
1794static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001795{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001796#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001797 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001798 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001799#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001800 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001801#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001802#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001803 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001804#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001805 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001806 ElfW(RelM) *rel, *relend;
1807 ElfW(Sym) *symtab, *extsym;
1808 const char *strtab, *name;
1809 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001810
Eric Andersen21adca72000-12-06 18:18:26 +00001811 for (i = 0; i < f->header.e_shnum; ++i) {
1812 relsec = f->sections[i];
1813 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001814 continue;
1815
Eric Andersen21adca72000-12-06 18:18:26 +00001816 symsec = f->sections[relsec->header.sh_link];
1817 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001818
Eric Andersen21adca72000-12-06 18:18:26 +00001819 rel = (ElfW(RelM) *) relsec->contents;
1820 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1821 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001822 strtab = (const char *) strsec->contents;
1823
1824 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001825 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001826
Eric Andersencffd5022002-05-24 06:50:15 +00001827#if defined(CONFIG_USE_GOT_ENTRIES)
1828 got_allocate = 0;
1829#endif
1830#if defined(CONFIG_USE_PLT_ENTRIES)
1831 plt_allocate = 0;
1832#endif
1833
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001834 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001835#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001836 case R_ARM_PC24:
1837 case R_ARM_PLT32:
1838 plt_allocate = 1;
1839 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001840
Eric Andersen3b1a7442003-12-24 20:30:45 +00001841 case R_ARM_GOTOFF:
1842 case R_ARM_GOTPC:
1843 got_needed = 1;
1844 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001845
Eric Andersen3b1a7442003-12-24 20:30:45 +00001846 case R_ARM_GOT32:
1847 got_allocate = 1;
1848 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001849
Eric Andersen21adca72000-12-06 18:18:26 +00001850#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001851 case R_386_GOTPC:
1852 case R_386_GOTOFF:
1853 got_needed = 1;
1854 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001855
Eric Andersen3b1a7442003-12-24 20:30:45 +00001856 case R_386_GOT32:
1857 got_allocate = 1;
1858 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001859
1860#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001861 case R_PPC_REL24:
1862 plt_allocate = 1;
1863 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001864
1865#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001866 case R_68K_GOT32:
1867 got_allocate = 1;
1868 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001869
Eric Andersen16451a02004-03-19 12:16:18 +00001870#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001871 case R_68K_GOTOFF:
1872 got_needed = 1;
1873 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001874#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001875
1876#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001877 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001878 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001879 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001880
Eric Andersen3b1a7442003-12-24 20:30:45 +00001881 case R_SH_GOTPC:
1882 case R_SH_GOTOFF:
1883 got_needed = 1;
1884 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001885
1886#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001887 case R_V850_22_PCREL:
1888 plt_needed = 1;
1889 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001890
1891#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001892 default:
1893 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001894 }
1895
Eric Andersen21adca72000-12-06 18:18:26 +00001896 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001897 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001898 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001899 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001900 }
1901 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001902#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001903 if (got_allocate) {
1904 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001905 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001906 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001907
1908 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001909 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001910#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001911#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001912 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001913#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001914 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001915 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001916 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001917#else
1918 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001919 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001920 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001921#endif
1922 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001923 }
1924#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001925 }
Miles Baderae28b042002-04-01 09:34:25 +00001926 }
Eric Andersen21adca72000-12-06 18:18:26 +00001927
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001928#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001929 if (got_needed) {
1930 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001931 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001932 }
Eric Andersen21adca72000-12-06 18:18:26 +00001933#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001934
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001935#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001936 if (plt_needed) {
1937 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001938 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001939 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001940#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001941
1942#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001943}
1944
Eric Andersen9f16d612000-06-12 23:11:16 +00001945/*======================================================================*/
1946
1947/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001948static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001949{
1950 unsigned long h = 0;
1951 unsigned long g;
1952 unsigned char ch;
1953
1954 while (n > 0) {
1955 ch = *name++;
1956 h = (h << 4) + ch;
1957 if ((g = (h & 0xf0000000)) != 0) {
1958 h ^= g >> 24;
1959 h &= ~g;
1960 }
1961 n--;
1962 }
1963 return h;
1964}
1965
Eric Andersen044228d2001-07-17 01:12:36 +00001966static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001967{
1968 return obj_elf_hash_n(name, strlen(name));
1969}
1970
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001971#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001972/* String comparison for non-co-versioned kernel and module. */
1973
1974static int ncv_strcmp(const char *a, const char *b)
1975{
1976 size_t alen = strlen(a), blen = strlen(b);
1977
1978 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1979 return strncmp(a, b, alen);
1980 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1981 return strncmp(a, b, blen);
1982 else
1983 return strcmp(a, b);
1984}
1985
1986/* String hashing for non-co-versioned kernel and module. Here
1987 we are simply forced to drop the crc from the hash. */
1988
1989static unsigned long ncv_symbol_hash(const char *str)
1990{
1991 size_t len = strlen(str);
1992 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1993 len -= 10;
1994 return obj_elf_hash_n(str, len);
1995}
1996
Eric Andersen044228d2001-07-17 01:12:36 +00001997static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001998obj_set_symbol_compare(struct obj_file *f,
1999 int (*cmp) (const char *, const char *),
2000 unsigned long (*hash) (const char *))
2001{
2002 if (cmp)
2003 f->symbol_cmp = cmp;
2004 if (hash) {
2005 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2006 int i;
2007
2008 f->symbol_hash = hash;
2009
2010 memcpy(tmptab, f->symtab, sizeof(tmptab));
2011 memset(f->symtab, 0, sizeof(f->symtab));
2012
2013 for (i = 0; i < HASH_BUCKETS; ++i)
2014 for (sym = tmptab[i]; sym; sym = next) {
2015 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2016 next = sym->next;
2017 sym->next = f->symtab[h];
2018 f->symtab[h] = sym;
2019 }
2020 }
2021}
2022
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002023#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002024
Eric Andersen044228d2001-07-17 01:12:36 +00002025static struct obj_symbol *
2026obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00002027 unsigned long symidx, int info,
2028 int secidx, ElfW(Addr) value,
2029 unsigned long size)
2030{
2031 struct obj_symbol *sym;
2032 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002033 int n_type = ELF_ST_TYPE(info);
2034 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002035
2036 for (sym = f->symtab[hash]; sym; sym = sym->next)
2037 if (f->symbol_cmp(sym->name, name) == 0) {
2038 int o_secidx = sym->secidx;
2039 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002040 int o_type = ELF_ST_TYPE(o_info);
2041 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002042
2043 /* A redefinition! Is it legal? */
2044
2045 if (secidx == SHN_UNDEF)
2046 return sym;
2047 else if (o_secidx == SHN_UNDEF)
2048 goto found;
2049 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2050 /* Cope with local and global symbols of the same name
2051 in the same object file, as might have been created
2052 by ld -r. The only reason locals are now seen at this
2053 level at all is so that we can do semi-sensible things
2054 with parameters. */
2055
2056 struct obj_symbol *nsym, **p;
2057
2058 nsym = arch_new_symbol();
2059 nsym->next = sym->next;
2060 nsym->ksymidx = -1;
2061
2062 /* Excise the old (local) symbol from the hash chain. */
2063 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2064 continue;
2065 *p = sym = nsym;
2066 goto found;
2067 } else if (n_binding == STB_LOCAL) {
2068 /* Another symbol of the same name has already been defined.
2069 Just add this to the local table. */
2070 sym = arch_new_symbol();
2071 sym->next = NULL;
2072 sym->ksymidx = -1;
2073 f->local_symtab[symidx] = sym;
2074 goto found;
2075 } else if (n_binding == STB_WEAK)
2076 return sym;
2077 else if (o_binding == STB_WEAK)
2078 goto found;
2079 /* Don't unify COMMON symbols with object types the programmer
2080 doesn't expect. */
2081 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002082 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002083 return sym;
2084 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002085 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002086 goto found;
2087 else {
2088 /* Don't report an error if the symbol is coming from
2089 the kernel or some external module. */
2090 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002091 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002092 return sym;
2093 }
2094 }
2095
2096 /* Completely new symbol. */
2097 sym = arch_new_symbol();
2098 sym->next = f->symtab[hash];
2099 f->symtab[hash] = sym;
2100 sym->ksymidx = -1;
2101
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002102 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002103 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002104 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002105 name, (long) symidx, (long) f->local_symtab_size);
2106 else
2107 f->local_symtab[symidx] = sym;
2108 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002109
Eric Andersen3b1a7442003-12-24 20:30:45 +00002110found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002111 sym->name = name;
2112 sym->value = value;
2113 sym->size = size;
2114 sym->secidx = secidx;
2115 sym->info = info;
2116
2117 return sym;
2118}
2119
Eric Andersen044228d2001-07-17 01:12:36 +00002120static struct obj_symbol *
2121obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002122{
2123 struct obj_symbol *sym;
2124 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2125
2126 for (sym = f->symtab[hash]; sym; sym = sym->next)
2127 if (f->symbol_cmp(sym->name, name) == 0)
2128 return sym;
2129
2130 return NULL;
2131}
2132
Eric Andersen044228d2001-07-17 01:12:36 +00002133static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002134 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2135{
2136 if (sym) {
2137 if (sym->secidx >= SHN_LORESERVE)
2138 return sym->value;
2139
2140 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2141 } else {
2142 /* As a special case, a NULL sym has value zero. */
2143 return 0;
2144 }
2145}
2146
Eric Andersen044228d2001-07-17 01:12:36 +00002147static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002148{
2149 int i, n = f->header.e_shnum;
2150
2151 for (i = 0; i < n; ++i)
2152 if (strcmp(f->sections[i]->name, name) == 0)
2153 return f->sections[i];
2154
2155 return NULL;
2156}
2157
2158static int obj_load_order_prio(struct obj_section *a)
2159{
2160 unsigned long af, ac;
2161
2162 af = a->header.sh_flags;
2163
2164 ac = 0;
2165 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002166 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002167 ac |= 32;
2168 if (af & SHF_ALLOC)
2169 ac |= 16;
2170 if (!(af & SHF_WRITE))
2171 ac |= 8;
2172 if (af & SHF_EXECINSTR)
2173 ac |= 4;
2174 if (a->header.sh_type != SHT_NOBITS)
2175 ac |= 2;
2176
2177 return ac;
2178}
2179
Eric Andersen044228d2001-07-17 01:12:36 +00002180static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002181obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2182{
2183 struct obj_section **p;
2184 int prio = obj_load_order_prio(sec);
2185 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2186 if (obj_load_order_prio(*p) < prio)
2187 break;
2188 sec->load_next = *p;
2189 *p = sec;
2190}
2191
Eric Andersen044228d2001-07-17 01:12:36 +00002192static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002193 const char *name,
2194 unsigned long align,
2195 unsigned long size)
2196{
2197 int newidx = f->header.e_shnum++;
2198 struct obj_section *sec;
2199
2200 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2201 f->sections[newidx] = sec = arch_new_section();
2202
2203 memset(sec, 0, sizeof(*sec));
2204 sec->header.sh_type = SHT_PROGBITS;
2205 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2206 sec->header.sh_size = size;
2207 sec->header.sh_addralign = align;
2208 sec->name = name;
2209 sec->idx = newidx;
2210 if (size)
2211 sec->contents = xmalloc(size);
2212
2213 obj_insert_section_load_order(f, sec);
2214
2215 return sec;
2216}
2217
Eric Andersen044228d2001-07-17 01:12:36 +00002218static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002219 const char *name,
2220 unsigned long align,
2221 unsigned long size)
2222{
2223 int newidx = f->header.e_shnum++;
2224 struct obj_section *sec;
2225
2226 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2227 f->sections[newidx] = sec = arch_new_section();
2228
2229 memset(sec, 0, sizeof(*sec));
2230 sec->header.sh_type = SHT_PROGBITS;
2231 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2232 sec->header.sh_size = size;
2233 sec->header.sh_addralign = align;
2234 sec->name = name;
2235 sec->idx = newidx;
2236 if (size)
2237 sec->contents = xmalloc(size);
2238
2239 sec->load_next = f->load_order;
2240 f->load_order = sec;
2241 if (f->load_order_search_start == &f->load_order)
2242 f->load_order_search_start = &sec->load_next;
2243
2244 return sec;
2245}
2246
Eric Andersen044228d2001-07-17 01:12:36 +00002247static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002248{
2249 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002250 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002251 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2252 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002253 return sec->contents + oldsize;
2254}
2255
2256
Eric Andersen9f16d612000-06-12 23:11:16 +00002257/* Conditionally add the symbols from the given symbol set to the
2258 new module. */
2259
2260static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002261add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002262 int idx, struct new_module_symbol *syms, size_t nsyms)
2263{
2264 struct new_module_symbol *s;
2265 size_t i;
2266 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002267#ifdef SYMBOL_PREFIX
2268 char *name_buf = 0;
2269 size_t name_alloced_size = 0;
2270#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002271#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2272 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002273
Glenn L McGrath759515c2003-08-30 06:00:33 +00002274 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002275#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002276 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002277 /* Only add symbols that are already marked external.
2278 If we override locals we may cause problems for
2279 argument initialization. We will also create a false
2280 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002281 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002282 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002283
Glenn L McGrath759515c2003-08-30 06:00:33 +00002284 /* GPL licensed modules can use symbols exported with
2285 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2286 * exported names. Non-GPL modules never see any GPLONLY_
2287 * symbols so they cannot fudge it by adding the prefix on
2288 * their references.
2289 */
2290 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002291#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002292 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002293 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002294 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002295#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002296 continue;
2297 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002298 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002299
Miles Baderae28b042002-04-01 09:34:25 +00002300#ifdef SYMBOL_PREFIX
2301 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2302 kernel exports `C names', but module object files
2303 reference `linker names'). */
2304 size_t extra = sizeof SYMBOL_PREFIX;
2305 size_t name_size = strlen (name) + extra;
2306 if (name_size > name_alloced_size) {
2307 name_alloced_size = name_size * 2;
2308 name_buf = alloca (name_alloced_size);
2309 }
2310 strcpy (name_buf, SYMBOL_PREFIX);
2311 strcpy (name_buf + extra - 1, name);
2312 name = name_buf;
2313#endif /* SYMBOL_PREFIX */
2314
2315 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002316 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002317#ifdef SYMBOL_PREFIX
2318 /* Put NAME_BUF into more permanent storage. */
2319 name = xmalloc (name_size);
2320 strcpy (name, name_buf);
2321#endif
2322 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002323 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002324 STT_NOTYPE),
2325 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002326 /* Did our symbol just get installed? If so, mark the
2327 module as "used". */
2328 if (sym->secidx == idx)
2329 used = 1;
2330 }
2331 }
2332
2333 return used;
2334}
2335
2336static void add_kernel_symbols(struct obj_file *f)
2337{
2338 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002339 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002340
2341 /* Add module symbols first. */
2342
2343 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2344 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002345 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2346 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002347
2348 n_ext_modules_used = nused;
2349
2350 /* And finally the symbols from the kernel proper. */
2351
2352 if (nksyms)
2353 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2354}
2355
2356static char *get_modinfo_value(struct obj_file *f, const char *key)
2357{
2358 struct obj_section *sec;
2359 char *p, *v, *n, *ep;
2360 size_t klen = strlen(key);
2361
2362 sec = obj_find_section(f, ".modinfo");
2363 if (sec == NULL)
2364 return NULL;
2365 p = sec->contents;
2366 ep = p + sec->header.sh_size;
2367 while (p < ep) {
2368 v = strchr(p, '=');
2369 n = strchr(p, '\0');
2370 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002371 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002372 return v + 1;
2373 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002374 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002375 return n;
2376 }
2377 p = n + 1;
2378 }
2379
2380 return NULL;
2381}
2382
2383
2384/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002385/* Functions relating to module loading after 2.1.18. */
2386
2387static int
2388new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2389{
2390 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002391 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002392 struct obj_symbol *sym;
2393 char *contents, *loc;
2394 int min, max, n;
2395
2396 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002397 if ((q = strchr(p, '=')) == NULL) {
2398 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002399 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002400 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002401
2402 key = alloca(q - p + 6);
2403 memcpy(key, "parm_", 5);
2404 memcpy(key + 5, p, q - p);
2405 key[q - p + 5] = 0;
2406
2407 p = get_modinfo_value(f, key);
2408 key += 5;
2409 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002410 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002411 return 0;
2412 }
2413
Miles Baderae28b042002-04-01 09:34:25 +00002414#ifdef SYMBOL_PREFIX
2415 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2416 strcpy (sym_name, SYMBOL_PREFIX);
2417 strcat (sym_name, key);
2418#else
2419 sym_name = key;
2420#endif
2421 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002422
2423 /* Also check that the parameter was not resolved from the kernel. */
2424 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002425 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002426 return 0;
2427 }
2428
2429 if (isdigit(*p)) {
2430 min = strtoul(p, &p, 10);
2431 if (*p == '-')
2432 max = strtoul(p + 1, &p, 10);
2433 else
2434 max = min;
2435 } else
2436 min = max = 1;
2437
2438 contents = f->sections[sym->secidx]->contents;
2439 loc = contents + sym->value;
2440 n = (*++q != '\0');
2441
2442 while (1) {
2443 if ((*p == 's') || (*p == 'c')) {
2444 char *str;
2445
2446 /* Do C quoting if we begin with a ", else slurp the lot. */
2447 if (*q == '"') {
2448 char *r;
2449
2450 str = alloca(strlen(q));
2451 for (r = str, q++; *q != '"'; ++q, ++r) {
2452 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002453 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002454 key);
2455 return 0;
2456 } else if (*q == '\\')
2457 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002458 case 'a':
2459 *r = '\a';
2460 break;
2461 case 'b':
2462 *r = '\b';
2463 break;
2464 case 'e':
2465 *r = '\033';
2466 break;
2467 case 'f':
2468 *r = '\f';
2469 break;
2470 case 'n':
2471 *r = '\n';
2472 break;
2473 case 'r':
2474 *r = '\r';
2475 break;
2476 case 't':
2477 *r = '\t';
2478 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002479
Eric Andersen3b1a7442003-12-24 20:30:45 +00002480 case '0':
2481 case '1':
2482 case '2':
2483 case '3':
2484 case '4':
2485 case '5':
2486 case '6':
2487 case '7':
2488 {
2489 int c = *q - '0';
2490 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002491 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002492 if (q[1] >= '0' && q[1] <= '7')
2493 c = (c * 8) + *++q - '0';
2494 }
2495 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002496 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002497 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002498
Eric Andersen3b1a7442003-12-24 20:30:45 +00002499 default:
2500 *r = *q;
2501 break;
2502 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002503 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002504 }
2505 *r = '\0';
2506 ++q;
2507 } else {
2508 char *r;
2509
2510 /* In this case, the string is not quoted. We will break
2511 it using the coma (like for ints). If the user wants to
2512 include comas in a string, he just has to quote it */
2513
2514 /* Search the next coma */
2515 r = strchr(q, ',');
2516
2517 /* Found ? */
2518 if (r != (char *) NULL) {
2519 /* Recopy the current field */
2520 str = alloca(r - q + 1);
2521 memcpy(str, q, r - q);
2522
Eric Andersenaff114c2004-04-14 17:51:38 +00002523 /* I don't know if it is useful, as the previous case
2524 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002525 str[r - q] = '\0';
2526
2527 /* Keep next fields */
2528 q = r;
2529 } else {
2530 /* last string */
2531 str = q;
2532 q = "";
2533 }
2534 }
2535
2536 if (*p == 's') {
2537 /* Normal string */
2538 obj_string_patch(f, sym->secidx, loc - contents, str);
2539 loc += tgt_sizeof_char_p;
2540 } else {
2541 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002542 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002543
2544 /* Get the size of each member */
2545 /* Probably we should do that outside the loop ? */
2546 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002547 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002548 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002549 return 0;
2550 }
2551 charssize = strtoul(p + 1, (char **) NULL, 10);
2552
2553 /* Check length */
2554 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002555 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002556 charssize - 1);
2557 return 0;
2558 }
2559
2560 /* Copy to location */
2561 strcpy((char *) loc, str);
2562 loc += charssize;
2563 }
2564 } else {
2565 long v = strtoul(q, &q, 0);
2566 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002567 case 'b':
2568 *loc++ = v;
2569 break;
2570 case 'h':
2571 *(short *) loc = v;
2572 loc += tgt_sizeof_short;
2573 break;
2574 case 'i':
2575 *(int *) loc = v;
2576 loc += tgt_sizeof_int;
2577 break;
2578 case 'l':
2579 *(long *) loc = v;
2580 loc += tgt_sizeof_long;
2581 break;
2582
2583 default:
2584 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2585 return 0;
2586 }
2587 }
2588
2589retry_end_of_value:
2590 switch (*q) {
2591 case '\0':
2592 goto end_of_arg;
2593
2594 case ' ':
2595 case '\t':
2596 case '\n':
2597 case '\r':
2598 ++q;
2599 goto retry_end_of_value;
2600
2601 case ',':
2602 if (++n > max) {
2603 bb_error_msg("too many values for %s (max %d)", key, max);
2604 return 0;
2605 }
2606 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002607 break;
2608
2609 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002610 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002611 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002612 }
2613 }
2614
Eric Andersen3b1a7442003-12-24 20:30:45 +00002615end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002616 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002617 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002618 return 0;
2619 }
2620
2621 argc--, argv++;
2622 }
2623
2624 return 1;
2625}
2626
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002627#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002628static int new_is_module_checksummed(struct obj_file *f)
2629{
2630 const char *p = get_modinfo_value(f, "using_checksums");
2631 if (p)
2632 return atoi(p);
2633 else
2634 return 0;
2635}
2636
2637/* Get the module's kernel version in the canonical integer form. */
2638
2639static int
2640new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2641{
2642 char *p, *q;
2643 int a, b, c;
2644
2645 p = get_modinfo_value(f, "kernel_version");
2646 if (p == NULL)
2647 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002648 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002649
2650 a = strtoul(p, &p, 10);
2651 if (*p != '.')
2652 return -1;
2653 b = strtoul(p + 1, &p, 10);
2654 if (*p != '.')
2655 return -1;
2656 c = strtoul(p + 1, &q, 10);
2657 if (p + 1 == q)
2658 return -1;
2659
2660 return a << 16 | b << 8 | c;
2661}
2662
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002663#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002664
2665
Eric Andersen9f16d612000-06-12 23:11:16 +00002666/* Fetch the loaded modules, and all currently exported symbols. */
2667
2668static int new_get_kernel_symbols(void)
2669{
2670 char *module_names, *mn;
2671 struct external_module *modules, *m;
2672 struct new_module_symbol *syms, *s;
2673 size_t ret, bufsize, nmod, nsyms, i, j;
2674
2675 /* Collect the loaded modules. */
2676
2677 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002678retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002679 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002680 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002681 module_names = xrealloc(module_names, bufsize = ret);
2682 goto retry_modules_load;
2683 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002684 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002685 return 0;
2686 }
2687
2688 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002689
2690 /* Collect the modules' symbols. */
2691
Mark Whitley94fd4802001-03-12 23:08:34 +00002692 if (nmod){
2693 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2694 memset(modules, 0, nmod * sizeof(*modules));
2695 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002696 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002697 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002698
Mark Whitley94fd4802001-03-12 23:08:34 +00002699 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2700 if (errno == ENOENT) {
2701 /* The module was removed out from underneath us. */
2702 continue;
2703 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002704 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002705 return 0;
2706 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002707
Mark Whitley94fd4802001-03-12 23:08:34 +00002708 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002709retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002710 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2711 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002712 case ENOSPC:
2713 syms = xrealloc(syms, bufsize = ret);
2714 goto retry_mod_sym_load;
2715 case ENOENT:
2716 /* The module was removed out from underneath us. */
2717 continue;
2718 default:
2719 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2720 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002721 }
2722 }
2723 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002724
Mark Whitley94fd4802001-03-12 23:08:34 +00002725 m->name = mn;
2726 m->addr = info.addr;
2727 m->nsyms = nsyms;
2728 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002729
Mark Whitley94fd4802001-03-12 23:08:34 +00002730 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2731 s->name += (unsigned long) syms;
2732 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002733 }
2734 }
2735
2736 /* Collect the kernel's symbols. */
2737
2738 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002739retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002740 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002741 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002742 syms = xrealloc(syms, bufsize = ret);
2743 goto retry_kern_sym_load;
2744 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002745 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002746 return 0;
2747 }
2748 nksyms = nsyms = ret;
2749 ksyms = syms;
2750
2751 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2752 s->name += (unsigned long) syms;
2753 }
2754 return 1;
2755}
2756
2757
2758/* Return the kernel symbol checksum version, or zero if not used. */
2759
2760static int new_is_kernel_checksummed(void)
2761{
2762 struct new_module_symbol *s;
2763 size_t i;
2764
2765 /* Using_Versions is not the first symbol, but it should be in there. */
2766
2767 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2768 if (strcmp((char *) s->name, "Using_Versions") == 0)
2769 return s->value;
2770
2771 return 0;
2772}
2773
2774
2775static int new_create_this_module(struct obj_file *f, const char *m_name)
2776{
2777 struct obj_section *sec;
2778
2779 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002780 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002781 memset(sec->contents, 0, sizeof(struct new_module));
2782
Miles Baderae28b042002-04-01 09:34:25 +00002783 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002784 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002785 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002786
2787 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002788 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002789
2790 return 1;
2791}
2792
Eric Andersen889dd202003-01-23 04:48:34 +00002793#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2794/* add an entry to the __ksymtab section, creating it if necessary */
2795static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2796{
2797 struct obj_section *sec;
2798 ElfW(Addr) ofs;
2799
2800 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2801 * If __ksymtab is defined but not marked alloc, x out the first character
2802 * (no obj_delete routine) and create a new __ksymtab with the correct
2803 * characteristics.
2804 */
2805 sec = obj_find_section(f, "__ksymtab");
2806 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2807 *((char *)(sec->name)) = 'x'; /* override const */
2808 sec = NULL;
2809 }
2810 if (!sec)
2811 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002812 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002813 if (!sec)
2814 return;
2815 sec->header.sh_flags |= SHF_ALLOC;
2816 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002817 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002818 ofs = sec->header.sh_size;
2819 obj_symbol_patch(f, sec->idx, ofs, sym);
2820 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2821 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2822}
2823#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002824
2825static int new_create_module_ksymtab(struct obj_file *f)
2826{
2827 struct obj_section *sec;
2828 int i;
2829
2830 /* We must always add the module references. */
2831
2832 if (n_ext_modules_used) {
2833 struct new_module_ref *dep;
2834 struct obj_symbol *tm;
2835
2836 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002837 (sizeof(struct new_module_ref)
2838 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002839 if (!sec)
2840 return 0;
2841
Miles Baderae28b042002-04-01 09:34:25 +00002842 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002843 dep = (struct new_module_ref *) sec->contents;
2844 for (i = 0; i < n_ext_modules; ++i)
2845 if (ext_modules[i].used) {
2846 dep->dep = ext_modules[i].addr;
2847 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002848 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002849 dep->next_ref = 0;
2850 ++dep;
2851 }
2852 }
2853
2854 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2855 size_t nsyms;
2856 int *loaded;
2857
2858 sec =
2859 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002860 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002861
2862 /* We don't want to export symbols residing in sections that
2863 aren't loaded. There are a number of these created so that
2864 we make sure certain module options don't appear twice. */
2865
2866 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2867 while (--i >= 0)
2868 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2869
2870 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2871 struct obj_symbol *sym;
2872 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002873 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002874 && sym->secidx <= SHN_HIRESERVE
2875 && (sym->secidx >= SHN_LORESERVE
2876 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002877 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2878
2879 obj_symbol_patch(f, sec->idx, ofs, sym);
2880 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002881 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002882
2883 nsyms++;
2884 }
2885 }
2886
2887 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2888 }
2889
2890 return 1;
2891}
2892
2893
2894static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002895new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002896{
2897 struct new_module *module;
2898 struct obj_section *sec;
2899 void *image;
2900 int ret;
2901 tgt_long m_addr;
2902
2903 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002904 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002905 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002906 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002907 module = (struct new_module *) sec->contents;
2908 m_addr = sec->header.sh_addr;
2909
2910 module->size_of_struct = sizeof(*module);
2911 module->size = m_size;
2912 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2913
2914 sec = obj_find_section(f, "__ksymtab");
2915 if (sec && sec->header.sh_size) {
2916 module->syms = sec->header.sh_addr;
2917 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2918 }
2919
2920 if (n_ext_modules_used) {
2921 sec = obj_find_section(f, ".kmodtab");
2922 module->deps = sec->header.sh_addr;
2923 module->ndeps = n_ext_modules_used;
2924 }
2925
2926 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002927 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002928 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002929 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002930
2931 sec = obj_find_section(f, "__ex_table");
2932 if (sec) {
2933 module->ex_table_start = sec->header.sh_addr;
2934 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2935 }
2936
2937 sec = obj_find_section(f, ".text.init");
2938 if (sec) {
2939 module->runsize = sec->header.sh_addr - m_addr;
2940 }
2941 sec = obj_find_section(f, ".data.init");
2942 if (sec) {
2943 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002944 module->runsize > sec->header.sh_addr - m_addr)
2945 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002946 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002947 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2948 if (sec && sec->header.sh_size) {
2949 module->archdata_start = (void*)sec->header.sh_addr;
2950 module->archdata_end = module->archdata_start + sec->header.sh_size;
2951 }
2952 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2953 if (sec && sec->header.sh_size) {
2954 module->kallsyms_start = (void*)sec->header.sh_addr;
2955 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2956 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002957
Eric Andersen9f16d612000-06-12 23:11:16 +00002958 /* Whew! All of the initialization is complete. Collect the final
2959 module image and give it to the kernel. */
2960
2961 image = xmalloc(m_size);
2962 obj_create_image(f, image);
2963
Eric Andersencb3b9b12004-06-22 11:50:52 +00002964 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002965 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002966 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002967
2968 free(image);
2969
2970 return ret == 0;
2971}
2972
Eric Andersen9f16d612000-06-12 23:11:16 +00002973
2974/*======================================================================*/
2975
Eric Andersen044228d2001-07-17 01:12:36 +00002976static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002977obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2978 const char *string)
2979{
2980 struct obj_string_patch *p;
2981 struct obj_section *strsec;
2982 size_t len = strlen(string) + 1;
2983 char *loc;
2984
2985 p = xmalloc(sizeof(*p));
2986 p->next = f->string_patches;
2987 p->reloc_secidx = secidx;
2988 p->reloc_offset = offset;
2989 f->string_patches = p;
2990
2991 strsec = obj_find_section(f, ".kstrtab");
2992 if (strsec == NULL) {
2993 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2994 p->string_offset = 0;
2995 loc = strsec->contents;
2996 } else {
2997 p->string_offset = strsec->header.sh_size;
2998 loc = obj_extend_section(strsec, len);
2999 }
3000 memcpy(loc, string, len);
3001
3002 return 1;
3003}
3004
Eric Andersen044228d2001-07-17 01:12:36 +00003005static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003006obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3007 struct obj_symbol *sym)
3008{
3009 struct obj_symbol_patch *p;
3010
3011 p = xmalloc(sizeof(*p));
3012 p->next = f->symbol_patches;
3013 p->reloc_secidx = secidx;
3014 p->reloc_offset = offset;
3015 p->sym = sym;
3016 f->symbol_patches = p;
3017
3018 return 1;
3019}
3020
Eric Andersen044228d2001-07-17 01:12:36 +00003021static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003022{
3023 unsigned long i;
3024 int ret = 1;
3025
3026 for (i = 0; i < HASH_BUCKETS; ++i) {
3027 struct obj_symbol *sym;
3028 for (sym = f->symtab[i]; sym; sym = sym->next)
3029 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003030 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003031 sym->secidx = SHN_ABS;
3032 sym->value = 0;
3033 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003034 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003035 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003036 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003037 ret = 0;
3038 }
3039 }
3040 }
3041
3042 return ret;
3043}
3044
Eric Andersen044228d2001-07-17 01:12:36 +00003045static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003046{
3047 struct common_entry {
3048 struct common_entry *next;
3049 struct obj_symbol *sym;
3050 } *common_head = NULL;
3051
3052 unsigned long i;
3053
3054 for (i = 0; i < HASH_BUCKETS; ++i) {
3055 struct obj_symbol *sym;
3056 for (sym = f->symtab[i]; sym; sym = sym->next)
3057 if (sym->secidx == SHN_COMMON) {
3058 /* Collect all COMMON symbols and sort them by size so as to
3059 minimize space wasted by alignment requirements. */
3060 {
3061 struct common_entry **p, *n;
3062 for (p = &common_head; *p; p = &(*p)->next)
3063 if (sym->size <= (*p)->sym->size)
3064 break;
3065
3066 n = alloca(sizeof(*n));
3067 n->next = *p;
3068 n->sym = sym;
3069 *p = n;
3070 }
3071 }
3072 }
3073
3074 for (i = 1; i < f->local_symtab_size; ++i) {
3075 struct obj_symbol *sym = f->local_symtab[i];
3076 if (sym && sym->secidx == SHN_COMMON) {
3077 struct common_entry **p, *n;
3078 for (p = &common_head; *p; p = &(*p)->next)
3079 if (sym == (*p)->sym)
3080 break;
3081 else if (sym->size < (*p)->sym->size) {
3082 n = alloca(sizeof(*n));
3083 n->next = *p;
3084 n->sym = sym;
3085 *p = n;
3086 break;
3087 }
3088 }
3089 }
3090
3091 if (common_head) {
3092 /* Find the bss section. */
3093 for (i = 0; i < f->header.e_shnum; ++i)
3094 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3095 break;
3096
3097 /* If for some reason there hadn't been one, create one. */
3098 if (i == f->header.e_shnum) {
3099 struct obj_section *sec;
3100
3101 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3102 f->sections[i] = sec = arch_new_section();
3103 f->header.e_shnum = i + 1;
3104
3105 memset(sec, 0, sizeof(*sec));
3106 sec->header.sh_type = SHT_PROGBITS;
3107 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3108 sec->name = ".bss";
3109 sec->idx = i;
3110 }
3111
3112 /* Allocate the COMMONS. */
3113 {
3114 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3115 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3116 struct common_entry *c;
3117
3118 for (c = common_head; c; c = c->next) {
3119 ElfW(Addr) align = c->sym->value;
3120
3121 if (align > max_align)
3122 max_align = align;
3123 if (bss_size & (align - 1))
3124 bss_size = (bss_size | (align - 1)) + 1;
3125
3126 c->sym->secidx = i;
3127 c->sym->value = bss_size;
3128
3129 bss_size += c->sym->size;
3130 }
3131
3132 f->sections[i]->header.sh_size = bss_size;
3133 f->sections[i]->header.sh_addralign = max_align;
3134 }
3135 }
3136
3137 /* For the sake of patch relocation and parameter initialization,
3138 allocate zeroed data for NOBITS sections now. Note that after
3139 this we cannot assume NOBITS are really empty. */
3140 for (i = 0; i < f->header.e_shnum; ++i) {
3141 struct obj_section *s = f->sections[i];
3142 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003143 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003144 s->contents = memset(xmalloc(s->header.sh_size),
3145 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003146 else
3147 s->contents = NULL;
3148
Eric Andersen9f16d612000-06-12 23:11:16 +00003149 s->header.sh_type = SHT_PROGBITS;
3150 }
3151 }
3152}
3153
Eric Andersen044228d2001-07-17 01:12:36 +00003154static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003155{
3156 unsigned long dot = 0;
3157 struct obj_section *sec;
3158
3159 /* Finalize the positions of the sections relative to one another. */
3160
3161 for (sec = f->load_order; sec; sec = sec->load_next) {
3162 ElfW(Addr) align;
3163
3164 align = sec->header.sh_addralign;
3165 if (align && (dot & (align - 1)))
3166 dot = (dot | (align - 1)) + 1;
3167
3168 sec->header.sh_addr = dot;
3169 dot += sec->header.sh_size;
3170 }
3171
3172 return dot;
3173}
3174
Eric Andersen044228d2001-07-17 01:12:36 +00003175static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003176{
3177 int i, n = f->header.e_shnum;
3178 int ret = 1;
3179
3180 /* Finalize the addresses of the sections. */
3181
3182 f->baseaddr = base;
3183 for (i = 0; i < n; ++i)
3184 f->sections[i]->header.sh_addr += base;
3185
3186 /* And iterate over all of the relocations. */
3187
3188 for (i = 0; i < n; ++i) {
3189 struct obj_section *relsec, *symsec, *targsec, *strsec;
3190 ElfW(RelM) * rel, *relend;
3191 ElfW(Sym) * symtab;
3192 const char *strtab;
3193
3194 relsec = f->sections[i];
3195 if (relsec->header.sh_type != SHT_RELM)
3196 continue;
3197
3198 symsec = f->sections[relsec->header.sh_link];
3199 targsec = f->sections[relsec->header.sh_info];
3200 strsec = f->sections[symsec->header.sh_link];
3201
3202 rel = (ElfW(RelM) *) relsec->contents;
3203 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3204 symtab = (ElfW(Sym) *) symsec->contents;
3205 strtab = (const char *) strsec->contents;
3206
3207 for (; rel < relend; ++rel) {
3208 ElfW(Addr) value = 0;
3209 struct obj_symbol *intsym = NULL;
3210 unsigned long symndx;
3211 ElfW(Sym) * extsym = 0;
3212 const char *errmsg;
3213
3214 /* Attempt to find a value to use for this relocation. */
3215
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003216 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003217 if (symndx) {
3218 /* Note we've already checked for undefined symbols. */
3219
3220 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003221 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003222 /* Local symbols we look up in the local table to be sure
3223 we get the one that is really intended. */
3224 intsym = f->local_symtab[symndx];
3225 } else {
3226 /* Others we look up in the hash table. */
3227 const char *name;
3228 if (extsym->st_name)
3229 name = strtab + extsym->st_name;
3230 else
3231 name = f->sections[extsym->st_shndx]->name;
3232 intsym = obj_find_symbol(f, name);
3233 }
3234
3235 value = obj_symbol_final_value(f, intsym);
3236 intsym->referenced = 1;
3237 }
3238#if SHT_RELM == SHT_RELA
3239#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3240 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3241 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003242 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003243#endif
3244 value += rel->r_addend;
3245#endif
3246
3247 /* Do it! */
3248 switch (arch_apply_relocation
3249 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003250 case obj_reloc_ok:
3251 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003252
Eric Andersen3b1a7442003-12-24 20:30:45 +00003253 case obj_reloc_overflow:
3254 errmsg = "Relocation overflow";
3255 goto bad_reloc;
3256 case obj_reloc_dangerous:
3257 errmsg = "Dangerous relocation";
3258 goto bad_reloc;
3259 case obj_reloc_unhandled:
3260 errmsg = "Unhandled relocation";
3261bad_reloc:
3262 if (extsym) {
3263 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003264 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003265 strtab + extsym->st_name);
3266 } else {
3267 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003268 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003269 }
3270 ret = 0;
3271 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003272 }
3273 }
3274 }
3275
3276 /* Finally, take care of the patches. */
3277
3278 if (f->string_patches) {
3279 struct obj_string_patch *p;
3280 struct obj_section *strsec;
3281 ElfW(Addr) strsec_base;
3282 strsec = obj_find_section(f, ".kstrtab");
3283 strsec_base = strsec->header.sh_addr;
3284
3285 for (p = f->string_patches; p; p = p->next) {
3286 struct obj_section *targsec = f->sections[p->reloc_secidx];
3287 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3288 = strsec_base + p->string_offset;
3289 }
3290 }
3291
3292 if (f->symbol_patches) {
3293 struct obj_symbol_patch *p;
3294
3295 for (p = f->symbol_patches; p; p = p->next) {
3296 struct obj_section *targsec = f->sections[p->reloc_secidx];
3297 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3298 = obj_symbol_final_value(f, p->sym);
3299 }
3300 }
3301
3302 return ret;
3303}
3304
Eric Andersen044228d2001-07-17 01:12:36 +00003305static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003306{
3307 struct obj_section *sec;
3308 ElfW(Addr) base = f->baseaddr;
3309
3310 for (sec = f->load_order; sec; sec = sec->load_next) {
3311 char *secimg;
3312
Eric Andersen2bf658d2001-02-24 20:01:53 +00003313 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003314 continue;
3315
3316 secimg = image + (sec->header.sh_addr - base);
3317
3318 /* Note that we allocated data for NOBITS sections earlier. */
3319 memcpy(secimg, sec->contents, sec->header.sh_size);
3320 }
3321
3322 return 1;
3323}
3324
3325/*======================================================================*/
3326
Eric Andersen044228d2001-07-17 01:12:36 +00003327static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003328{
3329 struct obj_file *f;
3330 ElfW(Shdr) * section_headers;
3331 int shnum, i;
3332 char *shstrtab;
3333
3334 /* Read the file header. */
3335
3336 f = arch_new_file();
3337 memset(f, 0, sizeof(*f));
3338 f->symbol_cmp = strcmp;
3339 f->symbol_hash = obj_elf_hash;
3340 f->load_order_search_start = &f->load_order;
3341
3342 fseek(fp, 0, SEEK_SET);
3343 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003344 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003345 return NULL;
3346 }
3347
3348 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003349 || f->header.e_ident[EI_MAG1] != ELFMAG1
3350 || f->header.e_ident[EI_MAG2] != ELFMAG2
3351 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003352 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003353 return NULL;
3354 }
3355 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003356 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003357 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003358 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3359 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003360 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003361 return NULL;
3362 }
3363 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003364 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003365 return NULL;
3366 }
3367
3368 /* Read the section headers. */
3369
3370 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003371 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003372 (unsigned long) f->header.e_shentsize,
3373 (unsigned long) sizeof(ElfW(Shdr)));
3374 return NULL;
3375 }
3376
3377 shnum = f->header.e_shnum;
3378 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3379 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3380
3381 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3382 fseek(fp, f->header.e_shoff, SEEK_SET);
3383 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003384 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003385 return NULL;
3386 }
3387
3388 /* Read the section data. */
3389
3390 for (i = 0; i < shnum; ++i) {
3391 struct obj_section *sec;
3392
3393 f->sections[i] = sec = arch_new_section();
3394 memset(sec, 0, sizeof(*sec));
3395
3396 sec->header = section_headers[i];
3397 sec->idx = i;
3398
Eric Andersen2bf658d2001-02-24 20:01:53 +00003399 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003400 case SHT_NULL:
3401 case SHT_NOTE:
3402 case SHT_NOBITS:
3403 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003404 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003405
3406 case SHT_PROGBITS:
3407#if LOADBITS
3408 if (!loadprogbits) {
3409 sec->contents = NULL;
3410 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003411 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003412#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003413 case SHT_SYMTAB:
3414 case SHT_STRTAB:
3415 case SHT_RELM:
3416 if (sec->header.sh_size > 0) {
3417 sec->contents = xmalloc(sec->header.sh_size);
3418 fseek(fp, sec->header.sh_offset, SEEK_SET);
3419 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3420 bb_perror_msg("error reading ELF section data");
3421 return NULL;
3422 }
3423 } else {
3424 sec->contents = NULL;
3425 }
3426 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003427
3428#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003429 case SHT_RELA:
3430 bb_error_msg("RELA relocations not supported on this architecture");
3431 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003432#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003433 case SHT_REL:
3434 bb_error_msg("REL relocations not supported on this architecture");
3435 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003436#endif
3437
Eric Andersen3b1a7442003-12-24 20:30:45 +00003438 default:
3439 if (sec->header.sh_type >= SHT_LOPROC) {
3440 /* Assume processor specific section types are debug
3441 info and can safely be ignored. If this is ever not
3442 the case (Hello MIPS?), don't put ifdefs here but
3443 create an arch_load_proc_section(). */
3444 break;
3445 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003446
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 bb_error_msg("can't handle sections of type %ld",
3448 (long) sec->header.sh_type);
3449 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003450 }
3451 }
3452
3453 /* Do what sort of interpretation as needed by each section. */
3454
3455 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3456
3457 for (i = 0; i < shnum; ++i) {
3458 struct obj_section *sec = f->sections[i];
3459 sec->name = shstrtab + sec->header.sh_name;
3460 }
3461
3462 for (i = 0; i < shnum; ++i) {
3463 struct obj_section *sec = f->sections[i];
3464
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003465 /* .modinfo should be contents only but gcc has no attribute for that.
3466 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3467 */
3468 if (strcmp(sec->name, ".modinfo") == 0)
3469 sec->header.sh_flags &= ~SHF_ALLOC;
3470
Eric Andersen9f16d612000-06-12 23:11:16 +00003471 if (sec->header.sh_flags & SHF_ALLOC)
3472 obj_insert_section_load_order(f, sec);
3473
3474 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003475 case SHT_SYMTAB:
3476 {
3477 unsigned long nsym, j;
3478 char *strtab;
3479 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003480
Eric Andersen3b1a7442003-12-24 20:30:45 +00003481 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3482 bb_error_msg("symbol size mismatch: %lu != %lu",
3483 (unsigned long) sec->header.sh_entsize,
3484 (unsigned long) sizeof(ElfW(Sym)));
3485 return NULL;
3486 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003487
Eric Andersen3b1a7442003-12-24 20:30:45 +00003488 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3489 strtab = f->sections[sec->header.sh_link]->contents;
3490 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003491
Eric Andersen3b1a7442003-12-24 20:30:45 +00003492 /* Allocate space for a table of local symbols. */
3493 j = f->local_symtab_size = sec->header.sh_info;
Rob Landley081e3842006-08-03 20:07:35 +00003494 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003495
Eric Andersen3b1a7442003-12-24 20:30:45 +00003496 /* Insert all symbols into the hash table. */
3497 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3498 ElfW(Addr) val = sym->st_value;
3499 const char *name;
3500 if (sym->st_name)
3501 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003502 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003503 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003504 else
3505 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003506
Eric Andersenbf833552003-08-13 19:56:33 +00003507#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003508 /*
3509 * For sh64 it is possible that the target of a branch
3510 * requires a mode switch (32 to 16 and back again).
3511 *
3512 * This is implied by the lsb being set in the target
3513 * address for SHmedia mode and clear for SHcompact.
3514 */
3515 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003516#endif
3517
Eric Andersen3b1a7442003-12-24 20:30:45 +00003518 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3519 val, sym->st_size);
3520 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003521 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003522 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003523
Eric Andersen3b1a7442003-12-24 20:30:45 +00003524 case SHT_RELM:
3525 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3526 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3527 (unsigned long) sec->header.sh_entsize,
3528 (unsigned long) sizeof(ElfW(RelM)));
3529 return NULL;
3530 }
3531 break;
3532 /* XXX Relocation code from modutils-2.3.19 is not here.
3533 * Why? That's about 20 lines of code from obj/obj_load.c,
3534 * which gets done in a second pass through the sections.
3535 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003536 }
3537 }
3538
3539 return f;
3540}
3541
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003542#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003543/*
3544 * load the unloaded sections directly into the memory allocated by
3545 * kernel for the module
3546 */
3547
Eric Andersenac5dbd12001-08-22 05:26:08 +00003548static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003549{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003550 ElfW(Addr) base = f->baseaddr;
3551 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003552
Eric Andersen8ae319a2001-05-21 16:09:18 +00003553 for (sec = f->load_order; sec; sec = sec->load_next) {
3554
3555 /* section already loaded? */
3556 if (sec->contents != NULL)
3557 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003558
Eric Andersen8ae319a2001-05-21 16:09:18 +00003559 if (sec->header.sh_size == 0)
3560 continue;
3561
3562 sec->contents = imagebase + (sec->header.sh_addr - base);
3563 fseek(fp, sec->header.sh_offset, SEEK_SET);
3564 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003565 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003566 return 0;
3567 }
3568
3569 }
3570 return 1;
3571}
3572#endif
3573
Eric Andersen9f16d612000-06-12 23:11:16 +00003574static void hide_special_symbols(struct obj_file *f)
3575{
3576 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003577 SPFX "cleanup_module",
3578 SPFX "init_module",
3579 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003580 NULL
3581 };
3582
3583 struct obj_symbol *sym;
3584 const char *const *p;
3585
3586 for (p = specials; *p; ++p)
3587 if ((sym = obj_find_symbol(f, *p)) != NULL)
3588 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003589 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003590}
3591
Glenn L McGrath759515c2003-08-30 06:00:33 +00003592
Eric Andersen71ae64b2002-10-10 04:20:21 +00003593#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003594static int obj_gpl_license(struct obj_file *f, const char **license)
3595{
3596 struct obj_section *sec;
3597 /* This list must match *exactly* the list of allowable licenses in
3598 * linux/include/linux/module.h. Checking for leading "GPL" will not
3599 * work, somebody will use "GPL sucks, this is proprietary".
3600 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003601 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003602 "GPL",
3603 "GPL v2",
3604 "GPL and additional rights",
3605 "Dual BSD/GPL",
3606 "Dual MPL/GPL",
3607 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003608
Eric Andersen166fa462002-09-16 05:30:24 +00003609 if ((sec = obj_find_section(f, ".modinfo"))) {
3610 const char *value, *ptr, *endptr;
3611 ptr = sec->contents;
3612 endptr = ptr + sec->header.sh_size;
3613 while (ptr < endptr) {
3614 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3615 int i;
3616 if (license)
3617 *license = value+1;
3618 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3619 if (strcmp(value+1, gpl_licenses[i]) == 0)
3620 return(0);
3621 }
3622 return(2);
3623 }
3624 if (strchr(ptr, '\0'))
3625 ptr = strchr(ptr, '\0') + 1;
3626 else
3627 ptr = endptr;
3628 }
3629 }
3630 return(1);
3631}
3632
3633#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3634#define TAINT_PROPRIETORY_MODULE (1<<0)
3635#define TAINT_FORCED_MODULE (1<<1)
3636#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003637#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003638
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003639static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003640 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3641{
3642 char buf[80];
3643 int oldval;
3644 static int first = 1;
3645 if (fd < 0 && !kernel_has_tainted)
3646 return; /* New modutils on old kernel */
3647 printf("Warning: loading %s will taint the kernel: %s%s\n",
3648 m_name, text1, text2);
3649 if (first) {
3650 printf(" See %s for information about tainted modules\n", TAINT_URL);
3651 first = 0;
3652 }
3653 if (fd >= 0) {
3654 read(fd, buf, sizeof(buf)-1);
3655 buf[sizeof(buf)-1] = '\0';
3656 oldval = strtoul(buf, NULL, 10);
3657 sprintf(buf, "%d\n", oldval | taint);
3658 write(fd, buf, strlen(buf));
3659 }
3660}
3661
3662/* Check if loading this module will taint the kernel. */
3663static void check_tainted_module(struct obj_file *f, char *m_name)
3664{
3665 static const char tainted_file[] = TAINT_FILENAME;
3666 int fd, kernel_has_tainted;
3667 const char *ptr;
3668
3669 kernel_has_tainted = 1;
3670 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3671 if (errno == ENOENT)
3672 kernel_has_tainted = 0;
3673 else if (errno == EACCES)
3674 kernel_has_tainted = 1;
3675 else {
3676 perror(tainted_file);
3677 kernel_has_tainted = 0;
3678 }
3679 }
3680
3681 switch (obj_gpl_license(f, &ptr)) {
3682 case 0:
3683 break;
3684 case 1:
3685 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3686 break;
3687 case 2:
3688 /* The module has a non-GPL license so we pretend that the
3689 * kernel always has a taint flag to get a warning even on
3690 * kernels without the proc flag.
3691 */
3692 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3693 break;
3694 default:
3695 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3696 break;
3697 }
3698
3699 if (flag_force_load)
3700 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3701
3702 if (fd >= 0)
3703 close(fd);
3704}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003705#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3706#define check_tainted_module(x, y) do { } while(0);
3707#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003708
Eric Andersen889dd202003-01-23 04:48:34 +00003709#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3710/* add module source, timestamp, kernel version and a symbol for the
3711 * start of some sections. this info is used by ksymoops to do better
3712 * debugging.
3713 */
3714static int
3715get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3716{
3717#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003718 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003719#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003720 strncpy(str, "???", sizeof(str));
3721 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003722#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3723}
3724
3725/* add module source, timestamp, kernel version and a symbol for the
3726 * start of some sections. this info is used by ksymoops to do better
3727 * debugging.
3728 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003729static void
Eric Andersen889dd202003-01-23 04:48:34 +00003730add_ksymoops_symbols(struct obj_file *f, const char *filename,
3731 const char *m_name)
3732{
3733 static const char symprefix[] = "__insmod_";
3734 struct obj_section *sec;
3735 struct obj_symbol *sym;
3736 char *name, *absolute_filename;
3737 char str[STRVERSIONLEN], real[PATH_MAX];
3738 int i, l, lm_name, lfilename, use_ksymtab, version;
3739 struct stat statbuf;
3740
3741 static const char *section_names[] = {
3742 ".text",
3743 ".rodata",
3744 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003745 ".bss",
3746 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003747 };
3748
3749 if (realpath(filename, real)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +00003750 absolute_filename = xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003751 }
3752 else {
3753 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003754 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003755 errno = save_errno;
3756 perror("");
Rob Landleyd921b2e2006-08-03 15:41:12 +00003757 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003758 }
3759
3760 lm_name = strlen(m_name);
3761 lfilename = strlen(absolute_filename);
3762
3763 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3764 * are not to be exported. otherwise leave ksymtab alone for now, the
3765 * "export all symbols" compatibility code will export these symbols later.
3766 */
3767 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3768
3769 if ((sec = obj_find_section(f, ".this"))) {
3770 /* tag the module header with the object name, last modified
3771 * timestamp and module version. worst case for module version
3772 * is 0xffffff, decimal 16777215. putting all three fields in
3773 * one symbol is less readable but saves kernel space.
3774 */
3775 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003776 lm_name+ /* module name */
3777 2+ /* "_O" */
3778 lfilename+ /* object filename */
3779 2+ /* "_M" */
3780 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3781 2+ /* "_V" */
3782 8+ /* version in dec */
3783 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003784 name = xmalloc(l);
3785 if (stat(absolute_filename, &statbuf) != 0)
3786 statbuf.st_mtime = 0;
3787 version = get_module_version(f, str); /* -1 if not found */
3788 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003789 symprefix, m_name, absolute_filename,
3790 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3791 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003792 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003793 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003794 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003795 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003796 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003797 }
3798 free(absolute_filename);
3799#ifdef _NOT_SUPPORTED_
3800 /* record where the persistent data is going, same address as previous symbol */
3801
3802 if (f->persist) {
3803 l = sizeof(symprefix)+ /* "__insmod_" */
3804 lm_name+ /* module name */
3805 2+ /* "_P" */
3806 strlen(f->persist)+ /* data store */
3807 1; /* nul */
3808 name = xmalloc(l);
3809 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003810 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003811 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003812 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003813 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003814 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003815 }
3816#endif /* _NOT_SUPPORTED_ */
3817 /* tag the desired sections if size is non-zero */
3818
3819 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3820 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003821 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003822 l = sizeof(symprefix)+ /* "__insmod_" */
3823 lm_name+ /* module name */
3824 2+ /* "_S" */
3825 strlen(sec->name)+ /* section name */
3826 2+ /* "_L" */
3827 8+ /* length in dec */
3828 1; /* nul */
3829 name = xmalloc(l);
3830 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003831 symprefix, m_name, sec->name,
3832 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003833 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003834 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003835 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003836 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003837 }
3838 }
3839}
3840#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3841
Eric Andersenbe65c352003-01-23 04:57:35 +00003842#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3843static void print_load_map(struct obj_file *f)
3844{
3845 struct obj_symbol *sym;
3846 struct obj_symbol **all, **p;
3847 struct obj_section *sec;
3848 int i, nsyms, *loaded;
3849
3850 /* Report on the section layout. */
3851
3852 printf("Sections: Size %-*s Align\n",
3853 (int) (2 * sizeof(void *)), "Address");
3854
3855 for (sec = f->load_order; sec; sec = sec->load_next) {
3856 int a;
3857 unsigned long tmp;
3858
3859 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3860 tmp >>= 1;
3861 if (a == -1)
3862 a = 0;
3863
3864 printf("%-15s %08lx %0*lx 2**%d\n",
3865 sec->name,
3866 (long)sec->header.sh_size,
3867 (int) (2 * sizeof(void *)),
3868 (long)sec->header.sh_addr,
3869 a);
3870 }
3871#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3872 /* Quick reference which section indicies are loaded. */
3873
3874 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3875 while (--i >= 0)
3876 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3877
3878 /* Collect the symbols we'll be listing. */
3879
3880 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3881 for (sym = f->symtab[i]; sym; sym = sym->next)
3882 if (sym->secidx <= SHN_HIRESERVE
3883 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3884 ++nsyms;
3885
3886 all = alloca(nsyms * sizeof(struct obj_symbol *));
3887
3888 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3889 for (sym = f->symtab[i]; sym; sym = sym->next)
3890 if (sym->secidx <= SHN_HIRESERVE
3891 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3892 *p++ = sym;
3893
3894 /* And list them. */
3895 printf("\nSymbols:\n");
3896 for (p = all; p < all + nsyms; ++p) {
3897 char type = '?';
3898 unsigned long value;
3899
3900 sym = *p;
3901 if (sym->secidx == SHN_ABS) {
3902 type = 'A';
3903 value = sym->value;
3904 } else if (sym->secidx == SHN_UNDEF) {
3905 type = 'U';
3906 value = 0;
3907 } else {
3908 sec = f->sections[sym->secidx];
3909
3910 if (sec->header.sh_type == SHT_NOBITS)
3911 type = 'B';
3912 else if (sec->header.sh_flags & SHF_ALLOC) {
3913 if (sec->header.sh_flags & SHF_EXECINSTR)
3914 type = 'T';
3915 else if (sec->header.sh_flags & SHF_WRITE)
3916 type = 'D';
3917 else
3918 type = 'R';
3919 }
3920 value = sym->value + sec->header.sh_addr;
3921 }
3922
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003923 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003924 type = tolower(type);
3925
3926 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3927 type, sym->name);
3928 }
3929#endif
3930}
3931
3932#endif
3933
Rob Landleydfba7412006-03-06 20:47:33 +00003934int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003935{
Eric Andersena18aaf12001-01-24 19:07:09 +00003936 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003937 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003938 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003939 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003940 unsigned long m_size;
3941 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003942 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003943 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003944 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003945 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003946 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003947#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003948 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003949 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003950 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003951#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003952#ifdef CONFIG_FEATURE_CLEAN_UP
3953 FILE *fp = 0;
3954#else
3955 FILE *fp;
3956#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003957#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3958 int flag_print_load_map = 0;
3959#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003960 int k_version = 0;
3961 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003962
Erik Andersene49d5ec2000-02-08 19:58:47 +00003963 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003964#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003965 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003966#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003967 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003968#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003969 {
3970 switch (opt) {
3971 case 'f': /* force loading */
3972 flag_force_load = 1;
3973 break;
3974 case 'k': /* module loaded by kerneld, auto-cleanable */
3975 flag_autoclean = 1;
3976 break;
3977 case 's': /* log to syslog */
3978 /* log to syslog -- not supported */
3979 /* but kernel needs this for request_module(), */
3980 /* as this calls: modprobe -k -s -- <module> */
3981 /* so silently ignore this flag */
3982 break;
3983 case 'v': /* verbose output */
3984 flag_verbose = 1;
3985 break;
3986 case 'q': /* silent */
3987 flag_quiet = 1;
3988 break;
3989 case 'x': /* do not export externs */
3990 flag_export = 0;
3991 break;
3992 case 'o': /* name the output module */
3993 free(m_name);
Rob Landleyd921b2e2006-08-03 15:41:12 +00003994 m_name = xstrdup(optarg);
Eric Andersen3b1a7442003-12-24 20:30:45 +00003995 break;
3996 case 'L': /* Stub warning */
3997 /* This is needed for compatibility with modprobe.
3998 * In theory, this does locking, but we don't do
3999 * that. So be careful and plan your life around not
4000 * loading the same module 50 times concurrently. */
4001 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004002#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00004003 case 'm': /* print module load map */
4004 flag_print_load_map = 1;
4005 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00004006#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004007 default:
4008 bb_show_usage();
4009 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004010 }
Eric Andersen03d80912003-12-19 21:04:19 +00004011
Eric Andersena18aaf12001-01-24 19:07:09 +00004012 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004013 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00004014 }
Eric Andersena18aaf12001-01-24 19:07:09 +00004015
Erik Andersene49d5ec2000-02-08 19:58:47 +00004016 /* Grab the module name */
Rob Landleyd921b2e2006-08-03 15:41:12 +00004017 tmp1 = xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00004018 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004019 len = strlen(tmp);
4020
Eric Andersen03d80912003-12-19 21:04:19 +00004021 if (uname(&myuname) == 0) {
4022 if (myuname.release[0] == '2') {
4023 k_version = myuname.release[2] - '0';
4024 }
4025 }
4026
4027#if defined(CONFIG_FEATURE_2_6_MODULES)
4028 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004029 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004030 len-=3;
4031 tmp[len] = '\0';
4032 }
4033 else
4034#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004035 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4036 len-=2;
4037 tmp[len] = '\0';
4038 }
Eric Andersen2d342152002-06-18 05:16:25 +00004039
Eric Andersen03d80912003-12-19 21:04:19 +00004040
4041#if defined(CONFIG_FEATURE_2_6_MODULES)
4042 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00004043 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004044 else
Eric Andersen03d80912003-12-19 21:04:19 +00004045#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00004046 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004047
Eric Andersen61f83052002-06-22 17:15:42 +00004048 if (!m_name) {
4049 m_name = tmp;
4050 } else {
4051 free(tmp1);
4052 tmp1 = 0; /* flag for free(m_name) before exit() */
4053 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004054
Eric Andersen14d35432001-05-14 17:07:32 +00004055 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004056 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4057 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004058 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4059 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004060 if (k_version) { /* uname succeedd */
4061 char *module_dir;
4062 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004063 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004064
Eric Andersen03d80912003-12-19 21:04:19 +00004065 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004066 /* Jump through hoops in case /lib/modules/`uname -r`
4067 * is a symlink. We do not want recursive_action to
4068 * follow symlinks, but we do want to follow the
4069 * /lib/modules/`uname -r` dir, So resolve it ourselves
4070 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004071 if (realpath (tmdn, real_module_dir) == NULL)
4072 module_dir = tmdn;
4073 else
4074 module_dir = real_module_dir;
4075 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004076 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004077 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004078 }
4079
4080 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004081 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004082 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004083 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004084
Eric Andersen03d80912003-12-19 21:04:19 +00004085 free(m_filename);
4086 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004087 if (realpath (_PATH_MODULES, module_dir) == NULL)
4088 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004089 /* No module found under /lib/modules/`uname -r`, this
4090 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004091 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004092 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004093 {
Eric Andersen61f83052002-06-22 17:15:42 +00004094 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004095 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004096 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004097 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004098 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004099 }
4100 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004101 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004102 }
Eric Andersen03d80912003-12-19 21:04:19 +00004103 } else
Rob Landleyd921b2e2006-08-03 15:41:12 +00004104 m_filename = xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004105
Rob Landley999af202005-12-11 20:14:12 +00004106 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004107 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004108
Eric Andersene7047882003-12-11 01:42:13 +00004109#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004110 if (k_version > 4)
4111 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004112 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004113 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004114 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004115 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004116#endif
4117
Eric Andersen8ae319a2001-05-21 16:09:18 +00004118 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004119 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004120
Eric Andersen9f16d612000-06-12 23:11:16 +00004121 if (get_modinfo_value(f, "kernel_version") == NULL)
4122 m_has_modinfo = 0;
4123 else
4124 m_has_modinfo = 1;
4125
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004126#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004127 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004128 if (!flag_quiet) {
4129 if (uname(&uts_info) < 0)
4130 uts_info.release[0] = '\0';
4131 if (m_has_modinfo) {
4132 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004133 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004134 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004135 "compiled for");
4136 goto out;
4137 }
4138 }
4139
4140 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4141 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004142 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004143 "\t%s was compiled for kernel version %s\n"
4144 "\twhile this kernel is version %s",
4145 m_filename, m_strversion, uts_info.release);
4146 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004147 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004148 "\t%s was compiled for kernel version %s\n"
4149 "\twhile this kernel is version %s.",
4150 m_filename, m_strversion, uts_info.release);
4151 goto out;
4152 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004153 }
4154 }
4155 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004156#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004157
Eric Andersencb3b9b12004-06-22 11:50:52 +00004158 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004159 if (!new_get_kernel_symbols())
4160 goto out;
4161 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004162 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004163 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004164 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004165 }
4166
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004167#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004168 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004169 if (m_has_modinfo)
4170 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004171
4172 if (m_crcs != k_crcs)
4173 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004174#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004175
Erik Andersene49d5ec2000-02-08 19:58:47 +00004176 /* Let the module know about the kernel symbols. */
4177 add_kernel_symbols(f);
4178
Eric Andersen9f16d612000-06-12 23:11:16 +00004179 /* Allocate common symbols, symbol tables, and string tables. */
4180
Eric Andersencb3b9b12004-06-22 11:50:52 +00004181 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004182 {
4183 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004184 }
4185
Eric Andersen9f16d612000-06-12 23:11:16 +00004186 if (!obj_check_undefineds(f)) {
4187 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004188 }
4189 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004190 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004191
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004192 /* done with the module name, on to the optional var=value arguments */
4193 ++optind;
4194
Eric Andersen9f16d612000-06-12 23:11:16 +00004195 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004196 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004197 {
4198 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004199 }
4200 }
4201
Eric Andersen9f16d612000-06-12 23:11:16 +00004202 arch_create_got(f);
4203 hide_special_symbols(f);
4204
Eric Andersen889dd202003-01-23 04:48:34 +00004205#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4206 add_ksymoops_symbols(f, m_filename, m_name);
4207#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4208
Eric Andersencb3b9b12004-06-22 11:50:52 +00004209 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004210
Erik Andersene49d5ec2000-02-08 19:58:47 +00004211 /* Find current size of the module */
4212 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004213
4214
Erik Andersene49d5ec2000-02-08 19:58:47 +00004215 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004216 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004217 case EEXIST:
4218 bb_error_msg("A module named %s already exists", m_name);
4219 goto out;
4220 case ENOMEM:
4221 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4222 m_size);
4223 goto out;
4224 default:
4225 bb_perror_msg("create_module: %s", m_name);
4226 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004227 }
Erik Andersend387d011999-12-21 02:55:11 +00004228
Eric Andersen8ae319a2001-05-21 16:09:18 +00004229#if !LOADBITS
4230 /*
4231 * the PROGBITS section was not loaded by the obj_load
4232 * now we can load them directly into the kernel memory
4233 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004234 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004235 delete_module(m_name);
4236 goto out;
4237 }
Eric Andersen03d80912003-12-19 21:04:19 +00004238#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004239
Eric Andersen9f16d612000-06-12 23:11:16 +00004240 if (!obj_relocate(f, m_addr)) {
4241 delete_module(m_name);
4242 goto out;
4243 }
Erik Andersend387d011999-12-21 02:55:11 +00004244
Eric Andersencb3b9b12004-06-22 11:50:52 +00004245 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004246 {
4247 delete_module(m_name);
4248 goto out;
4249 }
4250
Eric Andersenbe65c352003-01-23 04:57:35 +00004251#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4252 if(flag_print_load_map)
4253 print_load_map(f);
4254#endif
4255
Matt Kraai3e856ce2000-12-01 02:55:13 +00004256 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004257
4258out:
Eric Andersen61f83052002-06-22 17:15:42 +00004259#ifdef CONFIG_FEATURE_CLEAN_UP
4260 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004261 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004262 free(tmp1);
4263 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004264 free(m_name);
4265 }
4266 free(m_filename);
4267#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004268 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004269}
Eric Andersene7047882003-12-11 01:42:13 +00004270
4271
4272#endif
4273
4274
4275#ifdef CONFIG_FEATURE_2_6_MODULES
4276
4277#include <sys/mman.h>
4278#include <asm/unistd.h>
4279#include <sys/syscall.h>
4280
4281/* We use error numbers in a loose translation... */
4282static const char *moderror(int err)
4283{
4284 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004285 case ENOEXEC:
4286 return "Invalid module format";
4287 case ENOENT:
4288 return "Unknown symbol in module";
4289 case ESRCH:
4290 return "Module has wrong symbol version";
4291 case EINVAL:
4292 return "Invalid parameters";
4293 default:
4294 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004295 }
4296}
4297
Rob Landleydfba7412006-03-06 20:47:33 +00004298int insmod_ng_main( int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004299{
4300 int i;
4301 int fd;
4302 long int ret;
4303 struct stat st;
4304 unsigned long len;
4305 void *map;
Rob Landleyd921b2e2006-08-03 15:41:12 +00004306 char *filename, *options = xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004307
Eric Andersene7047882003-12-11 01:42:13 +00004308 filename = argv[1];
4309 if (!filename) {
4310 bb_show_usage();
4311 return -1;
4312 }
4313
4314 /* Rest is options */
4315 for (i = 2; i < argc; i++) {
4316 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4317 /* Spaces handled by "" pairs, but no way of escaping quotes */
4318 if (strchr(argv[i], ' ')) {
4319 strcat(options, "\"");
4320 strcat(options, argv[i]);
4321 strcat(options, "\"");
4322 } else {
4323 strcat(options, argv[i]);
4324 }
4325 strcat(options, " ");
4326 }
4327
Rob Landleyd921b2e2006-08-03 15:41:12 +00004328 fd = xopen3(filename, O_RDONLY, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004329
4330 fstat(fd, &st);
4331 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004332 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004333 if (map == MAP_FAILED) {
4334 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4335 }
4336
4337 ret = syscall(__NR_init_module, map, len, options);
4338 if (ret != 0) {
4339 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004340 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004341 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004342
Eric Andersene7047882003-12-11 01:42:13 +00004343 return 0;
4344}
4345
4346#endif