blob: 866e333ec635b15e290fa5b2123b0669b824e466 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
Eric Andersen2835efe2001-07-25 16:58:58 +00004 *
Eric Andersen45a05132004-09-02 23:03:25 +00005 * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
6 * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00008 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +00009 * and Ron Alder <alder@lineo.com>
10 *
Eric Andersena4d27d22004-08-19 19:17:30 +000011 * Rodney Radford <rradford@mindspring.com> 17-Aug-2004.
12 * Added x86_64 support.
13 *
Miles Bader75ce8d72002-04-01 14:25:51 +000014 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000015 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000017 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
18 *
19 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
20 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
21 * very minor changes required to also work with StrongArm and presumably
22 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000023 *
Eric Andersenee70fa52004-05-26 11:38:46 +000024 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
25 * added Renesas H8/300 support.
26 *
Eric Andersenbf833552003-08-13 19:56:33 +000027 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
28 * Integrated support for sh64 (SH-5), from preliminary modutils
29 * patches from Benedict Gaster <benedict.gaster@superh.com>.
30 * Currently limited to support for 32bit ABI.
31 *
Eric Andersencffd5022002-05-24 06:50:15 +000032 * Magnus Damm <damm@opensource.se> 22-May-2002.
33 * The plt and got code are now using the same structs.
34 * Added generic linked list code to fully support PowerPC.
35 * Replaced the mess in arch_apply_relocation() with architecture blocks.
36 * The arch_create_got() function got cleaned up with architecture blocks.
37 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
38 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000040 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
42 * I've only tested the code on mpc8xx platforms in big-endian mode.
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000043 * Did some cleanup and added USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000044 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000045 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
46 * based on modutils-2.4.2
47 * MIPS specific support for Elf loading and relocation.
48 * Copyright 1996, 1997 Linux International.
49 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
50 *
Eric Andersen9f16d612000-06-12 23:11:16 +000051 * Based almost entirely on the Linux modutils-2.3.11 implementation.
52 * Copyright 1996, 1997 Linux International.
53 * New implementation contributed by Richard Henderson <rth@tamu.edu>
54 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
55 * Restructured (and partly rewritten) by:
56 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000057 *
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +000058 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Erik Andersen02104321999-12-17 18:57:34 +000059 */
60
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +000061#include "busybox.h"
Rob Landley519d7df2006-08-09 20:56:23 +000062#include <libgen.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000063#include <sys/utsname.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000064
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000065#if !ENABLE_FEATURE_2_4_MODULES && !ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko3bba5452006-12-30 17:57:03 +000066#undef ENABLE_FEATURE_2_4_MODULES
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000067#define ENABLE_FEATURE_2_4_MODULES 1
Eric Andersene7047882003-12-11 01:42:13 +000068#endif
69
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000070#if !ENABLE_FEATURE_2_4_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000071#define insmod_ng_main insmod_main
72#endif
73
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000074#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +000075extern int insmod_ng_main( int argc, char **argv);
76#endif
77
Eric Andersencb3b9b12004-06-22 11:50:52 +000078
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000079#if ENABLE_FEATURE_2_4_MODULES
Eric Andersencb3b9b12004-06-22 11:50:52 +000080
Eric Andersen64c8b172001-04-05 07:33:10 +000081
Denis Vlasenko3aa2d512006-11-21 14:12:53 +000082#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +000083#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +000084#else
85#define LOADBITS 1
86#endif
87
Eric Andersen90fe7fe2001-02-20 20:47:08 +000088
Mike Frysinger63654c12004-12-26 09:13:32 +000089/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +000090#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +000091#define MATCH_MACHINE(x) (x == EM_ALPHA)
92#define SHT_RELM SHT_RELA
93#define Elf64_RelM Elf64_Rela
94#define ELFCLASSM ELFCLASS64
95#endif
96
Eric Andersen45a05132004-09-02 23:03:25 +000097/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +000098#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +000099#define MATCH_MACHINE(x) (x == EM_ARM)
100#define SHT_RELM SHT_REL
101#define Elf32_RelM Elf32_Rel
102#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000103#define USE_PLT_ENTRIES
104#define PLT_ENTRY_SIZE 8
105#define USE_GOT_ENTRIES
106#define GOT_ENTRY_SIZE 8
107#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000108#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000109
Mike Frysingerb306cb72006-06-06 06:15:52 +0000110/* blackfin */
111#if defined(BFIN)
112#define MATCH_MACHINE(x) (x == EM_BLACKFIN)
113#define SHT_RELM SHT_RELA
114#define Elf32_RelM Elf32_Rela
115#define ELFCLASSM ELFCLASS32
116#endif
117
Eric Andersen45a05132004-09-02 23:03:25 +0000118/* CRIS */
119#if defined(__cris__)
120#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000121#define SHT_RELM SHT_RELA
122#define Elf32_RelM Elf32_Rela
123#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000124#ifndef EM_CRIS
125#define EM_CRIS 76
126#define R_CRIS_NONE 0
127#define R_CRIS_32 3
128#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000129#endif
130
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000131/* H8/300 */
132#if defined(__H8300H__) || defined(__H8300S__)
133#define MATCH_MACHINE(x) (x == EM_H8_300)
134#define SHT_RELM SHT_RELA
135#define Elf32_RelM Elf32_Rela
136#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000137#define USE_SINGLE
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000138#define SYMBOL_PREFIX "_"
139#endif
140
Mike Frysinger63654c12004-12-26 09:13:32 +0000141/* PA-RISC / HP-PA */
142#if defined(__hppa__)
143#define MATCH_MACHINE(x) (x == EM_PARISC)
144#define SHT_RELM SHT_RELA
145#if defined(__LP64__)
146#define Elf64_RelM Elf64_Rela
147#define ELFCLASSM ELFCLASS64
148#else
149#define Elf32_RelM Elf32_Rela
150#define ELFCLASSM ELFCLASS32
151#endif
152#endif
153
Eric Andersen45a05132004-09-02 23:03:25 +0000154/* x86 */
155#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000156#ifndef EM_486
157#define MATCH_MACHINE(x) (x == EM_386)
158#else
159#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
160#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000161#define SHT_RELM SHT_REL
162#define Elf32_RelM Elf32_Rel
163#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000164#define USE_GOT_ENTRIES
165#define GOT_ENTRY_SIZE 4
166#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000167#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* IA64, aka Itanium */
170#if defined(__ia64__)
171#define MATCH_MACHINE(x) (x == EM_IA_64)
172#define SHT_RELM SHT_RELA
173#define Elf64_RelM Elf64_Rela
174#define ELFCLASSM ELFCLASS64
175#endif
176
177/* m68k */
178#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define MATCH_MACHINE(x) (x == EM_68K)
180#define SHT_RELM SHT_RELA
181#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000182#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000183#define USE_GOT_ENTRIES
184#define GOT_ENTRY_SIZE 4
185#define USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000186#endif
187
Mike Frysingerb306cb72006-06-06 06:15:52 +0000188/* Microblaze */
189#if defined(__microblaze__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000190#define USE_SINGLE
Mike Frysingerb306cb72006-06-06 06:15:52 +0000191#define MATCH_MACHINE(x) (x == EM_XILINX_MICROBLAZE)
192#define SHT_RELM SHT_RELA
193#define Elf32_RelM Elf32_Rela
194#define ELFCLASSM ELFCLASS32
195#endif
196
Eric Andersen45a05132004-09-02 23:03:25 +0000197/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000198#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000199#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
200#define SHT_RELM SHT_REL
201#define Elf32_RelM Elf32_Rel
202#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000203/* Account for ELF spec changes. */
204#ifndef EM_MIPS_RS3_LE
205#ifdef EM_MIPS_RS4_BE
206#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
207#else
208#define EM_MIPS_RS3_LE 10
209#endif
210#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000211#define ARCHDATAM "__dbe_table"
212#endif
213
Mike Frysingerf982d862006-01-04 00:11:26 +0000214/* Nios II */
215#if defined(__nios2__)
216#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
217#define SHT_RELM SHT_RELA
218#define Elf32_RelM Elf32_Rela
219#define ELFCLASSM ELFCLASS32
220#endif
221
Eric Andersen45a05132004-09-02 23:03:25 +0000222/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000223#if defined(__powerpc64__)
224#define MATCH_MACHINE(x) (x == EM_PPC64)
225#define SHT_RELM SHT_RELA
226#define Elf64_RelM Elf64_Rela
227#define ELFCLASSM ELFCLASS64
228#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000229#define MATCH_MACHINE(x) (x == EM_PPC)
230#define SHT_RELM SHT_RELA
231#define Elf32_RelM Elf32_Rela
232#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000233#define USE_PLT_ENTRIES
234#define PLT_ENTRY_SIZE 16
235#define USE_PLT_LIST
236#define LIST_ARCHTYPE ElfW(Addr)
237#define USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000238#define ARCHDATAM "__ftr_fixup"
239#endif
240
Eric Andersen45a05132004-09-02 23:03:25 +0000241/* S390 */
242#if defined(__s390__)
243#define MATCH_MACHINE(x) (x == EM_S390)
244#define SHT_RELM SHT_RELA
245#define Elf32_RelM Elf32_Rela
246#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000247#define USE_PLT_ENTRIES
248#define PLT_ENTRY_SIZE 8
249#define USE_GOT_ENTRIES
250#define GOT_ENTRY_SIZE 8
251#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000252#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000253
Eric Andersen45a05132004-09-02 23:03:25 +0000254/* SuperH */
255#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000256#define MATCH_MACHINE(x) (x == EM_SH)
257#define SHT_RELM SHT_RELA
258#define Elf32_RelM Elf32_Rela
259#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000260#define USE_GOT_ENTRIES
261#define GOT_ENTRY_SIZE 4
262#define USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000263/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000264/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000265#if defined(__sh__) && BB_BIG_ENDIAN
266# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000267#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000268/* it may or may not work on the SH1/SH2... Error on those also */
269#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000270#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000271#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000272#endif
273
Eric Andersen45a05132004-09-02 23:03:25 +0000274/* Sparc */
275#if defined(__sparc__)
276#define MATCH_MACHINE(x) (x == EM_SPARC)
277#define SHT_RELM SHT_RELA
278#define Elf32_RelM Elf32_Rela
279#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000280#endif
281
Eric Andersen45a05132004-09-02 23:03:25 +0000282/* v850e */
283#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000284#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
285#define SHT_RELM SHT_RELA
286#define Elf32_RelM Elf32_Rela
287#define ELFCLASSM ELFCLASS32
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000288#define USE_PLT_ENTRIES
289#define PLT_ENTRY_SIZE 8
290#define USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000291#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000292#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000293#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000294#define SYMBOL_PREFIX "_"
295#endif
296
Eric Andersen45a05132004-09-02 23:03:25 +0000297/* X86_64 */
298#if defined(__x86_64__)
299#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000300#define SHT_RELM SHT_RELA
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000301#define USE_GOT_ENTRIES
302#define GOT_ENTRY_SIZE 8
303#define USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000304#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000305#define ELFCLASSM ELFCLASS64
306#endif
307
Eric Andersencffd5022002-05-24 06:50:15 +0000308#ifndef SHT_RELM
309#error Sorry, but insmod.c does not yet support this architecture...
310#endif
311
312
Eric Andersen9f16d612000-06-12 23:11:16 +0000313//----------------------------------------------------------------------------
314//--------modutils module.h, lines 45-242
315//----------------------------------------------------------------------------
316
317/* Definitions for the Linux module syscall interface.
318 Copyright 1996, 1997 Linux International.
319
320 Contributed by Richard Henderson <rth@tamu.edu>
321
322 This file is part of the Linux modutils.
323
324 This program is free software; you can redistribute it and/or modify it
325 under the terms of the GNU General Public License as published by the
326 Free Software Foundation; either version 2 of the License, or (at your
327 option) any later version.
328
329 This program is distributed in the hope that it will be useful, but
330 WITHOUT ANY WARRANTY; without even the implied warranty of
331 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332 General Public License for more details.
333
334 You should have received a copy of the GNU General Public License
335 along with this program; if not, write to the Free Software Foundation,
336 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
337
338
339#ifndef MODUTILS_MODULE_H
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 */
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000371struct new_module_symbol {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000372 unsigned long value;
373 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000374};
375
376struct new_module_persist;
377
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000378struct new_module_ref {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000379 unsigned tgt_long dep; /* kernel addresses */
380 unsigned tgt_long ref;
381 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000382};
383
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000384struct new_module {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000385 unsigned tgt_long size_of_struct; /* == sizeof(module) */
386 unsigned tgt_long next;
387 unsigned tgt_long name;
388 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000389
Eric Andersen3b1a7442003-12-24 20:30:45 +0000390 tgt_long usecount;
391 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000392
Eric Andersen3b1a7442003-12-24 20:30:45 +0000393 unsigned nsyms;
394 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000395
Eric Andersen3b1a7442003-12-24 20:30:45 +0000396 unsigned tgt_long syms;
397 unsigned tgt_long deps;
398 unsigned tgt_long refs;
399 unsigned tgt_long init;
400 unsigned tgt_long cleanup;
401 unsigned tgt_long ex_table_start;
402 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000403#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000404 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000405#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000406 /* Everything after here is extension. */
407 unsigned tgt_long persist_start;
408 unsigned tgt_long persist_end;
409 unsigned tgt_long can_unload;
410 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000411 const char *kallsyms_start; /* All symbols for kernel debugging */
412 const char *kallsyms_end;
413 const char *archdata_start; /* arch specific data for module */
414 const char *archdata_end;
415 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000416};
417
Eric Andersencffd5022002-05-24 06:50:15 +0000418#ifdef ARCHDATAM
419#define ARCHDATA_SEC_NAME ARCHDATAM
420#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000421#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000422#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000423#define KALLSYMS_SEC_NAME "__kallsyms"
424
425
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000426struct new_module_info {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000427 unsigned long addr;
428 unsigned long size;
429 unsigned long flags;
430 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000431};
432
433/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000434enum {
435 NEW_MOD_RUNNING = 1,
436 NEW_MOD_DELETED = 2,
437 NEW_MOD_AUTOCLEAN = 4,
438 NEW_MOD_VISITED = 8,
439 NEW_MOD_USED_ONCE = 16
440};
Eric Andersen9f16d612000-06-12 23:11:16 +0000441
Eric Andersencb3b9b12004-06-22 11:50:52 +0000442int init_module(const char *name, const struct new_module *);
443int query_module(const char *name, int which, void *buf,
444 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000445
446/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000447enum {
448 QM_MODULES = 1,
449 QM_DEPS = 2,
450 QM_REFS = 3,
451 QM_SYMBOLS = 4,
452 QM_INFO = 5
453};
Eric Andersen9f16d612000-06-12 23:11:16 +0000454
455/*======================================================================*/
456/* The system calls unchanged between 2.0 and 2.1. */
457
458unsigned long create_module(const char *, size_t);
459int delete_module(const char *);
460
461
462#endif /* module.h */
463
464//----------------------------------------------------------------------------
465//--------end of modutils module.h
466//----------------------------------------------------------------------------
467
468
469
470//----------------------------------------------------------------------------
471//--------modutils obj.h, lines 253-462
472//----------------------------------------------------------------------------
473
474/* Elf object file loading and relocation routines.
475 Copyright 1996, 1997 Linux International.
476
477 Contributed by Richard Henderson <rth@tamu.edu>
478
479 This file is part of the Linux modutils.
480
481 This program is free software; you can redistribute it and/or modify it
482 under the terms of the GNU General Public License as published by the
483 Free Software Foundation; either version 2 of the License, or (at your
484 option) any later version.
485
486 This program is distributed in the hope that it will be useful, but
487 WITHOUT ANY WARRANTY; without even the implied warranty of
488 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
489 General Public License for more details.
490
491 You should have received a copy of the GNU General Public License
492 along with this program; if not, write to the Free Software Foundation,
493 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
494
495
496#ifndef MODUTILS_OBJ_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000497/* Why? static const int MODUTILS_OBJ_H = 1; */
Eric Andersen9f16d612000-06-12 23:11:16 +0000498
Eric Andersen9f16d612000-06-12 23:11:16 +0000499/* The relocatable object is manipulated using elfin types. */
500
501#include <stdio.h>
502#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000503#include <endian.h>
504
Eric Andersen9f16d612000-06-12 23:11:16 +0000505#ifndef ElfW
506# if ELFCLASSM == ELFCLASS32
507# define ElfW(x) Elf32_ ## x
508# define ELFW(x) ELF32_ ## x
509# else
510# define ElfW(x) Elf64_ ## x
511# define ELFW(x) ELF64_ ## x
512# endif
513#endif
514
Eric Andersen85e5e722003-07-22 08:56:55 +0000515/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000516#ifndef ELF32_ST_INFO
517# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
518#endif
519
520#ifndef ELF64_ST_INFO
521# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
522#endif
523
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000524#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
525#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
526#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
527#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
528#define ELF_R_SYM(val) ELFW(R_SYM)(val)
529
Eric Andersen9f16d612000-06-12 23:11:16 +0000530struct obj_string_patch;
531struct obj_symbol_patch;
532
533struct obj_section
534{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000535 ElfW(Shdr) header;
536 const char *name;
537 char *contents;
538 struct obj_section *load_next;
539 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000540};
541
542struct obj_symbol
543{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000544 struct obj_symbol *next; /* hash table link */
545 const char *name;
546 unsigned long value;
547 unsigned long size;
548 int secidx; /* the defining section index/module */
549 int info;
550 int ksymidx; /* for export to the kernel symtab */
551 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000552};
553
554/* Hardcode the hash table size. We shouldn't be needing so many
555 symbols that we begin to degrade performance, and we get a big win
556 by giving the compiler a constant divisor. */
557
558#define HASH_BUCKETS 521
559
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000560struct obj_file {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000561 ElfW(Ehdr) header;
562 ElfW(Addr) baseaddr;
563 struct obj_section **sections;
564 struct obj_section *load_order;
565 struct obj_section **load_order_search_start;
566 struct obj_string_patch *string_patches;
567 struct obj_symbol_patch *symbol_patches;
568 int (*symbol_cmp)(const char *, const char *);
569 unsigned long (*symbol_hash)(const char *);
570 unsigned long local_symtab_size;
571 struct obj_symbol **local_symtab;
572 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000573};
574
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000575enum obj_reloc {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000576 obj_reloc_ok,
577 obj_reloc_overflow,
578 obj_reloc_dangerous,
579 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000580};
581
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000582struct obj_string_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000583 struct obj_string_patch *next;
584 int reloc_secidx;
585 ElfW(Addr) reloc_offset;
586 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000587};
588
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000589struct obj_symbol_patch {
Eric Andersen3b1a7442003-12-24 20:30:45 +0000590 struct obj_symbol_patch *next;
591 int reloc_secidx;
592 ElfW(Addr) reloc_offset;
593 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000594};
595
596
597/* Generic object manipulation routines. */
598
Eric Andersen044228d2001-07-17 01:12:36 +0000599static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000600
Eric Andersen044228d2001-07-17 01:12:36 +0000601static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000602
Eric Andersen044228d2001-07-17 01:12:36 +0000603static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000604 const char *name);
605
Eric Andersen044228d2001-07-17 01:12:36 +0000606static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000607 struct obj_symbol *sym);
608
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000609#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000610static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000611 int (*cmp)(const char *, const char *),
612 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000613#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000614
Eric Andersen044228d2001-07-17 01:12:36 +0000615static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000616 const char *name);
617
Eric Andersen044228d2001-07-17 01:12:36 +0000618static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000619 struct obj_section *sec);
620
Eric Andersen044228d2001-07-17 01:12:36 +0000621static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000622 const char *name,
623 unsigned long align,
624 unsigned long size);
625
Eric Andersen044228d2001-07-17 01:12:36 +0000626static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000627 const char *name,
628 unsigned long align,
629 unsigned long size);
630
Eric Andersen044228d2001-07-17 01:12:36 +0000631static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000634 const char *string);
635
Eric Andersen044228d2001-07-17 01:12:36 +0000636static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000637 struct obj_symbol *sym);
638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000640
Eric Andersen044228d2001-07-17 01:12:36 +0000641static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000642
Eric Andersen044228d2001-07-17 01:12:36 +0000643static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000644
Eric Andersen044228d2001-07-17 01:12:36 +0000645static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000646
Eric Andersen044228d2001-07-17 01:12:36 +0000647static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000648
Eric Andersen044228d2001-07-17 01:12:36 +0000649static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
651/* Architecture specific manipulation routines. */
652
Eric Andersen044228d2001-07-17 01:12:36 +0000653static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000654
Eric Andersen044228d2001-07-17 01:12:36 +0000655static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000658
Eric Andersen044228d2001-07-17 01:12:36 +0000659static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000660 struct obj_section *targsec,
661 struct obj_section *symsec,
662 struct obj_symbol *sym,
663 ElfW(RelM) *rel, ElfW(Addr) value);
664
Eric Andersencffd5022002-05-24 06:50:15 +0000665static void arch_create_got (struct obj_file *f);
Bernhard Reutner-Fischere375e8c2006-03-29 18:57:09 +0000666#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +0000667static int obj_gpl_license(struct obj_file *f, const char **license);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000668#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +0000669#endif /* obj.h */
670//----------------------------------------------------------------------------
671//--------end of modutils obj.h
672//----------------------------------------------------------------------------
673
674
Miles Baderae28b042002-04-01 09:34:25 +0000675/* SPFX is always a string, so it can be concatenated to string constants. */
676#ifdef SYMBOL_PREFIX
677#define SPFX SYMBOL_PREFIX
678#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000679#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000680#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000681
Erik Andersen02104321999-12-17 18:57:34 +0000682
Erik Andersend387d011999-12-21 02:55:11 +0000683#define _PATH_MODULES "/lib/modules"
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000684enum { STRVERSIONLEN = 64 };
Erik Andersend387d011999-12-21 02:55:11 +0000685
Eric Andersen9f16d612000-06-12 23:11:16 +0000686/*======================================================================*/
687
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000688#define OPTION_STR "sLo:fkvqx" USE_FEATURE_INSMOD_LOAD_MAP("m")
689enum {
690 OPT_s = 0x1, // -s /* log to syslog */
691 /* Not supported but kernel needs this for request_module(),
692 as this calls: modprobe -k -s -- <module>
693 so silently ignore this flag */
694 OPT_L = 0x2, // -L /* Stub warning */
695 /* Compatibility with modprobe.
696 In theory, this does locking, but we don't do
697 that. So be careful and plan your life around not
698 loading the same module 50 times concurrently. */
699 OPT_o = 0x4, // -o /* name the output module */
700 OPT_f = 0x8, // -f /* force loading */
701 OPT_k = 0x10, // -k /* module loaded by kerneld, auto-cleanable */
702 OPT_v = 0x20, // -v /* verbose output */
703 OPT_q = 0x40, // -q /* silent */
704 OPT_x = 0x80, // -x /* do not export externs */
705 OPT_m = 0x100, // -m /* print module load map */
706};
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000707#define flag_force_load (option_mask32 & OPT_f)
708#define flag_autoclean (option_mask32 & OPT_k)
709#define flag_verbose (option_mask32 & OPT_v)
710#define flag_quiet (option_mask32 & OPT_q)
711#define flag_noexport (option_mask32 & OPT_x)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000712#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Denis Vlasenkoc12f5302006-10-06 09:49:47 +0000713#define flag_print_load_map (option_mask32 & OPT_m)
Denis Vlasenkofe76cd52006-09-23 12:32:58 +0000714#else
715#define flag_print_load_map 0
716#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000717
718/*======================================================================*/
719
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000720#if defined(USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000721
Eric Andersencffd5022002-05-24 06:50:15 +0000722struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000723{
Eric Andersencffd5022002-05-24 06:50:15 +0000724 struct arch_list_entry *next;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000725 LIST_ARCHTYPE addend;
Eric Andersencffd5022002-05-24 06:50:15 +0000726 int offset;
727 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000728};
Eric Andersencffd5022002-05-24 06:50:15 +0000729
Eric Andersen21adca72000-12-06 18:18:26 +0000730#endif
731
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000732#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +0000733
734struct arch_single_entry
735{
Eric Andersen9f16d612000-06-12 23:11:16 +0000736 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000737 int inited : 1;
738 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000739};
Eric Andersencffd5022002-05-24 06:50:15 +0000740
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000741#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000742
Eric Andersen2bf658d2001-02-24 20:01:53 +0000743#if defined(__mips__)
744struct mips_hi16
745{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000746 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000747 ElfW(Addr) *addr;
748 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000749};
750#endif
751
Eric Andersenfe4208f2000-09-24 03:44:29 +0000752struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000753 struct obj_file root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000754#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000755 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000756#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000757#if defined(USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000758 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000759#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000760#if defined(__mips__)
761 struct mips_hi16 *mips_hi16_list;
762#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000763};
764
Eric Andersenfe4208f2000-09-24 03:44:29 +0000765struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000766 struct obj_symbol root;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000767#if defined(USE_PLT_ENTRIES)
768#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000769 struct arch_list_entry *pltent;
770#else
771 struct arch_single_entry pltent;
772#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000773#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000774#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000775 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000776#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000777};
778
779
Eric Andersen9f16d612000-06-12 23:11:16 +0000780struct external_module {
781 const char *name;
782 ElfW(Addr) addr;
783 int used;
784 size_t nsyms;
785 struct new_module_symbol *syms;
786};
787
Eric Andersen044228d2001-07-17 01:12:36 +0000788static struct new_module_symbol *ksyms;
789static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000790
Eric Andersen044228d2001-07-17 01:12:36 +0000791static struct external_module *ext_modules;
792static int n_ext_modules;
793static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000794extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000795
Eric Andersen61f83052002-06-22 17:15:42 +0000796static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000797static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000798
Eric Andersenfe4208f2000-09-24 03:44:29 +0000799
Eric Andersen9f16d612000-06-12 23:11:16 +0000800/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000801
Eric Andersen9f16d612000-06-12 23:11:16 +0000802
Eric Andersen14d35432001-05-14 17:07:32 +0000803static int check_module_name_match(const char *filename, struct stat *statbuf,
Denis Vlasenko8c35d652006-10-27 23:42:25 +0000804 void *userdata, int depth)
Eric Andersen9f16d612000-06-12 23:11:16 +0000805{
Eric Andersen14d35432001-05-14 17:07:32 +0000806 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000807
Eric Andersen14d35432001-05-14 17:07:32 +0000808 if (fullname[0] == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000809 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000810 else {
Rob Landleyd921b2e2006-08-03 15:41:12 +0000811 char *tmp, *tmp1 = xstrdup(filename);
Manuel Novoa III cad53642003-03-19 09:13:01 +0000812 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000813 if (strcmp(tmp, fullname) == 0) {
814 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000815 /* Stop searching if we find a match */
Rob Landleyd921b2e2006-08-03 15:41:12 +0000816 m_filename = xstrdup(filename);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000817 return FALSE;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000818 }
Eric Andersen14d35432001-05-14 17:07:32 +0000819 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000820 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +0000821 return TRUE;
Erik Andersend387d011999-12-21 02:55:11 +0000822}
823
Erik Andersen02104321999-12-17 18:57:34 +0000824
Eric Andersen9f16d612000-06-12 23:11:16 +0000825/*======================================================================*/
826
Eric Andersen044228d2001-07-17 01:12:36 +0000827static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000828{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000829 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000830 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000831
Eric Andersencffd5022002-05-24 06:50:15 +0000832 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000833
Eric Andersen9f16d612000-06-12 23:11:16 +0000834 return &f->root;
835}
836
Eric Andersen044228d2001-07-17 01:12:36 +0000837static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000838{
839 return xmalloc(sizeof(struct obj_section));
840}
841
Eric Andersen044228d2001-07-17 01:12:36 +0000842static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000843{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000844 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000846
Eric Andersencffd5022002-05-24 06:50:15 +0000847 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000848
Eric Andersen9f16d612000-06-12 23:11:16 +0000849 return &sym->root;
850}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000851
Eric Andersen044228d2001-07-17 01:12:36 +0000852static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000853arch_apply_relocation(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +0000854 struct obj_section *targsec,
855 struct obj_section *symsec,
856 struct obj_symbol *sym,
857 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000858{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000859 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000860 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000861 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
862 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000863#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000864 struct arch_symbol *isym = (struct arch_symbol *) sym;
865#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000866#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000867#if defined(USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000868 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000869#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000870#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000871#if defined(USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000872 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000873 unsigned long *ip;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +0000874# if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000875 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000876# else
Eric Andersencffd5022002-05-24 06:50:15 +0000877 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000878# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000879#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000880
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000881 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000882
Eric Andersencffd5022002-05-24 06:50:15 +0000883#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000884
Eric Andersen3b1a7442003-12-24 20:30:45 +0000885 case R_ARM_NONE:
886 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000887
Eric Andersen3b1a7442003-12-24 20:30:45 +0000888 case R_ARM_ABS32:
889 *loc += v;
890 break;
Miles Baderae28b042002-04-01 09:34:25 +0000891
Eric Andersen3b1a7442003-12-24 20:30:45 +0000892 case R_ARM_GOT32:
893 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000894
Eric Andersen3b1a7442003-12-24 20:30:45 +0000895 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000896 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
897 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000898 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000899
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 *loc += got - dot;
901 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000902
Eric Andersen3b1a7442003-12-24 20:30:45 +0000903 case R_ARM_PC24:
904 case R_ARM_PLT32:
905 goto bb_use_plt;
906
907 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000908 *loc += v - got;
909 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000910
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000911#elif defined(__cris__)
912
913 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000914 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000915
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000916 case R_CRIS_32:
917 /* CRIS keeps the relocation value in the r_addend field and
918 * should not use whats in *loc at all
919 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000920 *loc = v;
921 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000922
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000923#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000924
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000925 case R_H8_DIR24R8:
926 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
927 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000928 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000929 case R_H8_DIR24A8:
930 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000931 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000932 case R_H8_DIR32:
933 case R_H8_DIR32A16:
934 *loc += v;
935 break;
936 case R_H8_PCREL16:
937 v -= dot + 2;
938 if ((ElfW(Sword))v > 0x7fff ||
939 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
940 ret = obj_reloc_overflow;
941 else
942 *(unsigned short *)loc = v;
943 break;
944 case R_H8_PCREL8:
945 v -= dot + 1;
946 if ((ElfW(Sword))v > 0x7f ||
947 (ElfW(Sword))v < -(ElfW(Sword))0x80)
948 ret = obj_reloc_overflow;
949 else
950 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000951 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000952
Eric Andersencffd5022002-05-24 06:50:15 +0000953#elif defined(__i386__)
954
Eric Andersen3b1a7442003-12-24 20:30:45 +0000955 case R_386_NONE:
956 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000957
Eric Andersen3b1a7442003-12-24 20:30:45 +0000958 case R_386_32:
959 *loc += v;
960 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000961
Eric Andersen3b1a7442003-12-24 20:30:45 +0000962 case R_386_PLT32:
963 case R_386_PC32:
964 *loc += v - dot;
965 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000966
Eric Andersen3b1a7442003-12-24 20:30:45 +0000967 case R_386_GLOB_DAT:
968 case R_386_JMP_SLOT:
969 *loc = v;
970 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000971
Eric Andersen3b1a7442003-12-24 20:30:45 +0000972 case R_386_RELATIVE:
973 *loc += f->baseaddr;
974 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000975
Eric Andersen3b1a7442003-12-24 20:30:45 +0000976 case R_386_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000977 *loc += got - dot;
978 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000979
Eric Andersen3b1a7442003-12-24 20:30:45 +0000980 case R_386_GOT32:
981 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000982
Eric Andersen3b1a7442003-12-24 20:30:45 +0000983 case R_386_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000984 *loc += v - got;
985 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000986
Mike Frysinger280dae72006-06-06 06:30:32 +0000987#elif defined (__microblaze__)
988 case R_MICROBLAZE_NONE:
989 case R_MICROBLAZE_64_NONE:
990 case R_MICROBLAZE_32_SYM_OP_SYM:
991 case R_MICROBLAZE_32_PCREL:
992 break;
993
994 case R_MICROBLAZE_64_PCREL: {
995 /* dot is the address of the current instruction.
996 * v is the target symbol address.
997 * So we need to extract the offset in the code,
Denis Vlasenko9213a9e2006-09-17 16:28:10 +0000998 * adding v, then subtrating the current address
Mike Frysinger280dae72006-06-06 06:30:32 +0000999 * of this instruction.
1000 * Ex: "IMM 0xFFFE bralid 0x0000" = "bralid 0xFFFE0000"
1001 */
1002
1003 /* Get split offset stored in code */
1004 unsigned int temp = (loc[0] & 0xFFFF) << 16 |
1005 (loc[1] & 0xFFFF);
1006
Denis Vlasenko9213a9e2006-09-17 16:28:10 +00001007 /* Adjust relative offset. -4 adjustment required
Mike Frysinger280dae72006-06-06 06:30:32 +00001008 * because dot points to the IMM insn, but branch
1009 * is computed relative to the branch instruction itself.
1010 */
1011 temp += v - dot - 4;
1012
1013 /* Store back into code */
1014 loc[0] = (loc[0] & 0xFFFF0000) | temp >> 16;
1015 loc[1] = (loc[1] & 0xFFFF0000) | (temp & 0xFFFF);
1016
1017 break;
1018 }
1019
1020 case R_MICROBLAZE_32:
1021 *loc += v;
1022 break;
1023
1024 case R_MICROBLAZE_64: {
1025 /* Get split pointer stored in code */
1026 unsigned int temp1 = (loc[0] & 0xFFFF) << 16 |
1027 (loc[1] & 0xFFFF);
1028
1029 /* Add reloc offset */
1030 temp1+=v;
1031
1032 /* Store back into code */
1033 loc[0] = (loc[0] & 0xFFFF0000) | temp1 >> 16;
1034 loc[1] = (loc[1] & 0xFFFF0000) | (temp1 & 0xFFFF);
1035
1036 break;
1037 }
1038
1039 case R_MICROBLAZE_32_PCREL_LO:
1040 case R_MICROBLAZE_32_LO:
1041 case R_MICROBLAZE_SRO32:
1042 case R_MICROBLAZE_SRW32:
1043 ret = obj_reloc_unhandled;
1044 break;
1045
Eric Andersencffd5022002-05-24 06:50:15 +00001046#elif defined(__mc68000__)
1047
Eric Andersen3b1a7442003-12-24 20:30:45 +00001048 case R_68K_NONE:
1049 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001050
Eric Andersen3b1a7442003-12-24 20:30:45 +00001051 case R_68K_32:
1052 *loc += v;
1053 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001054
Eric Andersen3b1a7442003-12-24 20:30:45 +00001055 case R_68K_8:
1056 if (v > 0xff) {
1057 ret = obj_reloc_overflow;
1058 }
1059 *(char *)loc = v;
1060 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001061
Eric Andersen3b1a7442003-12-24 20:30:45 +00001062 case R_68K_16:
1063 if (v > 0xffff) {
1064 ret = obj_reloc_overflow;
1065 }
1066 *(short *)loc = v;
1067 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001068
Eric Andersen3b1a7442003-12-24 20:30:45 +00001069 case R_68K_PC8:
1070 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001071 if ((ElfW(Sword))v > 0x7f ||
1072 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001073 ret = obj_reloc_overflow;
1074 }
1075 *(char *)loc = v;
1076 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001077
Eric Andersen3b1a7442003-12-24 20:30:45 +00001078 case R_68K_PC16:
1079 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001080 if ((ElfW(Sword))v > 0x7fff ||
1081 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001082 ret = obj_reloc_overflow;
1083 }
1084 *(short *)loc = v;
1085 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001086
Eric Andersen3b1a7442003-12-24 20:30:45 +00001087 case R_68K_PC32:
1088 *(int *)loc = v - dot;
1089 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001090
Eric Andersen3b1a7442003-12-24 20:30:45 +00001091 case R_68K_GLOB_DAT:
1092 case R_68K_JMP_SLOT:
1093 *loc = v;
1094 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001095
Eric Andersen3b1a7442003-12-24 20:30:45 +00001096 case R_68K_RELATIVE:
1097 *(int *)loc += f->baseaddr;
1098 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001099
Eric Andersen3b1a7442003-12-24 20:30:45 +00001100 case R_68K_GOT32:
1101 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001102
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001103# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001104 case R_68K_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001105 *loc += v - got;
1106 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001107# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001108
1109#elif defined(__mips__)
1110
Eric Andersen3b1a7442003-12-24 20:30:45 +00001111 case R_MIPS_NONE:
1112 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001113
Eric Andersen3b1a7442003-12-24 20:30:45 +00001114 case R_MIPS_32:
1115 *loc += v;
1116 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001117
Eric Andersen3b1a7442003-12-24 20:30:45 +00001118 case R_MIPS_26:
1119 if (v % 4)
1120 ret = obj_reloc_dangerous;
1121 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1122 ret = obj_reloc_overflow;
1123 *loc =
1124 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1125 0x03ffffff);
1126 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001127
Eric Andersen3b1a7442003-12-24 20:30:45 +00001128 case R_MIPS_HI16:
1129 {
1130 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001131
Eric Andersen3b1a7442003-12-24 20:30:45 +00001132 /* We cannot relocate this one now because we don't know the value
1133 of the carry we need to add. Save the information, and let LO16
1134 do the actual relocation. */
Denis Vlasenkob95636c2006-12-19 23:36:04 +00001135 n = xmalloc(sizeof *n);
Eric Andersen3b1a7442003-12-24 20:30:45 +00001136 n->addr = loc;
1137 n->value = v;
1138 n->next = ifile->mips_hi16_list;
1139 ifile->mips_hi16_list = n;
1140 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001141 }
1142
Eric Andersen3b1a7442003-12-24 20:30:45 +00001143 case R_MIPS_LO16:
1144 {
1145 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001146 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001147
1148 /* Sign extend the addend we extract from the lo insn. */
1149 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1150
1151 if (ifile->mips_hi16_list != NULL) {
1152 struct mips_hi16 *l;
1153
1154 l = ifile->mips_hi16_list;
1155 while (l != NULL) {
1156 struct mips_hi16 *next;
1157 unsigned long insn;
1158
Eric Andersen3b1a7442003-12-24 20:30:45 +00001159 /* Do the HI16 relocation. Note that we actually don't
1160 need to know anything about the LO16 itself, except where
1161 to find the low 16 bits of the addend needed by the LO16. */
1162 insn = *l->addr;
1163 val =
1164 ((insn & 0xffff) << 16) +
1165 vallo;
1166 val += v;
1167
1168 /* Account for the sign extension that will happen in the
1169 low bits. */
1170 val =
1171 ((val >> 16) +
1172 ((val & 0x8000) !=
1173 0)) & 0xffff;
1174
1175 insn = (insn & ~0xffff) | val;
1176 *l->addr = insn;
1177
1178 next = l->next;
1179 free(l);
1180 l = next;
1181 }
1182
1183 ifile->mips_hi16_list = NULL;
1184 }
1185
1186 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1187 val = v + vallo;
1188 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1189 *loc = insnlo;
1190 break;
1191 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001192
Mike Frysingerf982d862006-01-04 00:11:26 +00001193#elif defined(__nios2__)
1194
1195 case R_NIOS2_NONE:
1196 break;
1197
1198 case R_NIOS2_BFD_RELOC_32:
1199 *loc += v;
1200 break;
1201
1202 case R_NIOS2_BFD_RELOC_16:
1203 if (v > 0xffff) {
1204 ret = obj_reloc_overflow;
1205 }
1206 *(short *)loc = v;
1207 break;
1208
1209 case R_NIOS2_BFD_RELOC_8:
1210 if (v > 0xff) {
1211 ret = obj_reloc_overflow;
1212 }
1213 *(char *)loc = v;
1214 break;
1215
1216 case R_NIOS2_S16:
1217 {
1218 Elf32_Addr word;
1219
1220 if ((Elf32_Sword)v > 0x7fff ||
1221 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
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_U16:
1232 {
1233 Elf32_Addr word;
1234
1235 if (v > 0xffff) {
1236 ret = obj_reloc_overflow;
1237 }
1238
1239 word = *loc;
1240 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1241 (word & 0x3f);
1242 }
1243 break;
1244
1245 case R_NIOS2_PCREL16:
1246 {
1247 Elf32_Addr word;
1248
1249 v -= dot + 4;
1250 if ((Elf32_Sword)v > 0x7fff ||
1251 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1252 ret = obj_reloc_overflow;
1253 }
1254
1255 word = *loc;
1256 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1257 }
1258 break;
1259
1260 case R_NIOS2_GPREL:
1261 {
1262 Elf32_Addr word, gp;
1263 /* get _gp */
1264 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1265 v-=gp;
1266 if ((Elf32_Sword)v > 0x7fff ||
1267 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1268 ret = obj_reloc_overflow;
1269 }
1270
1271 word = *loc;
1272 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1273 }
1274 break;
1275
1276 case R_NIOS2_CALL26:
1277 if (v & 3)
1278 ret = obj_reloc_dangerous;
1279 if ((v >> 28) != (dot >> 28))
1280 ret = obj_reloc_overflow;
1281 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1282 break;
1283
1284 case R_NIOS2_IMM5:
1285 {
1286 Elf32_Addr word;
1287
1288 if (v > 0x1f) {
1289 ret = obj_reloc_overflow;
1290 }
1291
1292 word = *loc & ~0x7c0;
1293 *loc = word | ((v & 0x1f) << 6);
1294 }
1295 break;
1296
1297 case R_NIOS2_IMM6:
1298 {
1299 Elf32_Addr word;
1300
1301 if (v > 0x3f) {
1302 ret = obj_reloc_overflow;
1303 }
1304
1305 word = *loc & ~0xfc0;
1306 *loc = word | ((v & 0x3f) << 6);
1307 }
1308 break;
1309
1310 case R_NIOS2_IMM8:
1311 {
1312 Elf32_Addr word;
1313
1314 if (v > 0xff) {
1315 ret = obj_reloc_overflow;
1316 }
1317
1318 word = *loc & ~0x3fc0;
1319 *loc = word | ((v & 0xff) << 6);
1320 }
1321 break;
1322
1323 case R_NIOS2_HI16:
1324 {
1325 Elf32_Addr word;
1326
1327 word = *loc;
1328 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1329 (word & 0x3f);
1330 }
1331 break;
1332
1333 case R_NIOS2_LO16:
1334 {
1335 Elf32_Addr word;
1336
1337 word = *loc;
1338 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1339 (word & 0x3f);
1340 }
1341 break;
1342
1343 case R_NIOS2_HIADJ16:
1344 {
1345 Elf32_Addr word1, word2;
1346
1347 word1 = *loc;
1348 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1349 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1350 (word1 & 0x3f);
1351 }
1352 break;
1353
Mike Frysingerebee0e72006-02-18 06:14:31 +00001354#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001355 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001356
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001357#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001358
Eric Andersen3b1a7442003-12-24 20:30:45 +00001359 case R_PPC_ADDR16_HA:
1360 *(unsigned short *)loc = (v + 0x8000) >> 16;
1361 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001362
Eric Andersen3b1a7442003-12-24 20:30:45 +00001363 case R_PPC_ADDR16_HI:
1364 *(unsigned short *)loc = v >> 16;
1365 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001366
Eric Andersen3b1a7442003-12-24 20:30:45 +00001367 case R_PPC_ADDR16_LO:
1368 *(unsigned short *)loc = v;
1369 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001370
Eric Andersen3b1a7442003-12-24 20:30:45 +00001371 case R_PPC_REL24:
1372 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001373
Eric Andersen3b1a7442003-12-24 20:30:45 +00001374 case R_PPC_REL32:
1375 *loc = v - dot;
1376 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001377
Eric Andersen3b1a7442003-12-24 20:30:45 +00001378 case R_PPC_ADDR32:
1379 *loc = v;
1380 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001381
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001382#elif defined(__s390__)
1383
1384 case R_390_32:
1385 *(unsigned int *) loc += v;
1386 break;
1387 case R_390_16:
1388 *(unsigned short *) loc += v;
1389 break;
1390 case R_390_8:
1391 *(unsigned char *) loc += v;
1392 break;
1393
1394 case R_390_PC32:
1395 *(unsigned int *) loc += v - dot;
1396 break;
1397 case R_390_PC16DBL:
1398 *(unsigned short *) loc += (v - dot) >> 1;
1399 break;
1400 case R_390_PC16:
1401 *(unsigned short *) loc += v - dot;
1402 break;
1403
1404 case R_390_PLT32:
1405 case R_390_PLT16DBL:
1406 /* find the plt entry and initialize it. */
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001407 pe = (struct arch_single_entry *) &isym->pltent;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001408 if (pe->inited == 0) {
1409 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1410 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1411 ip[1] = 0x100607f1;
1412 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1413 ip[2] = v - 2;
1414 else
1415 ip[2] = v;
1416 pe->inited = 1;
1417 }
1418
1419 /* Insert relative distance to target. */
1420 v = plt + pe->offset - dot;
1421 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1422 *(unsigned int *) loc = (unsigned int) v;
1423 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1424 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1425 break;
1426
1427 case R_390_GLOB_DAT:
1428 case R_390_JMP_SLOT:
1429 *loc = v;
1430 break;
1431
1432 case R_390_RELATIVE:
1433 *loc += f->baseaddr;
1434 break;
1435
1436 case R_390_GOTPC:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001437 *(unsigned long *) loc += got - dot;
1438 break;
1439
1440 case R_390_GOT12:
1441 case R_390_GOT16:
1442 case R_390_GOT32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001443 if (!isym->gotent.inited)
1444 {
1445 isym->gotent.inited = 1;
1446 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1447 }
1448 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1449 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1450 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1451 *(unsigned short *) loc += isym->gotent.offset;
1452 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1453 *(unsigned int *) loc += isym->gotent.offset;
1454 break;
1455
1456# ifndef R_390_GOTOFF32
1457# define R_390_GOTOFF32 R_390_GOTOFF
1458# endif
1459 case R_390_GOTOFF32:
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001460 *loc += v - got;
1461 break;
1462
Eric Andersencffd5022002-05-24 06:50:15 +00001463#elif defined(__sh__)
1464
Eric Andersen3b1a7442003-12-24 20:30:45 +00001465 case R_SH_NONE:
1466 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001467
Eric Andersen3b1a7442003-12-24 20:30:45 +00001468 case R_SH_DIR32:
1469 *loc += v;
1470 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001471
Eric Andersen3b1a7442003-12-24 20:30:45 +00001472 case R_SH_REL32:
1473 *loc += v - dot;
1474 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001475
Eric Andersen3b1a7442003-12-24 20:30:45 +00001476 case R_SH_PLT32:
1477 *loc = v - dot;
1478 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001479
Eric Andersen3b1a7442003-12-24 20:30:45 +00001480 case R_SH_GLOB_DAT:
1481 case R_SH_JMP_SLOT:
1482 *loc = v;
1483 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001484
Eric Andersen3b1a7442003-12-24 20:30:45 +00001485 case R_SH_RELATIVE:
1486 *loc = f->baseaddr + rel->r_addend;
1487 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001488
Eric Andersen3b1a7442003-12-24 20:30:45 +00001489 case R_SH_GOTPC:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 *loc = got - dot + rel->r_addend;
1491 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001492
Eric Andersen3b1a7442003-12-24 20:30:45 +00001493 case R_SH_GOT32:
1494 goto bb_use_got;
1495
1496 case R_SH_GOTOFF:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001497 *loc = v - got;
1498 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001499
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001500# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001501 case R_SH_IMM_MEDLOW16:
1502 case R_SH_IMM_LOW16:
1503 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001504 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001505
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001506 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001507 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001508
Eric Andersen3b1a7442003-12-24 20:30:45 +00001509 /*
1510 * movi and shori have the format:
1511 *
1512 * | op | imm | reg | reserved |
1513 * 31..26 25..10 9.. 4 3 .. 0
1514 *
1515 * so we simply mask and or in imm.
1516 */
1517 word = *loc & ~0x3fffc00;
1518 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001519
Eric Andersen3b1a7442003-12-24 20:30:45 +00001520 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001521
Eric Andersen3b1a7442003-12-24 20:30:45 +00001522 break;
1523 }
Eric Andersenbf833552003-08-13 19:56:33 +00001524
Eric Andersen3b1a7442003-12-24 20:30:45 +00001525 case R_SH_IMM_MEDLOW16_PCREL:
1526 case R_SH_IMM_LOW16_PCREL:
1527 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001528 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001529
Eric Andersen3b1a7442003-12-24 20:30:45 +00001530 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001531
Eric Andersen3b1a7442003-12-24 20:30:45 +00001532 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001533
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001534 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001535 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001536
Eric Andersen3b1a7442003-12-24 20:30:45 +00001537 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001538
Eric Andersen3b1a7442003-12-24 20:30:45 +00001539 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001540
Eric Andersen3b1a7442003-12-24 20:30:45 +00001541 break;
1542 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001543# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001544
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001545#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001546
Eric Andersen3b1a7442003-12-24 20:30:45 +00001547 case R_V850_NONE:
1548 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001549
Eric Andersen3b1a7442003-12-24 20:30:45 +00001550 case R_V850_32:
1551 /* We write two shorts instead of a long because even
1552 32-bit insns only need half-word alignment, but
1553 32-bit data needs to be long-word aligned. */
1554 v += ((unsigned short *)loc)[0];
1555 v += ((unsigned short *)loc)[1] << 16;
1556 ((unsigned short *)loc)[0] = v & 0xffff;
1557 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1558 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001559
Eric Andersen3b1a7442003-12-24 20:30:45 +00001560 case R_V850_22_PCREL:
1561 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001562
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001563#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001564
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001565 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001566 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001567
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001568 case R_X86_64_64:
1569 *loc += v;
1570 break;
1571
1572 case R_X86_64_32:
1573 *(unsigned int *) loc += v;
1574 if (v > 0xffffffff)
1575 {
1576 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1577 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1578 }
1579 break;
1580
1581 case R_X86_64_32S:
1582 *(signed int *) loc += v;
1583 break;
1584
1585 case R_X86_64_16:
1586 *(unsigned short *) loc += v;
1587 break;
1588
1589 case R_X86_64_8:
1590 *(unsigned char *) loc += v;
1591 break;
1592
1593 case R_X86_64_PC32:
1594 *(unsigned int *) loc += v - dot;
1595 break;
1596
1597 case R_X86_64_PC16:
1598 *(unsigned short *) loc += v - dot;
1599 break;
1600
1601 case R_X86_64_PC8:
1602 *(unsigned char *) loc += v - dot;
1603 break;
1604
1605 case R_X86_64_GLOB_DAT:
1606 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001607 *loc = v;
1608 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001609
1610 case R_X86_64_RELATIVE:
1611 *loc += f->baseaddr;
1612 break;
1613
1614 case R_X86_64_GOT32:
1615 case R_X86_64_GOTPCREL:
1616 goto bb_use_got;
1617# if 0
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001618 if (!isym->gotent.reloc_done)
1619 {
1620 isym->gotent.reloc_done = 1;
1621 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1622 }
1623 /* XXX are these really correct? */
1624 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1625 *(unsigned int *) loc += v + isym->gotent.offset;
1626 else
1627 *loc += isym->gotent.offset;
1628 break;
1629# endif
1630
Mike Frysingerf982d862006-01-04 00:11:26 +00001631#else
1632# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001633#endif
1634
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001635 default:
1636 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1637 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001638 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001639
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001640#if defined(USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001641
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001643
Eric Andersen3b1a7442003-12-24 20:30:45 +00001644 /* find the plt entry and initialize it if necessary */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001645
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001646#if defined(USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001647 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1648 pe = pe->next;
Eric Andersencffd5022002-05-24 06:50:15 +00001649#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001651#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001652
Eric Andersen3b1a7442003-12-24 20:30:45 +00001653 if (! pe->inited) {
1654 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001655
Eric Andersen3b1a7442003-12-24 20:30:45 +00001656 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001657
1658#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001659 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1660 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001661#endif
1662#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001664 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001665 ip[2] = 0x7d6903a6; /* mtctr r11 */
1666 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001667#endif
Miles Baderae28b042002-04-01 09:34:25 +00001668#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001669 /* We have to trash a register, so we assume that any control
1670 transfer more than 21-bits away must be a function call
1671 (so we can use a call-clobbered register). */
1672 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1673 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001674#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001675 pe->inited = 1;
1676 }
Eric Andersen21adca72000-12-06 18:18:26 +00001677
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 /* relative distance to target */
1679 v -= dot;
1680 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001681#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001682 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001683#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001684 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001685#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 /* go via the plt */
1687 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001688
1689#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001691#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001692 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001693#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001694 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001695
Eric Andersen3b1a7442003-12-24 20:30:45 +00001696 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001697#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001698 /* Convert to words. */
1699 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001700
Eric Andersen3b1a7442003-12-24 20:30:45 +00001701 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001702#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001703#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001704 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001705#endif
Miles Baderae28b042002-04-01 09:34:25 +00001706#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001707 /* We write two shorts instead of a long because even 32-bit insns
1708 only need half-word alignment, but the 32-bit data write needs
1709 to be long-word aligned. */
1710 ((unsigned short *)loc)[0] =
1711 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1712 | ((v >> 16) & 0x3f); /* offs high part */
1713 ((unsigned short *)loc)[1] =
1714 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001715#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001716 break;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001717#endif /* USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001718
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001719#if defined(USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001720bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001721
Eric Andersen3b1a7442003-12-24 20:30:45 +00001722 /* needs an entry in the .got: set it, once */
1723 if (!isym->gotent.inited) {
1724 isym->gotent.inited = 1;
1725 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1726 }
1727 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001728#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001729 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001730#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001731 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001732#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001733 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001734
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001735#endif /* USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001736 }
1737
1738 return ret;
1739}
1740
Eric Andersencffd5022002-05-24 06:50:15 +00001741
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001742#if defined(USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001743
1744static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1745 int offset, int size)
1746{
1747 struct arch_list_entry *pe;
1748
1749 for (pe = *list; pe != NULL; pe = pe->next) {
1750 if (pe->addend == rel->r_addend) {
1751 break;
1752 }
1753 }
1754
1755 if (pe == NULL) {
1756 pe = xmalloc(sizeof(struct arch_list_entry));
1757 pe->next = *list;
1758 pe->addend = rel->r_addend;
1759 pe->offset = offset;
1760 pe->inited = 0;
1761 *list = pe;
1762 return size;
1763 }
1764 return 0;
1765}
1766
1767#endif
1768
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001769#if defined(USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001770
1771static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1772 int offset, int size)
1773{
1774 if (single->allocated == 0) {
1775 single->allocated = 1;
1776 single->offset = offset;
1777 single->inited = 0;
1778 return size;
1779 }
1780 return 0;
1781}
1782
1783#endif
1784
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001785#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001786
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001787static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001788 int offset, int size)
1789{
1790 struct obj_section *myrelsec = obj_find_section(f, name);
1791
1792 if (offset == 0) {
1793 offset += size;
1794 }
1795
1796 if (myrelsec) {
1797 obj_extend_section(myrelsec, offset);
1798 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001799 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001800 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001801 }
1802
1803 return myrelsec;
1804}
1805
1806#endif
1807
1808static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001809{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001810#if defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001811 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001812 int i;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001813#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001814 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001815#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001816#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001817 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001818#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001819 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001820 ElfW(RelM) *rel, *relend;
1821 ElfW(Sym) *symtab, *extsym;
1822 const char *strtab, *name;
1823 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001824
Eric Andersen21adca72000-12-06 18:18:26 +00001825 for (i = 0; i < f->header.e_shnum; ++i) {
1826 relsec = f->sections[i];
1827 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001828 continue;
1829
Eric Andersen21adca72000-12-06 18:18:26 +00001830 symsec = f->sections[relsec->header.sh_link];
1831 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001832
Eric Andersen21adca72000-12-06 18:18:26 +00001833 rel = (ElfW(RelM) *) relsec->contents;
1834 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1835 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001836 strtab = (const char *) strsec->contents;
1837
1838 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001839 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001840
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001841#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001842 got_allocate = 0;
1843#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001844#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001845 plt_allocate = 0;
1846#endif
1847
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001848 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001849#if defined(__arm__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001850 case R_ARM_PC24:
1851 case R_ARM_PLT32:
1852 plt_allocate = 1;
1853 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001854
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001855 case R_ARM_GOTOFF:
1856 case R_ARM_GOTPC:
1857 got_needed = 1;
1858 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001859
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001860 case R_ARM_GOT32:
1861 got_allocate = 1;
1862 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001863
Eric Andersen21adca72000-12-06 18:18:26 +00001864#elif defined(__i386__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001865 case R_386_GOTPC:
1866 case R_386_GOTOFF:
1867 got_needed = 1;
1868 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001869
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001870 case R_386_GOT32:
1871 got_allocate = 1;
1872 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001873
1874#elif defined(__powerpc__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001875 case R_PPC_REL24:
1876 plt_allocate = 1;
1877 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001878
1879#elif defined(__mc68000__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001880 case R_68K_GOT32:
1881 got_allocate = 1;
1882 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001883
Eric Andersen16451a02004-03-19 12:16:18 +00001884#ifdef R_68K_GOTOFF
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001885 case R_68K_GOTOFF:
1886 got_needed = 1;
1887 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001888#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001889
1890#elif defined(__sh__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001891 case R_SH_GOT32:
1892 got_allocate = 1;
1893 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001894
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001895 case R_SH_GOTPC:
1896 case R_SH_GOTOFF:
1897 got_needed = 1;
1898 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001899
1900#elif defined (__v850e__)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001901 case R_V850_22_PCREL:
1902 plt_needed = 1;
1903 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001904
1905#endif
Denis Vlasenko9c267b82006-10-12 20:06:18 +00001906 default:
1907 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001908 }
1909
Eric Andersen21adca72000-12-06 18:18:26 +00001910 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001911 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001912 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001913 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001914 }
1915 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001916#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001917 if (got_allocate) {
1918 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001919 rel, &intsym->gotent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001920 got_offset, GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001921
1922 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001923 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001924#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001925#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001926 if (plt_allocate) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001927#if defined(USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001928 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001929 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001930 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001931#else
1932 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001933 rel, &intsym->pltent,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001934 plt_offset, PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001935#endif
1936 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001937 }
1938#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001939 }
Miles Baderae28b042002-04-01 09:34:25 +00001940 }
Eric Andersen21adca72000-12-06 18:18:26 +00001941
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001942#if defined(USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001943 if (got_needed) {
1944 ifile->got = arch_xsect_init(f, ".got", got_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001945 GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001946 }
Eric Andersen21adca72000-12-06 18:18:26 +00001947#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001948
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001949#if defined(USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001950 if (plt_needed) {
1951 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001952 PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001953 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001954#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001955
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001956#endif /* defined(USE_GOT_ENTRIES) || defined(USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001957}
1958
Eric Andersen9f16d612000-06-12 23:11:16 +00001959/*======================================================================*/
1960
1961/* Standard ELF hash function. */
Rob Landley88621d72006-08-29 19:41:06 +00001962static unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001963{
1964 unsigned long h = 0;
1965 unsigned long g;
1966 unsigned char ch;
1967
1968 while (n > 0) {
1969 ch = *name++;
1970 h = (h << 4) + ch;
1971 if ((g = (h & 0xf0000000)) != 0) {
1972 h ^= g >> 24;
1973 h &= ~g;
1974 }
1975 n--;
1976 }
1977 return h;
1978}
1979
Eric Andersen044228d2001-07-17 01:12:36 +00001980static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001981{
1982 return obj_elf_hash_n(name, strlen(name));
1983}
1984
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00001985#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001986/* String comparison for non-co-versioned kernel and module. */
1987
1988static int ncv_strcmp(const char *a, const char *b)
1989{
1990 size_t alen = strlen(a), blen = strlen(b);
1991
1992 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1993 return strncmp(a, b, alen);
1994 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1995 return strncmp(a, b, blen);
1996 else
1997 return strcmp(a, b);
1998}
1999
2000/* String hashing for non-co-versioned kernel and module. Here
2001 we are simply forced to drop the crc from the hash. */
2002
2003static unsigned long ncv_symbol_hash(const char *str)
2004{
2005 size_t len = strlen(str);
2006 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
2007 len -= 10;
2008 return obj_elf_hash_n(str, len);
2009}
2010
Eric Andersen044228d2001-07-17 01:12:36 +00002011static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002012obj_set_symbol_compare(struct obj_file *f,
2013 int (*cmp) (const char *, const char *),
2014 unsigned long (*hash) (const char *))
2015{
2016 if (cmp)
2017 f->symbol_cmp = cmp;
2018 if (hash) {
2019 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
2020 int i;
2021
2022 f->symbol_hash = hash;
2023
2024 memcpy(tmptab, f->symtab, sizeof(tmptab));
2025 memset(f->symtab, 0, sizeof(f->symtab));
2026
2027 for (i = 0; i < HASH_BUCKETS; ++i)
2028 for (sym = tmptab[i]; sym; sym = next) {
2029 unsigned long h = hash(sym->name) % HASH_BUCKETS;
2030 next = sym->next;
2031 sym->next = f->symtab[h];
2032 f->symtab[h] = sym;
2033 }
2034 }
2035}
2036
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002037#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002038
Eric Andersen044228d2001-07-17 01:12:36 +00002039static struct obj_symbol *
2040obj_add_symbol(struct obj_file *f, const char *name,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002041 unsigned long symidx, int info,
2042 int secidx, ElfW(Addr) value,
2043 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002044{
2045 struct obj_symbol *sym;
2046 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002047 int n_type = ELF_ST_TYPE(info);
2048 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002049
2050 for (sym = f->symtab[hash]; sym; sym = sym->next)
2051 if (f->symbol_cmp(sym->name, name) == 0) {
2052 int o_secidx = sym->secidx;
2053 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002054 int o_type = ELF_ST_TYPE(o_info);
2055 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002056
2057 /* A redefinition! Is it legal? */
2058
2059 if (secidx == SHN_UNDEF)
2060 return sym;
2061 else if (o_secidx == SHN_UNDEF)
2062 goto found;
2063 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2064 /* Cope with local and global symbols of the same name
2065 in the same object file, as might have been created
2066 by ld -r. The only reason locals are now seen at this
2067 level at all is so that we can do semi-sensible things
2068 with parameters. */
2069
2070 struct obj_symbol *nsym, **p;
2071
2072 nsym = arch_new_symbol();
2073 nsym->next = sym->next;
2074 nsym->ksymidx = -1;
2075
2076 /* Excise the old (local) symbol from the hash chain. */
2077 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2078 continue;
2079 *p = sym = nsym;
2080 goto found;
2081 } else if (n_binding == STB_LOCAL) {
2082 /* Another symbol of the same name has already been defined.
2083 Just add this to the local table. */
2084 sym = arch_new_symbol();
2085 sym->next = NULL;
2086 sym->ksymidx = -1;
2087 f->local_symtab[symidx] = sym;
2088 goto found;
2089 } else if (n_binding == STB_WEAK)
2090 return sym;
2091 else if (o_binding == STB_WEAK)
2092 goto found;
2093 /* Don't unify COMMON symbols with object types the programmer
2094 doesn't expect. */
2095 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002096 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002097 return sym;
2098 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002099 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002100 goto found;
2101 else {
2102 /* Don't report an error if the symbol is coming from
2103 the kernel or some external module. */
2104 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002105 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002106 return sym;
2107 }
2108 }
2109
2110 /* Completely new symbol. */
2111 sym = arch_new_symbol();
2112 sym->next = f->symtab[hash];
2113 f->symtab[hash] = sym;
2114 sym->ksymidx = -1;
2115
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002116 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002117 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002118 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002119 name, (long) symidx, (long) f->local_symtab_size);
2120 else
2121 f->local_symtab[symidx] = sym;
2122 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002123
Eric Andersen3b1a7442003-12-24 20:30:45 +00002124found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002125 sym->name = name;
2126 sym->value = value;
2127 sym->size = size;
2128 sym->secidx = secidx;
2129 sym->info = info;
2130
2131 return sym;
2132}
2133
Eric Andersen044228d2001-07-17 01:12:36 +00002134static struct obj_symbol *
2135obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002136{
2137 struct obj_symbol *sym;
2138 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2139
2140 for (sym = f->symtab[hash]; sym; sym = sym->next)
2141 if (f->symbol_cmp(sym->name, name) == 0)
2142 return sym;
2143
2144 return NULL;
2145}
2146
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002147static ElfW(Addr) obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
Eric Andersen9f16d612000-06-12 23:11:16 +00002148{
2149 if (sym) {
2150 if (sym->secidx >= SHN_LORESERVE)
2151 return sym->value;
2152
2153 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2154 } else {
2155 /* As a special case, a NULL sym has value zero. */
2156 return 0;
2157 }
2158}
2159
Eric Andersen044228d2001-07-17 01:12:36 +00002160static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002161{
2162 int i, n = f->header.e_shnum;
2163
2164 for (i = 0; i < n; ++i)
2165 if (strcmp(f->sections[i]->name, name) == 0)
2166 return f->sections[i];
2167
2168 return NULL;
2169}
2170
2171static int obj_load_order_prio(struct obj_section *a)
2172{
2173 unsigned long af, ac;
2174
2175 af = a->header.sh_flags;
2176
2177 ac = 0;
2178 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002179 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002180 ac |= 32;
2181 if (af & SHF_ALLOC)
2182 ac |= 16;
2183 if (!(af & SHF_WRITE))
2184 ac |= 8;
2185 if (af & SHF_EXECINSTR)
2186 ac |= 4;
2187 if (a->header.sh_type != SHT_NOBITS)
2188 ac |= 2;
2189
2190 return ac;
2191}
2192
Eric Andersen044228d2001-07-17 01:12:36 +00002193static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002194obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2195{
2196 struct obj_section **p;
2197 int prio = obj_load_order_prio(sec);
2198 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2199 if (obj_load_order_prio(*p) < prio)
2200 break;
2201 sec->load_next = *p;
2202 *p = sec;
2203}
2204
Eric Andersen044228d2001-07-17 01:12:36 +00002205static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002206 const char *name,
2207 unsigned long align,
2208 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002209{
2210 int newidx = f->header.e_shnum++;
2211 struct obj_section *sec;
2212
2213 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2214 f->sections[newidx] = sec = arch_new_section();
2215
2216 memset(sec, 0, sizeof(*sec));
2217 sec->header.sh_type = SHT_PROGBITS;
2218 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2219 sec->header.sh_size = size;
2220 sec->header.sh_addralign = align;
2221 sec->name = name;
2222 sec->idx = newidx;
2223 if (size)
2224 sec->contents = xmalloc(size);
2225
2226 obj_insert_section_load_order(f, sec);
2227
2228 return sec;
2229}
2230
Eric Andersen044228d2001-07-17 01:12:36 +00002231static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002232 const char *name,
2233 unsigned long align,
2234 unsigned long size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002235{
2236 int newidx = f->header.e_shnum++;
2237 struct obj_section *sec;
2238
2239 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2240 f->sections[newidx] = sec = arch_new_section();
2241
2242 memset(sec, 0, sizeof(*sec));
2243 sec->header.sh_type = SHT_PROGBITS;
2244 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2245 sec->header.sh_size = size;
2246 sec->header.sh_addralign = align;
2247 sec->name = name;
2248 sec->idx = newidx;
2249 if (size)
2250 sec->contents = xmalloc(size);
2251
2252 sec->load_next = f->load_order;
2253 f->load_order = sec;
2254 if (f->load_order_search_start == &f->load_order)
2255 f->load_order_search_start = &sec->load_next;
2256
2257 return sec;
2258}
2259
Eric Andersen044228d2001-07-17 01:12:36 +00002260static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002261{
2262 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002263 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002264 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2265 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002266 return sec->contents + oldsize;
2267}
2268
2269
Eric Andersen9f16d612000-06-12 23:11:16 +00002270/* Conditionally add the symbols from the given symbol set to the
2271 new module. */
2272
2273static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002274add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002275 int idx, struct new_module_symbol *syms, size_t nsyms)
2276{
2277 struct new_module_symbol *s;
2278 size_t i;
2279 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002280#ifdef SYMBOL_PREFIX
2281 char *name_buf = 0;
2282 size_t name_alloced_size = 0;
2283#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002284#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002285 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002286
Glenn L McGrath759515c2003-08-30 06:00:33 +00002287 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002288#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002289 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002290 /* Only add symbols that are already marked external.
2291 If we override locals we may cause problems for
2292 argument initialization. We will also create a false
2293 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002294 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002295 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002296
Glenn L McGrath759515c2003-08-30 06:00:33 +00002297 /* GPL licensed modules can use symbols exported with
2298 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2299 * exported names. Non-GPL modules never see any GPLONLY_
2300 * symbols so they cannot fudge it by adding the prefix on
2301 * their references.
2302 */
2303 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002304#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002305 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002306 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002307 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002308#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002309 continue;
2310 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002311 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002312
Miles Baderae28b042002-04-01 09:34:25 +00002313#ifdef SYMBOL_PREFIX
2314 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2315 kernel exports `C names', but module object files
2316 reference `linker names'). */
2317 size_t extra = sizeof SYMBOL_PREFIX;
2318 size_t name_size = strlen (name) + extra;
2319 if (name_size > name_alloced_size) {
2320 name_alloced_size = name_size * 2;
2321 name_buf = alloca (name_alloced_size);
2322 }
2323 strcpy (name_buf, SYMBOL_PREFIX);
2324 strcpy (name_buf + extra - 1, name);
2325 name = name_buf;
2326#endif /* SYMBOL_PREFIX */
2327
2328 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002329 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002330#ifdef SYMBOL_PREFIX
2331 /* Put NAME_BUF into more permanent storage. */
2332 name = xmalloc (name_size);
2333 strcpy (name, name_buf);
2334#endif
2335 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002336 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002337 STT_NOTYPE),
2338 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002339 /* Did our symbol just get installed? If so, mark the
2340 module as "used". */
2341 if (sym->secidx == idx)
2342 used = 1;
2343 }
2344 }
2345
2346 return used;
2347}
2348
2349static void add_kernel_symbols(struct obj_file *f)
2350{
2351 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002352 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002353
2354 /* Add module symbols first. */
2355
2356 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2357 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002358 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2359 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002360
2361 n_ext_modules_used = nused;
2362
2363 /* And finally the symbols from the kernel proper. */
2364
2365 if (nksyms)
2366 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2367}
2368
2369static char *get_modinfo_value(struct obj_file *f, const char *key)
2370{
2371 struct obj_section *sec;
2372 char *p, *v, *n, *ep;
2373 size_t klen = strlen(key);
2374
2375 sec = obj_find_section(f, ".modinfo");
2376 if (sec == NULL)
2377 return NULL;
2378 p = sec->contents;
2379 ep = p + sec->header.sh_size;
2380 while (p < ep) {
2381 v = strchr(p, '=');
2382 n = strchr(p, '\0');
2383 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002384 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002385 return v + 1;
2386 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002387 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002388 return n;
2389 }
2390 p = n + 1;
2391 }
2392
2393 return NULL;
2394}
2395
2396
2397/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002398/* Functions relating to module loading after 2.1.18. */
2399
2400static int
2401new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2402{
2403 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002404 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002405 struct obj_symbol *sym;
2406 char *contents, *loc;
2407 int min, max, n;
2408
2409 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002410 if ((q = strchr(p, '=')) == NULL) {
2411 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002412 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002413 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002414
2415 key = alloca(q - p + 6);
2416 memcpy(key, "parm_", 5);
2417 memcpy(key + 5, p, q - p);
2418 key[q - p + 5] = 0;
2419
2420 p = get_modinfo_value(f, key);
2421 key += 5;
2422 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002423 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002424 return 0;
2425 }
2426
Miles Baderae28b042002-04-01 09:34:25 +00002427#ifdef SYMBOL_PREFIX
2428 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2429 strcpy (sym_name, SYMBOL_PREFIX);
2430 strcat (sym_name, key);
2431#else
2432 sym_name = key;
2433#endif
2434 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002435
2436 /* Also check that the parameter was not resolved from the kernel. */
2437 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002438 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002439 return 0;
2440 }
2441
2442 if (isdigit(*p)) {
2443 min = strtoul(p, &p, 10);
2444 if (*p == '-')
2445 max = strtoul(p + 1, &p, 10);
2446 else
2447 max = min;
2448 } else
2449 min = max = 1;
2450
2451 contents = f->sections[sym->secidx]->contents;
2452 loc = contents + sym->value;
2453 n = (*++q != '\0');
2454
2455 while (1) {
2456 if ((*p == 's') || (*p == 'c')) {
2457 char *str;
2458
2459 /* Do C quoting if we begin with a ", else slurp the lot. */
2460 if (*q == '"') {
2461 char *r;
2462
2463 str = alloca(strlen(q));
2464 for (r = str, q++; *q != '"'; ++q, ++r) {
2465 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002466 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002467 key);
2468 return 0;
2469 } else if (*q == '\\')
2470 switch (*++q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002471 case 'a':
2472 *r = '\a';
2473 break;
2474 case 'b':
2475 *r = '\b';
2476 break;
2477 case 'e':
2478 *r = '\033';
2479 break;
2480 case 'f':
2481 *r = '\f';
2482 break;
2483 case 'n':
2484 *r = '\n';
2485 break;
2486 case 'r':
2487 *r = '\r';
2488 break;
2489 case 't':
2490 *r = '\t';
2491 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002492
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002493 case '0':
2494 case '1':
2495 case '2':
2496 case '3':
2497 case '4':
2498 case '5':
2499 case '6':
2500 case '7':
2501 {
2502 int c = *q - '0';
2503 if (q[1] >= '0' && q[1] <= '7') {
2504 c = (c * 8) + *++q - '0';
2505 if (q[1] >= '0' && q[1] <= '7')
Eric Andersen9f16d612000-06-12 23:11:16 +00002506 c = (c * 8) + *++q - '0';
2507 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002508 *r = c;
2509 }
2510 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002511
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002512 default:
2513 *r = *q;
2514 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002515 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002516 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002517 }
2518 *r = '\0';
2519 ++q;
2520 } else {
2521 char *r;
2522
2523 /* In this case, the string is not quoted. We will break
2524 it using the coma (like for ints). If the user wants to
2525 include comas in a string, he just has to quote it */
2526
2527 /* Search the next coma */
2528 r = strchr(q, ',');
2529
2530 /* Found ? */
2531 if (r != (char *) NULL) {
2532 /* Recopy the current field */
2533 str = alloca(r - q + 1);
2534 memcpy(str, q, r - q);
2535
Eric Andersenaff114c2004-04-14 17:51:38 +00002536 /* I don't know if it is useful, as the previous case
2537 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002538 str[r - q] = '\0';
2539
2540 /* Keep next fields */
2541 q = r;
2542 } else {
2543 /* last string */
2544 str = q;
2545 q = "";
2546 }
2547 }
2548
2549 if (*p == 's') {
2550 /* Normal string */
2551 obj_string_patch(f, sym->secidx, loc - contents, str);
2552 loc += tgt_sizeof_char_p;
2553 } else {
2554 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002555 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002556
2557 /* Get the size of each member */
2558 /* Probably we should do that outside the loop ? */
2559 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002560 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002561 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002562 return 0;
2563 }
2564 charssize = strtoul(p + 1, (char **) NULL, 10);
2565
2566 /* Check length */
2567 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002568 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002569 charssize - 1);
2570 return 0;
2571 }
2572
2573 /* Copy to location */
2574 strcpy((char *) loc, str);
2575 loc += charssize;
2576 }
2577 } else {
2578 long v = strtoul(q, &q, 0);
2579 switch (*p) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002580 case 'b':
2581 *loc++ = v;
2582 break;
2583 case 'h':
2584 *(short *) loc = v;
2585 loc += tgt_sizeof_short;
2586 break;
2587 case 'i':
2588 *(int *) loc = v;
2589 loc += tgt_sizeof_int;
2590 break;
2591 case 'l':
2592 *(long *) loc = v;
2593 loc += tgt_sizeof_long;
2594 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002595
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002596 default:
2597 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2598 return 0;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002599 }
2600 }
2601
2602retry_end_of_value:
2603 switch (*q) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002604 case '\0':
2605 goto end_of_arg;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002606
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002607 case ' ':
2608 case '\t':
2609 case '\n':
2610 case '\r':
2611 ++q;
2612 goto retry_end_of_value;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002613
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002614 case ',':
2615 if (++n > max) {
2616 bb_error_msg("too many values for %s (max %d)", key, max);
Eric Andersen9f16d612000-06-12 23:11:16 +00002617 return 0;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002618 }
2619 ++q;
2620 break;
2621
2622 default:
2623 bb_error_msg("invalid argument syntax for %s", key);
2624 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002625 }
2626 }
2627
Eric Andersen3b1a7442003-12-24 20:30:45 +00002628end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002629 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002630 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002631 return 0;
2632 }
2633
2634 argc--, argv++;
2635 }
2636
2637 return 1;
2638}
2639
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002640#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002641static int new_is_module_checksummed(struct obj_file *f)
2642{
2643 const char *p = get_modinfo_value(f, "using_checksums");
2644 if (p)
Denis Vlasenko13858992006-10-08 12:49:22 +00002645 return xatoi(p);
Eric Andersen9f16d612000-06-12 23:11:16 +00002646 else
2647 return 0;
2648}
2649
2650/* Get the module's kernel version in the canonical integer form. */
2651
2652static int
2653new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2654{
2655 char *p, *q;
2656 int a, b, c;
2657
2658 p = get_modinfo_value(f, "kernel_version");
2659 if (p == NULL)
2660 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002661 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002662
2663 a = strtoul(p, &p, 10);
2664 if (*p != '.')
2665 return -1;
2666 b = strtoul(p + 1, &p, 10);
2667 if (*p != '.')
2668 return -1;
2669 c = strtoul(p + 1, &q, 10);
2670 if (p + 1 == q)
2671 return -1;
2672
2673 return a << 16 | b << 8 | c;
2674}
2675
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002676#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002677
2678
Eric Andersen9f16d612000-06-12 23:11:16 +00002679/* Fetch the loaded modules, and all currently exported symbols. */
2680
2681static int new_get_kernel_symbols(void)
2682{
2683 char *module_names, *mn;
2684 struct external_module *modules, *m;
2685 struct new_module_symbol *syms, *s;
2686 size_t ret, bufsize, nmod, nsyms, i, j;
2687
2688 /* Collect the loaded modules. */
2689
2690 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002691retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002692 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002693 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002694 module_names = xrealloc(module_names, bufsize = ret);
2695 goto retry_modules_load;
2696 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002697 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002698 return 0;
2699 }
2700
2701 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002702
2703 /* Collect the modules' symbols. */
2704
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002705 if (nmod) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002706 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2707 memset(modules, 0, nmod * sizeof(*modules));
2708 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002709 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002710 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002711
Mark Whitley94fd4802001-03-12 23:08:34 +00002712 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2713 if (errno == ENOENT) {
2714 /* The module was removed out from underneath us. */
2715 continue;
2716 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002717 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002718 return 0;
2719 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002720
Mark Whitley94fd4802001-03-12 23:08:34 +00002721 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002722retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002723 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2724 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002725 case ENOSPC:
2726 syms = xrealloc(syms, bufsize = ret);
2727 goto retry_mod_sym_load;
2728 case ENOENT:
2729 /* The module was removed out from underneath us. */
2730 continue;
2731 default:
2732 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2733 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002734 }
2735 }
2736 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002737
Mark Whitley94fd4802001-03-12 23:08:34 +00002738 m->name = mn;
2739 m->addr = info.addr;
2740 m->nsyms = nsyms;
2741 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002742
Mark Whitley94fd4802001-03-12 23:08:34 +00002743 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2744 s->name += (unsigned long) syms;
2745 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002746 }
2747 }
2748
2749 /* Collect the kernel's symbols. */
2750
2751 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002752retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002753 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002754 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002755 syms = xrealloc(syms, bufsize = ret);
2756 goto retry_kern_sym_load;
2757 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002758 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002759 return 0;
2760 }
2761 nksyms = nsyms = ret;
2762 ksyms = syms;
2763
2764 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2765 s->name += (unsigned long) syms;
2766 }
2767 return 1;
2768}
2769
2770
2771/* Return the kernel symbol checksum version, or zero if not used. */
2772
2773static int new_is_kernel_checksummed(void)
2774{
2775 struct new_module_symbol *s;
2776 size_t i;
2777
2778 /* Using_Versions is not the first symbol, but it should be in there. */
2779
2780 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2781 if (strcmp((char *) s->name, "Using_Versions") == 0)
2782 return s->value;
2783
2784 return 0;
2785}
2786
2787
2788static int new_create_this_module(struct obj_file *f, const char *m_name)
2789{
2790 struct obj_section *sec;
2791
2792 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002793 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002794 memset(sec->contents, 0, sizeof(struct new_module));
2795
Miles Baderae28b042002-04-01 09:34:25 +00002796 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002797 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002798 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002799
2800 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002801 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002802
2803 return 1;
2804}
2805
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002806#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00002807/* add an entry to the __ksymtab section, creating it if necessary */
2808static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2809{
2810 struct obj_section *sec;
2811 ElfW(Addr) ofs;
2812
2813 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2814 * If __ksymtab is defined but not marked alloc, x out the first character
2815 * (no obj_delete routine) and create a new __ksymtab with the correct
2816 * characteristics.
2817 */
2818 sec = obj_find_section(f, "__ksymtab");
2819 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2820 *((char *)(sec->name)) = 'x'; /* override const */
2821 sec = NULL;
2822 }
2823 if (!sec)
2824 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002825 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002826 if (!sec)
2827 return;
2828 sec->header.sh_flags |= SHF_ALLOC;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002829 /* Empty section might be byte-aligned */
2830 sec->header.sh_addralign = tgt_sizeof_void_p;
Eric Andersen889dd202003-01-23 04:48:34 +00002831 ofs = sec->header.sh_size;
2832 obj_symbol_patch(f, sec->idx, ofs, sym);
2833 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2834 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2835}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00002836#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002837
2838static int new_create_module_ksymtab(struct obj_file *f)
2839{
2840 struct obj_section *sec;
2841 int i;
2842
2843 /* We must always add the module references. */
2844
2845 if (n_ext_modules_used) {
2846 struct new_module_ref *dep;
2847 struct obj_symbol *tm;
2848
2849 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002850 (sizeof(struct new_module_ref)
2851 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002852 if (!sec)
2853 return 0;
2854
Miles Baderae28b042002-04-01 09:34:25 +00002855 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002856 dep = (struct new_module_ref *) sec->contents;
2857 for (i = 0; i < n_ext_modules; ++i)
2858 if (ext_modules[i].used) {
2859 dep->dep = ext_modules[i].addr;
2860 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002861 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002862 dep->next_ref = 0;
2863 ++dep;
2864 }
2865 }
2866
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00002867 if (!flag_noexport && !obj_find_section(f, "__ksymtab")) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002868 size_t nsyms;
2869 int *loaded;
2870
Denis Vlasenko9c267b82006-10-12 20:06:18 +00002871 sec = obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002872
2873 /* We don't want to export symbols residing in sections that
2874 aren't loaded. There are a number of these created so that
2875 we make sure certain module options don't appear twice. */
2876
2877 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2878 while (--i >= 0)
2879 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2880
2881 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2882 struct obj_symbol *sym;
2883 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002884 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002885 && sym->secidx <= SHN_HIRESERVE
2886 && (sym->secidx >= SHN_LORESERVE
2887 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002888 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2889
2890 obj_symbol_patch(f, sec->idx, ofs, sym);
2891 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002892 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002893
2894 nsyms++;
2895 }
2896 }
2897
2898 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2899 }
2900
2901 return 1;
2902}
2903
2904
2905static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002906new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002907{
2908 struct new_module *module;
2909 struct obj_section *sec;
2910 void *image;
2911 int ret;
2912 tgt_long m_addr;
2913
2914 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002915 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002916 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002917 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002918 module = (struct new_module *) sec->contents;
2919 m_addr = sec->header.sh_addr;
2920
2921 module->size_of_struct = sizeof(*module);
2922 module->size = m_size;
2923 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2924
2925 sec = obj_find_section(f, "__ksymtab");
2926 if (sec && sec->header.sh_size) {
2927 module->syms = sec->header.sh_addr;
2928 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2929 }
2930
2931 if (n_ext_modules_used) {
2932 sec = obj_find_section(f, ".kmodtab");
2933 module->deps = sec->header.sh_addr;
2934 module->ndeps = n_ext_modules_used;
2935 }
2936
2937 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002938 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002939 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002940 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002941
2942 sec = obj_find_section(f, "__ex_table");
2943 if (sec) {
2944 module->ex_table_start = sec->header.sh_addr;
2945 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2946 }
2947
2948 sec = obj_find_section(f, ".text.init");
2949 if (sec) {
2950 module->runsize = sec->header.sh_addr - m_addr;
2951 }
2952 sec = obj_find_section(f, ".data.init");
2953 if (sec) {
2954 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002955 module->runsize > sec->header.sh_addr - m_addr)
2956 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002957 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002958 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2959 if (sec && sec->header.sh_size) {
2960 module->archdata_start = (void*)sec->header.sh_addr;
2961 module->archdata_end = module->archdata_start + sec->header.sh_size;
2962 }
2963 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2964 if (sec && sec->header.sh_size) {
2965 module->kallsyms_start = (void*)sec->header.sh_addr;
2966 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2967 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002968
Eric Andersen9f16d612000-06-12 23:11:16 +00002969 /* Whew! All of the initialization is complete. Collect the final
2970 module image and give it to the kernel. */
2971
2972 image = xmalloc(m_size);
2973 obj_create_image(f, image);
2974
Eric Andersencb3b9b12004-06-22 11:50:52 +00002975 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002976 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002977 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002978
2979 free(image);
2980
2981 return ret == 0;
2982}
2983
Eric Andersen9f16d612000-06-12 23:11:16 +00002984
2985/*======================================================================*/
2986
Eric Andersen044228d2001-07-17 01:12:36 +00002987static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002988obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2989 const char *string)
2990{
2991 struct obj_string_patch *p;
2992 struct obj_section *strsec;
2993 size_t len = strlen(string) + 1;
2994 char *loc;
2995
2996 p = xmalloc(sizeof(*p));
2997 p->next = f->string_patches;
2998 p->reloc_secidx = secidx;
2999 p->reloc_offset = offset;
3000 f->string_patches = p;
3001
3002 strsec = obj_find_section(f, ".kstrtab");
3003 if (strsec == NULL) {
3004 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
3005 p->string_offset = 0;
3006 loc = strsec->contents;
3007 } else {
3008 p->string_offset = strsec->header.sh_size;
3009 loc = obj_extend_section(strsec, len);
3010 }
3011 memcpy(loc, string, len);
3012
3013 return 1;
3014}
3015
Eric Andersen044228d2001-07-17 01:12:36 +00003016static int
Eric Andersen9f16d612000-06-12 23:11:16 +00003017obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
3018 struct obj_symbol *sym)
3019{
3020 struct obj_symbol_patch *p;
3021
3022 p = xmalloc(sizeof(*p));
3023 p->next = f->symbol_patches;
3024 p->reloc_secidx = secidx;
3025 p->reloc_offset = offset;
3026 p->sym = sym;
3027 f->symbol_patches = p;
3028
3029 return 1;
3030}
3031
Eric Andersen044228d2001-07-17 01:12:36 +00003032static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003033{
3034 unsigned long i;
3035 int ret = 1;
3036
3037 for (i = 0; i < HASH_BUCKETS; ++i) {
3038 struct obj_symbol *sym;
3039 for (sym = f->symtab[i]; sym; sym = sym->next)
3040 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003041 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003042 sym->secidx = SHN_ABS;
3043 sym->value = 0;
3044 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003045 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003046 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003047 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003048 ret = 0;
3049 }
3050 }
3051 }
3052
3053 return ret;
3054}
3055
Eric Andersen044228d2001-07-17 01:12:36 +00003056static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003057{
3058 struct common_entry {
3059 struct common_entry *next;
3060 struct obj_symbol *sym;
3061 } *common_head = NULL;
3062
3063 unsigned long i;
3064
3065 for (i = 0; i < HASH_BUCKETS; ++i) {
3066 struct obj_symbol *sym;
3067 for (sym = f->symtab[i]; sym; sym = sym->next)
3068 if (sym->secidx == SHN_COMMON) {
3069 /* Collect all COMMON symbols and sort them by size so as to
3070 minimize space wasted by alignment requirements. */
3071 {
3072 struct common_entry **p, *n;
3073 for (p = &common_head; *p; p = &(*p)->next)
3074 if (sym->size <= (*p)->sym->size)
3075 break;
3076
3077 n = alloca(sizeof(*n));
3078 n->next = *p;
3079 n->sym = sym;
3080 *p = n;
3081 }
3082 }
3083 }
3084
3085 for (i = 1; i < f->local_symtab_size; ++i) {
3086 struct obj_symbol *sym = f->local_symtab[i];
3087 if (sym && sym->secidx == SHN_COMMON) {
3088 struct common_entry **p, *n;
3089 for (p = &common_head; *p; p = &(*p)->next)
3090 if (sym == (*p)->sym)
3091 break;
3092 else if (sym->size < (*p)->sym->size) {
3093 n = alloca(sizeof(*n));
3094 n->next = *p;
3095 n->sym = sym;
3096 *p = n;
3097 break;
3098 }
3099 }
3100 }
3101
3102 if (common_head) {
3103 /* Find the bss section. */
3104 for (i = 0; i < f->header.e_shnum; ++i)
3105 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3106 break;
3107
3108 /* If for some reason there hadn't been one, create one. */
3109 if (i == f->header.e_shnum) {
3110 struct obj_section *sec;
3111
3112 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3113 f->sections[i] = sec = arch_new_section();
3114 f->header.e_shnum = i + 1;
3115
3116 memset(sec, 0, sizeof(*sec));
3117 sec->header.sh_type = SHT_PROGBITS;
3118 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3119 sec->name = ".bss";
3120 sec->idx = i;
3121 }
3122
3123 /* Allocate the COMMONS. */
3124 {
3125 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3126 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3127 struct common_entry *c;
3128
3129 for (c = common_head; c; c = c->next) {
3130 ElfW(Addr) align = c->sym->value;
3131
3132 if (align > max_align)
3133 max_align = align;
3134 if (bss_size & (align - 1))
3135 bss_size = (bss_size | (align - 1)) + 1;
3136
3137 c->sym->secidx = i;
3138 c->sym->value = bss_size;
3139
3140 bss_size += c->sym->size;
3141 }
3142
3143 f->sections[i]->header.sh_size = bss_size;
3144 f->sections[i]->header.sh_addralign = max_align;
3145 }
3146 }
3147
3148 /* For the sake of patch relocation and parameter initialization,
3149 allocate zeroed data for NOBITS sections now. Note that after
3150 this we cannot assume NOBITS are really empty. */
3151 for (i = 0; i < f->header.e_shnum; ++i) {
3152 struct obj_section *s = f->sections[i];
3153 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003154 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003155 s->contents = memset(xmalloc(s->header.sh_size),
3156 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003157 else
3158 s->contents = NULL;
3159
Eric Andersen9f16d612000-06-12 23:11:16 +00003160 s->header.sh_type = SHT_PROGBITS;
3161 }
3162 }
3163}
3164
Eric Andersen044228d2001-07-17 01:12:36 +00003165static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003166{
3167 unsigned long dot = 0;
3168 struct obj_section *sec;
3169
3170 /* Finalize the positions of the sections relative to one another. */
3171
3172 for (sec = f->load_order; sec; sec = sec->load_next) {
3173 ElfW(Addr) align;
3174
3175 align = sec->header.sh_addralign;
3176 if (align && (dot & (align - 1)))
3177 dot = (dot | (align - 1)) + 1;
3178
3179 sec->header.sh_addr = dot;
3180 dot += sec->header.sh_size;
3181 }
3182
3183 return dot;
3184}
3185
Eric Andersen044228d2001-07-17 01:12:36 +00003186static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003187{
3188 int i, n = f->header.e_shnum;
3189 int ret = 1;
3190
3191 /* Finalize the addresses of the sections. */
3192
3193 f->baseaddr = base;
3194 for (i = 0; i < n; ++i)
3195 f->sections[i]->header.sh_addr += base;
3196
3197 /* And iterate over all of the relocations. */
3198
3199 for (i = 0; i < n; ++i) {
3200 struct obj_section *relsec, *symsec, *targsec, *strsec;
3201 ElfW(RelM) * rel, *relend;
3202 ElfW(Sym) * symtab;
3203 const char *strtab;
3204
3205 relsec = f->sections[i];
3206 if (relsec->header.sh_type != SHT_RELM)
3207 continue;
3208
3209 symsec = f->sections[relsec->header.sh_link];
3210 targsec = f->sections[relsec->header.sh_info];
3211 strsec = f->sections[symsec->header.sh_link];
3212
3213 rel = (ElfW(RelM) *) relsec->contents;
3214 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3215 symtab = (ElfW(Sym) *) symsec->contents;
3216 strtab = (const char *) strsec->contents;
3217
3218 for (; rel < relend; ++rel) {
3219 ElfW(Addr) value = 0;
3220 struct obj_symbol *intsym = NULL;
3221 unsigned long symndx;
3222 ElfW(Sym) * extsym = 0;
3223 const char *errmsg;
3224
3225 /* Attempt to find a value to use for this relocation. */
3226
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003227 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003228 if (symndx) {
3229 /* Note we've already checked for undefined symbols. */
3230
3231 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003232 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003233 /* Local symbols we look up in the local table to be sure
3234 we get the one that is really intended. */
3235 intsym = f->local_symtab[symndx];
3236 } else {
3237 /* Others we look up in the hash table. */
3238 const char *name;
3239 if (extsym->st_name)
3240 name = strtab + extsym->st_name;
3241 else
3242 name = f->sections[extsym->st_shndx]->name;
3243 intsym = obj_find_symbol(f, name);
3244 }
3245
3246 value = obj_symbol_final_value(f, intsym);
3247 intsym->referenced = 1;
3248 }
3249#if SHT_RELM == SHT_RELA
3250#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3251 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3252 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003253 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003254#endif
3255 value += rel->r_addend;
3256#endif
3257
3258 /* Do it! */
3259 switch (arch_apply_relocation
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003260 (f, targsec, symsec, intsym, rel, value)
3261 ) {
3262 case obj_reloc_ok:
3263 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003264
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003265 case obj_reloc_overflow:
3266 errmsg = "Relocation overflow";
3267 goto bad_reloc;
3268 case obj_reloc_dangerous:
3269 errmsg = "Dangerous relocation";
3270 goto bad_reloc;
3271 case obj_reloc_unhandled:
3272 errmsg = "Unhandled relocation";
Eric Andersen3b1a7442003-12-24 20:30:45 +00003273bad_reloc:
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003274 if (extsym) {
3275 bb_error_msg("%s of type %ld for %s", errmsg,
3276 (long) ELF_R_TYPE(rel->r_info),
3277 strtab + extsym->st_name);
3278 } else {
3279 bb_error_msg("%s of type %ld", errmsg,
3280 (long) ELF_R_TYPE(rel->r_info));
3281 }
3282 ret = 0;
3283 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003284 }
3285 }
3286 }
3287
3288 /* Finally, take care of the patches. */
3289
3290 if (f->string_patches) {
3291 struct obj_string_patch *p;
3292 struct obj_section *strsec;
3293 ElfW(Addr) strsec_base;
3294 strsec = obj_find_section(f, ".kstrtab");
3295 strsec_base = strsec->header.sh_addr;
3296
3297 for (p = f->string_patches; p; p = p->next) {
3298 struct obj_section *targsec = f->sections[p->reloc_secidx];
3299 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3300 = strsec_base + p->string_offset;
3301 }
3302 }
3303
3304 if (f->symbol_patches) {
3305 struct obj_symbol_patch *p;
3306
3307 for (p = f->symbol_patches; p; p = p->next) {
3308 struct obj_section *targsec = f->sections[p->reloc_secidx];
3309 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3310 = obj_symbol_final_value(f, p->sym);
3311 }
3312 }
3313
3314 return ret;
3315}
3316
Eric Andersen044228d2001-07-17 01:12:36 +00003317static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003318{
3319 struct obj_section *sec;
3320 ElfW(Addr) base = f->baseaddr;
3321
3322 for (sec = f->load_order; sec; sec = sec->load_next) {
3323 char *secimg;
3324
Eric Andersen2bf658d2001-02-24 20:01:53 +00003325 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003326 continue;
3327
3328 secimg = image + (sec->header.sh_addr - base);
3329
3330 /* Note that we allocated data for NOBITS sections earlier. */
3331 memcpy(secimg, sec->contents, sec->header.sh_size);
3332 }
3333
3334 return 1;
3335}
3336
3337/*======================================================================*/
3338
Eric Andersen044228d2001-07-17 01:12:36 +00003339static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003340{
3341 struct obj_file *f;
3342 ElfW(Shdr) * section_headers;
3343 int shnum, i;
3344 char *shstrtab;
3345
3346 /* Read the file header. */
3347
3348 f = arch_new_file();
3349 memset(f, 0, sizeof(*f));
3350 f->symbol_cmp = strcmp;
3351 f->symbol_hash = obj_elf_hash;
3352 f->load_order_search_start = &f->load_order;
3353
3354 fseek(fp, 0, SEEK_SET);
3355 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003356 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 return NULL;
3358 }
3359
3360 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003361 || f->header.e_ident[EI_MAG1] != ELFMAG1
3362 || f->header.e_ident[EI_MAG2] != ELFMAG2
3363 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003364 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003365 return NULL;
3366 }
3367 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003368 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
Bernhard Reutner-Fischerdeda6a52006-06-03 19:35:15 +00003369 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003370 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3371 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003372 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003373 return NULL;
3374 }
3375 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003376 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003377 return NULL;
3378 }
3379
3380 /* Read the section headers. */
3381
3382 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003383 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003384 (unsigned long) f->header.e_shentsize,
3385 (unsigned long) sizeof(ElfW(Shdr)));
3386 return NULL;
3387 }
3388
3389 shnum = f->header.e_shnum;
3390 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3391 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3392
3393 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3394 fseek(fp, f->header.e_shoff, SEEK_SET);
3395 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003396 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003397 return NULL;
3398 }
3399
3400 /* Read the section data. */
3401
3402 for (i = 0; i < shnum; ++i) {
3403 struct obj_section *sec;
3404
3405 f->sections[i] = sec = arch_new_section();
3406 memset(sec, 0, sizeof(*sec));
3407
3408 sec->header = section_headers[i];
3409 sec->idx = i;
3410
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003411 if(sec->header.sh_size) {
3412 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003413 case SHT_NULL:
3414 case SHT_NOTE:
3415 case SHT_NOBITS:
3416 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003417 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003418
3419 case SHT_PROGBITS:
3420#if LOADBITS
3421 if (!loadprogbits) {
3422 sec->contents = NULL;
3423 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003424 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003425#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003426 case SHT_SYMTAB:
3427 case SHT_STRTAB:
3428 case SHT_RELM:
3429 if (sec->header.sh_size > 0) {
3430 sec->contents = xmalloc(sec->header.sh_size);
3431 fseek(fp, sec->header.sh_offset, SEEK_SET);
3432 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3433 bb_perror_msg("error reading ELF section data");
3434 return NULL;
3435 }
3436 } else {
3437 sec->contents = NULL;
3438 }
3439 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003440
3441#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003442 case SHT_RELA:
3443 bb_error_msg("RELA relocations not supported on this architecture");
3444 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003445#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003446 case SHT_REL:
3447 bb_error_msg("REL relocations not supported on this architecture");
3448 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003449#endif
3450
Eric Andersen3b1a7442003-12-24 20:30:45 +00003451 default:
3452 if (sec->header.sh_type >= SHT_LOPROC) {
3453 /* Assume processor specific section types are debug
3454 info and can safely be ignored. If this is ever not
3455 the case (Hello MIPS?), don't put ifdefs here but
3456 create an arch_load_proc_section(). */
3457 break;
3458 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003459
Eric Andersen3b1a7442003-12-24 20:30:45 +00003460 bb_error_msg("can't handle sections of type %ld",
3461 (long) sec->header.sh_type);
3462 return NULL;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003463 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003464 }
3465 }
3466
3467 /* Do what sort of interpretation as needed by each section. */
3468
3469 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3470
3471 for (i = 0; i < shnum; ++i) {
3472 struct obj_section *sec = f->sections[i];
3473 sec->name = shstrtab + sec->header.sh_name;
3474 }
3475
3476 for (i = 0; i < shnum; ++i) {
3477 struct obj_section *sec = f->sections[i];
3478
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003479 /* .modinfo should be contents only but gcc has no attribute for that.
3480 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3481 */
3482 if (strcmp(sec->name, ".modinfo") == 0)
3483 sec->header.sh_flags &= ~SHF_ALLOC;
3484
Eric Andersen9f16d612000-06-12 23:11:16 +00003485 if (sec->header.sh_flags & SHF_ALLOC)
3486 obj_insert_section_load_order(f, sec);
3487
3488 switch (sec->header.sh_type) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003489 case SHT_SYMTAB:
3490 {
3491 unsigned long nsym, j;
3492 char *strtab;
3493 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003494
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003495 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3496 bb_error_msg("symbol size mismatch: %lu != %lu",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003497 (unsigned long) sec->header.sh_entsize,
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003498 (unsigned long) sizeof(ElfW(Sym)));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003499 return NULL;
3500 }
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003501
3502 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3503 strtab = f->sections[sec->header.sh_link]->contents;
3504 sym = (ElfW(Sym) *) sec->contents;
3505
3506 /* Allocate space for a table of local symbols. */
3507 j = f->local_symtab_size = sec->header.sh_info;
3508 f->local_symtab = xzalloc(j * sizeof(struct obj_symbol *));
3509
3510 /* Insert all symbols into the hash table. */
3511 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3512 ElfW(Addr) val = sym->st_value;
3513 const char *name;
3514 if (sym->st_name)
3515 name = strtab + sym->st_name;
3516 else if (sym->st_shndx < shnum)
3517 name = f->sections[sym->st_shndx]->name;
3518 else
3519 continue;
3520#if defined(__SH5__)
3521 /*
3522 * For sh64 it is possible that the target of a branch
3523 * requires a mode switch (32 to 16 and back again).
3524 *
3525 * This is implied by the lsb being set in the target
3526 * address for SHmedia mode and clear for SHcompact.
3527 */
3528 val |= sym->st_other & 4;
3529#endif
3530
3531 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3532 val, sym->st_size);
3533 }
3534 }
3535 break;
3536
3537 case SHT_RELM:
3538 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3539 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3540 (unsigned long) sec->header.sh_entsize,
3541 (unsigned long) sizeof(ElfW(RelM)));
3542 return NULL;
3543 }
3544 break;
3545 /* XXX Relocation code from modutils-2.3.19 is not here.
3546 * Why? That's about 20 lines of code from obj/obj_load.c,
3547 * which gets done in a second pass through the sections.
3548 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003549 }
3550 }
3551
3552 return f;
3553}
3554
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003555#if ENABLE_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003556/*
3557 * load the unloaded sections directly into the memory allocated by
3558 * kernel for the module
3559 */
3560
Eric Andersenac5dbd12001-08-22 05:26:08 +00003561static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003562{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003563 ElfW(Addr) base = f->baseaddr;
3564 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003565
Eric Andersen8ae319a2001-05-21 16:09:18 +00003566 for (sec = f->load_order; sec; sec = sec->load_next) {
3567
3568 /* section already loaded? */
3569 if (sec->contents != NULL)
3570 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003571
Eric Andersen8ae319a2001-05-21 16:09:18 +00003572 if (sec->header.sh_size == 0)
3573 continue;
3574
3575 sec->contents = imagebase + (sec->header.sh_addr - base);
3576 fseek(fp, sec->header.sh_offset, SEEK_SET);
3577 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Denis Vlasenko6d655be2006-09-06 19:02:46 +00003578 bb_perror_msg("error reading ELF section data");
Eric Andersen8ae319a2001-05-21 16:09:18 +00003579 return 0;
3580 }
3581
3582 }
3583 return 1;
3584}
3585#endif
3586
Eric Andersen9f16d612000-06-12 23:11:16 +00003587static void hide_special_symbols(struct obj_file *f)
3588{
3589 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003590 SPFX "cleanup_module",
3591 SPFX "init_module",
3592 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003593 NULL
3594 };
3595
3596 struct obj_symbol *sym;
3597 const char *const *p;
3598
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003599 for (p = specials; *p; ++p) {
3600 sym = obj_find_symbol(f, *p);
3601 if (sym != NULL)
3602 sym->info = ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
3603 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003604}
3605
Glenn L McGrath759515c2003-08-30 06:00:33 +00003606
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003607#if ENABLE_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003608static int obj_gpl_license(struct obj_file *f, const char **license)
3609{
3610 struct obj_section *sec;
3611 /* This list must match *exactly* the list of allowable licenses in
3612 * linux/include/linux/module.h. Checking for leading "GPL" will not
3613 * work, somebody will use "GPL sucks, this is proprietary".
3614 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003615 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003616 "GPL",
3617 "GPL v2",
3618 "GPL and additional rights",
3619 "Dual BSD/GPL",
3620 "Dual MPL/GPL",
3621 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003622
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003623 sec = obj_find_section(f, ".modinfo");
3624 if (sec) {
Eric Andersen166fa462002-09-16 05:30:24 +00003625 const char *value, *ptr, *endptr;
3626 ptr = sec->contents;
3627 endptr = ptr + sec->header.sh_size;
3628 while (ptr < endptr) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003629 value = strchr(ptr, '=');
3630 if (value && strncmp(ptr, "license", value-ptr) == 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003631 int i;
3632 if (license)
3633 *license = value+1;
3634 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3635 if (strcmp(value+1, gpl_licenses[i]) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003636 return 0;
Eric Andersen166fa462002-09-16 05:30:24 +00003637 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003638 return 2;
Eric Andersen166fa462002-09-16 05:30:24 +00003639 }
3640 if (strchr(ptr, '\0'))
3641 ptr = strchr(ptr, '\0') + 1;
3642 else
3643 ptr = endptr;
3644 }
3645 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003646 return 1;
Eric Andersen166fa462002-09-16 05:30:24 +00003647}
3648
3649#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3650#define TAINT_PROPRIETORY_MODULE (1<<0)
3651#define TAINT_FORCED_MODULE (1<<1)
3652#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003653#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003654
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003655static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003656 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3657{
3658 char buf[80];
3659 int oldval;
3660 static int first = 1;
3661 if (fd < 0 && !kernel_has_tainted)
3662 return; /* New modutils on old kernel */
3663 printf("Warning: loading %s will taint the kernel: %s%s\n",
3664 m_name, text1, text2);
3665 if (first) {
3666 printf(" See %s for information about tainted modules\n", TAINT_URL);
3667 first = 0;
3668 }
3669 if (fd >= 0) {
3670 read(fd, buf, sizeof(buf)-1);
3671 buf[sizeof(buf)-1] = '\0';
3672 oldval = strtoul(buf, NULL, 10);
3673 sprintf(buf, "%d\n", oldval | taint);
3674 write(fd, buf, strlen(buf));
3675 }
3676}
3677
3678/* Check if loading this module will taint the kernel. */
3679static void check_tainted_module(struct obj_file *f, char *m_name)
3680{
3681 static const char tainted_file[] = TAINT_FILENAME;
3682 int fd, kernel_has_tainted;
3683 const char *ptr;
3684
3685 kernel_has_tainted = 1;
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003686 fd = open(tainted_file, O_RDWR);
3687 if (fd < 0) {
Eric Andersen166fa462002-09-16 05:30:24 +00003688 if (errno == ENOENT)
3689 kernel_has_tainted = 0;
3690 else if (errno == EACCES)
3691 kernel_has_tainted = 1;
3692 else {
3693 perror(tainted_file);
3694 kernel_has_tainted = 0;
3695 }
3696 }
3697
3698 switch (obj_gpl_license(f, &ptr)) {
3699 case 0:
3700 break;
3701 case 1:
3702 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3703 break;
3704 case 2:
3705 /* The module has a non-GPL license so we pretend that the
3706 * kernel always has a taint flag to get a warning even on
3707 * kernels without the proc flag.
3708 */
3709 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3710 break;
3711 default:
3712 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3713 break;
3714 }
3715
3716 if (flag_force_load)
3717 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3718
3719 if (fd >= 0)
3720 close(fd);
3721}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003722#else /* FEATURE_CHECK_TAINTED_MODULE */
Denis Vlasenkobf0a2012006-12-26 10:42:51 +00003723#define check_tainted_module(x, y) do { } while (0);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003724#endif /* FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003725
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003726#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00003727/* add module source, timestamp, kernel version and a symbol for the
3728 * start of some sections. this info is used by ksymoops to do better
3729 * debugging.
3730 */
3731static int
3732get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3733{
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003734#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003735 return new_get_module_version(f, str);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003736#else /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003737 strncpy(str, "???", sizeof(str));
3738 return -1;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003739#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen889dd202003-01-23 04:48:34 +00003740}
3741
3742/* add module source, timestamp, kernel version and a symbol for the
3743 * start of some sections. this info is used by ksymoops to do better
3744 * debugging.
3745 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003746static void
Eric Andersen889dd202003-01-23 04:48:34 +00003747add_ksymoops_symbols(struct obj_file *f, const char *filename,
3748 const char *m_name)
3749{
3750 static const char symprefix[] = "__insmod_";
3751 struct obj_section *sec;
3752 struct obj_symbol *sym;
3753 char *name, *absolute_filename;
3754 char str[STRVERSIONLEN], real[PATH_MAX];
3755 int i, l, lm_name, lfilename, use_ksymtab, version;
3756 struct stat statbuf;
3757
3758 static const char *section_names[] = {
3759 ".text",
3760 ".rodata",
3761 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003762 ".bss",
3763 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003764 };
3765
3766 if (realpath(filename, real)) {
Rob Landleyd921b2e2006-08-03 15:41:12 +00003767 absolute_filename = xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003768 }
3769 else {
3770 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003771 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003772 errno = save_errno;
3773 perror("");
Rob Landleyd921b2e2006-08-03 15:41:12 +00003774 absolute_filename = xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003775 }
3776
3777 lm_name = strlen(m_name);
3778 lfilename = strlen(absolute_filename);
3779
3780 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3781 * are not to be exported. otherwise leave ksymtab alone for now, the
3782 * "export all symbols" compatibility code will export these symbols later.
3783 */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003784 use_ksymtab = obj_find_section(f, "__ksymtab") || flag_noexport;
Eric Andersen889dd202003-01-23 04:48:34 +00003785
3786 if ((sec = obj_find_section(f, ".this"))) {
3787 /* tag the module header with the object name, last modified
3788 * timestamp and module version. worst case for module version
3789 * is 0xffffff, decimal 16777215. putting all three fields in
3790 * one symbol is less readable but saves kernel space.
3791 */
3792 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003793 lm_name+ /* module name */
3794 2+ /* "_O" */
3795 lfilename+ /* object filename */
3796 2+ /* "_M" */
3797 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3798 2+ /* "_V" */
3799 8+ /* version in dec */
3800 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003801 name = xmalloc(l);
3802 if (stat(absolute_filename, &statbuf) != 0)
3803 statbuf.st_mtime = 0;
3804 version = get_module_version(f, str); /* -1 if not found */
3805 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003806 symprefix, m_name, absolute_filename,
3807 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3808 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003809 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003810 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003811 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003812 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003813 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003814 }
3815 free(absolute_filename);
3816#ifdef _NOT_SUPPORTED_
3817 /* record where the persistent data is going, same address as previous symbol */
3818
3819 if (f->persist) {
3820 l = sizeof(symprefix)+ /* "__insmod_" */
3821 lm_name+ /* module name */
3822 2+ /* "_P" */
3823 strlen(f->persist)+ /* data store */
3824 1; /* nul */
3825 name = xmalloc(l);
3826 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003827 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003828 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003829 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003830 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003831 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003832 }
3833#endif /* _NOT_SUPPORTED_ */
3834 /* tag the desired sections if size is non-zero */
3835
3836 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3837 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003838 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003839 l = sizeof(symprefix)+ /* "__insmod_" */
3840 lm_name+ /* module name */
3841 2+ /* "_S" */
3842 strlen(sec->name)+ /* section name */
3843 2+ /* "_L" */
3844 8+ /* length in dec */
3845 1; /* nul */
3846 name = xmalloc(l);
3847 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003848 symprefix, m_name, sec->name,
3849 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003850 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003851 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003852 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003853 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003854 }
3855 }
3856}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003857#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00003858
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003859#if ENABLE_FEATURE_INSMOD_LOAD_MAP
Eric Andersenbe65c352003-01-23 04:57:35 +00003860static void print_load_map(struct obj_file *f)
3861{
Eric Andersenbe65c352003-01-23 04:57:35 +00003862 struct obj_section *sec;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003863#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
3864 struct obj_symbol **all, **p;
Eric Andersenbe65c352003-01-23 04:57:35 +00003865 int i, nsyms, *loaded;
Denis Vlasenko6a5dc5d2006-12-30 18:42:29 +00003866 struct obj_symbol *sym;
3867#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003868 /* Report on the section layout. */
3869
3870 printf("Sections: Size %-*s Align\n",
3871 (int) (2 * sizeof(void *)), "Address");
3872
3873 for (sec = f->load_order; sec; sec = sec->load_next) {
3874 int a;
3875 unsigned long tmp;
3876
3877 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3878 tmp >>= 1;
3879 if (a == -1)
3880 a = 0;
3881
3882 printf("%-15s %08lx %0*lx 2**%d\n",
3883 sec->name,
3884 (long)sec->header.sh_size,
3885 (int) (2 * sizeof(void *)),
3886 (long)sec->header.sh_addr,
3887 a);
3888 }
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003889#if ENABLE_FEATURE_INSMOD_LOAD_MAP_FULL
Eric Andersenbe65c352003-01-23 04:57:35 +00003890 /* Quick reference which section indicies are loaded. */
3891
3892 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3893 while (--i >= 0)
3894 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3895
3896 /* Collect the symbols we'll be listing. */
3897
3898 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3899 for (sym = f->symtab[i]; sym; sym = sym->next)
3900 if (sym->secidx <= SHN_HIRESERVE
3901 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3902 ++nsyms;
3903
3904 all = alloca(nsyms * sizeof(struct obj_symbol *));
3905
3906 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3907 for (sym = f->symtab[i]; sym; sym = sym->next)
3908 if (sym->secidx <= SHN_HIRESERVE
3909 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3910 *p++ = sym;
3911
3912 /* And list them. */
3913 printf("\nSymbols:\n");
3914 for (p = all; p < all + nsyms; ++p) {
3915 char type = '?';
3916 unsigned long value;
3917
3918 sym = *p;
3919 if (sym->secidx == SHN_ABS) {
3920 type = 'A';
3921 value = sym->value;
3922 } else if (sym->secidx == SHN_UNDEF) {
3923 type = 'U';
3924 value = 0;
3925 } else {
3926 sec = f->sections[sym->secidx];
3927
3928 if (sec->header.sh_type == SHT_NOBITS)
3929 type = 'B';
3930 else if (sec->header.sh_flags & SHF_ALLOC) {
3931 if (sec->header.sh_flags & SHF_EXECINSTR)
3932 type = 'T';
3933 else if (sec->header.sh_flags & SHF_WRITE)
3934 type = 'D';
3935 else
3936 type = 'R';
3937 }
3938 value = sym->value + sec->header.sh_addr;
3939 }
3940
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003941 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003942 type = tolower(type);
3943
3944 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3945 type, sym->name);
3946 }
3947#endif
3948}
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003949#else /* !FEATURE_INSMOD_LOAD_MAP */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003950void print_load_map(struct obj_file *f);
Eric Andersenbe65c352003-01-23 04:57:35 +00003951#endif
3952
Rob Landleydfba7412006-03-06 20:47:33 +00003953int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003954{
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003955 char *opt_o, *arg1;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003956 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003957 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003958 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003959 unsigned long m_size;
3960 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003961 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003962 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003963 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003964 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003965 int m_has_modinfo;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003966#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003967 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003968 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003969 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003970#endif
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00003971#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00003972 FILE *fp = 0;
3973#else
3974 FILE *fp;
3975#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003976 int k_version = 0;
3977 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003978
Erik Andersene49d5ec2000-02-08 19:58:47 +00003979 /* Parse any options */
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003980 getopt32(argc, argv, OPTION_STR, &opt_o);
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003981 arg1 = argv[optind];
Denis Vlasenkoc12f5302006-10-06 09:49:47 +00003982 if (option_mask32 & OPT_o) { // -o /* name the output module */
Denis Vlasenkofe76cd52006-09-23 12:32:58 +00003983 free(m_name);
3984 m_name = xstrdup(opt_o);
3985 }
Eric Andersen03d80912003-12-19 21:04:19 +00003986
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003987 if (arg1 == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003988 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003989 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003990
Erik Andersene49d5ec2000-02-08 19:58:47 +00003991 /* Grab the module name */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00003992 tmp1 = xstrdup(arg1);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003993 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003994 len = strlen(tmp);
3995
Eric Andersen03d80912003-12-19 21:04:19 +00003996 if (uname(&myuname) == 0) {
3997 if (myuname.release[0] == '2') {
3998 k_version = myuname.release[2] - '0';
3999 }
4000 }
4001
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004002#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004003 if (k_version > 4 && len > 3 && tmp[len - 3] == '.'
4004 && tmp[len - 2] == 'k' && tmp[len - 1] == 'o'
4005 ) {
4006 len -= 3;
Eric Andersen03d80912003-12-19 21:04:19 +00004007 tmp[len] = '\0';
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004008 } else
Eric Andersen03d80912003-12-19 21:04:19 +00004009#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004010 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004011 len -= 2;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004012 tmp[len] = '\0';
4013 }
Eric Andersen2d342152002-06-18 05:16:25 +00004014
Eric Andersen03d80912003-12-19 21:04:19 +00004015
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004016#if ENABLE_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004017 if (k_version > 4)
Rob Landleyd921b2e2006-08-03 15:41:12 +00004018 m_fullName = xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004019 else
Eric Andersen03d80912003-12-19 21:04:19 +00004020#endif
Rob Landleyd921b2e2006-08-03 15:41:12 +00004021 m_fullName = xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004022
Eric Andersen61f83052002-06-22 17:15:42 +00004023 if (!m_name) {
4024 m_name = tmp;
4025 } else {
4026 free(tmp1);
4027 tmp1 = 0; /* flag for free(m_name) before exit() */
4028 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004029
Eric Andersen14d35432001-05-14 17:07:32 +00004030 /* Get a filedesc for the module. Check we we have a complete path */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004031 if (stat(arg1, &st) < 0 || !S_ISREG(st.st_mode)
4032 || (fp = fopen(arg1, "r")) == NULL
4033 ) {
Eric Andersen14d35432001-05-14 17:07:32 +00004034 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4035 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004036 if (k_version) { /* uname succeedd */
4037 char *module_dir;
4038 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004039 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004040
Eric Andersen03d80912003-12-19 21:04:19 +00004041 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004042 /* Jump through hoops in case /lib/modules/`uname -r`
4043 * is a symlink. We do not want recursive_action to
4044 * follow symlinks, but we do want to follow the
4045 * /lib/modules/`uname -r` dir, So resolve it ourselves
4046 * if it is a link... */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004047 if (realpath(tmdn, real_module_dir) == NULL)
Eric Andersen03d80912003-12-19 21:04:19 +00004048 module_dir = tmdn;
4049 else
4050 module_dir = real_module_dir;
4051 recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004052 check_module_name_match, 0, m_fullName, 0);
Eric Andersen03d80912003-12-19 21:04:19 +00004053 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004054 }
4055
4056 /* Check if we have found anything yet */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004057 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL)) {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004058 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004059
Eric Andersen03d80912003-12-19 21:04:19 +00004060 free(m_filename);
4061 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004062 if (realpath (_PATH_MODULES, module_dir) == NULL)
4063 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004064 /* No module found under /lib/modules/`uname -r`, this
4065 * time cast the net a bit wider. Search /lib/modules/ */
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004066 if (!recursive_action(module_dir, TRUE, FALSE, FALSE,
Denis Vlasenko8c35d652006-10-27 23:42:25 +00004067 check_module_name_match, 0, m_fullName, 0)
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004068 ) {
Eric Andersen61f83052002-06-22 17:15:42 +00004069 if (m_filename == 0
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004070 || ((fp = fopen(m_filename, "r")) == NULL)
4071 ) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004072 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004073 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004074 }
4075 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004076 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004077 }
Eric Andersen03d80912003-12-19 21:04:19 +00004078 } else
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004079 m_filename = xstrdup(arg1);
Erik Andersend387d011999-12-21 02:55:11 +00004080
Rob Landley999af202005-12-11 20:14:12 +00004081 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004082 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004083
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004084#if ENABLE_FEATURE_2_6_MODULES
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004085 if (k_version > 4) {
4086 argv[optind] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004087 optind--;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004088 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004089 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004090#endif
4091
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004092 f = obj_load(fp, LOADBITS);
4093 if (f == NULL)
4094 bb_perror_msg_and_die("cannot load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004095
Eric Andersen9f16d612000-06-12 23:11:16 +00004096 if (get_modinfo_value(f, "kernel_version") == NULL)
4097 m_has_modinfo = 0;
4098 else
4099 m_has_modinfo = 1;
4100
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004101#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004102 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004103 if (!flag_quiet) {
4104 if (uname(&uts_info) < 0)
4105 uts_info.release[0] = '\0';
4106 if (m_has_modinfo) {
4107 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004108 if (m_version == -1) {
Denis Vlasenkoa9595882006-09-29 21:30:43 +00004109 bb_error_msg("cannot find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004110 "compiled for");
4111 goto out;
4112 }
4113 }
4114
4115 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4116 if (flag_force_load) {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004117 bb_error_msg("warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004118 "\t%s was compiled for kernel version %s\n"
4119 "\twhile this kernel is version %s",
4120 m_filename, m_strversion, uts_info.release);
4121 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004122 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004123 "\t%s was compiled for kernel version %s\n"
4124 "\twhile this kernel is version %s.",
4125 m_filename, m_strversion, uts_info.release);
4126 goto out;
4127 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004128 }
4129 }
4130 k_crcs = 0;
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004131#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004132
Eric Andersencb3b9b12004-06-22 11:50:52 +00004133 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004134 if (!new_get_kernel_symbols())
4135 goto out;
4136 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 } else {
Denis Vlasenkoe1a0d482006-10-20 13:28:22 +00004138 bb_error_msg("not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004139 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004140 }
4141
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004142#if ENABLE_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004143 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004144 if (m_has_modinfo)
4145 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004146
4147 if (m_crcs != k_crcs)
4148 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004149#endif /* FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004150
Erik Andersene49d5ec2000-02-08 19:58:47 +00004151 /* Let the module know about the kernel symbols. */
4152 add_kernel_symbols(f);
4153
Eric Andersen9f16d612000-06-12 23:11:16 +00004154 /* Allocate common symbols, symbol tables, and string tables. */
4155
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004156 if (!new_create_this_module(f, m_name)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004157 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004158 }
4159
Eric Andersen9f16d612000-06-12 23:11:16 +00004160 if (!obj_check_undefineds(f)) {
4161 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004162 }
4163 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004164 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004165
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004166 /* done with the module name, on to the optional var=value arguments */
4167 ++optind;
Eric Andersen9f16d612000-06-12 23:11:16 +00004168 if (optind < argc) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004169 if (!new_process_module_arguments(f, argc - optind, argv + optind)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004170 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004171 }
4172 }
4173
Eric Andersen9f16d612000-06-12 23:11:16 +00004174 arch_create_got(f);
4175 hide_special_symbols(f);
4176
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004177#if ENABLE_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
Eric Andersen889dd202003-01-23 04:48:34 +00004178 add_ksymoops_symbols(f, m_filename, m_name);
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004179#endif /* FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen889dd202003-01-23 04:48:34 +00004180
Eric Andersencb3b9b12004-06-22 11:50:52 +00004181 new_create_module_ksymtab(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004182
Erik Andersene49d5ec2000-02-08 19:58:47 +00004183 /* Find current size of the module */
4184 m_size = obj_load_size(f);
Erik Andersend387d011999-12-21 02:55:11 +00004185
4186
Erik Andersene49d5ec2000-02-08 19:58:47 +00004187 m_addr = create_module(m_name, m_size);
Eric Andersen61f83052002-06-22 17:15:42 +00004188 if (m_addr == -1) switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004189 case EEXIST:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004190 bb_error_msg("a module named %s already exists", m_name);
Eric Andersen3b1a7442003-12-24 20:30:45 +00004191 goto out;
4192 case ENOMEM:
Denis Vlasenkoea620772006-10-14 02:23:43 +00004193 bb_error_msg("can't allocate kernel memory for module; needed %lu bytes",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004194 m_size);
4195 goto out;
4196 default:
4197 bb_perror_msg("create_module: %s", m_name);
4198 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004199 }
Erik Andersend387d011999-12-21 02:55:11 +00004200
Eric Andersen8ae319a2001-05-21 16:09:18 +00004201#if !LOADBITS
4202 /*
4203 * the PROGBITS section was not loaded by the obj_load
4204 * now we can load them directly into the kernel memory
4205 */
Eric Andersenac5dbd12001-08-22 05:26:08 +00004206 if (!obj_load_progbits(fp, f, (char*)m_addr)) {
Eric Andersen8ae319a2001-05-21 16:09:18 +00004207 delete_module(m_name);
4208 goto out;
4209 }
Eric Andersen03d80912003-12-19 21:04:19 +00004210#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +00004211
Eric Andersen9f16d612000-06-12 23:11:16 +00004212 if (!obj_relocate(f, m_addr)) {
4213 delete_module(m_name);
4214 goto out;
4215 }
Erik Andersend387d011999-12-21 02:55:11 +00004216
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004217 if (!new_init_module(m_name, f, m_size)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004218 delete_module(m_name);
4219 goto out;
4220 }
4221
Eric Andersenbe65c352003-01-23 04:57:35 +00004222 if(flag_print_load_map)
4223 print_load_map(f);
Eric Andersenbe65c352003-01-23 04:57:35 +00004224
Matt Kraai3e856ce2000-12-01 02:55:13 +00004225 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004226
4227out:
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004228#if ENABLE_FEATURE_CLEAN_UP
Eric Andersen61f83052002-06-22 17:15:42 +00004229 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004230 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004231 free(tmp1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004232 if(!tmp1)
Eric Andersen61f83052002-06-22 17:15:42 +00004233 free(m_name);
Eric Andersen61f83052002-06-22 17:15:42 +00004234 free(m_filename);
4235#endif
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004236 return exit_status;
Erik Andersen02104321999-12-17 18:57:34 +00004237}
Eric Andersene7047882003-12-11 01:42:13 +00004238
4239
4240#endif
4241
4242
Denis Vlasenko3aa2d512006-11-21 14:12:53 +00004243#if ENABLE_FEATURE_2_6_MODULES
Eric Andersene7047882003-12-11 01:42:13 +00004244
4245#include <sys/mman.h>
4246#include <asm/unistd.h>
4247#include <sys/syscall.h>
4248
4249/* We use error numbers in a loose translation... */
4250static const char *moderror(int err)
4251{
4252 switch (err) {
Denis Vlasenko9c267b82006-10-12 20:06:18 +00004253 case ENOEXEC:
4254 return "Invalid module format";
4255 case ENOENT:
4256 return "Unknown symbol in module";
4257 case ESRCH:
4258 return "Module has wrong symbol version";
4259 case EINVAL:
4260 return "Invalid parameters";
4261 default:
4262 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004263 }
4264}
4265
Denis Vlasenko92297942006-11-21 11:58:14 +00004266int insmod_ng_main(int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004267{
Denis Vlasenko92297942006-11-21 11:58:14 +00004268 long ret;
4269 size_t len;
Eric Andersene7047882003-12-11 01:42:13 +00004270 void *map;
Denis Vlasenko92297942006-11-21 11:58:14 +00004271 char *filename, *options;
Eric Andersen3b1a7442003-12-24 20:30:45 +00004272
Denis Vlasenko92297942006-11-21 11:58:14 +00004273 filename = *++argv;
4274 if (!filename)
Eric Andersene7047882003-12-11 01:42:13 +00004275 bb_show_usage();
Eric Andersene7047882003-12-11 01:42:13 +00004276
4277 /* Rest is options */
Denis Vlasenko92297942006-11-21 11:58:14 +00004278 options = xstrdup("");
4279 while (*++argv) {
4280 int optlen = strlen(options);
4281 options = xrealloc(options, optlen + 2 + strlen(*argv) + 2);
Eric Andersene7047882003-12-11 01:42:13 +00004282 /* Spaces handled by "" pairs, but no way of escaping quotes */
Denis Vlasenko92297942006-11-21 11:58:14 +00004283 sprintf(options + optlen, (strchr(*argv,' ') ? "\"%s\" " : "%s "), *argv);
Eric Andersene7047882003-12-11 01:42:13 +00004284 }
4285
Denis Vlasenko92297942006-11-21 11:58:14 +00004286#if 0
4287 /* Any special reason why mmap? It isn't performace critical... */
4288 int fd;
4289 struct stat st;
4290 unsigned long len;
Denis Vlasenkod5d614c2006-09-09 12:25:20 +00004291 fd = xopen(filename, O_RDONLY);
Eric Andersene7047882003-12-11 01:42:13 +00004292 fstat(fd, &st);
4293 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004294 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004295 if (map == MAP_FAILED) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004296 bb_perror_msg_and_die("cannot mmap '%s'", filename);
Eric Andersene7047882003-12-11 01:42:13 +00004297 }
4298
Denis Vlasenko92297942006-11-21 11:58:14 +00004299 /* map == NULL on Blackfin, probably on other MMU-less systems too. Workaround. */
4300 if (map == NULL) {
4301 map = xmalloc(len);
4302 xread(fd, map, len);
4303 }
4304#else
4305 len = MAXINT(ssize_t);
4306 map = xmalloc_open_read_close(filename, &len);
4307#endif
4308
Eric Andersene7047882003-12-11 01:42:13 +00004309 ret = syscall(__NR_init_module, map, len, options);
4310 if (ret != 0) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00004311 bb_perror_msg_and_die("cannot insert '%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004312 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004313 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314
Eric Andersene7047882003-12-11 01:42:13 +00004315 return 0;
4316}
4317
4318#endif