blob: efa0499e49e4ce771692046d8ab2fc7354c816e6 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Erik Andersen02104321999-12-17 18:57:34 +00002/*
3 * Mini insmod implementation for busybox
Eric Andersen2835efe2001-07-25 16:58:58 +00004 *
Eric Andersen45a05132004-09-02 23:03:25 +00005 * This version of insmod supports ARM, CRIS, H8/300, x86, ia64, x86_64,
6 * m68k, MIPS, PowerPC, S390, SH3/4/5, Sparc, v850e, and x86_64.
Eric Andersen2835efe2001-07-25 16:58:58 +00007 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00008 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersen9f16d612000-06-12 23:11:16 +00009 * and Ron Alder <alder@lineo.com>
10 *
Eric Andersena4d27d22004-08-19 19:17:30 +000011 * Rodney Radford <rradford@mindspring.com> 17-Aug-2004.
12 * Added x86_64 support.
13 *
Miles Bader75ce8d72002-04-01 14:25:51 +000014 * Miles Bader <miles@gnu.org> added NEC V850E support.
Miles Baderae28b042002-04-01 09:34:25 +000015 *
Eric Andersenfe4208f2000-09-24 03:44:29 +000016 * Modified by Bryan Rittmeyer <bryan@ixiacom.com> to support SH4
Eric Andersen21adca72000-12-06 18:18:26 +000017 * and (theoretically) SH3. I have only tested SH4 in little endian mode.
18 *
19 * Modified by Alcove, Julien Gaulmin <julien.gaulmin@alcove.fr> and
20 * Nicolas Ferre <nicolas.ferre@alcove.fr> to support ARM7TDMI. Only
21 * very minor changes required to also work with StrongArm and presumably
22 * all ARM based systems.
Eric Andersenfe4208f2000-09-24 03:44:29 +000023 *
Eric Andersenee70fa52004-05-26 11:38:46 +000024 * Yoshinori Sato <ysato@users.sourceforge.jp> 19-May-2004.
25 * added Renesas H8/300 support.
26 *
Eric Andersenbf833552003-08-13 19:56:33 +000027 * Paul Mundt <lethal@linux-sh.org> 08-Aug-2003.
28 * Integrated support for sh64 (SH-5), from preliminary modutils
29 * patches from Benedict Gaster <benedict.gaster@superh.com>.
30 * Currently limited to support for 32bit ABI.
31 *
Eric Andersencffd5022002-05-24 06:50:15 +000032 * Magnus Damm <damm@opensource.se> 22-May-2002.
33 * The plt and got code are now using the same structs.
34 * Added generic linked list code to fully support PowerPC.
35 * Replaced the mess in arch_apply_relocation() with architecture blocks.
36 * The arch_create_got() function got cleaned up with architecture blocks.
37 * These blocks should be easy maintain and sync with obj_xxx.c in modutils.
38 *
Eric Andersen90fe7fe2001-02-20 20:47:08 +000039 * Magnus Damm <damm@opensource.se> added PowerPC support 20-Feb-2001.
Eric Andersenc7bda1c2004-03-15 08:29:22 +000040 * PowerPC specific code stolen from modutils-2.3.16,
Eric Andersen90fe7fe2001-02-20 20:47:08 +000041 * written by Paul Mackerras, Copyright 1996, 1997 Linux International.
42 * I've only tested the code on mpc8xx platforms in big-endian mode.
Eric Andersenbdfd0d72001-10-24 05:00:29 +000043 * Did some cleanup and added CONFIG_USE_xxx_ENTRIES...
Eric Andersen90fe7fe2001-02-20 20:47:08 +000044 *
Eric Andersen2bf658d2001-02-24 20:01:53 +000045 * Quinn Jensen <jensenq@lineo.com> added MIPS support 23-Feb-2001.
46 * based on modutils-2.4.2
47 * MIPS specific support for Elf loading and relocation.
48 * Copyright 1996, 1997 Linux International.
49 * Contributed by Ralf Baechle <ralf@gnu.ai.mit.edu>
50 *
Eric Andersen9f16d612000-06-12 23:11:16 +000051 * Based almost entirely on the Linux modutils-2.3.11 implementation.
52 * Copyright 1996, 1997 Linux International.
53 * New implementation contributed by Richard Henderson <rth@tamu.edu>
54 * Based on original work by Bjorn Ekwall <bj0rn@blox.se>
55 * Restructured (and partly rewritten) by:
56 * Björn Ekwall <bj0rn@blox.se> February 1999
Erik Andersen02104321999-12-17 18:57:34 +000057 *
58 * This program is free software; you can redistribute it and/or modify
59 * it under the terms of the GNU General Public License as published by
60 * the Free Software Foundation; either version 2 of the License, or
61 * (at your option) any later version.
62 *
63 * This program is distributed in the hope that it will be useful,
64 * but WITHOUT ANY WARRANTY; without even the implied warranty of
65 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
66 * General Public License for more details.
67 *
68 * You should have received a copy of the GNU General Public License
69 * along with this program; if not, write to the Free Software
70 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
71 *
72 */
73
Erik Andersen02104321999-12-17 18:57:34 +000074#include <stdlib.h>
75#include <stdio.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000076#include <stddef.h>
Erik Andersen02104321999-12-17 18:57:34 +000077#include <errno.h>
78#include <unistd.h>
79#include <dirent.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000080#include <ctype.h>
81#include <assert.h>
Eric Andersened3ef502001-01-27 08:24:39 +000082#include <string.h>
Eric Andersen999bf722000-07-09 06:59:58 +000083#include <getopt.h>
Eric Andersen166fa462002-09-16 05:30:24 +000084#include <fcntl.h>
Eric Andersen9f16d612000-06-12 23:11:16 +000085#include <sys/utsname.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000086#include "busybox.h"
Eric Andersen9f16d612000-06-12 23:11:16 +000087
Eric Andersene7047882003-12-11 01:42:13 +000088#if !defined(CONFIG_FEATURE_2_4_MODULES) && \
Eric Andersene7047882003-12-11 01:42:13 +000089 !defined(CONFIG_FEATURE_2_6_MODULES)
90#define CONFIG_FEATURE_2_4_MODULES
91#endif
92
Eric Andersencb3b9b12004-06-22 11:50:52 +000093#if !defined(CONFIG_FEATURE_2_4_MODULES)
Eric Andersene7047882003-12-11 01:42:13 +000094#define insmod_ng_main insmod_main
95#endif
96
Eric Andersene7047882003-12-11 01:42:13 +000097#if defined(CONFIG_FEATURE_2_6_MODULES)
98extern int insmod_ng_main( int argc, char **argv);
99#endif
100
Eric Andersencb3b9b12004-06-22 11:50:52 +0000101
102#if defined(CONFIG_FEATURE_2_4_MODULES)
103
Eric Andersen64c8b172001-04-05 07:33:10 +0000104
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000105#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000106#define LOADBITS 0
Eric Andersen8ae319a2001-05-21 16:09:18 +0000107#else
108#define LOADBITS 1
109#endif
110
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000111
Mike Frysinger63654c12004-12-26 09:13:32 +0000112/* Alpha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000113#if defined(__alpha__)
Mike Frysinger63654c12004-12-26 09:13:32 +0000114#define MATCH_MACHINE(x) (x == EM_ALPHA)
115#define SHT_RELM SHT_RELA
116#define Elf64_RelM Elf64_Rela
117#define ELFCLASSM ELFCLASS64
118#endif
119
Eric Andersen45a05132004-09-02 23:03:25 +0000120/* ARM support */
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000121#if defined(__arm__)
Eric Andersencffd5022002-05-24 06:50:15 +0000122#define MATCH_MACHINE(x) (x == EM_ARM)
123#define SHT_RELM SHT_REL
124#define Elf32_RelM Elf32_Rel
125#define ELFCLASSM ELFCLASS32
Eric Andersenc3b2dbe2003-03-13 18:57:08 +0000126#define CONFIG_USE_PLT_ENTRIES
127#define CONFIG_PLT_ENTRY_SIZE 8
128#define CONFIG_USE_GOT_ENTRIES
129#define CONFIG_GOT_ENTRY_SIZE 8
130#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000131#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000132
Eric Andersen45a05132004-09-02 23:03:25 +0000133/* CRIS */
134#if defined(__cris__)
135#define MATCH_MACHINE(x) (x == EM_CRIS)
Eric Andersenbf77f612003-01-23 06:02:39 +0000136#define SHT_RELM SHT_RELA
137#define Elf32_RelM Elf32_Rela
138#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000139#ifndef EM_CRIS
140#define EM_CRIS 76
141#define R_CRIS_NONE 0
142#define R_CRIS_32 3
143#endif
Eric Andersenbf77f612003-01-23 06:02:39 +0000144#endif
145
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000146/* H8/300 */
147#if defined(__H8300H__) || defined(__H8300S__)
148#define MATCH_MACHINE(x) (x == EM_H8_300)
149#define SHT_RELM SHT_RELA
150#define Elf32_RelM Elf32_Rela
151#define ELFCLASSM ELFCLASS32
152#define CONFIG_USE_SINGLE
153#define SYMBOL_PREFIX "_"
154#endif
155
Mike Frysinger63654c12004-12-26 09:13:32 +0000156/* PA-RISC / HP-PA */
157#if defined(__hppa__)
158#define MATCH_MACHINE(x) (x == EM_PARISC)
159#define SHT_RELM SHT_RELA
160#if defined(__LP64__)
161#define Elf64_RelM Elf64_Rela
162#define ELFCLASSM ELFCLASS64
163#else
164#define Elf32_RelM Elf32_Rela
165#define ELFCLASSM ELFCLASS32
166#endif
167#endif
168
Eric Andersen45a05132004-09-02 23:03:25 +0000169/* x86 */
170#if defined(__i386__)
Eric Andersencffd5022002-05-24 06:50:15 +0000171#ifndef EM_486
172#define MATCH_MACHINE(x) (x == EM_386)
173#else
174#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
175#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000176#define SHT_RELM SHT_REL
177#define Elf32_RelM Elf32_Rel
178#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000179#define CONFIG_USE_GOT_ENTRIES
180#define CONFIG_GOT_ENTRY_SIZE 4
181#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000182#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000183
Eric Andersen45a05132004-09-02 23:03:25 +0000184/* IA64, aka Itanium */
185#if defined(__ia64__)
186#define MATCH_MACHINE(x) (x == EM_IA_64)
187#define SHT_RELM SHT_RELA
188#define Elf64_RelM Elf64_Rela
189#define ELFCLASSM ELFCLASS64
190#endif
191
192/* m68k */
193#if defined(__mc68000__)
Eric Andersencffd5022002-05-24 06:50:15 +0000194#define MATCH_MACHINE(x) (x == EM_68K)
195#define SHT_RELM SHT_RELA
196#define Elf32_RelM Elf32_Rela
Eric Andersen9e458f52004-03-19 12:17:04 +0000197#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000198#define CONFIG_USE_GOT_ENTRIES
199#define CONFIG_GOT_ENTRY_SIZE 4
200#define CONFIG_USE_SINGLE
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000201#endif
202
Eric Andersen45a05132004-09-02 23:03:25 +0000203/* MIPS */
Eric Andersen2bf658d2001-02-24 20:01:53 +0000204#if defined(__mips__)
Eric Andersen45a05132004-09-02 23:03:25 +0000205#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
206#define SHT_RELM SHT_REL
207#define Elf32_RelM Elf32_Rel
208#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000209/* Account for ELF spec changes. */
210#ifndef EM_MIPS_RS3_LE
211#ifdef EM_MIPS_RS4_BE
212#define EM_MIPS_RS3_LE EM_MIPS_RS4_BE
213#else
214#define EM_MIPS_RS3_LE 10
215#endif
216#endif /* !EM_MIPS_RS3_LE */
Eric Andersencffd5022002-05-24 06:50:15 +0000217#define ARCHDATAM "__dbe_table"
218#endif
219
Mike Frysingerf982d862006-01-04 00:11:26 +0000220/* Nios II */
221#if defined(__nios2__)
222#define MATCH_MACHINE(x) (x == EM_ALTERA_NIOS2)
223#define SHT_RELM SHT_RELA
224#define Elf32_RelM Elf32_Rela
225#define ELFCLASSM ELFCLASS32
226#endif
227
Eric Andersen45a05132004-09-02 23:03:25 +0000228/* PowerPC */
Mike Frysingerbc48ebd2005-09-14 00:07:26 +0000229#if defined(__powerpc64__)
230#define MATCH_MACHINE(x) (x == EM_PPC64)
231#define SHT_RELM SHT_RELA
232#define Elf64_RelM Elf64_Rela
233#define ELFCLASSM ELFCLASS64
234#elif defined(__powerpc__)
Eric Andersen45a05132004-09-02 23:03:25 +0000235#define MATCH_MACHINE(x) (x == EM_PPC)
236#define SHT_RELM SHT_RELA
237#define Elf32_RelM Elf32_Rela
238#define ELFCLASSM ELFCLASS32
Eric Andersencffd5022002-05-24 06:50:15 +0000239#define CONFIG_USE_PLT_ENTRIES
240#define CONFIG_PLT_ENTRY_SIZE 16
241#define CONFIG_USE_PLT_LIST
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000242#define CONFIG_LIST_ARCHTYPE ElfW(Addr)
Eric Andersencffd5022002-05-24 06:50:15 +0000243#define CONFIG_USE_LIST
Eric Andersencffd5022002-05-24 06:50:15 +0000244#define ARCHDATAM "__ftr_fixup"
245#endif
246
Eric Andersen45a05132004-09-02 23:03:25 +0000247/* S390 */
248#if defined(__s390__)
249#define MATCH_MACHINE(x) (x == EM_S390)
250#define SHT_RELM SHT_RELA
251#define Elf32_RelM Elf32_Rela
252#define ELFCLASSM ELFCLASS32
253#define CONFIG_USE_PLT_ENTRIES
254#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000255#define CONFIG_USE_GOT_ENTRIES
Eric Andersen45a05132004-09-02 23:03:25 +0000256#define CONFIG_GOT_ENTRY_SIZE 8
Eric Andersencffd5022002-05-24 06:50:15 +0000257#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000258#endif
Eric Andersencffd5022002-05-24 06:50:15 +0000259
Eric Andersen45a05132004-09-02 23:03:25 +0000260/* SuperH */
261#if defined(__sh__)
Eric Andersencffd5022002-05-24 06:50:15 +0000262#define MATCH_MACHINE(x) (x == EM_SH)
263#define SHT_RELM SHT_RELA
264#define Elf32_RelM Elf32_Rela
265#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000266#define CONFIG_USE_GOT_ENTRIES
267#define CONFIG_GOT_ENTRY_SIZE 4
268#define CONFIG_USE_SINGLE
Eric Andersenbf833552003-08-13 19:56:33 +0000269/* the SH changes have only been tested in =little endian= mode */
Eric Andersencffd5022002-05-24 06:50:15 +0000270/* I'm not sure about big endian, so let's warn: */
Rob Landley688ed0d2006-03-04 22:40:25 +0000271#if defined(__sh__) && BB_BIG_ENDIAN
272# error insmod.c may require changes for use on big endian SH
Eric Andersencffd5022002-05-24 06:50:15 +0000273#endif
Eric Andersen45a05132004-09-02 23:03:25 +0000274/* it may or may not work on the SH1/SH2... Error on those also */
275#if ((!(defined(__SH3__) || defined(__SH4__) || defined(__SH5__)))) && (defined(__sh__))
Eric Andersenbf833552003-08-13 19:56:33 +0000276#error insmod.c may require changes for SH1 or SH2 use
Eric Andersencffd5022002-05-24 06:50:15 +0000277#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000278#endif
279
Eric Andersen45a05132004-09-02 23:03:25 +0000280/* Sparc */
281#if defined(__sparc__)
282#define MATCH_MACHINE(x) (x == EM_SPARC)
283#define SHT_RELM SHT_RELA
284#define Elf32_RelM Elf32_Rela
285#define ELFCLASSM ELFCLASS32
Miles Baderae28b042002-04-01 09:34:25 +0000286#endif
287
Eric Andersen45a05132004-09-02 23:03:25 +0000288/* v850e */
289#if defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +0000290#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
291#define SHT_RELM SHT_RELA
292#define Elf32_RelM Elf32_Rela
293#define ELFCLASSM ELFCLASS32
Eric Andersen45a05132004-09-02 23:03:25 +0000294#define CONFIG_USE_PLT_ENTRIES
295#define CONFIG_PLT_ENTRY_SIZE 8
Eric Andersenee70fa52004-05-26 11:38:46 +0000296#define CONFIG_USE_SINGLE
Eric Andersen45a05132004-09-02 23:03:25 +0000297#ifndef EM_CYGNUS_V850 /* grumble */
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000298#define EM_CYGNUS_V850 0x9080
Eric Andersen45a05132004-09-02 23:03:25 +0000299#endif
Eric Andersenee70fa52004-05-26 11:38:46 +0000300#define SYMBOL_PREFIX "_"
301#endif
302
Eric Andersen45a05132004-09-02 23:03:25 +0000303/* X86_64 */
304#if defined(__x86_64__)
305#define MATCH_MACHINE(x) (x == EM_X86_64)
Mike Frysinger354b5272005-03-30 06:29:41 +0000306#define SHT_RELM SHT_RELA
Mike Frysinger91fbdac2005-10-02 06:44:39 +0000307#define CONFIG_USE_GOT_ENTRIES
308#define CONFIG_GOT_ENTRY_SIZE 8
309#define CONFIG_USE_SINGLE
Mike Frysinger354b5272005-03-30 06:29:41 +0000310#define Elf64_RelM Elf64_Rela
Eric Andersen45a05132004-09-02 23:03:25 +0000311#define ELFCLASSM ELFCLASS64
312#endif
313
Eric Andersencffd5022002-05-24 06:50:15 +0000314#ifndef SHT_RELM
315#error Sorry, but insmod.c does not yet support this architecture...
316#endif
317
318
Eric Andersen9f16d612000-06-12 23:11:16 +0000319//----------------------------------------------------------------------------
320//--------modutils module.h, lines 45-242
321//----------------------------------------------------------------------------
322
323/* Definitions for the Linux module syscall interface.
324 Copyright 1996, 1997 Linux International.
325
326 Contributed by Richard Henderson <rth@tamu.edu>
327
328 This file is part of the Linux modutils.
329
330 This program is free software; you can redistribute it and/or modify it
331 under the terms of the GNU General Public License as published by the
332 Free Software Foundation; either version 2 of the License, or (at your
333 option) any later version.
334
335 This program is distributed in the hope that it will be useful, but
336 WITHOUT ANY WARRANTY; without even the implied warranty of
337 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
338 General Public License for more details.
339
340 You should have received a copy of the GNU General Public License
341 along with this program; if not, write to the Free Software Foundation,
342 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
343
344
345#ifndef MODUTILS_MODULE_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000346/* Why? static const int MODUTILS_MODULE_H = 1;*/
Eric Andersen9f16d612000-06-12 23:11:16 +0000347
Mike Frysinger63654c12004-12-26 09:13:32 +0000348#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000349
350/*======================================================================*/
351/* For sizeof() which are related to the module platform and not to the
352 environment isnmod is running in, use sizeof_xx instead of sizeof(xx). */
353
354#define tgt_sizeof_char sizeof(char)
355#define tgt_sizeof_short sizeof(short)
356#define tgt_sizeof_int sizeof(int)
357#define tgt_sizeof_long sizeof(long)
358#define tgt_sizeof_char_p sizeof(char *)
359#define tgt_sizeof_void_p sizeof(void *)
360#define tgt_long long
361
362#if defined(__sparc__) && !defined(__sparc_v9__) && defined(ARCH_sparc64)
363#undef tgt_sizeof_long
364#undef tgt_sizeof_char_p
365#undef tgt_sizeof_void_p
366#undef tgt_long
Rob Landleybc68cd12006-03-10 19:22:06 +0000367enum {
368 tgt_sizeof_long = 8,
369 tgt_sizeof_char_p = 8,
370 tgt_sizeof_void_p = 8
371};
Eric Andersen9f16d612000-06-12 23:11:16 +0000372#define tgt_long long long
373#endif
374
375/*======================================================================*/
376/* The structures used in Linux 2.1. */
377
378/* Note: new_module_symbol does not use tgt_long intentionally */
379struct new_module_symbol
380{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000381 unsigned long value;
382 unsigned long name;
Eric Andersen9f16d612000-06-12 23:11:16 +0000383};
384
385struct new_module_persist;
386
387struct new_module_ref
388{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000389 unsigned tgt_long dep; /* kernel addresses */
390 unsigned tgt_long ref;
391 unsigned tgt_long next_ref;
Eric Andersen9f16d612000-06-12 23:11:16 +0000392};
393
394struct new_module
395{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000396 unsigned tgt_long size_of_struct; /* == sizeof(module) */
397 unsigned tgt_long next;
398 unsigned tgt_long name;
399 unsigned tgt_long size;
Eric Andersen9f16d612000-06-12 23:11:16 +0000400
Eric Andersen3b1a7442003-12-24 20:30:45 +0000401 tgt_long usecount;
402 unsigned tgt_long flags; /* AUTOCLEAN et al */
Eric Andersen9f16d612000-06-12 23:11:16 +0000403
Eric Andersen3b1a7442003-12-24 20:30:45 +0000404 unsigned nsyms;
405 unsigned ndeps;
Eric Andersen9f16d612000-06-12 23:11:16 +0000406
Eric Andersen3b1a7442003-12-24 20:30:45 +0000407 unsigned tgt_long syms;
408 unsigned tgt_long deps;
409 unsigned tgt_long refs;
410 unsigned tgt_long init;
411 unsigned tgt_long cleanup;
412 unsigned tgt_long ex_table_start;
413 unsigned tgt_long ex_table_end;
Eric Andersen9f16d612000-06-12 23:11:16 +0000414#ifdef __alpha__
Eric Andersen3b1a7442003-12-24 20:30:45 +0000415 unsigned tgt_long gp;
Eric Andersen9f16d612000-06-12 23:11:16 +0000416#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +0000417 /* Everything after here is extension. */
418 unsigned tgt_long persist_start;
419 unsigned tgt_long persist_end;
420 unsigned tgt_long can_unload;
421 unsigned tgt_long runsize;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000422 const char *kallsyms_start; /* All symbols for kernel debugging */
423 const char *kallsyms_end;
424 const char *archdata_start; /* arch specific data for module */
425 const char *archdata_end;
426 const char *kernel_data; /* Reserved for kernel internal use */
Eric Andersen9f16d612000-06-12 23:11:16 +0000427};
428
Eric Andersencffd5022002-05-24 06:50:15 +0000429#ifdef ARCHDATAM
430#define ARCHDATA_SEC_NAME ARCHDATAM
431#else
Eric Andersen8ae319a2001-05-21 16:09:18 +0000432#define ARCHDATA_SEC_NAME "__archdata"
Eric Andersencffd5022002-05-24 06:50:15 +0000433#endif
Eric Andersen8ae319a2001-05-21 16:09:18 +0000434#define KALLSYMS_SEC_NAME "__kallsyms"
435
436
Eric Andersen9f16d612000-06-12 23:11:16 +0000437struct new_module_info
438{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000439 unsigned long addr;
440 unsigned long size;
441 unsigned long flags;
442 long usecount;
Eric Andersen9f16d612000-06-12 23:11:16 +0000443};
444
445/* Bits of module.flags. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000446enum {
447 NEW_MOD_RUNNING = 1,
448 NEW_MOD_DELETED = 2,
449 NEW_MOD_AUTOCLEAN = 4,
450 NEW_MOD_VISITED = 8,
451 NEW_MOD_USED_ONCE = 16
452};
Eric Andersen9f16d612000-06-12 23:11:16 +0000453
Eric Andersencb3b9b12004-06-22 11:50:52 +0000454int init_module(const char *name, const struct new_module *);
455int query_module(const char *name, int which, void *buf,
456 size_t bufsize, size_t *ret);
Eric Andersen9f16d612000-06-12 23:11:16 +0000457
458/* Values for query_module's which. */
Rob Landleybc68cd12006-03-10 19:22:06 +0000459enum {
460 QM_MODULES = 1,
461 QM_DEPS = 2,
462 QM_REFS = 3,
463 QM_SYMBOLS = 4,
464 QM_INFO = 5
465};
Eric Andersen9f16d612000-06-12 23:11:16 +0000466
467/*======================================================================*/
468/* The system calls unchanged between 2.0 and 2.1. */
469
470unsigned long create_module(const char *, size_t);
471int delete_module(const char *);
472
473
474#endif /* module.h */
475
476//----------------------------------------------------------------------------
477//--------end of modutils module.h
478//----------------------------------------------------------------------------
479
480
481
482//----------------------------------------------------------------------------
483//--------modutils obj.h, lines 253-462
484//----------------------------------------------------------------------------
485
486/* Elf object file loading and relocation routines.
487 Copyright 1996, 1997 Linux International.
488
489 Contributed by Richard Henderson <rth@tamu.edu>
490
491 This file is part of the Linux modutils.
492
493 This program is free software; you can redistribute it and/or modify it
494 under the terms of the GNU General Public License as published by the
495 Free Software Foundation; either version 2 of the License, or (at your
496 option) any later version.
497
498 This program is distributed in the hope that it will be useful, but
499 WITHOUT ANY WARRANTY; without even the implied warranty of
500 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
501 General Public License for more details.
502
503 You should have received a copy of the GNU General Public License
504 along with this program; if not, write to the Free Software Foundation,
505 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
506
507
508#ifndef MODUTILS_OBJ_H
Rob Landleybc68cd12006-03-10 19:22:06 +0000509/* Why? static const int MODUTILS_OBJ_H = 1; */
Eric Andersen9f16d612000-06-12 23:11:16 +0000510
Mike Frysinger63654c12004-12-26 09:13:32 +0000511#ident "$Id: insmod.c,v 1.126 2004/12/26 09:13:32 vapier Exp $"
Eric Andersen9f16d612000-06-12 23:11:16 +0000512
513/* The relocatable object is manipulated using elfin types. */
514
515#include <stdio.h>
516#include <elf.h>
Eric Andersenb1591d12002-04-12 00:28:59 +0000517#include <endian.h>
518
Eric Andersen9f16d612000-06-12 23:11:16 +0000519#ifndef ElfW
520# if ELFCLASSM == ELFCLASS32
521# define ElfW(x) Elf32_ ## x
522# define ELFW(x) ELF32_ ## x
523# else
524# define ElfW(x) Elf64_ ## x
525# define ELFW(x) ELF64_ ## x
526# endif
527#endif
528
Eric Andersen85e5e722003-07-22 08:56:55 +0000529/* For some reason this is missing from some ancient C libraries.... */
Eric Andersen9f16d612000-06-12 23:11:16 +0000530#ifndef ELF32_ST_INFO
531# define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
532#endif
533
534#ifndef ELF64_ST_INFO
535# define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
536#endif
537
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000538#define ELF_ST_BIND(info) ELFW(ST_BIND)(info)
539#define ELF_ST_TYPE(info) ELFW(ST_TYPE)(info)
540#define ELF_ST_INFO(bind, type) ELFW(ST_INFO)(bind, type)
541#define ELF_R_TYPE(val) ELFW(R_TYPE)(val)
542#define ELF_R_SYM(val) ELFW(R_SYM)(val)
543
Eric Andersen9f16d612000-06-12 23:11:16 +0000544struct obj_string_patch;
545struct obj_symbol_patch;
546
547struct obj_section
548{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000549 ElfW(Shdr) header;
550 const char *name;
551 char *contents;
552 struct obj_section *load_next;
553 int idx;
Eric Andersen9f16d612000-06-12 23:11:16 +0000554};
555
556struct obj_symbol
557{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000558 struct obj_symbol *next; /* hash table link */
559 const char *name;
560 unsigned long value;
561 unsigned long size;
562 int secidx; /* the defining section index/module */
563 int info;
564 int ksymidx; /* for export to the kernel symtab */
565 int referenced; /* actually used in the link */
Eric Andersen9f16d612000-06-12 23:11:16 +0000566};
567
568/* Hardcode the hash table size. We shouldn't be needing so many
569 symbols that we begin to degrade performance, and we get a big win
570 by giving the compiler a constant divisor. */
571
572#define HASH_BUCKETS 521
573
574struct obj_file
575{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000576 ElfW(Ehdr) header;
577 ElfW(Addr) baseaddr;
578 struct obj_section **sections;
579 struct obj_section *load_order;
580 struct obj_section **load_order_search_start;
581 struct obj_string_patch *string_patches;
582 struct obj_symbol_patch *symbol_patches;
583 int (*symbol_cmp)(const char *, const char *);
584 unsigned long (*symbol_hash)(const char *);
585 unsigned long local_symtab_size;
586 struct obj_symbol **local_symtab;
587 struct obj_symbol *symtab[HASH_BUCKETS];
Eric Andersen9f16d612000-06-12 23:11:16 +0000588};
589
590enum obj_reloc
591{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000592 obj_reloc_ok,
593 obj_reloc_overflow,
594 obj_reloc_dangerous,
595 obj_reloc_unhandled
Eric Andersen9f16d612000-06-12 23:11:16 +0000596};
597
598struct obj_string_patch
599{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000600 struct obj_string_patch *next;
601 int reloc_secidx;
602 ElfW(Addr) reloc_offset;
603 ElfW(Addr) string_offset;
Eric Andersen9f16d612000-06-12 23:11:16 +0000604};
605
606struct obj_symbol_patch
607{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000608 struct obj_symbol_patch *next;
609 int reloc_secidx;
610 ElfW(Addr) reloc_offset;
611 struct obj_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000612};
613
614
615/* Generic object manipulation routines. */
616
Eric Andersen044228d2001-07-17 01:12:36 +0000617static unsigned long obj_elf_hash(const char *);
Eric Andersen9f16d612000-06-12 23:11:16 +0000618
Eric Andersen044228d2001-07-17 01:12:36 +0000619static unsigned long obj_elf_hash_n(const char *, unsigned long len);
Eric Andersen9f16d612000-06-12 23:11:16 +0000620
Eric Andersen044228d2001-07-17 01:12:36 +0000621static struct obj_symbol *obj_find_symbol (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000622 const char *name);
623
Eric Andersen044228d2001-07-17 01:12:36 +0000624static ElfW(Addr) obj_symbol_final_value(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000625 struct obj_symbol *sym);
626
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000627#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen044228d2001-07-17 01:12:36 +0000628static void obj_set_symbol_compare(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000629 int (*cmp)(const char *, const char *),
630 unsigned long (*hash)(const char *));
Eric Andersenf672c9e2001-07-31 22:51:49 +0000631#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000632
Eric Andersen044228d2001-07-17 01:12:36 +0000633static struct obj_section *obj_find_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000634 const char *name);
635
Eric Andersen044228d2001-07-17 01:12:36 +0000636static void obj_insert_section_load_order (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000637 struct obj_section *sec);
638
Eric Andersen044228d2001-07-17 01:12:36 +0000639static struct obj_section *obj_create_alloced_section (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000640 const char *name,
641 unsigned long align,
642 unsigned long size);
643
Eric Andersen044228d2001-07-17 01:12:36 +0000644static struct obj_section *obj_create_alloced_section_first (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000645 const char *name,
646 unsigned long align,
647 unsigned long size);
648
Eric Andersen044228d2001-07-17 01:12:36 +0000649static void *obj_extend_section (struct obj_section *sec, unsigned long more);
Eric Andersen9f16d612000-06-12 23:11:16 +0000650
Eric Andersen044228d2001-07-17 01:12:36 +0000651static int obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000652 const char *string);
653
Eric Andersen044228d2001-07-17 01:12:36 +0000654static int obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
Eric Andersen9f16d612000-06-12 23:11:16 +0000655 struct obj_symbol *sym);
656
Eric Andersen044228d2001-07-17 01:12:36 +0000657static int obj_check_undefineds(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000658
Eric Andersen044228d2001-07-17 01:12:36 +0000659static void obj_allocate_commons(struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000660
Eric Andersen044228d2001-07-17 01:12:36 +0000661static unsigned long obj_load_size (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000662
Eric Andersen044228d2001-07-17 01:12:36 +0000663static int obj_relocate (struct obj_file *f, ElfW(Addr) base);
Eric Andersen9f16d612000-06-12 23:11:16 +0000664
Eric Andersen044228d2001-07-17 01:12:36 +0000665static struct obj_file *obj_load(FILE *f, int loadprogbits);
Eric Andersen9f16d612000-06-12 23:11:16 +0000666
Eric Andersen044228d2001-07-17 01:12:36 +0000667static int obj_create_image (struct obj_file *f, char *image);
Eric Andersen9f16d612000-06-12 23:11:16 +0000668
669/* Architecture specific manipulation routines. */
670
Eric Andersen044228d2001-07-17 01:12:36 +0000671static struct obj_file *arch_new_file (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000672
Eric Andersen044228d2001-07-17 01:12:36 +0000673static struct obj_section *arch_new_section (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000674
Eric Andersen044228d2001-07-17 01:12:36 +0000675static struct obj_symbol *arch_new_symbol (void);
Eric Andersen9f16d612000-06-12 23:11:16 +0000676
Eric Andersen044228d2001-07-17 01:12:36 +0000677static enum obj_reloc arch_apply_relocation (struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +0000678 struct obj_section *targsec,
679 struct obj_section *symsec,
680 struct obj_symbol *sym,
681 ElfW(RelM) *rel, ElfW(Addr) value);
682
Eric Andersencffd5022002-05-24 06:50:15 +0000683static void arch_create_got (struct obj_file *f);
Eric Andersen9f16d612000-06-12 23:11:16 +0000684
Glenn L McGrath759515c2003-08-30 06:00:33 +0000685static int obj_gpl_license(struct obj_file *f, const char **license);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000686
Eric Andersen9f16d612000-06-12 23:11:16 +0000687#endif /* obj.h */
688//----------------------------------------------------------------------------
689//--------end of modutils obj.h
690//----------------------------------------------------------------------------
691
692
Miles Baderae28b042002-04-01 09:34:25 +0000693/* SPFX is always a string, so it can be concatenated to string constants. */
694#ifdef SYMBOL_PREFIX
695#define SPFX SYMBOL_PREFIX
696#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000697#define SPFX ""
Miles Baderae28b042002-04-01 09:34:25 +0000698#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000699
Erik Andersen02104321999-12-17 18:57:34 +0000700
Erik Andersend387d011999-12-21 02:55:11 +0000701#define _PATH_MODULES "/lib/modules"
Rob Landleybc68cd12006-03-10 19:22:06 +0000702enum { STRVERSIONLEN = 32 };
Erik Andersend387d011999-12-21 02:55:11 +0000703
Eric Andersen9f16d612000-06-12 23:11:16 +0000704/*======================================================================*/
705
Eric Andersen044228d2001-07-17 01:12:36 +0000706static int flag_force_load = 0;
707static int flag_autoclean = 0;
708static int flag_verbose = 0;
Eric Andersenb493dec2002-07-02 19:14:23 +0000709static int flag_quiet = 0;
Eric Andersen044228d2001-07-17 01:12:36 +0000710static int flag_export = 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000711
712
713/*======================================================================*/
714
Eric Andersencffd5022002-05-24 06:50:15 +0000715#if defined(CONFIG_USE_LIST)
Eric Andersenfe4208f2000-09-24 03:44:29 +0000716
Eric Andersencffd5022002-05-24 06:50:15 +0000717struct arch_list_entry
Eric Andersen21adca72000-12-06 18:18:26 +0000718{
Eric Andersencffd5022002-05-24 06:50:15 +0000719 struct arch_list_entry *next;
720 CONFIG_LIST_ARCHTYPE addend;
721 int offset;
722 int inited : 1;
Eric Andersen21adca72000-12-06 18:18:26 +0000723};
Eric Andersencffd5022002-05-24 06:50:15 +0000724
Eric Andersen21adca72000-12-06 18:18:26 +0000725#endif
726
Eric Andersencffd5022002-05-24 06:50:15 +0000727#if defined(CONFIG_USE_SINGLE)
728
729struct arch_single_entry
730{
Eric Andersen9f16d612000-06-12 23:11:16 +0000731 int offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000732 int inited : 1;
733 int allocated : 1;
Eric Andersen9f16d612000-06-12 23:11:16 +0000734};
Eric Andersencffd5022002-05-24 06:50:15 +0000735
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000736#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000737
Eric Andersen2bf658d2001-02-24 20:01:53 +0000738#if defined(__mips__)
739struct mips_hi16
740{
Eric Andersen3b1a7442003-12-24 20:30:45 +0000741 struct mips_hi16 *next;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000742 ElfW(Addr) *addr;
743 ElfW(Addr) value;
Eric Andersen2bf658d2001-02-24 20:01:53 +0000744};
745#endif
746
Eric Andersenfe4208f2000-09-24 03:44:29 +0000747struct arch_file {
Eric Andersen9f16d612000-06-12 23:11:16 +0000748 struct obj_file root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000749#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000750 struct obj_section *plt;
Eric Andersen21adca72000-12-06 18:18:26 +0000751#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000752#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen9f16d612000-06-12 23:11:16 +0000753 struct obj_section *got;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000754#endif
Eric Andersen2bf658d2001-02-24 20:01:53 +0000755#if defined(__mips__)
756 struct mips_hi16 *mips_hi16_list;
757#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000758};
759
Eric Andersenfe4208f2000-09-24 03:44:29 +0000760struct arch_symbol {
Eric Andersen9f16d612000-06-12 23:11:16 +0000761 struct obj_symbol root;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000762#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000763#if defined(CONFIG_USE_PLT_LIST)
764 struct arch_list_entry *pltent;
765#else
766 struct arch_single_entry pltent;
767#endif
Eric Andersen21adca72000-12-06 18:18:26 +0000768#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000769#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +0000770 struct arch_single_entry gotent;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000771#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000772};
773
774
Eric Andersen9f16d612000-06-12 23:11:16 +0000775struct external_module {
776 const char *name;
777 ElfW(Addr) addr;
778 int used;
779 size_t nsyms;
780 struct new_module_symbol *syms;
781};
782
Eric Andersen044228d2001-07-17 01:12:36 +0000783static struct new_module_symbol *ksyms;
784static size_t nksyms;
Eric Andersen9f16d612000-06-12 23:11:16 +0000785
Eric Andersen044228d2001-07-17 01:12:36 +0000786static struct external_module *ext_modules;
787static int n_ext_modules;
788static int n_ext_modules_used;
Erik Andersen02104321999-12-17 18:57:34 +0000789extern int delete_module(const char *);
Eric Andersena2a978a2001-04-05 06:08:14 +0000790
Eric Andersen61f83052002-06-22 17:15:42 +0000791static char *m_filename;
Robert Griebld378c312002-07-19 00:05:54 +0000792static char *m_fullName;
Erik Andersen02104321999-12-17 18:57:34 +0000793
Eric Andersenfe4208f2000-09-24 03:44:29 +0000794
Erik Andersen02104321999-12-17 18:57:34 +0000795
Eric Andersen9f16d612000-06-12 23:11:16 +0000796/*======================================================================*/
Erik Andersen02104321999-12-17 18:57:34 +0000797
Eric Andersen9f16d612000-06-12 23:11:16 +0000798
Eric Andersen14d35432001-05-14 17:07:32 +0000799static int check_module_name_match(const char *filename, struct stat *statbuf,
800 void *userdata)
Eric Andersen9f16d612000-06-12 23:11:16 +0000801{
Eric Andersen14d35432001-05-14 17:07:32 +0000802 char *fullname = (char *) userdata;
Eric Andersen9f16d612000-06-12 23:11:16 +0000803
Eric Andersen14d35432001-05-14 17:07:32 +0000804 if (fullname[0] == '\0')
Erik Andersene49d5ec2000-02-08 19:58:47 +0000805 return (FALSE);
806 else {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000807 char *tmp, *tmp1 = bb_xstrdup(filename);
808 tmp = bb_get_last_path_component(tmp1);
Eric Andersen14d35432001-05-14 17:07:32 +0000809 if (strcmp(tmp, fullname) == 0) {
810 free(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000811 /* Stop searching if we find a match */
Manuel Novoa III cad53642003-03-19 09:13:01 +0000812 m_filename = bb_xstrdup(filename);
Eric Andersen3f47c452004-04-06 11:56:26 +0000813 return (FALSE);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000814 }
Eric Andersen14d35432001-05-14 17:07:32 +0000815 free(tmp1);
Erik Andersend387d011999-12-21 02:55:11 +0000816 }
Eric Andersen3f47c452004-04-06 11:56:26 +0000817 return (TRUE);
Erik Andersend387d011999-12-21 02:55:11 +0000818}
819
Erik Andersen02104321999-12-17 18:57:34 +0000820
Eric Andersen9f16d612000-06-12 23:11:16 +0000821/*======================================================================*/
822
Eric Andersen044228d2001-07-17 01:12:36 +0000823static struct obj_file *arch_new_file(void)
Erik Andersen02104321999-12-17 18:57:34 +0000824{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000825 struct arch_file *f;
Eric Andersen9f16d612000-06-12 23:11:16 +0000826 f = xmalloc(sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000827
Eric Andersencffd5022002-05-24 06:50:15 +0000828 memset(f, 0, sizeof(*f));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000829
Eric Andersen9f16d612000-06-12 23:11:16 +0000830 return &f->root;
831}
832
Eric Andersen044228d2001-07-17 01:12:36 +0000833static struct obj_section *arch_new_section(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000834{
835 return xmalloc(sizeof(struct obj_section));
836}
837
Eric Andersen044228d2001-07-17 01:12:36 +0000838static struct obj_symbol *arch_new_symbol(void)
Eric Andersen9f16d612000-06-12 23:11:16 +0000839{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000840 struct arch_symbol *sym;
Eric Andersen9f16d612000-06-12 23:11:16 +0000841 sym = xmalloc(sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000842
Eric Andersencffd5022002-05-24 06:50:15 +0000843 memset(sym, 0, sizeof(*sym));
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000844
Eric Andersen9f16d612000-06-12 23:11:16 +0000845 return &sym->root;
846}
Eric Andersenfe4208f2000-09-24 03:44:29 +0000847
Eric Andersen044228d2001-07-17 01:12:36 +0000848static enum obj_reloc
Eric Andersen9f16d612000-06-12 23:11:16 +0000849arch_apply_relocation(struct obj_file *f,
850 struct obj_section *targsec,
851 struct obj_section *symsec,
852 struct obj_symbol *sym,
Mike Frysingerfa17c4b2005-10-02 07:14:06 +0000853 ElfW(RelM) *rel, ElfW(Addr) v)
Eric Andersen9f16d612000-06-12 23:11:16 +0000854{
Eric Andersenfe4208f2000-09-24 03:44:29 +0000855 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersencffd5022002-05-24 06:50:15 +0000856 enum obj_reloc ret = obj_reloc_ok;
Eric Andersen21adca72000-12-06 18:18:26 +0000857 ElfW(Addr) *loc = (ElfW(Addr) *) (targsec->contents + rel->r_offset);
858 ElfW(Addr) dot = targsec->header.sh_addr + rel->r_offset;
Eric Andersencffd5022002-05-24 06:50:15 +0000859#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
860 struct arch_symbol *isym = (struct arch_symbol *) sym;
861#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000862#if defined(__arm__) || defined(__i386__) || defined(__mc68000__) || defined(__sh__) || defined(__s390__)
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000863#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000864 ElfW(Addr) got = ifile->got ? ifile->got->header.sh_addr : 0;
Eric Andersen90fe7fe2001-02-20 20:47:08 +0000865#endif
Eric Andersen3496fdc2006-01-30 23:09:20 +0000866#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000867#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen21adca72000-12-06 18:18:26 +0000868 ElfW(Addr) plt = ifile->plt ? ifile->plt->header.sh_addr : 0;
Eric Andersen21adca72000-12-06 18:18:26 +0000869 unsigned long *ip;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000870# if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +0000871 struct arch_list_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000872# else
Eric Andersencffd5022002-05-24 06:50:15 +0000873 struct arch_single_entry *pe;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000874# endif
Eric Andersencffd5022002-05-24 06:50:15 +0000875#endif
Eric Andersen9f16d612000-06-12 23:11:16 +0000876
Mike Frysinger86a4bfb2005-10-02 07:02:16 +0000877 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersenfe4208f2000-09-24 03:44:29 +0000878
Eric Andersencffd5022002-05-24 06:50:15 +0000879#if defined(__arm__)
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000880
Eric Andersen3b1a7442003-12-24 20:30:45 +0000881 case R_ARM_NONE:
882 break;
Eric Andersen9f16d612000-06-12 23:11:16 +0000883
Eric Andersen3b1a7442003-12-24 20:30:45 +0000884 case R_ARM_ABS32:
885 *loc += v;
886 break;
Miles Baderae28b042002-04-01 09:34:25 +0000887
Eric Andersen3b1a7442003-12-24 20:30:45 +0000888 case R_ARM_GOT32:
889 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000890
Eric Andersen3b1a7442003-12-24 20:30:45 +0000891 case R_ARM_GOTPC:
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000892 /* relative reloc, always to _GLOBAL_OFFSET_TABLE_
893 * (which is .got) similar to branch,
Eric Andersen3b1a7442003-12-24 20:30:45 +0000894 * but is full 32 bits relative */
Eric Andersencffd5022002-05-24 06:50:15 +0000895
Eric Andersen3496fdc2006-01-30 23:09:20 +0000896 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000897 *loc += got - dot;
898 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000899
Eric Andersen3b1a7442003-12-24 20:30:45 +0000900 case R_ARM_PC24:
901 case R_ARM_PLT32:
902 goto bb_use_plt;
903
904 case R_ARM_GOTOFF: /* address relative to the got */
Eric Andersen3496fdc2006-01-30 23:09:20 +0000905 assert(got != 0);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000906 *loc += v - got;
907 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000908
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000909#elif defined(__cris__)
910
911 case R_CRIS_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +0000912 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000913
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000914 case R_CRIS_32:
915 /* CRIS keeps the relocation value in the r_addend field and
916 * should not use whats in *loc at all
917 */
Eric Andersen3b1a7442003-12-24 20:30:45 +0000918 *loc = v;
919 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000920
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000921#elif defined(__H8300H__) || defined(__H8300S__)
Eric Andersenbf77f612003-01-23 06:02:39 +0000922
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000923 case R_H8_DIR24R8:
924 loc = (ElfW(Addr) *)((ElfW(Addr))loc - 1);
925 *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
Eric Andersen3b1a7442003-12-24 20:30:45 +0000926 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000927 case R_H8_DIR24A8:
928 *loc += v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000929 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +0000930 case R_H8_DIR32:
931 case R_H8_DIR32A16:
932 *loc += v;
933 break;
934 case R_H8_PCREL16:
935 v -= dot + 2;
936 if ((ElfW(Sword))v > 0x7fff ||
937 (ElfW(Sword))v < -(ElfW(Sword))0x8000)
938 ret = obj_reloc_overflow;
939 else
940 *(unsigned short *)loc = v;
941 break;
942 case R_H8_PCREL8:
943 v -= dot + 1;
944 if ((ElfW(Sword))v > 0x7f ||
945 (ElfW(Sword))v < -(ElfW(Sword))0x80)
946 ret = obj_reloc_overflow;
947 else
948 *(unsigned char *)loc = v;
Eric Andersen3b1a7442003-12-24 20:30:45 +0000949 break;
Eric Andersenbf77f612003-01-23 06:02:39 +0000950
Eric Andersencffd5022002-05-24 06:50:15 +0000951#elif defined(__i386__)
952
Eric Andersen3b1a7442003-12-24 20:30:45 +0000953 case R_386_NONE:
954 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000955
Eric Andersen3b1a7442003-12-24 20:30:45 +0000956 case R_386_32:
957 *loc += v;
958 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000959
Eric Andersen3b1a7442003-12-24 20:30:45 +0000960 case R_386_PLT32:
961 case R_386_PC32:
962 *loc += v - dot;
963 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000964
Eric Andersen3b1a7442003-12-24 20:30:45 +0000965 case R_386_GLOB_DAT:
966 case R_386_JMP_SLOT:
967 *loc = v;
968 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000969
Eric Andersen3b1a7442003-12-24 20:30:45 +0000970 case R_386_RELATIVE:
971 *loc += f->baseaddr;
972 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000973
Eric Andersen3b1a7442003-12-24 20:30:45 +0000974 case R_386_GOTPC:
975 assert(got != 0);
976 *loc += got - dot;
977 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000978
Eric Andersen3b1a7442003-12-24 20:30:45 +0000979 case R_386_GOT32:
980 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +0000981
Eric Andersen3b1a7442003-12-24 20:30:45 +0000982 case R_386_GOTOFF:
983 assert(got != 0);
984 *loc += v - got;
985 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000986
987#elif defined(__mc68000__)
988
Eric Andersen3b1a7442003-12-24 20:30:45 +0000989 case R_68K_NONE:
990 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000991
Eric Andersen3b1a7442003-12-24 20:30:45 +0000992 case R_68K_32:
993 *loc += v;
994 break;
Eric Andersencffd5022002-05-24 06:50:15 +0000995
Eric Andersen3b1a7442003-12-24 20:30:45 +0000996 case R_68K_8:
997 if (v > 0xff) {
998 ret = obj_reloc_overflow;
999 }
1000 *(char *)loc = v;
1001 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001002
Eric Andersen3b1a7442003-12-24 20:30:45 +00001003 case R_68K_16:
1004 if (v > 0xffff) {
1005 ret = obj_reloc_overflow;
1006 }
1007 *(short *)loc = v;
1008 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001009
Eric Andersen3b1a7442003-12-24 20:30:45 +00001010 case R_68K_PC8:
1011 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001012 if ((ElfW(Sword))v > 0x7f ||
1013 (ElfW(Sword))v < -(ElfW(Sword))0x80) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001014 ret = obj_reloc_overflow;
1015 }
1016 *(char *)loc = v;
1017 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001018
Eric Andersen3b1a7442003-12-24 20:30:45 +00001019 case R_68K_PC16:
1020 v -= dot;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001021 if ((ElfW(Sword))v > 0x7fff ||
1022 (ElfW(Sword))v < -(ElfW(Sword))0x8000) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00001023 ret = obj_reloc_overflow;
1024 }
1025 *(short *)loc = v;
1026 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001027
Eric Andersen3b1a7442003-12-24 20:30:45 +00001028 case R_68K_PC32:
1029 *(int *)loc = v - dot;
1030 break;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001031
Eric Andersen3b1a7442003-12-24 20:30:45 +00001032 case R_68K_GLOB_DAT:
1033 case R_68K_JMP_SLOT:
1034 *loc = v;
1035 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001036
Eric Andersen3b1a7442003-12-24 20:30:45 +00001037 case R_68K_RELATIVE:
1038 *(int *)loc += f->baseaddr;
1039 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001040
Eric Andersen3b1a7442003-12-24 20:30:45 +00001041 case R_68K_GOT32:
1042 goto bb_use_got;
Eric Andersencffd5022002-05-24 06:50:15 +00001043
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001044# ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001045 case R_68K_GOTOFF:
1046 assert(got != 0);
1047 *loc += v - got;
1048 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001049# endif
Eric Andersencffd5022002-05-24 06:50:15 +00001050
1051#elif defined(__mips__)
1052
Eric Andersen3b1a7442003-12-24 20:30:45 +00001053 case R_MIPS_NONE:
1054 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001055
Eric Andersen3b1a7442003-12-24 20:30:45 +00001056 case R_MIPS_32:
1057 *loc += v;
1058 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001059
Eric Andersen3b1a7442003-12-24 20:30:45 +00001060 case R_MIPS_26:
1061 if (v % 4)
1062 ret = obj_reloc_dangerous;
1063 if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
1064 ret = obj_reloc_overflow;
1065 *loc =
1066 (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
1067 0x03ffffff);
1068 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001069
Eric Andersen3b1a7442003-12-24 20:30:45 +00001070 case R_MIPS_HI16:
1071 {
1072 struct mips_hi16 *n;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001073
Eric Andersen3b1a7442003-12-24 20:30:45 +00001074 /* We cannot relocate this one now because we don't know the value
1075 of the carry we need to add. Save the information, and let LO16
1076 do the actual relocation. */
1077 n = (struct mips_hi16 *) xmalloc(sizeof *n);
1078 n->addr = loc;
1079 n->value = v;
1080 n->next = ifile->mips_hi16_list;
1081 ifile->mips_hi16_list = n;
1082 break;
Eric Andersen2bf658d2001-02-24 20:01:53 +00001083 }
1084
Eric Andersen3b1a7442003-12-24 20:30:45 +00001085 case R_MIPS_LO16:
1086 {
1087 unsigned long insnlo = *loc;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001088 ElfW(Addr) val, vallo;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001089
1090 /* Sign extend the addend we extract from the lo insn. */
1091 vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
1092
1093 if (ifile->mips_hi16_list != NULL) {
1094 struct mips_hi16 *l;
1095
1096 l = ifile->mips_hi16_list;
1097 while (l != NULL) {
1098 struct mips_hi16 *next;
1099 unsigned long insn;
1100
1101 /* The value for the HI16 had best be the same. */
1102 assert(v == l->value);
1103
1104 /* Do the HI16 relocation. Note that we actually don't
1105 need to know anything about the LO16 itself, except where
1106 to find the low 16 bits of the addend needed by the LO16. */
1107 insn = *l->addr;
1108 val =
1109 ((insn & 0xffff) << 16) +
1110 vallo;
1111 val += v;
1112
1113 /* Account for the sign extension that will happen in the
1114 low bits. */
1115 val =
1116 ((val >> 16) +
1117 ((val & 0x8000) !=
1118 0)) & 0xffff;
1119
1120 insn = (insn & ~0xffff) | val;
1121 *l->addr = insn;
1122
1123 next = l->next;
1124 free(l);
1125 l = next;
1126 }
1127
1128 ifile->mips_hi16_list = NULL;
1129 }
1130
1131 /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
1132 val = v + vallo;
1133 insnlo = (insnlo & ~0xffff) | (val & 0xffff);
1134 *loc = insnlo;
1135 break;
1136 }
Eric Andersen2bf658d2001-02-24 20:01:53 +00001137
Mike Frysingerf982d862006-01-04 00:11:26 +00001138#elif defined(__nios2__)
1139
1140 case R_NIOS2_NONE:
1141 break;
1142
1143 case R_NIOS2_BFD_RELOC_32:
1144 *loc += v;
1145 break;
1146
1147 case R_NIOS2_BFD_RELOC_16:
1148 if (v > 0xffff) {
1149 ret = obj_reloc_overflow;
1150 }
1151 *(short *)loc = v;
1152 break;
1153
1154 case R_NIOS2_BFD_RELOC_8:
1155 if (v > 0xff) {
1156 ret = obj_reloc_overflow;
1157 }
1158 *(char *)loc = v;
1159 break;
1160
1161 case R_NIOS2_S16:
1162 {
1163 Elf32_Addr word;
1164
1165 if ((Elf32_Sword)v > 0x7fff ||
1166 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1167 ret = obj_reloc_overflow;
1168 }
1169
1170 word = *loc;
1171 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1172 (word & 0x3f);
1173 }
1174 break;
1175
1176 case R_NIOS2_U16:
1177 {
1178 Elf32_Addr word;
1179
1180 if (v > 0xffff) {
1181 ret = obj_reloc_overflow;
1182 }
1183
1184 word = *loc;
1185 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1186 (word & 0x3f);
1187 }
1188 break;
1189
1190 case R_NIOS2_PCREL16:
1191 {
1192 Elf32_Addr word;
1193
1194 v -= dot + 4;
1195 if ((Elf32_Sword)v > 0x7fff ||
1196 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1197 ret = obj_reloc_overflow;
1198 }
1199
1200 word = *loc;
1201 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1202 }
1203 break;
1204
1205 case R_NIOS2_GPREL:
1206 {
1207 Elf32_Addr word, gp;
1208 /* get _gp */
1209 gp = obj_symbol_final_value(f, obj_find_symbol(f, SPFX "_gp"));
1210 v-=gp;
1211 if ((Elf32_Sword)v > 0x7fff ||
1212 (Elf32_Sword)v < -(Elf32_Sword)0x8000) {
1213 ret = obj_reloc_overflow;
1214 }
1215
1216 word = *loc;
1217 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) | (word & 0x3f);
1218 }
1219 break;
1220
1221 case R_NIOS2_CALL26:
1222 if (v & 3)
1223 ret = obj_reloc_dangerous;
1224 if ((v >> 28) != (dot >> 28))
1225 ret = obj_reloc_overflow;
1226 *loc = (*loc & 0x3f) | ((v >> 2) << 6);
1227 break;
1228
1229 case R_NIOS2_IMM5:
1230 {
1231 Elf32_Addr word;
1232
1233 if (v > 0x1f) {
1234 ret = obj_reloc_overflow;
1235 }
1236
1237 word = *loc & ~0x7c0;
1238 *loc = word | ((v & 0x1f) << 6);
1239 }
1240 break;
1241
1242 case R_NIOS2_IMM6:
1243 {
1244 Elf32_Addr word;
1245
1246 if (v > 0x3f) {
1247 ret = obj_reloc_overflow;
1248 }
1249
1250 word = *loc & ~0xfc0;
1251 *loc = word | ((v & 0x3f) << 6);
1252 }
1253 break;
1254
1255 case R_NIOS2_IMM8:
1256 {
1257 Elf32_Addr word;
1258
1259 if (v > 0xff) {
1260 ret = obj_reloc_overflow;
1261 }
1262
1263 word = *loc & ~0x3fc0;
1264 *loc = word | ((v & 0xff) << 6);
1265 }
1266 break;
1267
1268 case R_NIOS2_HI16:
1269 {
1270 Elf32_Addr word;
1271
1272 word = *loc;
1273 *loc = ((((word >> 22) << 16) | ((v >>16) & 0xffff)) << 6) |
1274 (word & 0x3f);
1275 }
1276 break;
1277
1278 case R_NIOS2_LO16:
1279 {
1280 Elf32_Addr word;
1281
1282 word = *loc;
1283 *loc = ((((word >> 22) << 16) | (v & 0xffff)) << 6) |
1284 (word & 0x3f);
1285 }
1286 break;
1287
1288 case R_NIOS2_HIADJ16:
1289 {
1290 Elf32_Addr word1, word2;
1291
1292 word1 = *loc;
1293 word2 = ((v >> 16) + ((v >> 15) & 1)) & 0xffff;
1294 *loc = ((((word1 >> 22) << 16) | word2) << 6) |
1295 (word1 & 0x3f);
1296 }
1297 break;
1298
Mike Frysingerebee0e72006-02-18 06:14:31 +00001299#elif defined(__powerpc64__)
Rob Landleyb4ec3392006-02-20 14:39:55 +00001300 /* PPC64 needs a 2.6 kernel, 2.4 module relocation irrelevant */
Mike Frysingerebee0e72006-02-18 06:14:31 +00001301
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001302#elif defined(__powerpc__)
Eric Andersencffd5022002-05-24 06:50:15 +00001303
Eric Andersen3b1a7442003-12-24 20:30:45 +00001304 case R_PPC_ADDR16_HA:
1305 *(unsigned short *)loc = (v + 0x8000) >> 16;
1306 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001307
Eric Andersen3b1a7442003-12-24 20:30:45 +00001308 case R_PPC_ADDR16_HI:
1309 *(unsigned short *)loc = v >> 16;
1310 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001311
Eric Andersen3b1a7442003-12-24 20:30:45 +00001312 case R_PPC_ADDR16_LO:
1313 *(unsigned short *)loc = v;
1314 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001315
Eric Andersen3b1a7442003-12-24 20:30:45 +00001316 case R_PPC_REL24:
1317 goto bb_use_plt;
Eric Andersencffd5022002-05-24 06:50:15 +00001318
Eric Andersen3b1a7442003-12-24 20:30:45 +00001319 case R_PPC_REL32:
1320 *loc = v - dot;
1321 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001322
Eric Andersen3b1a7442003-12-24 20:30:45 +00001323 case R_PPC_ADDR32:
1324 *loc = v;
1325 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001326
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001327#elif defined(__s390__)
1328
1329 case R_390_32:
1330 *(unsigned int *) loc += v;
1331 break;
1332 case R_390_16:
1333 *(unsigned short *) loc += v;
1334 break;
1335 case R_390_8:
1336 *(unsigned char *) loc += v;
1337 break;
1338
1339 case R_390_PC32:
1340 *(unsigned int *) loc += v - dot;
1341 break;
1342 case R_390_PC16DBL:
1343 *(unsigned short *) loc += (v - dot) >> 1;
1344 break;
1345 case R_390_PC16:
1346 *(unsigned short *) loc += v - dot;
1347 break;
1348
1349 case R_390_PLT32:
1350 case R_390_PLT16DBL:
1351 /* find the plt entry and initialize it. */
1352 assert(isym != NULL);
1353 pe = (struct arch_single_entry *) &isym->pltent;
1354 assert(pe->allocated);
1355 if (pe->inited == 0) {
1356 ip = (unsigned long *)(ifile->plt->contents + pe->offset);
1357 ip[0] = 0x0d105810; /* basr 1,0; lg 1,10(1); br 1 */
1358 ip[1] = 0x100607f1;
1359 if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1360 ip[2] = v - 2;
1361 else
1362 ip[2] = v;
1363 pe->inited = 1;
1364 }
1365
1366 /* Insert relative distance to target. */
1367 v = plt + pe->offset - dot;
1368 if (ELF_R_TYPE(rel->r_info) == R_390_PLT32)
1369 *(unsigned int *) loc = (unsigned int) v;
1370 else if (ELF_R_TYPE(rel->r_info) == R_390_PLT16DBL)
1371 *(unsigned short *) loc = (unsigned short) ((v + 2) >> 1);
1372 break;
1373
1374 case R_390_GLOB_DAT:
1375 case R_390_JMP_SLOT:
1376 *loc = v;
1377 break;
1378
1379 case R_390_RELATIVE:
1380 *loc += f->baseaddr;
1381 break;
1382
1383 case R_390_GOTPC:
1384 assert(got != 0);
1385 *(unsigned long *) loc += got - dot;
1386 break;
1387
1388 case R_390_GOT12:
1389 case R_390_GOT16:
1390 case R_390_GOT32:
1391 assert(isym != NULL);
1392 assert(got != 0);
1393 if (!isym->gotent.inited)
1394 {
1395 isym->gotent.inited = 1;
1396 *(ElfW(Addr) *)(ifile->got->contents + isym->gotent.offset) = v;
1397 }
1398 if (ELF_R_TYPE(rel->r_info) == R_390_GOT12)
1399 *(unsigned short *) loc |= (*(unsigned short *) loc + isym->gotent.offset) & 0xfff;
1400 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT16)
1401 *(unsigned short *) loc += isym->gotent.offset;
1402 else if (ELF_R_TYPE(rel->r_info) == R_390_GOT32)
1403 *(unsigned int *) loc += isym->gotent.offset;
1404 break;
1405
1406# ifndef R_390_GOTOFF32
1407# define R_390_GOTOFF32 R_390_GOTOFF
1408# endif
1409 case R_390_GOTOFF32:
1410 assert(got != 0);
1411 *loc += v - got;
1412 break;
1413
Eric Andersencffd5022002-05-24 06:50:15 +00001414#elif defined(__sh__)
1415
Eric Andersen3b1a7442003-12-24 20:30:45 +00001416 case R_SH_NONE:
1417 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001418
Eric Andersen3b1a7442003-12-24 20:30:45 +00001419 case R_SH_DIR32:
1420 *loc += v;
1421 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001422
Eric Andersen3b1a7442003-12-24 20:30:45 +00001423 case R_SH_REL32:
1424 *loc += v - dot;
1425 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001426
Eric Andersen3b1a7442003-12-24 20:30:45 +00001427 case R_SH_PLT32:
1428 *loc = v - dot;
1429 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001430
Eric Andersen3b1a7442003-12-24 20:30:45 +00001431 case R_SH_GLOB_DAT:
1432 case R_SH_JMP_SLOT:
1433 *loc = v;
1434 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001435
Eric Andersen3b1a7442003-12-24 20:30:45 +00001436 case R_SH_RELATIVE:
1437 *loc = f->baseaddr + rel->r_addend;
1438 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001439
Eric Andersen3b1a7442003-12-24 20:30:45 +00001440 case R_SH_GOTPC:
1441 assert(got != 0);
1442 *loc = got - dot + rel->r_addend;
1443 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001444
Eric Andersen3b1a7442003-12-24 20:30:45 +00001445 case R_SH_GOT32:
1446 goto bb_use_got;
1447
1448 case R_SH_GOTOFF:
1449 assert(got != 0);
1450 *loc = v - got;
1451 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001452
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001453# if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001454 case R_SH_IMM_MEDLOW16:
1455 case R_SH_IMM_LOW16:
1456 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001457 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001458
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001459 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001460 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001461
Eric Andersen3b1a7442003-12-24 20:30:45 +00001462 /*
1463 * movi and shori have the format:
1464 *
1465 * | op | imm | reg | reserved |
1466 * 31..26 25..10 9.. 4 3 .. 0
1467 *
1468 * so we simply mask and or in imm.
1469 */
1470 word = *loc & ~0x3fffc00;
1471 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001472
Eric Andersen3b1a7442003-12-24 20:30:45 +00001473 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001474
Eric Andersen3b1a7442003-12-24 20:30:45 +00001475 break;
1476 }
Eric Andersenbf833552003-08-13 19:56:33 +00001477
Eric Andersen3b1a7442003-12-24 20:30:45 +00001478 case R_SH_IMM_MEDLOW16_PCREL:
1479 case R_SH_IMM_LOW16_PCREL:
1480 {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001481 ElfW(Addr) word;
Eric Andersenbf833552003-08-13 19:56:33 +00001482
Eric Andersen3b1a7442003-12-24 20:30:45 +00001483 word = *loc & ~0x3fffc00;
Eric Andersenbf833552003-08-13 19:56:33 +00001484
Eric Andersen3b1a7442003-12-24 20:30:45 +00001485 v -= dot;
Eric Andersenbf833552003-08-13 19:56:33 +00001486
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001487 if (ELF_R_TYPE(rel->r_info) == R_SH_IMM_MEDLOW16_PCREL)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001488 v >>= 16;
Eric Andersenbf833552003-08-13 19:56:33 +00001489
Eric Andersen3b1a7442003-12-24 20:30:45 +00001490 word |= (v & 0xffff) << 10;
Eric Andersenbf833552003-08-13 19:56:33 +00001491
Eric Andersen3b1a7442003-12-24 20:30:45 +00001492 *loc = word;
Eric Andersenbf833552003-08-13 19:56:33 +00001493
Eric Andersen3b1a7442003-12-24 20:30:45 +00001494 break;
1495 }
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001496# endif /* __SH5__ */
Eric Andersen9f16d612000-06-12 23:11:16 +00001497
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001498#elif defined (__v850e__)
Eric Andersencffd5022002-05-24 06:50:15 +00001499
Eric Andersen3b1a7442003-12-24 20:30:45 +00001500 case R_V850_NONE:
1501 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001502
Eric Andersen3b1a7442003-12-24 20:30:45 +00001503 case R_V850_32:
1504 /* We write two shorts instead of a long because even
1505 32-bit insns only need half-word alignment, but
1506 32-bit data needs to be long-word aligned. */
1507 v += ((unsigned short *)loc)[0];
1508 v += ((unsigned short *)loc)[1] << 16;
1509 ((unsigned short *)loc)[0] = v & 0xffff;
1510 ((unsigned short *)loc)[1] = (v >> 16) & 0xffff;
1511 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001512
Eric Andersen3b1a7442003-12-24 20:30:45 +00001513 case R_V850_22_PCREL:
1514 goto bb_use_plt;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001515
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001516#elif defined(__x86_64__)
Mike Frysingerc31fcbb2005-10-02 07:54:07 +00001517
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001518 case R_X86_64_NONE:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001519 break;
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001520
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001521 case R_X86_64_64:
1522 *loc += v;
1523 break;
1524
1525 case R_X86_64_32:
1526 *(unsigned int *) loc += v;
1527 if (v > 0xffffffff)
1528 {
1529 ret = obj_reloc_overflow; /* Kernel module compiled without -mcmodel=kernel. */
1530 /* error("Possibly is module compiled without -mcmodel=kernel!"); */
1531 }
1532 break;
1533
1534 case R_X86_64_32S:
1535 *(signed int *) loc += v;
1536 break;
1537
1538 case R_X86_64_16:
1539 *(unsigned short *) loc += v;
1540 break;
1541
1542 case R_X86_64_8:
1543 *(unsigned char *) loc += v;
1544 break;
1545
1546 case R_X86_64_PC32:
1547 *(unsigned int *) loc += v - dot;
1548 break;
1549
1550 case R_X86_64_PC16:
1551 *(unsigned short *) loc += v - dot;
1552 break;
1553
1554 case R_X86_64_PC8:
1555 *(unsigned char *) loc += v - dot;
1556 break;
1557
1558 case R_X86_64_GLOB_DAT:
1559 case R_X86_64_JUMP_SLOT:
Eric Andersen3b1a7442003-12-24 20:30:45 +00001560 *loc = v;
1561 break;
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001562
1563 case R_X86_64_RELATIVE:
1564 *loc += f->baseaddr;
1565 break;
1566
1567 case R_X86_64_GOT32:
1568 case R_X86_64_GOTPCREL:
1569 goto bb_use_got;
1570# if 0
1571 assert(isym != NULL);
1572 if (!isym->gotent.reloc_done)
1573 {
1574 isym->gotent.reloc_done = 1;
1575 *(Elf64_Addr *)(ifile->got->contents + isym->gotent.offset) = v;
1576 }
1577 /* XXX are these really correct? */
1578 if (ELF64_R_TYPE(rel->r_info) == R_X86_64_GOTPCREL)
1579 *(unsigned int *) loc += v + isym->gotent.offset;
1580 else
1581 *loc += isym->gotent.offset;
1582 break;
1583# endif
1584
Mike Frysingerf982d862006-01-04 00:11:26 +00001585#else
1586# warning "no idea how to handle relocations on your arch"
Manuel Novoa III 22e1ca32003-12-04 15:02:57 +00001587#endif
1588
Mike Frysingercb1ce7b2005-10-02 07:50:49 +00001589 default:
1590 printf("Warning: unhandled reloc %d\n",(int)ELF_R_TYPE(rel->r_info));
1591 ret = obj_reloc_unhandled;
Eric Andersenee70fa52004-05-26 11:38:46 +00001592 break;
Eric Andersenee70fa52004-05-26 11:38:46 +00001593
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001594#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001595
Eric Andersen3b1a7442003-12-24 20:30:45 +00001596bb_use_plt:
Eric Andersencffd5022002-05-24 06:50:15 +00001597
Eric Andersen3b1a7442003-12-24 20:30:45 +00001598 /* find the plt entry and initialize it if necessary */
1599 assert(isym != NULL);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001600
Eric Andersencffd5022002-05-24 06:50:15 +00001601#if defined(CONFIG_USE_PLT_LIST)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001602 for (pe = isym->pltent; pe != NULL && pe->addend != rel->r_addend;)
1603 pe = pe->next;
1604 assert(pe != NULL);
Eric Andersencffd5022002-05-24 06:50:15 +00001605#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001606 pe = &isym->pltent;
Eric Andersencffd5022002-05-24 06:50:15 +00001607#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001608
Eric Andersen3b1a7442003-12-24 20:30:45 +00001609 if (! pe->inited) {
1610 ip = (unsigned long *) (ifile->plt->contents + pe->offset);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001611
Eric Andersen3b1a7442003-12-24 20:30:45 +00001612 /* generate some machine code */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001613
1614#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001615 ip[0] = 0xe51ff004; /* ldr pc,[pc,#-4] */
1616 ip[1] = v; /* sym@ */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001617#endif
1618#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001619 ip[0] = 0x3d600000 + ((v + 0x8000) >> 16); /* lis r11,sym@ha */
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00001620 ip[1] = 0x396b0000 + (v & 0xffff); /* addi r11,r11,sym@l */
Eric Andersen3b1a7442003-12-24 20:30:45 +00001621 ip[2] = 0x7d6903a6; /* mtctr r11 */
1622 ip[3] = 0x4e800420; /* bctr */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001623#endif
Miles Baderae28b042002-04-01 09:34:25 +00001624#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001625 /* We have to trash a register, so we assume that any control
1626 transfer more than 21-bits away must be a function call
1627 (so we can use a call-clobbered register). */
1628 ip[0] = 0x0621 + ((v & 0xffff) << 16); /* mov sym, r1 ... */
1629 ip[1] = ((v >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
Miles Baderae28b042002-04-01 09:34:25 +00001630#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001631 pe->inited = 1;
1632 }
Eric Andersen21adca72000-12-06 18:18:26 +00001633
Eric Andersen3b1a7442003-12-24 20:30:45 +00001634 /* relative distance to target */
1635 v -= dot;
1636 /* if the target is too far away.... */
Miles Baderae28b042002-04-01 09:34:25 +00001637#if defined (__arm__) || defined (__powerpc__)
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001638 if ((int)v < -0x02000000 || (int)v >= 0x02000000)
Miles Baderae28b042002-04-01 09:34:25 +00001639#elif defined (__v850e__)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001640 if ((ElfW(Sword))v > 0x1fffff || (ElfW(Sword))v < (ElfW(Sword))-0x200000)
Miles Baderae28b042002-04-01 09:34:25 +00001641#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001642 /* go via the plt */
1643 v = plt + pe->offset - dot;
Miles Baderae28b042002-04-01 09:34:25 +00001644
1645#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001646 if (v & 1)
Miles Baderae28b042002-04-01 09:34:25 +00001647#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00001648 if (v & 3)
Miles Baderae28b042002-04-01 09:34:25 +00001649#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001650 ret = obj_reloc_dangerous;
Eric Andersen21adca72000-12-06 18:18:26 +00001651
Eric Andersen3b1a7442003-12-24 20:30:45 +00001652 /* merge the offset into the instruction. */
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001653#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001654 /* Convert to words. */
1655 v >>= 2;
Eric Andersen21adca72000-12-06 18:18:26 +00001656
Eric Andersen3b1a7442003-12-24 20:30:45 +00001657 *loc = (*loc & ~0x00ffffff) | ((v + *loc) & 0x00ffffff);
Eric Andersenfe4208f2000-09-24 03:44:29 +00001658#endif
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001659#if defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001660 *loc = (*loc & ~0x03fffffc) | (v & 0x03fffffc);
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001661#endif
Miles Baderae28b042002-04-01 09:34:25 +00001662#if defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001663 /* We write two shorts instead of a long because even 32-bit insns
1664 only need half-word alignment, but the 32-bit data write needs
1665 to be long-word aligned. */
1666 ((unsigned short *)loc)[0] =
1667 (*(unsigned short *)loc & 0xffc0) /* opcode + reg */
1668 | ((v >> 16) & 0x3f); /* offs high part */
1669 ((unsigned short *)loc)[1] =
1670 (v & 0xffff); /* offs low part */
Miles Baderae28b042002-04-01 09:34:25 +00001671#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001672 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001673#endif /* CONFIG_USE_PLT_ENTRIES */
Eric Andersenfe4208f2000-09-24 03:44:29 +00001674
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001675#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001676bb_use_got:
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001677
Eric Andersen3b1a7442003-12-24 20:30:45 +00001678 assert(isym != NULL);
1679 /* needs an entry in the .got: set it, once */
1680 if (!isym->gotent.inited) {
1681 isym->gotent.inited = 1;
1682 *(ElfW(Addr) *) (ifile->got->contents + isym->gotent.offset) = v;
1683 }
1684 /* make the reloc with_respect_to_.got */
Eric Andersen21adca72000-12-06 18:18:26 +00001685#if defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001686 *loc += isym->gotent.offset + rel->r_addend;
Eric Andersenb4a26e62001-06-19 15:00:52 +00001687#elif defined(__i386__) || defined(__arm__) || defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001688 *loc += isym->gotent.offset;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001689#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001690 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00001691
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001692#endif /* CONFIG_USE_GOT_ENTRIES */
Eric Andersen9f16d612000-06-12 23:11:16 +00001693 }
1694
1695 return ret;
1696}
1697
Eric Andersencffd5022002-05-24 06:50:15 +00001698
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001699#if defined(CONFIG_USE_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001700
1701static int arch_list_add(ElfW(RelM) *rel, struct arch_list_entry **list,
1702 int offset, int size)
1703{
1704 struct arch_list_entry *pe;
1705
1706 for (pe = *list; pe != NULL; pe = pe->next) {
1707 if (pe->addend == rel->r_addend) {
1708 break;
1709 }
1710 }
1711
1712 if (pe == NULL) {
1713 pe = xmalloc(sizeof(struct arch_list_entry));
1714 pe->next = *list;
1715 pe->addend = rel->r_addend;
1716 pe->offset = offset;
1717 pe->inited = 0;
1718 *list = pe;
1719 return size;
1720 }
1721 return 0;
1722}
1723
1724#endif
1725
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001726#if defined(CONFIG_USE_SINGLE)
Eric Andersencffd5022002-05-24 06:50:15 +00001727
1728static int arch_single_init(ElfW(RelM) *rel, struct arch_single_entry *single,
1729 int offset, int size)
1730{
1731 if (single->allocated == 0) {
1732 single->allocated = 1;
1733 single->offset = offset;
1734 single->inited = 0;
1735 return size;
1736 }
1737 return 0;
1738}
1739
1740#endif
1741
1742#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
1743
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001744static struct obj_section *arch_xsect_init(struct obj_file *f, char *name,
Eric Andersencffd5022002-05-24 06:50:15 +00001745 int offset, int size)
1746{
1747 struct obj_section *myrelsec = obj_find_section(f, name);
1748
1749 if (offset == 0) {
1750 offset += size;
1751 }
1752
1753 if (myrelsec) {
1754 obj_extend_section(myrelsec, offset);
1755 } else {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001756 myrelsec = obj_create_alloced_section(f, name,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001757 size, offset);
Eric Andersencffd5022002-05-24 06:50:15 +00001758 assert(myrelsec);
1759 }
1760
1761 return myrelsec;
1762}
1763
1764#endif
1765
1766static void arch_create_got(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00001767{
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001768#if defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersenfe4208f2000-09-24 03:44:29 +00001769 struct arch_file *ifile = (struct arch_file *) f;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001770 int i;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001771#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001772 int got_offset = 0, got_needed = 0, got_allocate;
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001773#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001774#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001775 int plt_offset = 0, plt_needed = 0, plt_allocate;
Eric Andersenfe4208f2000-09-24 03:44:29 +00001776#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001777 struct obj_section *relsec, *symsec, *strsec;
Eric Andersen21adca72000-12-06 18:18:26 +00001778 ElfW(RelM) *rel, *relend;
1779 ElfW(Sym) *symtab, *extsym;
1780 const char *strtab, *name;
1781 struct arch_symbol *intsym;
Eric Andersen9f16d612000-06-12 23:11:16 +00001782
Eric Andersen21adca72000-12-06 18:18:26 +00001783 for (i = 0; i < f->header.e_shnum; ++i) {
1784 relsec = f->sections[i];
1785 if (relsec->header.sh_type != SHT_RELM)
Eric Andersen9f16d612000-06-12 23:11:16 +00001786 continue;
1787
Eric Andersen21adca72000-12-06 18:18:26 +00001788 symsec = f->sections[relsec->header.sh_link];
1789 strsec = f->sections[symsec->header.sh_link];
Eric Andersen9f16d612000-06-12 23:11:16 +00001790
Eric Andersen21adca72000-12-06 18:18:26 +00001791 rel = (ElfW(RelM) *) relsec->contents;
1792 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
1793 symtab = (ElfW(Sym) *) symsec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00001794 strtab = (const char *) strsec->contents;
1795
1796 for (; rel < relend; ++rel) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001797 extsym = &symtab[ELF_R_SYM(rel->r_info)];
Eric Andersen9f16d612000-06-12 23:11:16 +00001798
Eric Andersencffd5022002-05-24 06:50:15 +00001799#if defined(CONFIG_USE_GOT_ENTRIES)
1800 got_allocate = 0;
1801#endif
1802#if defined(CONFIG_USE_PLT_ENTRIES)
1803 plt_allocate = 0;
1804#endif
1805
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00001806 switch (ELF_R_TYPE(rel->r_info)) {
Eric Andersen21adca72000-12-06 18:18:26 +00001807#if defined(__arm__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001808 case R_ARM_PC24:
1809 case R_ARM_PLT32:
1810 plt_allocate = 1;
1811 break;
Eric Andersen21adca72000-12-06 18:18:26 +00001812
Eric Andersen3b1a7442003-12-24 20:30:45 +00001813 case R_ARM_GOTOFF:
1814 case R_ARM_GOTPC:
1815 got_needed = 1;
1816 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001817
Eric Andersen3b1a7442003-12-24 20:30:45 +00001818 case R_ARM_GOT32:
1819 got_allocate = 1;
1820 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001821
Eric Andersen21adca72000-12-06 18:18:26 +00001822#elif defined(__i386__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001823 case R_386_GOTPC:
1824 case R_386_GOTOFF:
1825 got_needed = 1;
1826 continue;
Eric Andersen21adca72000-12-06 18:18:26 +00001827
Eric Andersen3b1a7442003-12-24 20:30:45 +00001828 case R_386_GOT32:
1829 got_allocate = 1;
1830 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001831
1832#elif defined(__powerpc__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001833 case R_PPC_REL24:
1834 plt_allocate = 1;
1835 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001836
1837#elif defined(__mc68000__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001838 case R_68K_GOT32:
1839 got_allocate = 1;
1840 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001841
Eric Andersen16451a02004-03-19 12:16:18 +00001842#ifdef R_68K_GOTOFF
Eric Andersen3b1a7442003-12-24 20:30:45 +00001843 case R_68K_GOTOFF:
1844 got_needed = 1;
1845 continue;
Eric Andersen16451a02004-03-19 12:16:18 +00001846#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001847
1848#elif defined(__sh__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001849 case R_SH_GOT32:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001850 got_allocate = 1;
Eric Andersen3b1a7442003-12-24 20:30:45 +00001851 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001852
Eric Andersen3b1a7442003-12-24 20:30:45 +00001853 case R_SH_GOTPC:
1854 case R_SH_GOTOFF:
1855 got_needed = 1;
1856 continue;
Eric Andersencffd5022002-05-24 06:50:15 +00001857
1858#elif defined (__v850e__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00001859 case R_V850_22_PCREL:
1860 plt_needed = 1;
1861 break;
Eric Andersencffd5022002-05-24 06:50:15 +00001862
1863#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00001864 default:
1865 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00001866 }
1867
Eric Andersen21adca72000-12-06 18:18:26 +00001868 if (extsym->st_name != 0) {
Eric Andersen9f16d612000-06-12 23:11:16 +00001869 name = strtab + extsym->st_name;
Eric Andersen21adca72000-12-06 18:18:26 +00001870 } else {
Eric Andersen9f16d612000-06-12 23:11:16 +00001871 name = f->sections[extsym->st_shndx]->name;
Eric Andersen21adca72000-12-06 18:18:26 +00001872 }
1873 intsym = (struct arch_symbol *) obj_find_symbol(f, name);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001874#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001875 if (got_allocate) {
1876 got_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001877 rel, &intsym->gotent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001878 got_offset, CONFIG_GOT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001879
1880 got_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001881 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001882#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001883#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001884 if (plt_allocate) {
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001885#if defined(CONFIG_USE_PLT_LIST)
Eric Andersencffd5022002-05-24 06:50:15 +00001886 plt_offset += arch_list_add(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001887 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001888 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001889#else
1890 plt_offset += arch_single_init(
Eric Andersenc7bda1c2004-03-15 08:29:22 +00001891 rel, &intsym->pltent,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001892 plt_offset, CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001893#endif
1894 plt_needed = 1;
Eric Andersen21adca72000-12-06 18:18:26 +00001895 }
1896#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001897 }
Miles Baderae28b042002-04-01 09:34:25 +00001898 }
Eric Andersen21adca72000-12-06 18:18:26 +00001899
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001900#if defined(CONFIG_USE_GOT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001901 if (got_needed) {
1902 ifile->got = arch_xsect_init(f, ".got", got_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001903 CONFIG_GOT_ENTRY_SIZE);
Eric Andersen9f16d612000-06-12 23:11:16 +00001904 }
Eric Andersen21adca72000-12-06 18:18:26 +00001905#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00001906
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001907#if defined(CONFIG_USE_PLT_ENTRIES)
Eric Andersencffd5022002-05-24 06:50:15 +00001908 if (plt_needed) {
1909 ifile->plt = arch_xsect_init(f, ".plt", plt_offset,
Eric Andersen3b1a7442003-12-24 20:30:45 +00001910 CONFIG_PLT_ENTRY_SIZE);
Eric Andersencffd5022002-05-24 06:50:15 +00001911 }
Eric Andersen90fe7fe2001-02-20 20:47:08 +00001912#endif
Eric Andersencffd5022002-05-24 06:50:15 +00001913
1914#endif /* defined(CONFIG_USE_GOT_ENTRIES) || defined(CONFIG_USE_PLT_ENTRIES) */
Eric Andersen9f16d612000-06-12 23:11:16 +00001915}
1916
Eric Andersen9f16d612000-06-12 23:11:16 +00001917/*======================================================================*/
1918
1919/* Standard ELF hash function. */
Eric Andersen044228d2001-07-17 01:12:36 +00001920static inline unsigned long obj_elf_hash_n(const char *name, unsigned long n)
Eric Andersen9f16d612000-06-12 23:11:16 +00001921{
1922 unsigned long h = 0;
1923 unsigned long g;
1924 unsigned char ch;
1925
1926 while (n > 0) {
1927 ch = *name++;
1928 h = (h << 4) + ch;
1929 if ((g = (h & 0xf0000000)) != 0) {
1930 h ^= g >> 24;
1931 h &= ~g;
1932 }
1933 n--;
1934 }
1935 return h;
1936}
1937
Eric Andersen044228d2001-07-17 01:12:36 +00001938static unsigned long obj_elf_hash(const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00001939{
1940 return obj_elf_hash_n(name, strlen(name));
1941}
1942
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001943#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00001944/* String comparison for non-co-versioned kernel and module. */
1945
1946static int ncv_strcmp(const char *a, const char *b)
1947{
1948 size_t alen = strlen(a), blen = strlen(b);
1949
1950 if (blen == alen + 10 && b[alen] == '_' && b[alen + 1] == 'R')
1951 return strncmp(a, b, alen);
1952 else if (alen == blen + 10 && a[blen] == '_' && a[blen + 1] == 'R')
1953 return strncmp(a, b, blen);
1954 else
1955 return strcmp(a, b);
1956}
1957
1958/* String hashing for non-co-versioned kernel and module. Here
1959 we are simply forced to drop the crc from the hash. */
1960
1961static unsigned long ncv_symbol_hash(const char *str)
1962{
1963 size_t len = strlen(str);
1964 if (len > 10 && str[len - 10] == '_' && str[len - 9] == 'R')
1965 len -= 10;
1966 return obj_elf_hash_n(str, len);
1967}
1968
Eric Andersen044228d2001-07-17 01:12:36 +00001969static void
Eric Andersen9f16d612000-06-12 23:11:16 +00001970obj_set_symbol_compare(struct obj_file *f,
1971 int (*cmp) (const char *, const char *),
1972 unsigned long (*hash) (const char *))
1973{
1974 if (cmp)
1975 f->symbol_cmp = cmp;
1976 if (hash) {
1977 struct obj_symbol *tmptab[HASH_BUCKETS], *sym, *next;
1978 int i;
1979
1980 f->symbol_hash = hash;
1981
1982 memcpy(tmptab, f->symtab, sizeof(tmptab));
1983 memset(f->symtab, 0, sizeof(f->symtab));
1984
1985 for (i = 0; i < HASH_BUCKETS; ++i)
1986 for (sym = tmptab[i]; sym; sym = next) {
1987 unsigned long h = hash(sym->name) % HASH_BUCKETS;
1988 next = sym->next;
1989 sym->next = f->symtab[h];
1990 f->symtab[h] = sym;
1991 }
1992 }
1993}
1994
Eric Andersenbdfd0d72001-10-24 05:00:29 +00001995#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00001996
Eric Andersen044228d2001-07-17 01:12:36 +00001997static struct obj_symbol *
1998obj_add_symbol(struct obj_file *f, const char *name,
Eric Andersen9f16d612000-06-12 23:11:16 +00001999 unsigned long symidx, int info,
2000 int secidx, ElfW(Addr) value,
2001 unsigned long size)
2002{
2003 struct obj_symbol *sym;
2004 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002005 int n_type = ELF_ST_TYPE(info);
2006 int n_binding = ELF_ST_BIND(info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002007
2008 for (sym = f->symtab[hash]; sym; sym = sym->next)
2009 if (f->symbol_cmp(sym->name, name) == 0) {
2010 int o_secidx = sym->secidx;
2011 int o_info = sym->info;
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002012 int o_type = ELF_ST_TYPE(o_info);
2013 int o_binding = ELF_ST_BIND(o_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00002014
2015 /* A redefinition! Is it legal? */
2016
2017 if (secidx == SHN_UNDEF)
2018 return sym;
2019 else if (o_secidx == SHN_UNDEF)
2020 goto found;
2021 else if (n_binding == STB_GLOBAL && o_binding == STB_LOCAL) {
2022 /* Cope with local and global symbols of the same name
2023 in the same object file, as might have been created
2024 by ld -r. The only reason locals are now seen at this
2025 level at all is so that we can do semi-sensible things
2026 with parameters. */
2027
2028 struct obj_symbol *nsym, **p;
2029
2030 nsym = arch_new_symbol();
2031 nsym->next = sym->next;
2032 nsym->ksymidx = -1;
2033
2034 /* Excise the old (local) symbol from the hash chain. */
2035 for (p = &f->symtab[hash]; *p != sym; p = &(*p)->next)
2036 continue;
2037 *p = sym = nsym;
2038 goto found;
2039 } else if (n_binding == STB_LOCAL) {
2040 /* Another symbol of the same name has already been defined.
2041 Just add this to the local table. */
2042 sym = arch_new_symbol();
2043 sym->next = NULL;
2044 sym->ksymidx = -1;
2045 f->local_symtab[symidx] = sym;
2046 goto found;
2047 } else if (n_binding == STB_WEAK)
2048 return sym;
2049 else if (o_binding == STB_WEAK)
2050 goto found;
2051 /* Don't unify COMMON symbols with object types the programmer
2052 doesn't expect. */
2053 else if (secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002054 && (o_type == STT_NOTYPE || o_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002055 return sym;
2056 else if (o_secidx == SHN_COMMON
Eric Andersen3b1a7442003-12-24 20:30:45 +00002057 && (n_type == STT_NOTYPE || n_type == STT_OBJECT))
Eric Andersen9f16d612000-06-12 23:11:16 +00002058 goto found;
2059 else {
2060 /* Don't report an error if the symbol is coming from
2061 the kernel or some external module. */
2062 if (secidx <= SHN_HIRESERVE)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002063 bb_error_msg("%s multiply defined", name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002064 return sym;
2065 }
2066 }
2067
2068 /* Completely new symbol. */
2069 sym = arch_new_symbol();
2070 sym->next = f->symtab[hash];
2071 f->symtab[hash] = sym;
2072 sym->ksymidx = -1;
2073
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002074 if (ELF_ST_BIND(info) == STB_LOCAL && symidx != -1) {
Eric Andersen66ca9482001-06-28 21:36:06 +00002075 if (symidx >= f->local_symtab_size)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002076 bb_error_msg("local symbol %s with index %ld exceeds local_symtab_size %ld",
Eric Andersen66ca9482001-06-28 21:36:06 +00002077 name, (long) symidx, (long) f->local_symtab_size);
2078 else
2079 f->local_symtab[symidx] = sym;
2080 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002081
Eric Andersen3b1a7442003-12-24 20:30:45 +00002082found:
Eric Andersen9f16d612000-06-12 23:11:16 +00002083 sym->name = name;
2084 sym->value = value;
2085 sym->size = size;
2086 sym->secidx = secidx;
2087 sym->info = info;
2088
2089 return sym;
2090}
2091
Eric Andersen044228d2001-07-17 01:12:36 +00002092static struct obj_symbol *
2093obj_find_symbol(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002094{
2095 struct obj_symbol *sym;
2096 unsigned long hash = f->symbol_hash(name) % HASH_BUCKETS;
2097
2098 for (sym = f->symtab[hash]; sym; sym = sym->next)
2099 if (f->symbol_cmp(sym->name, name) == 0)
2100 return sym;
2101
2102 return NULL;
2103}
2104
Eric Andersen044228d2001-07-17 01:12:36 +00002105static ElfW(Addr)
Eric Andersen9f16d612000-06-12 23:11:16 +00002106 obj_symbol_final_value(struct obj_file * f, struct obj_symbol * sym)
2107{
2108 if (sym) {
2109 if (sym->secidx >= SHN_LORESERVE)
2110 return sym->value;
2111
2112 return sym->value + f->sections[sym->secidx]->header.sh_addr;
2113 } else {
2114 /* As a special case, a NULL sym has value zero. */
2115 return 0;
2116 }
2117}
2118
Eric Andersen044228d2001-07-17 01:12:36 +00002119static struct obj_section *obj_find_section(struct obj_file *f, const char *name)
Eric Andersen9f16d612000-06-12 23:11:16 +00002120{
2121 int i, n = f->header.e_shnum;
2122
2123 for (i = 0; i < n; ++i)
2124 if (strcmp(f->sections[i]->name, name) == 0)
2125 return f->sections[i];
2126
2127 return NULL;
2128}
2129
2130static int obj_load_order_prio(struct obj_section *a)
2131{
2132 unsigned long af, ac;
2133
2134 af = a->header.sh_flags;
2135
2136 ac = 0;
2137 if (a->name[0] != '.' || strlen(a->name) != 10 ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002138 strcmp(a->name + 5, ".init"))
Eric Andersen9f16d612000-06-12 23:11:16 +00002139 ac |= 32;
2140 if (af & SHF_ALLOC)
2141 ac |= 16;
2142 if (!(af & SHF_WRITE))
2143 ac |= 8;
2144 if (af & SHF_EXECINSTR)
2145 ac |= 4;
2146 if (a->header.sh_type != SHT_NOBITS)
2147 ac |= 2;
2148
2149 return ac;
2150}
2151
Eric Andersen044228d2001-07-17 01:12:36 +00002152static void
Eric Andersen9f16d612000-06-12 23:11:16 +00002153obj_insert_section_load_order(struct obj_file *f, struct obj_section *sec)
2154{
2155 struct obj_section **p;
2156 int prio = obj_load_order_prio(sec);
2157 for (p = f->load_order_search_start; *p; p = &(*p)->load_next)
2158 if (obj_load_order_prio(*p) < prio)
2159 break;
2160 sec->load_next = *p;
2161 *p = sec;
2162}
2163
Eric Andersen044228d2001-07-17 01:12:36 +00002164static struct obj_section *obj_create_alloced_section(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002165 const char *name,
2166 unsigned long align,
2167 unsigned long size)
2168{
2169 int newidx = f->header.e_shnum++;
2170 struct obj_section *sec;
2171
2172 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2173 f->sections[newidx] = sec = arch_new_section();
2174
2175 memset(sec, 0, sizeof(*sec));
2176 sec->header.sh_type = SHT_PROGBITS;
2177 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2178 sec->header.sh_size = size;
2179 sec->header.sh_addralign = align;
2180 sec->name = name;
2181 sec->idx = newidx;
2182 if (size)
2183 sec->contents = xmalloc(size);
2184
2185 obj_insert_section_load_order(f, sec);
2186
2187 return sec;
2188}
2189
Eric Andersen044228d2001-07-17 01:12:36 +00002190static struct obj_section *obj_create_alloced_section_first(struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002191 const char *name,
2192 unsigned long align,
2193 unsigned long size)
2194{
2195 int newidx = f->header.e_shnum++;
2196 struct obj_section *sec;
2197
2198 f->sections = xrealloc(f->sections, (newidx + 1) * sizeof(sec));
2199 f->sections[newidx] = sec = arch_new_section();
2200
2201 memset(sec, 0, sizeof(*sec));
2202 sec->header.sh_type = SHT_PROGBITS;
2203 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
2204 sec->header.sh_size = size;
2205 sec->header.sh_addralign = align;
2206 sec->name = name;
2207 sec->idx = newidx;
2208 if (size)
2209 sec->contents = xmalloc(size);
2210
2211 sec->load_next = f->load_order;
2212 f->load_order = sec;
2213 if (f->load_order_search_start == &f->load_order)
2214 f->load_order_search_start = &sec->load_next;
2215
2216 return sec;
2217}
2218
Eric Andersen044228d2001-07-17 01:12:36 +00002219static void *obj_extend_section(struct obj_section *sec, unsigned long more)
Eric Andersen9f16d612000-06-12 23:11:16 +00002220{
2221 unsigned long oldsize = sec->header.sh_size;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002222 if (more) {
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002223 sec->contents = xrealloc(sec->contents, sec->header.sh_size += more);
2224 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002225 return sec->contents + oldsize;
2226}
2227
2228
Eric Andersen9f16d612000-06-12 23:11:16 +00002229/* Conditionally add the symbols from the given symbol set to the
2230 new module. */
2231
2232static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002233add_symbols_from( struct obj_file *f,
Eric Andersen9f16d612000-06-12 23:11:16 +00002234 int idx, struct new_module_symbol *syms, size_t nsyms)
2235{
2236 struct new_module_symbol *s;
2237 size_t i;
2238 int used = 0;
Miles Baderae28b042002-04-01 09:34:25 +00002239#ifdef SYMBOL_PREFIX
2240 char *name_buf = 0;
2241 size_t name_alloced_size = 0;
2242#endif
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002243#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
2244 int gpl;
Eric Andersen9f16d612000-06-12 23:11:16 +00002245
Glenn L McGrath759515c2003-08-30 06:00:33 +00002246 gpl = obj_gpl_license(f, NULL) == 0;
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002247#endif
Eric Andersen9f16d612000-06-12 23:11:16 +00002248 for (i = 0, s = syms; i < nsyms; ++i, ++s) {
Miles Baderae28b042002-04-01 09:34:25 +00002249 /* Only add symbols that are already marked external.
2250 If we override locals we may cause problems for
2251 argument initialization. We will also create a false
2252 dependency on the module. */
Eric Andersen9f16d612000-06-12 23:11:16 +00002253 struct obj_symbol *sym;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002254 char *name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002255
Glenn L McGrath759515c2003-08-30 06:00:33 +00002256 /* GPL licensed modules can use symbols exported with
2257 * EXPORT_SYMBOL_GPL, so ignore any GPLONLY_ prefix on the
2258 * exported names. Non-GPL modules never see any GPLONLY_
2259 * symbols so they cannot fudge it by adding the prefix on
2260 * their references.
2261 */
2262 if (strncmp((char *)s->name, "GPLONLY_", 8) == 0) {
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002263#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Glenn L McGrath759515c2003-08-30 06:00:33 +00002264 if (gpl)
Eric Andersenb225e2a2004-08-28 00:43:07 +00002265 s->name += 8;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002266 else
Glenn L McGrath759d7ec2003-09-03 00:42:58 +00002267#endif
Glenn L McGrath759515c2003-08-30 06:00:33 +00002268 continue;
2269 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00002270 name = (char *)s->name;
Glenn L McGrath759515c2003-08-30 06:00:33 +00002271
Miles Baderae28b042002-04-01 09:34:25 +00002272#ifdef SYMBOL_PREFIX
2273 /* Prepend SYMBOL_PREFIX to the symbol's name (the
2274 kernel exports `C names', but module object files
2275 reference `linker names'). */
2276 size_t extra = sizeof SYMBOL_PREFIX;
2277 size_t name_size = strlen (name) + extra;
2278 if (name_size > name_alloced_size) {
2279 name_alloced_size = name_size * 2;
2280 name_buf = alloca (name_alloced_size);
2281 }
2282 strcpy (name_buf, SYMBOL_PREFIX);
2283 strcpy (name_buf + extra - 1, name);
2284 name = name_buf;
2285#endif /* SYMBOL_PREFIX */
2286
2287 sym = obj_find_symbol(f, name);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002288 if (sym && !(ELF_ST_BIND(sym->info) == STB_LOCAL)) {
Miles Baderae28b042002-04-01 09:34:25 +00002289#ifdef SYMBOL_PREFIX
2290 /* Put NAME_BUF into more permanent storage. */
2291 name = xmalloc (name_size);
2292 strcpy (name, name_buf);
2293#endif
2294 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002295 ELF_ST_INFO(STB_GLOBAL,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002296 STT_NOTYPE),
2297 idx, s->value, 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002298 /* Did our symbol just get installed? If so, mark the
2299 module as "used". */
2300 if (sym->secidx == idx)
2301 used = 1;
2302 }
2303 }
2304
2305 return used;
2306}
2307
2308static void add_kernel_symbols(struct obj_file *f)
2309{
2310 struct external_module *m;
Pavel Roskinff5a9032000-07-14 16:23:32 +00002311 int i, nused = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002312
2313 /* Add module symbols first. */
2314
2315 for (i = 0, m = ext_modules; i < n_ext_modules; ++i, ++m)
2316 if (m->nsyms
Eric Andersen3b1a7442003-12-24 20:30:45 +00002317 && add_symbols_from(f, SHN_HIRESERVE + 2 + i, m->syms,
2318 m->nsyms)) m->used = 1, ++nused;
Eric Andersen9f16d612000-06-12 23:11:16 +00002319
2320 n_ext_modules_used = nused;
2321
2322 /* And finally the symbols from the kernel proper. */
2323
2324 if (nksyms)
2325 add_symbols_from(f, SHN_HIRESERVE + 1, ksyms, nksyms);
2326}
2327
2328static char *get_modinfo_value(struct obj_file *f, const char *key)
2329{
2330 struct obj_section *sec;
2331 char *p, *v, *n, *ep;
2332 size_t klen = strlen(key);
2333
2334 sec = obj_find_section(f, ".modinfo");
2335 if (sec == NULL)
2336 return NULL;
2337 p = sec->contents;
2338 ep = p + sec->header.sh_size;
2339 while (p < ep) {
2340 v = strchr(p, '=');
2341 n = strchr(p, '\0');
2342 if (v) {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002343 if (p + klen == v && strncmp(p, key, klen) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002344 return v + 1;
2345 } else {
Pavel Roskinff5a9032000-07-14 16:23:32 +00002346 if (p + klen == n && strcmp(p, key) == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00002347 return n;
2348 }
2349 p = n + 1;
2350 }
2351
2352 return NULL;
2353}
2354
2355
2356/*======================================================================*/
Eric Andersen9f16d612000-06-12 23:11:16 +00002357/* Functions relating to module loading after 2.1.18. */
2358
2359static int
2360new_process_module_arguments(struct obj_file *f, int argc, char **argv)
2361{
2362 while (argc > 0) {
Miles Baderae28b042002-04-01 09:34:25 +00002363 char *p, *q, *key, *sym_name;
Eric Andersen9f16d612000-06-12 23:11:16 +00002364 struct obj_symbol *sym;
2365 char *contents, *loc;
2366 int min, max, n;
2367
2368 p = *argv;
Eric Andersenef40aa82000-06-26 11:16:22 +00002369 if ((q = strchr(p, '=')) == NULL) {
2370 argc--;
Eric Andersen9f16d612000-06-12 23:11:16 +00002371 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002372 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002373
2374 key = alloca(q - p + 6);
2375 memcpy(key, "parm_", 5);
2376 memcpy(key + 5, p, q - p);
2377 key[q - p + 5] = 0;
2378
2379 p = get_modinfo_value(f, key);
2380 key += 5;
2381 if (p == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002382 bb_error_msg("invalid parameter %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002383 return 0;
2384 }
2385
Miles Baderae28b042002-04-01 09:34:25 +00002386#ifdef SYMBOL_PREFIX
2387 sym_name = alloca (strlen (key) + sizeof SYMBOL_PREFIX);
2388 strcpy (sym_name, SYMBOL_PREFIX);
2389 strcat (sym_name, key);
2390#else
2391 sym_name = key;
2392#endif
2393 sym = obj_find_symbol(f, sym_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002394
2395 /* Also check that the parameter was not resolved from the kernel. */
2396 if (sym == NULL || sym->secidx > SHN_HIRESERVE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002397 bb_error_msg("symbol for parameter %s not found", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002398 return 0;
2399 }
2400
2401 if (isdigit(*p)) {
2402 min = strtoul(p, &p, 10);
2403 if (*p == '-')
2404 max = strtoul(p + 1, &p, 10);
2405 else
2406 max = min;
2407 } else
2408 min = max = 1;
2409
2410 contents = f->sections[sym->secidx]->contents;
2411 loc = contents + sym->value;
2412 n = (*++q != '\0');
2413
2414 while (1) {
2415 if ((*p == 's') || (*p == 'c')) {
2416 char *str;
2417
2418 /* Do C quoting if we begin with a ", else slurp the lot. */
2419 if (*q == '"') {
2420 char *r;
2421
2422 str = alloca(strlen(q));
2423 for (r = str, q++; *q != '"'; ++q, ++r) {
2424 if (*q == '\0') {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002425 bb_error_msg("improperly terminated string argument for %s",
Eric Andersen9f16d612000-06-12 23:11:16 +00002426 key);
2427 return 0;
2428 } else if (*q == '\\')
2429 switch (*++q) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002430 case 'a':
2431 *r = '\a';
2432 break;
2433 case 'b':
2434 *r = '\b';
2435 break;
2436 case 'e':
2437 *r = '\033';
2438 break;
2439 case 'f':
2440 *r = '\f';
2441 break;
2442 case 'n':
2443 *r = '\n';
2444 break;
2445 case 'r':
2446 *r = '\r';
2447 break;
2448 case 't':
2449 *r = '\t';
2450 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002451
Eric Andersen3b1a7442003-12-24 20:30:45 +00002452 case '0':
2453 case '1':
2454 case '2':
2455 case '3':
2456 case '4':
2457 case '5':
2458 case '6':
2459 case '7':
2460 {
2461 int c = *q - '0';
2462 if (q[1] >= '0' && q[1] <= '7') {
Eric Andersen9f16d612000-06-12 23:11:16 +00002463 c = (c * 8) + *++q - '0';
Eric Andersen3b1a7442003-12-24 20:30:45 +00002464 if (q[1] >= '0' && q[1] <= '7')
2465 c = (c * 8) + *++q - '0';
2466 }
2467 *r = c;
Eric Andersen9f16d612000-06-12 23:11:16 +00002468 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002469 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00002470
Eric Andersen3b1a7442003-12-24 20:30:45 +00002471 default:
2472 *r = *q;
2473 break;
2474 } else
Eric Andersen9f16d612000-06-12 23:11:16 +00002475 *r = *q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002476 }
2477 *r = '\0';
2478 ++q;
2479 } else {
2480 char *r;
2481
2482 /* In this case, the string is not quoted. We will break
2483 it using the coma (like for ints). If the user wants to
2484 include comas in a string, he just has to quote it */
2485
2486 /* Search the next coma */
2487 r = strchr(q, ',');
2488
2489 /* Found ? */
2490 if (r != (char *) NULL) {
2491 /* Recopy the current field */
2492 str = alloca(r - q + 1);
2493 memcpy(str, q, r - q);
2494
Eric Andersenaff114c2004-04-14 17:51:38 +00002495 /* I don't know if it is useful, as the previous case
2496 doesn't nul terminate the string ??? */
Eric Andersen9f16d612000-06-12 23:11:16 +00002497 str[r - q] = '\0';
2498
2499 /* Keep next fields */
2500 q = r;
2501 } else {
2502 /* last string */
2503 str = q;
2504 q = "";
2505 }
2506 }
2507
2508 if (*p == 's') {
2509 /* Normal string */
2510 obj_string_patch(f, sym->secidx, loc - contents, str);
2511 loc += tgt_sizeof_char_p;
2512 } else {
2513 /* Array of chars (in fact, matrix !) */
Pavel Roskinff5a9032000-07-14 16:23:32 +00002514 unsigned long charssize; /* size of each member */
Eric Andersen9f16d612000-06-12 23:11:16 +00002515
2516 /* Get the size of each member */
2517 /* Probably we should do that outside the loop ? */
2518 if (!isdigit(*(p + 1))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002519 bb_error_msg("parameter type 'c' for %s must be followed by"
Matt Kraaidd19c692001-01-31 19:00:21 +00002520 " the maximum size", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002521 return 0;
2522 }
2523 charssize = strtoul(p + 1, (char **) NULL, 10);
2524
2525 /* Check length */
2526 if (strlen(str) >= charssize) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002527 bb_error_msg("string too long for %s (max %ld)", key,
Eric Andersen9f16d612000-06-12 23:11:16 +00002528 charssize - 1);
2529 return 0;
2530 }
2531
2532 /* Copy to location */
2533 strcpy((char *) loc, str);
2534 loc += charssize;
2535 }
2536 } else {
2537 long v = strtoul(q, &q, 0);
2538 switch (*p) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002539 case 'b':
2540 *loc++ = v;
2541 break;
2542 case 'h':
2543 *(short *) loc = v;
2544 loc += tgt_sizeof_short;
2545 break;
2546 case 'i':
2547 *(int *) loc = v;
2548 loc += tgt_sizeof_int;
2549 break;
2550 case 'l':
2551 *(long *) loc = v;
2552 loc += tgt_sizeof_long;
2553 break;
2554
2555 default:
2556 bb_error_msg("unknown parameter type '%c' for %s", *p, key);
2557 return 0;
2558 }
2559 }
2560
2561retry_end_of_value:
2562 switch (*q) {
2563 case '\0':
2564 goto end_of_arg;
2565
2566 case ' ':
2567 case '\t':
2568 case '\n':
2569 case '\r':
2570 ++q;
2571 goto retry_end_of_value;
2572
2573 case ',':
2574 if (++n > max) {
2575 bb_error_msg("too many values for %s (max %d)", key, max);
2576 return 0;
2577 }
2578 ++q;
Eric Andersen9f16d612000-06-12 23:11:16 +00002579 break;
2580
2581 default:
Eric Andersen3b1a7442003-12-24 20:30:45 +00002582 bb_error_msg("invalid argument syntax for %s", key);
Eric Andersen9f16d612000-06-12 23:11:16 +00002583 return 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00002584 }
2585 }
2586
Eric Andersen3b1a7442003-12-24 20:30:45 +00002587end_of_arg:
Eric Andersen9f16d612000-06-12 23:11:16 +00002588 if (n < min) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002589 bb_error_msg("too few values for %s (min %d)", key, min);
Eric Andersen9f16d612000-06-12 23:11:16 +00002590 return 0;
2591 }
2592
2593 argc--, argv++;
2594 }
2595
2596 return 1;
2597}
2598
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002599#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00002600static int new_is_module_checksummed(struct obj_file *f)
2601{
2602 const char *p = get_modinfo_value(f, "using_checksums");
2603 if (p)
2604 return atoi(p);
2605 else
2606 return 0;
2607}
2608
2609/* Get the module's kernel version in the canonical integer form. */
2610
2611static int
2612new_get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
2613{
2614 char *p, *q;
2615 int a, b, c;
2616
2617 p = get_modinfo_value(f, "kernel_version");
2618 if (p == NULL)
2619 return -1;
Eric Andersen2d342152002-06-18 05:16:25 +00002620 safe_strncpy(str, p, STRVERSIONLEN);
Eric Andersen9f16d612000-06-12 23:11:16 +00002621
2622 a = strtoul(p, &p, 10);
2623 if (*p != '.')
2624 return -1;
2625 b = strtoul(p + 1, &p, 10);
2626 if (*p != '.')
2627 return -1;
2628 c = strtoul(p + 1, &q, 10);
2629 if (p + 1 == q)
2630 return -1;
2631
2632 return a << 16 | b << 8 | c;
2633}
2634
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002635#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00002636
2637
Eric Andersen9f16d612000-06-12 23:11:16 +00002638/* Fetch the loaded modules, and all currently exported symbols. */
2639
2640static int new_get_kernel_symbols(void)
2641{
2642 char *module_names, *mn;
2643 struct external_module *modules, *m;
2644 struct new_module_symbol *syms, *s;
2645 size_t ret, bufsize, nmod, nsyms, i, j;
2646
2647 /* Collect the loaded modules. */
2648
2649 module_names = xmalloc(bufsize = 256);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002650retry_modules_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002651 if (query_module(NULL, QM_MODULES, module_names, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002652 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002653 module_names = xrealloc(module_names, bufsize = ret);
2654 goto retry_modules_load;
2655 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002656 bb_perror_msg("QM_MODULES");
Eric Andersen9f16d612000-06-12 23:11:16 +00002657 return 0;
2658 }
2659
2660 n_ext_modules = nmod = ret;
Eric Andersen9f16d612000-06-12 23:11:16 +00002661
2662 /* Collect the modules' symbols. */
2663
Mark Whitley94fd4802001-03-12 23:08:34 +00002664 if (nmod){
2665 ext_modules = modules = xmalloc(nmod * sizeof(*modules));
2666 memset(modules, 0, nmod * sizeof(*modules));
2667 for (i = 0, mn = module_names, m = modules;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002668 i < nmod; ++i, ++m, mn += strlen(mn) + 1) {
Mark Whitley94fd4802001-03-12 23:08:34 +00002669 struct new_module_info info;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002670
Mark Whitley94fd4802001-03-12 23:08:34 +00002671 if (query_module(mn, QM_INFO, &info, sizeof(info), &ret)) {
2672 if (errno == ENOENT) {
2673 /* The module was removed out from underneath us. */
2674 continue;
2675 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002676 bb_perror_msg("query_module: QM_INFO: %s", mn);
Eric Andersen9f16d612000-06-12 23:11:16 +00002677 return 0;
2678 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00002679
Mark Whitley94fd4802001-03-12 23:08:34 +00002680 syms = xmalloc(bufsize = 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002681retry_mod_sym_load:
Mark Whitley94fd4802001-03-12 23:08:34 +00002682 if (query_module(mn, QM_SYMBOLS, syms, bufsize, &ret)) {
2683 switch (errno) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00002684 case ENOSPC:
2685 syms = xrealloc(syms, bufsize = ret);
2686 goto retry_mod_sym_load;
2687 case ENOENT:
2688 /* The module was removed out from underneath us. */
2689 continue;
2690 default:
2691 bb_perror_msg("query_module: QM_SYMBOLS: %s", mn);
2692 return 0;
Mark Whitley94fd4802001-03-12 23:08:34 +00002693 }
2694 }
2695 nsyms = ret;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002696
Mark Whitley94fd4802001-03-12 23:08:34 +00002697 m->name = mn;
2698 m->addr = info.addr;
2699 m->nsyms = nsyms;
2700 m->syms = syms;
Eric Andersen3b1a7442003-12-24 20:30:45 +00002701
Mark Whitley94fd4802001-03-12 23:08:34 +00002702 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2703 s->name += (unsigned long) syms;
2704 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002705 }
2706 }
2707
2708 /* Collect the kernel's symbols. */
2709
2710 syms = xmalloc(bufsize = 16 * 1024);
Eric Andersen3b1a7442003-12-24 20:30:45 +00002711retry_kern_sym_load:
Eric Andersen9f16d612000-06-12 23:11:16 +00002712 if (query_module(NULL, QM_SYMBOLS, syms, bufsize, &ret)) {
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00002713 if (errno == ENOSPC && bufsize < ret) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002714 syms = xrealloc(syms, bufsize = ret);
2715 goto retry_kern_sym_load;
2716 }
Manuel Novoa III cad53642003-03-19 09:13:01 +00002717 bb_perror_msg("kernel: QM_SYMBOLS");
Eric Andersen9f16d612000-06-12 23:11:16 +00002718 return 0;
2719 }
2720 nksyms = nsyms = ret;
2721 ksyms = syms;
2722
2723 for (j = 0, s = syms; j < nsyms; ++j, ++s) {
2724 s->name += (unsigned long) syms;
2725 }
2726 return 1;
2727}
2728
2729
2730/* Return the kernel symbol checksum version, or zero if not used. */
2731
2732static int new_is_kernel_checksummed(void)
2733{
2734 struct new_module_symbol *s;
2735 size_t i;
2736
2737 /* Using_Versions is not the first symbol, but it should be in there. */
2738
2739 for (i = 0, s = ksyms; i < nksyms; ++i, ++s)
2740 if (strcmp((char *) s->name, "Using_Versions") == 0)
2741 return s->value;
2742
2743 return 0;
2744}
2745
2746
2747static int new_create_this_module(struct obj_file *f, const char *m_name)
2748{
2749 struct obj_section *sec;
2750
2751 sec = obj_create_alloced_section_first(f, ".this", tgt_sizeof_long,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002752 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002753 memset(sec->contents, 0, sizeof(struct new_module));
2754
Miles Baderae28b042002-04-01 09:34:25 +00002755 obj_add_symbol(f, SPFX "__this_module", -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002756 ELF_ST_INFO(STB_LOCAL, STT_OBJECT), sec->idx, 0,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002757 sizeof(struct new_module));
Eric Andersen9f16d612000-06-12 23:11:16 +00002758
2759 obj_string_patch(f, sec->idx, offsetof(struct new_module, name),
Eric Andersen3b1a7442003-12-24 20:30:45 +00002760 m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002761
2762 return 1;
2763}
2764
Eric Andersen889dd202003-01-23 04:48:34 +00002765#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
2766/* add an entry to the __ksymtab section, creating it if necessary */
2767static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym)
2768{
2769 struct obj_section *sec;
2770 ElfW(Addr) ofs;
2771
2772 /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section.
2773 * If __ksymtab is defined but not marked alloc, x out the first character
2774 * (no obj_delete routine) and create a new __ksymtab with the correct
2775 * characteristics.
2776 */
2777 sec = obj_find_section(f, "__ksymtab");
2778 if (sec && !(sec->header.sh_flags & SHF_ALLOC)) {
2779 *((char *)(sec->name)) = 'x'; /* override const */
2780 sec = NULL;
2781 }
2782 if (!sec)
2783 sec = obj_create_alloced_section(f, "__ksymtab",
Eric Andersen3b1a7442003-12-24 20:30:45 +00002784 tgt_sizeof_void_p, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00002785 if (!sec)
2786 return;
2787 sec->header.sh_flags |= SHF_ALLOC;
2788 sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might
Eric Andersen3b1a7442003-12-24 20:30:45 +00002789 be byte-aligned */
Eric Andersen889dd202003-01-23 04:48:34 +00002790 ofs = sec->header.sh_size;
2791 obj_symbol_patch(f, sec->idx, ofs, sym);
2792 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name);
2793 obj_extend_section(sec, 2 * tgt_sizeof_char_p);
2794}
2795#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
Eric Andersen9f16d612000-06-12 23:11:16 +00002796
2797static int new_create_module_ksymtab(struct obj_file *f)
2798{
2799 struct obj_section *sec;
2800 int i;
2801
2802 /* We must always add the module references. */
2803
2804 if (n_ext_modules_used) {
2805 struct new_module_ref *dep;
2806 struct obj_symbol *tm;
2807
2808 sec = obj_create_alloced_section(f, ".kmodtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002809 (sizeof(struct new_module_ref)
2810 * n_ext_modules_used));
Eric Andersen9f16d612000-06-12 23:11:16 +00002811 if (!sec)
2812 return 0;
2813
Miles Baderae28b042002-04-01 09:34:25 +00002814 tm = obj_find_symbol(f, SPFX "__this_module");
Eric Andersen9f16d612000-06-12 23:11:16 +00002815 dep = (struct new_module_ref *) sec->contents;
2816 for (i = 0; i < n_ext_modules; ++i)
2817 if (ext_modules[i].used) {
2818 dep->dep = ext_modules[i].addr;
2819 obj_symbol_patch(f, sec->idx,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002820 (char *) &dep->ref - sec->contents, tm);
Eric Andersen9f16d612000-06-12 23:11:16 +00002821 dep->next_ref = 0;
2822 ++dep;
2823 }
2824 }
2825
2826 if (flag_export && !obj_find_section(f, "__ksymtab")) {
2827 size_t nsyms;
2828 int *loaded;
2829
2830 sec =
2831 obj_create_alloced_section(f, "__ksymtab", tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002832 0);
Eric Andersen9f16d612000-06-12 23:11:16 +00002833
2834 /* We don't want to export symbols residing in sections that
2835 aren't loaded. There are a number of these created so that
2836 we make sure certain module options don't appear twice. */
2837
2838 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
2839 while (--i >= 0)
2840 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
2841
2842 for (nsyms = i = 0; i < HASH_BUCKETS; ++i) {
2843 struct obj_symbol *sym;
2844 for (sym = f->symtab[i]; sym; sym = sym->next)
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00002845 if (ELF_ST_BIND(sym->info) != STB_LOCAL
Eric Andersen3b1a7442003-12-24 20:30:45 +00002846 && sym->secidx <= SHN_HIRESERVE
2847 && (sym->secidx >= SHN_LORESERVE
2848 || loaded[sym->secidx])) {
Eric Andersen9f16d612000-06-12 23:11:16 +00002849 ElfW(Addr) ofs = nsyms * 2 * tgt_sizeof_void_p;
2850
2851 obj_symbol_patch(f, sec->idx, ofs, sym);
2852 obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p,
Eric Andersen3b1a7442003-12-24 20:30:45 +00002853 sym->name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002854
2855 nsyms++;
2856 }
2857 }
2858
2859 obj_extend_section(sec, nsyms * 2 * tgt_sizeof_char_p);
2860 }
2861
2862 return 1;
2863}
2864
2865
2866static int
Eric Andersencb3b9b12004-06-22 11:50:52 +00002867new_init_module(const char *m_name, struct obj_file *f, unsigned long m_size)
Eric Andersen9f16d612000-06-12 23:11:16 +00002868{
2869 struct new_module *module;
2870 struct obj_section *sec;
2871 void *image;
2872 int ret;
2873 tgt_long m_addr;
2874
2875 sec = obj_find_section(f, ".this");
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002876 if (!sec || !sec->contents) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00002877 bb_perror_msg_and_die("corrupt module %s?",m_name);
Eric Andersen7f3b86e2001-04-26 19:29:58 +00002878 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002879 module = (struct new_module *) sec->contents;
2880 m_addr = sec->header.sh_addr;
2881
2882 module->size_of_struct = sizeof(*module);
2883 module->size = m_size;
2884 module->flags = flag_autoclean ? NEW_MOD_AUTOCLEAN : 0;
2885
2886 sec = obj_find_section(f, "__ksymtab");
2887 if (sec && sec->header.sh_size) {
2888 module->syms = sec->header.sh_addr;
2889 module->nsyms = sec->header.sh_size / (2 * tgt_sizeof_char_p);
2890 }
2891
2892 if (n_ext_modules_used) {
2893 sec = obj_find_section(f, ".kmodtab");
2894 module->deps = sec->header.sh_addr;
2895 module->ndeps = n_ext_modules_used;
2896 }
2897
2898 module->init =
Miles Baderae28b042002-04-01 09:34:25 +00002899 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "init_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002900 module->cleanup =
Miles Baderae28b042002-04-01 09:34:25 +00002901 obj_symbol_final_value(f, obj_find_symbol(f, SPFX "cleanup_module"));
Eric Andersen9f16d612000-06-12 23:11:16 +00002902
2903 sec = obj_find_section(f, "__ex_table");
2904 if (sec) {
2905 module->ex_table_start = sec->header.sh_addr;
2906 module->ex_table_end = sec->header.sh_addr + sec->header.sh_size;
2907 }
2908
2909 sec = obj_find_section(f, ".text.init");
2910 if (sec) {
2911 module->runsize = sec->header.sh_addr - m_addr;
2912 }
2913 sec = obj_find_section(f, ".data.init");
2914 if (sec) {
2915 if (!module->runsize ||
Eric Andersen3b1a7442003-12-24 20:30:45 +00002916 module->runsize > sec->header.sh_addr - m_addr)
2917 module->runsize = sec->header.sh_addr - m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00002918 }
Eric Andersen8ae319a2001-05-21 16:09:18 +00002919 sec = obj_find_section(f, ARCHDATA_SEC_NAME);
2920 if (sec && sec->header.sh_size) {
2921 module->archdata_start = (void*)sec->header.sh_addr;
2922 module->archdata_end = module->archdata_start + sec->header.sh_size;
2923 }
2924 sec = obj_find_section(f, KALLSYMS_SEC_NAME);
2925 if (sec && sec->header.sh_size) {
2926 module->kallsyms_start = (void*)sec->header.sh_addr;
2927 module->kallsyms_end = module->kallsyms_start + sec->header.sh_size;
2928 }
Eric Andersen9f16d612000-06-12 23:11:16 +00002929
Eric Andersen9f16d612000-06-12 23:11:16 +00002930 /* Whew! All of the initialization is complete. Collect the final
2931 module image and give it to the kernel. */
2932
2933 image = xmalloc(m_size);
2934 obj_create_image(f, image);
2935
Eric Andersencb3b9b12004-06-22 11:50:52 +00002936 ret = init_module(m_name, (struct new_module *) image);
Eric Andersen9f16d612000-06-12 23:11:16 +00002937 if (ret)
Manuel Novoa III cad53642003-03-19 09:13:01 +00002938 bb_perror_msg("init_module: %s", m_name);
Eric Andersen9f16d612000-06-12 23:11:16 +00002939
2940 free(image);
2941
2942 return ret == 0;
2943}
2944
Eric Andersen9f16d612000-06-12 23:11:16 +00002945
2946/*======================================================================*/
2947
Eric Andersen044228d2001-07-17 01:12:36 +00002948static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002949obj_string_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2950 const char *string)
2951{
2952 struct obj_string_patch *p;
2953 struct obj_section *strsec;
2954 size_t len = strlen(string) + 1;
2955 char *loc;
2956
2957 p = xmalloc(sizeof(*p));
2958 p->next = f->string_patches;
2959 p->reloc_secidx = secidx;
2960 p->reloc_offset = offset;
2961 f->string_patches = p;
2962
2963 strsec = obj_find_section(f, ".kstrtab");
2964 if (strsec == NULL) {
2965 strsec = obj_create_alloced_section(f, ".kstrtab", 1, len);
2966 p->string_offset = 0;
2967 loc = strsec->contents;
2968 } else {
2969 p->string_offset = strsec->header.sh_size;
2970 loc = obj_extend_section(strsec, len);
2971 }
2972 memcpy(loc, string, len);
2973
2974 return 1;
2975}
2976
Eric Andersen044228d2001-07-17 01:12:36 +00002977static int
Eric Andersen9f16d612000-06-12 23:11:16 +00002978obj_symbol_patch(struct obj_file *f, int secidx, ElfW(Addr) offset,
2979 struct obj_symbol *sym)
2980{
2981 struct obj_symbol_patch *p;
2982
2983 p = xmalloc(sizeof(*p));
2984 p->next = f->symbol_patches;
2985 p->reloc_secidx = secidx;
2986 p->reloc_offset = offset;
2987 p->sym = sym;
2988 f->symbol_patches = p;
2989
2990 return 1;
2991}
2992
Eric Andersen044228d2001-07-17 01:12:36 +00002993static int obj_check_undefineds(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00002994{
2995 unsigned long i;
2996 int ret = 1;
2997
2998 for (i = 0; i < HASH_BUCKETS; ++i) {
2999 struct obj_symbol *sym;
3000 for (sym = f->symtab[i]; sym; sym = sym->next)
3001 if (sym->secidx == SHN_UNDEF) {
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003002 if (ELF_ST_BIND(sym->info) == STB_WEAK) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003003 sym->secidx = SHN_ABS;
3004 sym->value = 0;
3005 } else {
Eric Andersenb493dec2002-07-02 19:14:23 +00003006 if (!flag_quiet) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003007 bb_error_msg("unresolved symbol %s", sym->name);
Eric Andersenb493dec2002-07-02 19:14:23 +00003008 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003009 ret = 0;
3010 }
3011 }
3012 }
3013
3014 return ret;
3015}
3016
Eric Andersen044228d2001-07-17 01:12:36 +00003017static void obj_allocate_commons(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003018{
3019 struct common_entry {
3020 struct common_entry *next;
3021 struct obj_symbol *sym;
3022 } *common_head = NULL;
3023
3024 unsigned long i;
3025
3026 for (i = 0; i < HASH_BUCKETS; ++i) {
3027 struct obj_symbol *sym;
3028 for (sym = f->symtab[i]; sym; sym = sym->next)
3029 if (sym->secidx == SHN_COMMON) {
3030 /* Collect all COMMON symbols and sort them by size so as to
3031 minimize space wasted by alignment requirements. */
3032 {
3033 struct common_entry **p, *n;
3034 for (p = &common_head; *p; p = &(*p)->next)
3035 if (sym->size <= (*p)->sym->size)
3036 break;
3037
3038 n = alloca(sizeof(*n));
3039 n->next = *p;
3040 n->sym = sym;
3041 *p = n;
3042 }
3043 }
3044 }
3045
3046 for (i = 1; i < f->local_symtab_size; ++i) {
3047 struct obj_symbol *sym = f->local_symtab[i];
3048 if (sym && sym->secidx == SHN_COMMON) {
3049 struct common_entry **p, *n;
3050 for (p = &common_head; *p; p = &(*p)->next)
3051 if (sym == (*p)->sym)
3052 break;
3053 else if (sym->size < (*p)->sym->size) {
3054 n = alloca(sizeof(*n));
3055 n->next = *p;
3056 n->sym = sym;
3057 *p = n;
3058 break;
3059 }
3060 }
3061 }
3062
3063 if (common_head) {
3064 /* Find the bss section. */
3065 for (i = 0; i < f->header.e_shnum; ++i)
3066 if (f->sections[i]->header.sh_type == SHT_NOBITS)
3067 break;
3068
3069 /* If for some reason there hadn't been one, create one. */
3070 if (i == f->header.e_shnum) {
3071 struct obj_section *sec;
3072
3073 f->sections = xrealloc(f->sections, (i + 1) * sizeof(sec));
3074 f->sections[i] = sec = arch_new_section();
3075 f->header.e_shnum = i + 1;
3076
3077 memset(sec, 0, sizeof(*sec));
3078 sec->header.sh_type = SHT_PROGBITS;
3079 sec->header.sh_flags = SHF_WRITE | SHF_ALLOC;
3080 sec->name = ".bss";
3081 sec->idx = i;
3082 }
3083
3084 /* Allocate the COMMONS. */
3085 {
3086 ElfW(Addr) bss_size = f->sections[i]->header.sh_size;
3087 ElfW(Addr) max_align = f->sections[i]->header.sh_addralign;
3088 struct common_entry *c;
3089
3090 for (c = common_head; c; c = c->next) {
3091 ElfW(Addr) align = c->sym->value;
3092
3093 if (align > max_align)
3094 max_align = align;
3095 if (bss_size & (align - 1))
3096 bss_size = (bss_size | (align - 1)) + 1;
3097
3098 c->sym->secidx = i;
3099 c->sym->value = bss_size;
3100
3101 bss_size += c->sym->size;
3102 }
3103
3104 f->sections[i]->header.sh_size = bss_size;
3105 f->sections[i]->header.sh_addralign = max_align;
3106 }
3107 }
3108
3109 /* For the sake of patch relocation and parameter initialization,
3110 allocate zeroed data for NOBITS sections now. Note that after
3111 this we cannot assume NOBITS are really empty. */
3112 for (i = 0; i < f->header.e_shnum; ++i) {
3113 struct obj_section *s = f->sections[i];
3114 if (s->header.sh_type == SHT_NOBITS) {
Eric Andersen21adca72000-12-06 18:18:26 +00003115 if (s->header.sh_size != 0)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003116 s->contents = memset(xmalloc(s->header.sh_size),
3117 0, s->header.sh_size);
Eric Andersen21adca72000-12-06 18:18:26 +00003118 else
3119 s->contents = NULL;
3120
Eric Andersen9f16d612000-06-12 23:11:16 +00003121 s->header.sh_type = SHT_PROGBITS;
3122 }
3123 }
3124}
3125
Eric Andersen044228d2001-07-17 01:12:36 +00003126static unsigned long obj_load_size(struct obj_file *f)
Eric Andersen9f16d612000-06-12 23:11:16 +00003127{
3128 unsigned long dot = 0;
3129 struct obj_section *sec;
3130
3131 /* Finalize the positions of the sections relative to one another. */
3132
3133 for (sec = f->load_order; sec; sec = sec->load_next) {
3134 ElfW(Addr) align;
3135
3136 align = sec->header.sh_addralign;
3137 if (align && (dot & (align - 1)))
3138 dot = (dot | (align - 1)) + 1;
3139
3140 sec->header.sh_addr = dot;
3141 dot += sec->header.sh_size;
3142 }
3143
3144 return dot;
3145}
3146
Eric Andersen044228d2001-07-17 01:12:36 +00003147static int obj_relocate(struct obj_file *f, ElfW(Addr) base)
Eric Andersen9f16d612000-06-12 23:11:16 +00003148{
3149 int i, n = f->header.e_shnum;
3150 int ret = 1;
3151
3152 /* Finalize the addresses of the sections. */
3153
3154 f->baseaddr = base;
3155 for (i = 0; i < n; ++i)
3156 f->sections[i]->header.sh_addr += base;
3157
3158 /* And iterate over all of the relocations. */
3159
3160 for (i = 0; i < n; ++i) {
3161 struct obj_section *relsec, *symsec, *targsec, *strsec;
3162 ElfW(RelM) * rel, *relend;
3163 ElfW(Sym) * symtab;
3164 const char *strtab;
3165
3166 relsec = f->sections[i];
3167 if (relsec->header.sh_type != SHT_RELM)
3168 continue;
3169
3170 symsec = f->sections[relsec->header.sh_link];
3171 targsec = f->sections[relsec->header.sh_info];
3172 strsec = f->sections[symsec->header.sh_link];
3173
3174 rel = (ElfW(RelM) *) relsec->contents;
3175 relend = rel + (relsec->header.sh_size / sizeof(ElfW(RelM)));
3176 symtab = (ElfW(Sym) *) symsec->contents;
3177 strtab = (const char *) strsec->contents;
3178
3179 for (; rel < relend; ++rel) {
3180 ElfW(Addr) value = 0;
3181 struct obj_symbol *intsym = NULL;
3182 unsigned long symndx;
3183 ElfW(Sym) * extsym = 0;
3184 const char *errmsg;
3185
3186 /* Attempt to find a value to use for this relocation. */
3187
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003188 symndx = ELF_R_SYM(rel->r_info);
Eric Andersen9f16d612000-06-12 23:11:16 +00003189 if (symndx) {
3190 /* Note we've already checked for undefined symbols. */
3191
3192 extsym = &symtab[symndx];
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003193 if (ELF_ST_BIND(extsym->st_info) == STB_LOCAL) {
Eric Andersen9f16d612000-06-12 23:11:16 +00003194 /* Local symbols we look up in the local table to be sure
3195 we get the one that is really intended. */
3196 intsym = f->local_symtab[symndx];
3197 } else {
3198 /* Others we look up in the hash table. */
3199 const char *name;
3200 if (extsym->st_name)
3201 name = strtab + extsym->st_name;
3202 else
3203 name = f->sections[extsym->st_shndx]->name;
3204 intsym = obj_find_symbol(f, name);
3205 }
3206
3207 value = obj_symbol_final_value(f, intsym);
3208 intsym->referenced = 1;
3209 }
3210#if SHT_RELM == SHT_RELA
3211#if defined(__alpha__) && defined(AXP_BROKEN_GAS)
3212 /* Work around a nasty GAS bug, that is fixed as of 2.7.0.9. */
3213 if (!extsym || !extsym->st_name ||
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003214 ELF_ST_BIND(extsym->st_info) != STB_LOCAL)
Eric Andersen9f16d612000-06-12 23:11:16 +00003215#endif
3216 value += rel->r_addend;
3217#endif
3218
3219 /* Do it! */
3220 switch (arch_apply_relocation
3221 (f, targsec, symsec, intsym, rel, value)) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003222 case obj_reloc_ok:
3223 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003224
Eric Andersen3b1a7442003-12-24 20:30:45 +00003225 case obj_reloc_overflow:
3226 errmsg = "Relocation overflow";
3227 goto bad_reloc;
3228 case obj_reloc_dangerous:
3229 errmsg = "Dangerous relocation";
3230 goto bad_reloc;
3231 case obj_reloc_unhandled:
3232 errmsg = "Unhandled relocation";
3233bad_reloc:
3234 if (extsym) {
3235 bb_error_msg("%s of type %ld for %s", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003236 (long) ELF_R_TYPE(rel->r_info),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003237 strtab + extsym->st_name);
3238 } else {
3239 bb_error_msg("%s of type %ld", errmsg,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003240 (long) ELF_R_TYPE(rel->r_info));
Eric Andersen3b1a7442003-12-24 20:30:45 +00003241 }
3242 ret = 0;
3243 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003244 }
3245 }
3246 }
3247
3248 /* Finally, take care of the patches. */
3249
3250 if (f->string_patches) {
3251 struct obj_string_patch *p;
3252 struct obj_section *strsec;
3253 ElfW(Addr) strsec_base;
3254 strsec = obj_find_section(f, ".kstrtab");
3255 strsec_base = strsec->header.sh_addr;
3256
3257 for (p = f->string_patches; p; p = p->next) {
3258 struct obj_section *targsec = f->sections[p->reloc_secidx];
3259 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3260 = strsec_base + p->string_offset;
3261 }
3262 }
3263
3264 if (f->symbol_patches) {
3265 struct obj_symbol_patch *p;
3266
3267 for (p = f->symbol_patches; p; p = p->next) {
3268 struct obj_section *targsec = f->sections[p->reloc_secidx];
3269 *(ElfW(Addr) *) (targsec->contents + p->reloc_offset)
3270 = obj_symbol_final_value(f, p->sym);
3271 }
3272 }
3273
3274 return ret;
3275}
3276
Eric Andersen044228d2001-07-17 01:12:36 +00003277static int obj_create_image(struct obj_file *f, char *image)
Eric Andersen9f16d612000-06-12 23:11:16 +00003278{
3279 struct obj_section *sec;
3280 ElfW(Addr) base = f->baseaddr;
3281
3282 for (sec = f->load_order; sec; sec = sec->load_next) {
3283 char *secimg;
3284
Eric Andersen2bf658d2001-02-24 20:01:53 +00003285 if (sec->contents == 0 || sec->header.sh_size == 0)
Eric Andersen9f16d612000-06-12 23:11:16 +00003286 continue;
3287
3288 secimg = image + (sec->header.sh_addr - base);
3289
3290 /* Note that we allocated data for NOBITS sections earlier. */
3291 memcpy(secimg, sec->contents, sec->header.sh_size);
3292 }
3293
3294 return 1;
3295}
3296
3297/*======================================================================*/
3298
Eric Andersen044228d2001-07-17 01:12:36 +00003299static struct obj_file *obj_load(FILE * fp, int loadprogbits)
Eric Andersen9f16d612000-06-12 23:11:16 +00003300{
3301 struct obj_file *f;
3302 ElfW(Shdr) * section_headers;
3303 int shnum, i;
3304 char *shstrtab;
3305
3306 /* Read the file header. */
3307
3308 f = arch_new_file();
3309 memset(f, 0, sizeof(*f));
3310 f->symbol_cmp = strcmp;
3311 f->symbol_hash = obj_elf_hash;
3312 f->load_order_search_start = &f->load_order;
3313
3314 fseek(fp, 0, SEEK_SET);
3315 if (fread(&f->header, sizeof(f->header), 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003316 bb_perror_msg("error reading ELF header");
Eric Andersen9f16d612000-06-12 23:11:16 +00003317 return NULL;
3318 }
3319
3320 if (f->header.e_ident[EI_MAG0] != ELFMAG0
Eric Andersen3b1a7442003-12-24 20:30:45 +00003321 || f->header.e_ident[EI_MAG1] != ELFMAG1
3322 || f->header.e_ident[EI_MAG2] != ELFMAG2
3323 || f->header.e_ident[EI_MAG3] != ELFMAG3) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003324 bb_error_msg("not an ELF file");
Eric Andersen9f16d612000-06-12 23:11:16 +00003325 return NULL;
3326 }
3327 if (f->header.e_ident[EI_CLASS] != ELFCLASSM
Rob Landley0bafd472006-03-25 02:49:28 +00003328 || f->header.e_ident[EI_DATA] != (BB_BIG_ENDIAN
3329 ? ELFDATA2MSB : ELFDATA2LSB)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003330 || f->header.e_ident[EI_VERSION] != EV_CURRENT
3331 || !MATCH_MACHINE(f->header.e_machine)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003332 bb_error_msg("ELF file not for this architecture");
Eric Andersen9f16d612000-06-12 23:11:16 +00003333 return NULL;
3334 }
3335 if (f->header.e_type != ET_REL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003336 bb_error_msg("ELF file not a relocatable object");
Eric Andersen9f16d612000-06-12 23:11:16 +00003337 return NULL;
3338 }
3339
3340 /* Read the section headers. */
3341
3342 if (f->header.e_shentsize != sizeof(ElfW(Shdr))) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003343 bb_error_msg("section header size mismatch: %lu != %lu",
Eric Andersen9f16d612000-06-12 23:11:16 +00003344 (unsigned long) f->header.e_shentsize,
3345 (unsigned long) sizeof(ElfW(Shdr)));
3346 return NULL;
3347 }
3348
3349 shnum = f->header.e_shnum;
3350 f->sections = xmalloc(sizeof(struct obj_section *) * shnum);
3351 memset(f->sections, 0, sizeof(struct obj_section *) * shnum);
3352
3353 section_headers = alloca(sizeof(ElfW(Shdr)) * shnum);
3354 fseek(fp, f->header.e_shoff, SEEK_SET);
3355 if (fread(section_headers, sizeof(ElfW(Shdr)), shnum, fp) != shnum) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003356 bb_perror_msg("error reading ELF section headers");
Eric Andersen9f16d612000-06-12 23:11:16 +00003357 return NULL;
3358 }
3359
3360 /* Read the section data. */
3361
3362 for (i = 0; i < shnum; ++i) {
3363 struct obj_section *sec;
3364
3365 f->sections[i] = sec = arch_new_section();
3366 memset(sec, 0, sizeof(*sec));
3367
3368 sec->header = section_headers[i];
3369 sec->idx = i;
3370
Eric Andersen2bf658d2001-02-24 20:01:53 +00003371 if(sec->header.sh_size) switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003372 case SHT_NULL:
3373 case SHT_NOTE:
3374 case SHT_NOBITS:
3375 /* ignore */
Eric Andersen8ae319a2001-05-21 16:09:18 +00003376 break;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003377
3378 case SHT_PROGBITS:
3379#if LOADBITS
3380 if (!loadprogbits) {
3381 sec->contents = NULL;
3382 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003383 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003384#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003385 case SHT_SYMTAB:
3386 case SHT_STRTAB:
3387 case SHT_RELM:
3388 if (sec->header.sh_size > 0) {
3389 sec->contents = xmalloc(sec->header.sh_size);
3390 fseek(fp, sec->header.sh_offset, SEEK_SET);
3391 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
3392 bb_perror_msg("error reading ELF section data");
3393 return NULL;
3394 }
3395 } else {
3396 sec->contents = NULL;
3397 }
3398 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003399
3400#if SHT_RELM == SHT_REL
Eric Andersen3b1a7442003-12-24 20:30:45 +00003401 case SHT_RELA:
3402 bb_error_msg("RELA relocations not supported on this architecture");
3403 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003404#else
Eric Andersen3b1a7442003-12-24 20:30:45 +00003405 case SHT_REL:
3406 bb_error_msg("REL relocations not supported on this architecture");
3407 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003408#endif
3409
Eric Andersen3b1a7442003-12-24 20:30:45 +00003410 default:
3411 if (sec->header.sh_type >= SHT_LOPROC) {
3412 /* Assume processor specific section types are debug
3413 info and can safely be ignored. If this is ever not
3414 the case (Hello MIPS?), don't put ifdefs here but
3415 create an arch_load_proc_section(). */
3416 break;
3417 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003418
Eric Andersen3b1a7442003-12-24 20:30:45 +00003419 bb_error_msg("can't handle sections of type %ld",
3420 (long) sec->header.sh_type);
3421 return NULL;
Eric Andersen9f16d612000-06-12 23:11:16 +00003422 }
3423 }
3424
3425 /* Do what sort of interpretation as needed by each section. */
3426
3427 shstrtab = f->sections[f->header.e_shstrndx]->contents;
3428
3429 for (i = 0; i < shnum; ++i) {
3430 struct obj_section *sec = f->sections[i];
3431 sec->name = shstrtab + sec->header.sh_name;
3432 }
3433
3434 for (i = 0; i < shnum; ++i) {
3435 struct obj_section *sec = f->sections[i];
3436
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003437 /* .modinfo should be contents only but gcc has no attribute for that.
3438 * The kernel may have marked .modinfo as ALLOC, ignore this bit.
3439 */
3440 if (strcmp(sec->name, ".modinfo") == 0)
3441 sec->header.sh_flags &= ~SHF_ALLOC;
3442
Eric Andersen9f16d612000-06-12 23:11:16 +00003443 if (sec->header.sh_flags & SHF_ALLOC)
3444 obj_insert_section_load_order(f, sec);
3445
3446 switch (sec->header.sh_type) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00003447 case SHT_SYMTAB:
3448 {
3449 unsigned long nsym, j;
3450 char *strtab;
3451 ElfW(Sym) * sym;
Eric Andersen9f16d612000-06-12 23:11:16 +00003452
Eric Andersen3b1a7442003-12-24 20:30:45 +00003453 if (sec->header.sh_entsize != sizeof(ElfW(Sym))) {
3454 bb_error_msg("symbol size mismatch: %lu != %lu",
3455 (unsigned long) sec->header.sh_entsize,
3456 (unsigned long) sizeof(ElfW(Sym)));
3457 return NULL;
3458 }
Eric Andersen9f16d612000-06-12 23:11:16 +00003459
Eric Andersen3b1a7442003-12-24 20:30:45 +00003460 nsym = sec->header.sh_size / sizeof(ElfW(Sym));
3461 strtab = f->sections[sec->header.sh_link]->contents;
3462 sym = (ElfW(Sym) *) sec->contents;
Eric Andersen9f16d612000-06-12 23:11:16 +00003463
Eric Andersen3b1a7442003-12-24 20:30:45 +00003464 /* Allocate space for a table of local symbols. */
3465 j = f->local_symtab_size = sec->header.sh_info;
3466 f->local_symtab = xcalloc(j, sizeof(struct obj_symbol *));
Eric Andersen9f16d612000-06-12 23:11:16 +00003467
Eric Andersen3b1a7442003-12-24 20:30:45 +00003468 /* Insert all symbols into the hash table. */
3469 for (j = 1, ++sym; j < nsym; ++j, ++sym) {
3470 ElfW(Addr) val = sym->st_value;
3471 const char *name;
3472 if (sym->st_name)
3473 name = strtab + sym->st_name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003474 else if (sym->st_shndx < shnum)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003475 name = f->sections[sym->st_shndx]->name;
Manuel Novoa III 21fbe0e2004-02-18 10:14:17 +00003476 else
3477 continue;
Eric Andersen9f16d612000-06-12 23:11:16 +00003478
Eric Andersenbf833552003-08-13 19:56:33 +00003479#if defined(__SH5__)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003480 /*
3481 * For sh64 it is possible that the target of a branch
3482 * requires a mode switch (32 to 16 and back again).
3483 *
3484 * This is implied by the lsb being set in the target
3485 * address for SHmedia mode and clear for SHcompact.
3486 */
3487 val |= sym->st_other & 4;
Eric Andersenbf833552003-08-13 19:56:33 +00003488#endif
3489
Eric Andersen3b1a7442003-12-24 20:30:45 +00003490 obj_add_symbol(f, name, j, sym->st_info, sym->st_shndx,
3491 val, sym->st_size);
3492 }
Eric Andersen4f4bcfc2001-04-25 17:22:32 +00003493 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00003494 break;
Eric Andersen9f16d612000-06-12 23:11:16 +00003495
Eric Andersen3b1a7442003-12-24 20:30:45 +00003496 case SHT_RELM:
3497 if (sec->header.sh_entsize != sizeof(ElfW(RelM))) {
3498 bb_error_msg("relocation entry size mismatch: %lu != %lu",
3499 (unsigned long) sec->header.sh_entsize,
3500 (unsigned long) sizeof(ElfW(RelM)));
3501 return NULL;
3502 }
3503 break;
3504 /* XXX Relocation code from modutils-2.3.19 is not here.
3505 * Why? That's about 20 lines of code from obj/obj_load.c,
3506 * which gets done in a second pass through the sections.
3507 * This BusyBox insmod does similar work in obj_relocate(). */
Eric Andersen9f16d612000-06-12 23:11:16 +00003508 }
3509 }
3510
3511 return f;
3512}
3513
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003514#ifdef CONFIG_FEATURE_INSMOD_LOADINKMEM
Eric Andersen8ae319a2001-05-21 16:09:18 +00003515/*
3516 * load the unloaded sections directly into the memory allocated by
3517 * kernel for the module
3518 */
3519
Eric Andersenac5dbd12001-08-22 05:26:08 +00003520static int obj_load_progbits(FILE * fp, struct obj_file* f, char* imagebase)
Eric Andersen8ae319a2001-05-21 16:09:18 +00003521{
Eric Andersen8ae319a2001-05-21 16:09:18 +00003522 ElfW(Addr) base = f->baseaddr;
3523 struct obj_section* sec;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003524
Eric Andersen8ae319a2001-05-21 16:09:18 +00003525 for (sec = f->load_order; sec; sec = sec->load_next) {
3526
3527 /* section already loaded? */
3528 if (sec->contents != NULL)
3529 continue;
Eric Andersen3b1a7442003-12-24 20:30:45 +00003530
Eric Andersen8ae319a2001-05-21 16:09:18 +00003531 if (sec->header.sh_size == 0)
3532 continue;
3533
3534 sec->contents = imagebase + (sec->header.sh_addr - base);
3535 fseek(fp, sec->header.sh_offset, SEEK_SET);
3536 if (fread(sec->contents, sec->header.sh_size, 1, fp) != 1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003537 bb_error_msg("error reading ELF section data: %s\n", strerror(errno));
Eric Andersen8ae319a2001-05-21 16:09:18 +00003538 return 0;
3539 }
3540
3541 }
3542 return 1;
3543}
3544#endif
3545
Eric Andersen9f16d612000-06-12 23:11:16 +00003546static void hide_special_symbols(struct obj_file *f)
3547{
3548 static const char *const specials[] = {
Miles Baderae28b042002-04-01 09:34:25 +00003549 SPFX "cleanup_module",
3550 SPFX "init_module",
3551 SPFX "kernel_version",
Eric Andersen9f16d612000-06-12 23:11:16 +00003552 NULL
3553 };
3554
3555 struct obj_symbol *sym;
3556 const char *const *p;
3557
3558 for (p = specials; *p; ++p)
3559 if ((sym = obj_find_symbol(f, *p)) != NULL)
3560 sym->info =
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003561 ELF_ST_INFO(STB_LOCAL, ELF_ST_TYPE(sym->info));
Eric Andersen9f16d612000-06-12 23:11:16 +00003562}
3563
Glenn L McGrath759515c2003-08-30 06:00:33 +00003564
Eric Andersen71ae64b2002-10-10 04:20:21 +00003565#ifdef CONFIG_FEATURE_CHECK_TAINTED_MODULE
Eric Andersen166fa462002-09-16 05:30:24 +00003566static int obj_gpl_license(struct obj_file *f, const char **license)
3567{
3568 struct obj_section *sec;
3569 /* This list must match *exactly* the list of allowable licenses in
3570 * linux/include/linux/module.h. Checking for leading "GPL" will not
3571 * work, somebody will use "GPL sucks, this is proprietary".
3572 */
"Vladimir N. Oleynik"1f0262b2005-10-20 11:17:48 +00003573 static const char * const gpl_licenses[] = {
Eric Andersen166fa462002-09-16 05:30:24 +00003574 "GPL",
3575 "GPL v2",
3576 "GPL and additional rights",
3577 "Dual BSD/GPL",
3578 "Dual MPL/GPL",
3579 };
Eric Andersen9f16d612000-06-12 23:11:16 +00003580
Eric Andersen166fa462002-09-16 05:30:24 +00003581 if ((sec = obj_find_section(f, ".modinfo"))) {
3582 const char *value, *ptr, *endptr;
3583 ptr = sec->contents;
3584 endptr = ptr + sec->header.sh_size;
3585 while (ptr < endptr) {
3586 if ((value = strchr(ptr, '=')) && strncmp(ptr, "license", value-ptr) == 0) {
3587 int i;
3588 if (license)
3589 *license = value+1;
3590 for (i = 0; i < sizeof(gpl_licenses)/sizeof(gpl_licenses[0]); ++i) {
3591 if (strcmp(value+1, gpl_licenses[i]) == 0)
3592 return(0);
3593 }
3594 return(2);
3595 }
3596 if (strchr(ptr, '\0'))
3597 ptr = strchr(ptr, '\0') + 1;
3598 else
3599 ptr = endptr;
3600 }
3601 }
3602 return(1);
3603}
3604
3605#define TAINT_FILENAME "/proc/sys/kernel/tainted"
3606#define TAINT_PROPRIETORY_MODULE (1<<0)
3607#define TAINT_FORCED_MODULE (1<<1)
3608#define TAINT_UNSAFE_SMP (1<<2)
Mike Frysingerfa17c4b2005-10-02 07:14:06 +00003609#define TAINT_URL "http://www.tux.org/lkml/#export-tainted"
Eric Andersen166fa462002-09-16 05:30:24 +00003610
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003611static void set_tainted(struct obj_file *f, int fd, char *m_name,
Eric Andersen166fa462002-09-16 05:30:24 +00003612 int kernel_has_tainted, int taint, const char *text1, const char *text2)
3613{
3614 char buf[80];
3615 int oldval;
3616 static int first = 1;
3617 if (fd < 0 && !kernel_has_tainted)
3618 return; /* New modutils on old kernel */
3619 printf("Warning: loading %s will taint the kernel: %s%s\n",
3620 m_name, text1, text2);
3621 if (first) {
3622 printf(" See %s for information about tainted modules\n", TAINT_URL);
3623 first = 0;
3624 }
3625 if (fd >= 0) {
3626 read(fd, buf, sizeof(buf)-1);
3627 buf[sizeof(buf)-1] = '\0';
3628 oldval = strtoul(buf, NULL, 10);
3629 sprintf(buf, "%d\n", oldval | taint);
3630 write(fd, buf, strlen(buf));
3631 }
3632}
3633
3634/* Check if loading this module will taint the kernel. */
3635static void check_tainted_module(struct obj_file *f, char *m_name)
3636{
3637 static const char tainted_file[] = TAINT_FILENAME;
3638 int fd, kernel_has_tainted;
3639 const char *ptr;
3640
3641 kernel_has_tainted = 1;
3642 if ((fd = open(tainted_file, O_RDWR)) < 0) {
3643 if (errno == ENOENT)
3644 kernel_has_tainted = 0;
3645 else if (errno == EACCES)
3646 kernel_has_tainted = 1;
3647 else {
3648 perror(tainted_file);
3649 kernel_has_tainted = 0;
3650 }
3651 }
3652
3653 switch (obj_gpl_license(f, &ptr)) {
3654 case 0:
3655 break;
3656 case 1:
3657 set_tainted(f, fd, m_name, kernel_has_tainted, TAINT_PROPRIETORY_MODULE, "no license", "");
3658 break;
3659 case 2:
3660 /* The module has a non-GPL license so we pretend that the
3661 * kernel always has a taint flag to get a warning even on
3662 * kernels without the proc flag.
3663 */
3664 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "non-GPL license - ", ptr);
3665 break;
3666 default:
3667 set_tainted(f, fd, m_name, 1, TAINT_PROPRIETORY_MODULE, "Unexpected return from obj_gpl_license", "");
3668 break;
3669 }
3670
3671 if (flag_force_load)
3672 set_tainted(f, fd, m_name, 1, TAINT_FORCED_MODULE, "forced load", "");
3673
3674 if (fd >= 0)
3675 close(fd);
3676}
Eric Andersen71ae64b2002-10-10 04:20:21 +00003677#else /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
3678#define check_tainted_module(x, y) do { } while(0);
3679#endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */
Eric Andersen9f16d612000-06-12 23:11:16 +00003680
Eric Andersen889dd202003-01-23 04:48:34 +00003681#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
3682/* add module source, timestamp, kernel version and a symbol for the
3683 * start of some sections. this info is used by ksymoops to do better
3684 * debugging.
3685 */
3686static int
3687get_module_version(struct obj_file *f, char str[STRVERSIONLEN])
3688{
3689#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00003690 return new_get_module_version(f, str);
Eric Andersen889dd202003-01-23 04:48:34 +00003691#else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003692 strncpy(str, "???", sizeof(str));
3693 return -1;
Eric Andersen889dd202003-01-23 04:48:34 +00003694#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
3695}
3696
3697/* add module source, timestamp, kernel version and a symbol for the
3698 * start of some sections. this info is used by ksymoops to do better
3699 * debugging.
3700 */
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003701static void
Eric Andersen889dd202003-01-23 04:48:34 +00003702add_ksymoops_symbols(struct obj_file *f, const char *filename,
3703 const char *m_name)
3704{
3705 static const char symprefix[] = "__insmod_";
3706 struct obj_section *sec;
3707 struct obj_symbol *sym;
3708 char *name, *absolute_filename;
3709 char str[STRVERSIONLEN], real[PATH_MAX];
3710 int i, l, lm_name, lfilename, use_ksymtab, version;
3711 struct stat statbuf;
3712
3713 static const char *section_names[] = {
3714 ".text",
3715 ".rodata",
3716 ".data",
Peter Kjellerstedt540769d2005-03-30 16:36:40 +00003717 ".bss",
3718 ".sbss"
Eric Andersen889dd202003-01-23 04:48:34 +00003719 };
3720
3721 if (realpath(filename, real)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003722 absolute_filename = bb_xstrdup(real);
Eric Andersen889dd202003-01-23 04:48:34 +00003723 }
3724 else {
3725 int save_errno = errno;
Manuel Novoa III cad53642003-03-19 09:13:01 +00003726 bb_error_msg("cannot get realpath for %s", filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003727 errno = save_errno;
3728 perror("");
Manuel Novoa III cad53642003-03-19 09:13:01 +00003729 absolute_filename = bb_xstrdup(filename);
Eric Andersen889dd202003-01-23 04:48:34 +00003730 }
3731
3732 lm_name = strlen(m_name);
3733 lfilename = strlen(absolute_filename);
3734
3735 /* add to ksymtab if it already exists or there is no ksymtab and other symbols
3736 * are not to be exported. otherwise leave ksymtab alone for now, the
3737 * "export all symbols" compatibility code will export these symbols later.
3738 */
3739 use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export;
3740
3741 if ((sec = obj_find_section(f, ".this"))) {
3742 /* tag the module header with the object name, last modified
3743 * timestamp and module version. worst case for module version
3744 * is 0xffffff, decimal 16777215. putting all three fields in
3745 * one symbol is less readable but saves kernel space.
3746 */
3747 l = sizeof(symprefix)+ /* "__insmod_" */
Eric Andersen3b1a7442003-12-24 20:30:45 +00003748 lm_name+ /* module name */
3749 2+ /* "_O" */
3750 lfilename+ /* object filename */
3751 2+ /* "_M" */
3752 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */
3753 2+ /* "_V" */
3754 8+ /* version in dec */
3755 1; /* nul */
Eric Andersen889dd202003-01-23 04:48:34 +00003756 name = xmalloc(l);
3757 if (stat(absolute_filename, &statbuf) != 0)
3758 statbuf.st_mtime = 0;
3759 version = get_module_version(f, str); /* -1 if not found */
3760 snprintf(name, l, "%s%s_O%s_M%0*lX_V%d",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003761 symprefix, m_name, absolute_filename,
3762 (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime,
3763 version);
Eric Andersen889dd202003-01-23 04:48:34 +00003764 sym = obj_add_symbol(f, name, -1,
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003765 ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003766 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003767 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003768 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003769 }
3770 free(absolute_filename);
3771#ifdef _NOT_SUPPORTED_
3772 /* record where the persistent data is going, same address as previous symbol */
3773
3774 if (f->persist) {
3775 l = sizeof(symprefix)+ /* "__insmod_" */
3776 lm_name+ /* module name */
3777 2+ /* "_P" */
3778 strlen(f->persist)+ /* data store */
3779 1; /* nul */
3780 name = xmalloc(l);
3781 snprintf(name, l, "%s%s_P%s",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003782 symprefix, m_name, f->persist);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003783 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003784 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003785 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003786 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003787 }
3788#endif /* _NOT_SUPPORTED_ */
3789 /* tag the desired sections if size is non-zero */
3790
3791 for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) {
3792 if ((sec = obj_find_section(f, section_names[i])) &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00003793 sec->header.sh_size) {
Eric Andersen889dd202003-01-23 04:48:34 +00003794 l = sizeof(symprefix)+ /* "__insmod_" */
3795 lm_name+ /* module name */
3796 2+ /* "_S" */
3797 strlen(sec->name)+ /* section name */
3798 2+ /* "_L" */
3799 8+ /* length in dec */
3800 1; /* nul */
3801 name = xmalloc(l);
3802 snprintf(name, l, "%s%s_S%s_L%ld",
Eric Andersen3b1a7442003-12-24 20:30:45 +00003803 symprefix, m_name, sec->name,
3804 (long)sec->header.sh_size);
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003805 sym = obj_add_symbol(f, name, -1, ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE),
Eric Andersen3b1a7442003-12-24 20:30:45 +00003806 sec->idx, sec->header.sh_addr, 0);
Eric Andersen889dd202003-01-23 04:48:34 +00003807 if (use_ksymtab)
Eric Andersen3b1a7442003-12-24 20:30:45 +00003808 new_add_ksymtab(f, sym);
Eric Andersen889dd202003-01-23 04:48:34 +00003809 }
3810 }
3811}
3812#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
3813
Eric Andersenbe65c352003-01-23 04:57:35 +00003814#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3815static void print_load_map(struct obj_file *f)
3816{
3817 struct obj_symbol *sym;
3818 struct obj_symbol **all, **p;
3819 struct obj_section *sec;
3820 int i, nsyms, *loaded;
3821
3822 /* Report on the section layout. */
3823
3824 printf("Sections: Size %-*s Align\n",
3825 (int) (2 * sizeof(void *)), "Address");
3826
3827 for (sec = f->load_order; sec; sec = sec->load_next) {
3828 int a;
3829 unsigned long tmp;
3830
3831 for (a = -1, tmp = sec->header.sh_addralign; tmp; ++a)
3832 tmp >>= 1;
3833 if (a == -1)
3834 a = 0;
3835
3836 printf("%-15s %08lx %0*lx 2**%d\n",
3837 sec->name,
3838 (long)sec->header.sh_size,
3839 (int) (2 * sizeof(void *)),
3840 (long)sec->header.sh_addr,
3841 a);
3842 }
3843#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL
3844 /* Quick reference which section indicies are loaded. */
3845
3846 loaded = alloca(sizeof(int) * (i = f->header.e_shnum));
3847 while (--i >= 0)
3848 loaded[i] = (f->sections[i]->header.sh_flags & SHF_ALLOC) != 0;
3849
3850 /* Collect the symbols we'll be listing. */
3851
3852 for (nsyms = i = 0; i < HASH_BUCKETS; ++i)
3853 for (sym = f->symtab[i]; sym; sym = sym->next)
3854 if (sym->secidx <= SHN_HIRESERVE
3855 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3856 ++nsyms;
3857
3858 all = alloca(nsyms * sizeof(struct obj_symbol *));
3859
3860 for (i = 0, p = all; i < HASH_BUCKETS; ++i)
3861 for (sym = f->symtab[i]; sym; sym = sym->next)
3862 if (sym->secidx <= SHN_HIRESERVE
3863 && (sym->secidx >= SHN_LORESERVE || loaded[sym->secidx]))
3864 *p++ = sym;
3865
3866 /* And list them. */
3867 printf("\nSymbols:\n");
3868 for (p = all; p < all + nsyms; ++p) {
3869 char type = '?';
3870 unsigned long value;
3871
3872 sym = *p;
3873 if (sym->secidx == SHN_ABS) {
3874 type = 'A';
3875 value = sym->value;
3876 } else if (sym->secidx == SHN_UNDEF) {
3877 type = 'U';
3878 value = 0;
3879 } else {
3880 sec = f->sections[sym->secidx];
3881
3882 if (sec->header.sh_type == SHT_NOBITS)
3883 type = 'B';
3884 else if (sec->header.sh_flags & SHF_ALLOC) {
3885 if (sec->header.sh_flags & SHF_EXECINSTR)
3886 type = 'T';
3887 else if (sec->header.sh_flags & SHF_WRITE)
3888 type = 'D';
3889 else
3890 type = 'R';
3891 }
3892 value = sym->value + sec->header.sh_addr;
3893 }
3894
Mike Frysinger86a4bfb2005-10-02 07:02:16 +00003895 if (ELF_ST_BIND(sym->info) == STB_LOCAL)
Eric Andersenbe65c352003-01-23 04:57:35 +00003896 type = tolower(type);
3897
3898 printf("%0*lx %c %s\n", (int) (2 * sizeof(void *)), value,
3899 type, sym->name);
3900 }
3901#endif
3902}
3903
3904#endif
3905
Rob Landleydfba7412006-03-06 20:47:33 +00003906int insmod_main( int argc, char **argv)
Eric Andersen9f16d612000-06-12 23:11:16 +00003907{
Eric Andersena18aaf12001-01-24 19:07:09 +00003908 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +00003909 int len;
Eric Andersen5275b1e2004-06-22 20:10:53 +00003910 int k_crcs;
Eric Andersen6fb4e482002-06-06 14:24:57 +00003911 char *tmp, *tmp1;
Eric Andersen9f16d612000-06-12 23:11:16 +00003912 unsigned long m_size;
3913 ElfW(Addr) m_addr;
Eric Andersen9f16d612000-06-12 23:11:16 +00003914 struct obj_file *f;
Eric Andersen02b9f422001-02-15 19:07:43 +00003915 struct stat st;
Eric Andersen61f83052002-06-22 17:15:42 +00003916 char *m_name = 0;
Matt Kraai3e856ce2000-12-01 02:55:13 +00003917 int exit_status = EXIT_FAILURE;
Eric Andersen9f16d612000-06-12 23:11:16 +00003918 int m_has_modinfo;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003919#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Matt Kraai063c1f52001-08-06 14:18:08 +00003920 struct utsname uts_info;
Eric Andersen9f16d612000-06-12 23:11:16 +00003921 char m_strversion[STRVERSIONLEN];
Eric Andersen5275b1e2004-06-22 20:10:53 +00003922 int m_version, m_crcs;
Eric Andersen9f16d612000-06-12 23:11:16 +00003923#endif
Eric Andersen61f83052002-06-22 17:15:42 +00003924#ifdef CONFIG_FEATURE_CLEAN_UP
3925 FILE *fp = 0;
3926#else
3927 FILE *fp;
3928#endif
Eric Andersenbe65c352003-01-23 04:57:35 +00003929#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
3930 int flag_print_load_map = 0;
3931#endif
Eric Andersen03d80912003-12-19 21:04:19 +00003932 int k_version = 0;
3933 struct utsname myuname;
Eric Andersen9f16d612000-06-12 23:11:16 +00003934
Erik Andersene49d5ec2000-02-08 19:58:47 +00003935 /* Parse any options */
Eric Andersenbe65c352003-01-23 04:57:35 +00003936#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003937 while ((opt = getopt(argc, argv, "fkqsvxmLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003938#else
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003939 while ((opt = getopt(argc, argv, "fkqsvxLo:")) > 0)
Eric Andersenbe65c352003-01-23 04:57:35 +00003940#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003941 {
3942 switch (opt) {
3943 case 'f': /* force loading */
3944 flag_force_load = 1;
3945 break;
3946 case 'k': /* module loaded by kerneld, auto-cleanable */
3947 flag_autoclean = 1;
3948 break;
3949 case 's': /* log to syslog */
3950 /* log to syslog -- not supported */
3951 /* but kernel needs this for request_module(), */
3952 /* as this calls: modprobe -k -s -- <module> */
3953 /* so silently ignore this flag */
3954 break;
3955 case 'v': /* verbose output */
3956 flag_verbose = 1;
3957 break;
3958 case 'q': /* silent */
3959 flag_quiet = 1;
3960 break;
3961 case 'x': /* do not export externs */
3962 flag_export = 0;
3963 break;
3964 case 'o': /* name the output module */
3965 free(m_name);
3966 m_name = bb_xstrdup(optarg);
3967 break;
3968 case 'L': /* Stub warning */
3969 /* This is needed for compatibility with modprobe.
3970 * In theory, this does locking, but we don't do
3971 * that. So be careful and plan your life around not
3972 * loading the same module 50 times concurrently. */
3973 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003974#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
Eric Andersen3b1a7442003-12-24 20:30:45 +00003975 case 'm': /* print module load map */
3976 flag_print_load_map = 1;
3977 break;
Eric Andersenbe65c352003-01-23 04:57:35 +00003978#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00003979 default:
3980 bb_show_usage();
3981 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00003982 }
Eric Andersen03d80912003-12-19 21:04:19 +00003983
Eric Andersena18aaf12001-01-24 19:07:09 +00003984 if (argv[optind] == NULL) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00003985 bb_show_usage();
Eric Andersen9f16d612000-06-12 23:11:16 +00003986 }
Eric Andersena18aaf12001-01-24 19:07:09 +00003987
Erik Andersene49d5ec2000-02-08 19:58:47 +00003988 /* Grab the module name */
Manuel Novoa III cad53642003-03-19 09:13:01 +00003989 tmp1 = bb_xstrdup(argv[optind]);
Eric Andersen6fb4e482002-06-06 14:24:57 +00003990 tmp = basename(tmp1);
Erik Andersene49d5ec2000-02-08 19:58:47 +00003991 len = strlen(tmp);
3992
Eric Andersen03d80912003-12-19 21:04:19 +00003993 if (uname(&myuname) == 0) {
3994 if (myuname.release[0] == '2') {
3995 k_version = myuname.release[2] - '0';
3996 }
3997 }
3998
3999#if defined(CONFIG_FEATURE_2_6_MODULES)
4000 if (k_version > 4 && len > 3 && tmp[len - 3] == '.' &&
Eric Andersen3b1a7442003-12-24 20:30:45 +00004001 tmp[len - 2] == 'k' && tmp[len - 1] == 'o') {
Eric Andersen03d80912003-12-19 21:04:19 +00004002 len-=3;
4003 tmp[len] = '\0';
4004 }
4005 else
4006#endif
Eric Andersen3b1a7442003-12-24 20:30:45 +00004007 if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o') {
4008 len-=2;
4009 tmp[len] = '\0';
4010 }
Eric Andersen2d342152002-06-18 05:16:25 +00004011
Eric Andersen03d80912003-12-19 21:04:19 +00004012
4013#if defined(CONFIG_FEATURE_2_6_MODULES)
4014 if (k_version > 4)
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004015 m_fullName = bb_xasprintf("%s.ko", tmp);
Eric Andersen03d80912003-12-19 21:04:19 +00004016 else
Eric Andersen03d80912003-12-19 21:04:19 +00004017#endif
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +00004018 m_fullName = bb_xasprintf("%s.o", tmp);
Eric Andersen61f83052002-06-22 17:15:42 +00004019
Eric Andersen61f83052002-06-22 17:15:42 +00004020 if (!m_name) {
4021 m_name = tmp;
4022 } else {
4023 free(tmp1);
4024 tmp1 = 0; /* flag for free(m_name) before exit() */
4025 }
Erik Andersene49d5ec2000-02-08 19:58:47 +00004026
Eric Andersen14d35432001-05-14 17:07:32 +00004027 /* Get a filedesc for the module. Check we we have a complete path */
Eric Andersen02b9f422001-02-15 19:07:43 +00004028 if (stat(argv[optind], &st) < 0 || !S_ISREG(st.st_mode) ||
4029 (fp = fopen(argv[optind], "r")) == NULL) {
Eric Andersen14d35432001-05-14 17:07:32 +00004030 /* Hmm. Could not open it. First search under /lib/modules/`uname -r`,
4031 * but do not error out yet if we fail to find it... */
Eric Andersen03d80912003-12-19 21:04:19 +00004032 if (k_version) { /* uname succeedd */
4033 char *module_dir;
4034 char *tmdn;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004035 char real_module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004036
Eric Andersen03d80912003-12-19 21:04:19 +00004037 tmdn = concat_path_file(_PATH_MODULES, myuname.release);
Eric Andersen2416dfc2001-05-14 20:03:04 +00004038 /* Jump through hoops in case /lib/modules/`uname -r`
4039 * is a symlink. We do not want recursive_action to
4040 * follow symlinks, but we do want to follow the
4041 * /lib/modules/`uname -r` dir, So resolve it ourselves
4042 * if it is a link... */
Eric Andersen03d80912003-12-19 21:04:19 +00004043 if (realpath (tmdn, real_module_dir) == NULL)
4044 module_dir = tmdn;
4045 else
4046 module_dir = real_module_dir;
4047 recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen3b1a7442003-12-24 20:30:45 +00004048 check_module_name_match, 0, m_fullName);
Eric Andersen03d80912003-12-19 21:04:19 +00004049 free(tmdn);
Eric Andersen14d35432001-05-14 17:07:32 +00004050 }
4051
4052 /* Check if we have found anything yet */
Eric Andersen61f83052002-06-22 17:15:42 +00004053 if (m_filename == 0 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen9f16d612000-06-12 23:11:16 +00004054 {
Eric Andersen2416dfc2001-05-14 20:03:04 +00004055 char module_dir[FILENAME_MAX];
Robert Griebld378c312002-07-19 00:05:54 +00004056
Eric Andersen03d80912003-12-19 21:04:19 +00004057 free(m_filename);
4058 m_filename = 0;
Eric Andersen2416dfc2001-05-14 20:03:04 +00004059 if (realpath (_PATH_MODULES, module_dir) == NULL)
4060 strcpy(module_dir, _PATH_MODULES);
Eric Andersen14d35432001-05-14 17:07:32 +00004061 /* No module found under /lib/modules/`uname -r`, this
4062 * time cast the net a bit wider. Search /lib/modules/ */
Matt Kraai1f0c4362001-12-20 23:13:26 +00004063 if (! recursive_action(module_dir, TRUE, FALSE, FALSE,
Eric Andersen03d80912003-12-19 21:04:19 +00004064 check_module_name_match, 0, m_fullName))
Eric Andersen9f16d612000-06-12 23:11:16 +00004065 {
Eric Andersen61f83052002-06-22 17:15:42 +00004066 if (m_filename == 0
Eric Andersen03d80912003-12-19 21:04:19 +00004067 || ((fp = fopen(m_filename, "r")) == NULL))
Eric Andersen14d35432001-05-14 17:07:32 +00004068 {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004069 bb_error_msg("%s: no module by that name found", m_fullName);
Eric Andersen61f83052002-06-22 17:15:42 +00004070 goto out;
Eric Andersen14d35432001-05-14 17:07:32 +00004071 }
4072 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004073 bb_error_msg_and_die("%s: no module by that name found", m_fullName);
Eric Andersen14d35432001-05-14 17:07:32 +00004074 }
Eric Andersen03d80912003-12-19 21:04:19 +00004075 } else
Manuel Novoa III cad53642003-03-19 09:13:01 +00004076 m_filename = bb_xstrdup(argv[optind]);
Erik Andersend387d011999-12-21 02:55:11 +00004077
Rob Landley999af202005-12-11 20:14:12 +00004078 if (flag_verbose)
Glenn L McGrath5c9f0d02003-12-31 23:20:10 +00004079 printf("Using %s\n", m_filename);
Erik Andersend387d011999-12-21 02:55:11 +00004080
Eric Andersene7047882003-12-11 01:42:13 +00004081#ifdef CONFIG_FEATURE_2_6_MODULES
Eric Andersen03d80912003-12-19 21:04:19 +00004082 if (k_version > 4)
4083 {
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004084 optind--;
Eric Andersen03d80912003-12-19 21:04:19 +00004085 argv[optind + 1] = m_filename;
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004086 return insmod_ng_main(argc - optind, argv + optind);
Eric Andersen03d80912003-12-19 21:04:19 +00004087 }
Glenn L McGrathc2942f02003-08-31 01:58:18 +00004088#endif
4089
Eric Andersen8ae319a2001-05-21 16:09:18 +00004090 if ((f = obj_load(fp, LOADBITS)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +00004091 bb_perror_msg_and_die("Could not load the module");
Erik Andersend387d011999-12-21 02:55:11 +00004092
Eric Andersen9f16d612000-06-12 23:11:16 +00004093 if (get_modinfo_value(f, "kernel_version") == NULL)
4094 m_has_modinfo = 0;
4095 else
4096 m_has_modinfo = 1;
4097
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004098#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersen9f16d612000-06-12 23:11:16 +00004099 /* Version correspondence? */
Eric Andersenb493dec2002-07-02 19:14:23 +00004100 if (!flag_quiet) {
4101 if (uname(&uts_info) < 0)
4102 uts_info.release[0] = '\0';
4103 if (m_has_modinfo) {
4104 m_version = new_get_module_version(f, m_strversion);
Eric Andersenb493dec2002-07-02 19:14:23 +00004105 if (m_version == -1) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004106 bb_error_msg("couldn't find the kernel version the module was "
Eric Andersenb493dec2002-07-02 19:14:23 +00004107 "compiled for");
4108 goto out;
4109 }
4110 }
4111
4112 if (strncmp(uts_info.release, m_strversion, STRVERSIONLEN) != 0) {
4113 if (flag_force_load) {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004114 bb_error_msg("Warning: kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004115 "\t%s was compiled for kernel version %s\n"
4116 "\twhile this kernel is version %s",
4117 m_filename, m_strversion, uts_info.release);
4118 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004119 bb_error_msg("kernel-module version mismatch\n"
Eric Andersenb493dec2002-07-02 19:14:23 +00004120 "\t%s was compiled for kernel version %s\n"
4121 "\twhile this kernel is version %s.",
4122 m_filename, m_strversion, uts_info.release);
4123 goto out;
4124 }
Eric Andersen9f16d612000-06-12 23:11:16 +00004125 }
4126 }
4127 k_crcs = 0;
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004128#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004129
Eric Andersencb3b9b12004-06-22 11:50:52 +00004130 if (!query_module(NULL, 0, NULL, 0, NULL)) {
Eric Andersen9f16d612000-06-12 23:11:16 +00004131 if (!new_get_kernel_symbols())
4132 goto out;
4133 k_crcs = new_is_kernel_checksummed();
Eric Andersen9f16d612000-06-12 23:11:16 +00004134 } else {
Manuel Novoa III cad53642003-03-19 09:13:01 +00004135 bb_error_msg("Not configured to support old kernels");
Eric Andersen9f16d612000-06-12 23:11:16 +00004136 goto out;
Eric Andersen9f16d612000-06-12 23:11:16 +00004137 }
4138
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004139#ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING
Eric Andersencb3b9b12004-06-22 11:50:52 +00004140 m_crcs = 0;
Eric Andersen9f16d612000-06-12 23:11:16 +00004141 if (m_has_modinfo)
4142 m_crcs = new_is_module_checksummed(f);
Eric Andersen9f16d612000-06-12 23:11:16 +00004143
4144 if (m_crcs != k_crcs)
4145 obj_set_symbol_compare(f, ncv_strcmp, ncv_symbol_hash);
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004146#endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */
Eric Andersen9f16d612000-06-12 23:11:16 +00004147
Erik Andersene49d5ec2000-02-08 19:58:47 +00004148 /* Let the module know about the kernel symbols. */
4149 add_kernel_symbols(f);
4150
Eric Andersen9f16d612000-06-12 23:11:16 +00004151 /* Allocate common symbols, symbol tables, and string tables. */
4152
Eric Andersencb3b9b12004-06-22 11:50:52 +00004153 if (!new_create_this_module(f, m_name))
Eric Andersen9f16d612000-06-12 23:11:16 +00004154 {
4155 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004156 }
4157
Eric Andersen9f16d612000-06-12 23:11:16 +00004158 if (!obj_check_undefineds(f)) {
4159 goto out;
Erik Andersene49d5ec2000-02-08 19:58:47 +00004160 }
4161 obj_allocate_commons(f);
Eric Andersen166fa462002-09-16 05:30:24 +00004162 check_tainted_module(f, m_name);
Erik Andersene49d5ec2000-02-08 19:58:47 +00004163
Eric Andersen86f3d5b2001-01-24 23:59:50 +00004164 /* done with the module name, on to the optional var=value arguments */
4165 ++optind;
4166
Eric Andersen9f16d612000-06-12 23:11:16 +00004167 if (optind < argc) {
Robert Griebl809387f2004-07-20 15:43:57 +00004168 if (!new_process_module_arguments(f, argc - optind, argv + optind))
Eric Andersen9f16d612000-06-12 23:11:16 +00004169 {
4170 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
Eric Andersen889dd202003-01-23 04:48:34 +00004177#ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS
4178 add_ksymoops_symbols(f, m_filename, m_name);
4179#endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */
4180
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:
4190 bb_error_msg("A module named %s already exists", m_name);
4191 goto out;
4192 case ENOMEM:
4193 bb_error_msg("Can't allocate kernel memory for module; needed %lu bytes",
4194 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
Eric Andersencb3b9b12004-06-22 11:50:52 +00004217 if (!new_init_module(m_name, f, m_size))
Eric Andersen9f16d612000-06-12 23:11:16 +00004218 {
4219 delete_module(m_name);
4220 goto out;
4221 }
4222
Eric Andersenbe65c352003-01-23 04:57:35 +00004223#ifdef CONFIG_FEATURE_INSMOD_LOAD_MAP
4224 if(flag_print_load_map)
4225 print_load_map(f);
4226#endif
4227
Matt Kraai3e856ce2000-12-01 02:55:13 +00004228 exit_status = EXIT_SUCCESS;
Eric Andersen9f16d612000-06-12 23:11:16 +00004229
4230out:
Eric Andersen61f83052002-06-22 17:15:42 +00004231#ifdef CONFIG_FEATURE_CLEAN_UP
4232 if(fp)
Eric Andersen3b1a7442003-12-24 20:30:45 +00004233 fclose(fp);
Rob Landleye7c43b62006-03-01 16:39:45 +00004234 free(tmp1);
4235 if(!tmp1) {
Eric Andersen61f83052002-06-22 17:15:42 +00004236 free(m_name);
4237 }
4238 free(m_filename);
4239#endif
Eric Andersenbb245ba2000-06-19 19:53:30 +00004240 return(exit_status);
Erik Andersen02104321999-12-17 18:57:34 +00004241}
Eric Andersene7047882003-12-11 01:42:13 +00004242
4243
4244#endif
4245
4246
4247#ifdef CONFIG_FEATURE_2_6_MODULES
4248
4249#include <sys/mman.h>
4250#include <asm/unistd.h>
4251#include <sys/syscall.h>
4252
4253/* We use error numbers in a loose translation... */
4254static const char *moderror(int err)
4255{
4256 switch (err) {
Eric Andersen3b1a7442003-12-24 20:30:45 +00004257 case ENOEXEC:
4258 return "Invalid module format";
4259 case ENOENT:
4260 return "Unknown symbol in module";
4261 case ESRCH:
4262 return "Module has wrong symbol version";
4263 case EINVAL:
4264 return "Invalid parameters";
4265 default:
4266 return strerror(err);
Eric Andersene7047882003-12-11 01:42:13 +00004267 }
4268}
4269
Rob Landleydfba7412006-03-06 20:47:33 +00004270int insmod_ng_main( int argc, char **argv)
Eric Andersene7047882003-12-11 01:42:13 +00004271{
4272 int i;
4273 int fd;
4274 long int ret;
4275 struct stat st;
4276 unsigned long len;
4277 void *map;
4278 char *filename, *options = bb_xstrdup("");
Eric Andersen3b1a7442003-12-24 20:30:45 +00004279
Eric Andersene7047882003-12-11 01:42:13 +00004280 filename = argv[1];
4281 if (!filename) {
4282 bb_show_usage();
4283 return -1;
4284 }
4285
4286 /* Rest is options */
4287 for (i = 2; i < argc; i++) {
4288 options = xrealloc(options, strlen(options) + 2 + strlen(argv[i]) + 2);
4289 /* Spaces handled by "" pairs, but no way of escaping quotes */
4290 if (strchr(argv[i], ' ')) {
4291 strcat(options, "\"");
4292 strcat(options, argv[i]);
4293 strcat(options, "\"");
4294 } else {
4295 strcat(options, argv[i]);
4296 }
4297 strcat(options, " ");
4298 }
4299
4300 if ((fd = open(filename, O_RDONLY, 0)) < 0) {
4301 bb_perror_msg_and_die("cannot open module `%s'", filename);
4302 }
4303
4304 fstat(fd, &st);
4305 len = st.st_size;
Rob Landley07fffc52005-12-07 22:45:28 +00004306 map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
Eric Andersene7047882003-12-11 01:42:13 +00004307 if (map == MAP_FAILED) {
4308 bb_perror_msg_and_die("cannot mmap `%s'", filename);
4309 }
4310
4311 ret = syscall(__NR_init_module, map, len, options);
4312 if (ret != 0) {
4313 bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
Eric Andersen3b1a7442003-12-24 20:30:45 +00004314 filename, moderror(errno), ret);
Eric Andersene7047882003-12-11 01:42:13 +00004315 }
Eric Andersen3b1a7442003-12-24 20:30:45 +00004316
Eric Andersene7047882003-12-11 01:42:13 +00004317 return 0;
4318}
4319
4320#endif